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