comparison src/org/tmatesoft/hg/repo/HgDataFile.java @ 276:6355ecda1f08

Tailored Map implementation with int keys
author Artem Tikhomirov <tikhomirov.artem@gmail.com>
date Mon, 29 Aug 2011 22:15:12 +0200
parents 6d1804fe0ed7
children 74e7493a042a
comparison
equal deleted inserted replaced
275:6d1804fe0ed7 276:6355ecda1f08
26 import java.nio.ByteBuffer; 26 import java.nio.ByteBuffer;
27 import java.nio.channels.FileChannel; 27 import java.nio.channels.FileChannel;
28 import java.util.ArrayList; 28 import java.util.ArrayList;
29 import java.util.Arrays; 29 import java.util.Arrays;
30 import java.util.Collection; 30 import java.util.Collection;
31 import java.util.TreeMap;
32 31
33 import org.tmatesoft.hg.core.HgDataStreamException; 32 import org.tmatesoft.hg.core.HgDataStreamException;
34 import org.tmatesoft.hg.core.HgException; 33 import org.tmatesoft.hg.core.HgException;
35 import org.tmatesoft.hg.core.Nodeid; 34 import org.tmatesoft.hg.core.Nodeid;
36 import org.tmatesoft.hg.internal.DataAccess; 35 import org.tmatesoft.hg.internal.DataAccess;
37 import org.tmatesoft.hg.internal.FilterByteChannel; 36 import org.tmatesoft.hg.internal.FilterByteChannel;
37 import org.tmatesoft.hg.internal.IntMap;
38 import org.tmatesoft.hg.internal.RevlogStream; 38 import org.tmatesoft.hg.internal.RevlogStream;
39 import org.tmatesoft.hg.util.ByteChannel; 39 import org.tmatesoft.hg.util.ByteChannel;
40 import org.tmatesoft.hg.util.CancelSupport; 40 import org.tmatesoft.hg.util.CancelSupport;
41 import org.tmatesoft.hg.util.CancelledException; 41 import org.tmatesoft.hg.util.CancelledException;
42 import org.tmatesoft.hg.util.Path; 42 import org.tmatesoft.hg.util.Path;
345 return entry.substring(valueStart); 345 return entry.substring(valueStart);
346 } 346 }
347 } 347 }
348 348
349 private static class Metadata { 349 private static class Metadata {
350 private static class Record {
351 public final int offset;
352 public final MetadataEntry[] entries;
353
354 public Record(int off, MetadataEntry[] entr) {
355 offset = off;
356 entries = entr;
357 }
358 }
350 // XXX sparse array needed 359 // XXX sparse array needed
351 private final TreeMap<Integer, Integer> offsets = new TreeMap<Integer, Integer>(); 360 private final IntMap<Record> entries = new IntMap<Record>(5);
352 private final TreeMap<Integer, MetadataEntry[]> entries = new TreeMap<Integer, MetadataEntry[]>();
353 361
354 private final Integer NONE = new Integer(-1); // do not duplicate -1 integers at least within single file (don't want statics) 362 private final Record NONE = new Record(-1, null); // don't want statics
355 363
356 // true when there's metadata for given revision 364 // true when there's metadata for given revision
357 boolean known(int revision) { 365 boolean known(int revision) {
358 Integer i = offsets.get(revision); 366 Record i = entries.get(revision);
359 return i != null && NONE != i; 367 return i != null && NONE != i;
360 } 368 }
361 369
362 // true when revision has been checked for metadata presence. 370 // true when revision has been checked for metadata presence.
363 public boolean checked(int revision) { 371 public boolean checked(int revision) {
364 return offsets.containsKey(revision); 372 return entries.containsKey(revision);
365 } 373 }
366 374
367 // true when revision has been checked and found not having any metadata 375 // true when revision has been checked and found not having any metadata
368 boolean none(int revision) { 376 boolean none(int revision) {
369 Integer i = offsets.get(revision); 377 Record i = entries.get(revision);
370 return i == NONE; 378 return i == NONE;
371 } 379 }
372 380
373 // mark revision as having no metadata. 381 // mark revision as having no metadata.
374 void recordNone(int revision) { 382 void recordNone(int revision) {
375 Integer i = offsets.get(revision); 383 Record i = entries.get(revision);
376 if (i == NONE) { 384 if (i == NONE) {
377 return; // already there 385 return; // already there
378 } 386 }
379 if (i != null) { 387 if (i != null) {
380 throw new IllegalStateException(String.format("Trying to override Metadata state for revision %d (known offset: %d)", revision, i)); 388 throw new IllegalStateException(String.format("Trying to override Metadata state for revision %d (known offset: %d)", revision, i));
381 } 389 }
382 offsets.put(revision, NONE); 390 entries.put(revision, NONE);
383 } 391 }
384 392
385 // since this is internal class, callers are supposed to ensure arg correctness (i.e. ask known() before) 393 // since this is internal class, callers are supposed to ensure arg correctness (i.e. ask known() before)
386 int dataOffset(int revision) { 394 int dataOffset(int revision) {
387 return offsets.get(revision); 395 return entries.get(revision).offset;
388 } 396 }
389 void add(int revision, int dataOffset, Collection<MetadataEntry> e) { 397 void add(int revision, int dataOffset, Collection<MetadataEntry> e) {
390 assert !offsets.containsKey(revision); 398 assert !entries.containsKey(revision);
391 offsets.put(revision, dataOffset); 399 entries.put(revision, new Record(dataOffset, e.toArray(new MetadataEntry[e.size()])));
392 entries.put(revision, e.toArray(new MetadataEntry[e.size()])); 400 }
393 } 401
394 String find(int revision, String key) { 402 String find(int revision, String key) {
395 for (MetadataEntry me : entries.get(revision)) { 403 for (MetadataEntry me : entries.get(revision).entries) {
396 if (me.matchKey(key)) { 404 if (me.matchKey(key)) {
397 return me.value(); 405 return me.value();
398 } 406 }
399 } 407 }
400 return null; 408 return null;
464 byteOne = true; 472 byteOne = true;
465 } else { 473 } else {
466 bos.write(b); 474 bos.write(b);
467 } 475 }
468 } 476 }
469 _metadata.trimToSize();
470 metadata.add(revisionNumber, lastEntryStart, _metadata); 477 metadata.add(revisionNumber, lastEntryStart, _metadata);
471 if (da.isEmpty() || !byteOne) { 478 if (da.isEmpty() || !byteOne) {
472 throw new HgDataStreamException(fname, String.format("Metadata for revision %d is not closed properly", revisionNumber), null); 479 throw new HgDataStreamException(fname, String.format("Metadata for revision %d is not closed properly", revisionNumber), null);
473 } 480 }
474 // da is in prepared state (i.e. we consumed all bytes up to metadata end). 481 // da is in prepared state (i.e. we consumed all bytes up to metadata end).