Mercurial > jhg
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). |
