summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorColby Ranger <cranger@google.com>2013-06-28 14:02:26 -0700
committerColby Ranger <cranger@google.com>2013-06-28 15:36:20 -0700
commit903fb9c7395cc45b5e8c98948c3a627c0bcc01d9 (patch)
tree7e9dca652d2205474ecf8b91f403561470126d0d
parenta2e5653d5af56e190102624159d734efd0a4f4c0 (diff)
downloadjgit-903fb9c7395cc45b5e8c98948c3a627c0bcc01d9.tar.gz
jgit-903fb9c7395cc45b5e8c98948c3a627c0bcc01d9.zip
Implement get nth offset in PackIndex.
Currently, the offset can only be retrieved by ObjectId or iterating all of the entries. Add a method to lookup the offset by position in the index sorted by SHA1. Change-Id: I45e9ac8b752d1dab47b202753a1dcca7122b958e
-rw-r--r--org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java15
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java13
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java27
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java30
4 files changed, 73 insertions, 12 deletions
diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
index aa3817e3ad..7eeb0c0eaa 100644
--- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
+++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/file/PackIndexTestCase.java
@@ -158,6 +158,21 @@ public abstract class PackIndexTestCase extends RepositoryTestCase {
}
/**
+ * Compare offset from iterator entries with output of getOffset() method.
+ */
+ @Test
+ public void testCompareEntriesOffsetsWithGetOffsets() {
+ int i = 0;
+ for (MutableEntry me : smallIdx) {
+ assertEquals(smallIdx.getOffset(i++), me.getOffset());
+ }
+ int j = 0;
+ for (MutableEntry me : denseIdx) {
+ assertEquals(denseIdx.getOffset(j++), me.getOffset());
+ }
+ }
+
+ /**
* Test partial results of iterator comparing to content of well-known
* (prepared) dense index, that may need multi-level indexing.
*/
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
index 44baeb190c..0040aea713 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndex.java
@@ -245,6 +245,19 @@ public abstract class PackIndex implements Iterable<PackIndex.MutableEntry> {
}
/**
+ * Get offset in a pack for the n-th object entry returned by
+ * {@link #iterator()}.
+ *
+ * @param nthPosition
+ * unsigned 32 bit position within the traversal of
+ * {@link #iterator()} for which the caller needs the offset. The
+ * first returned {@link MutableEntry} is 0, the second is 1,
+ * etc. Positions past 2**31-1 are negative, but still valid.
+ * @return the offset in a pack for the corresponding entry.
+ */
+ abstract long getOffset(long nthPosition);
+
+ /**
* Locate the file offset position for the requested object.
*
* @param objId
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java
index 8c381fb830..2d574d80a0 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV1.java
@@ -113,15 +113,13 @@ class PackIndexV1 extends PackIndex {
return n64;
}
- @Override
- public ObjectId getObjectId(final long nthPosition) {
+ private int findLevelOne(final long nthPosition) {
int levelOne = Arrays.binarySearch(idxHeader, nthPosition + 1);
- long base;
if (levelOne >= 0) {
// If we hit the bucket exactly the item is in the bucket, or
// any bucket before it which has the same object count.
//
- base = idxHeader[levelOne];
+ long base = idxHeader[levelOne];
while (levelOne > 0 && base == idxHeader[levelOne - 1])
levelOne--;
} else {
@@ -129,14 +127,31 @@ class PackIndexV1 extends PackIndex {
//
levelOne = -(levelOne + 1);
}
+ return levelOne;
+ }
+
+ private int getLevelTwo(final long nthPosition, final int levelOne) {
+ final long base = levelOne > 0 ? idxHeader[levelOne - 1] : 0;
+ return (int) (nthPosition - base);
+ }
- base = levelOne > 0 ? idxHeader[levelOne - 1] : 0;
- final int p = (int) (nthPosition - base);
+ @Override
+ public ObjectId getObjectId(final long nthPosition) {
+ final int levelOne = findLevelOne(nthPosition);
+ final int p = getLevelTwo(nthPosition, levelOne);
final int dataIdx = idOffset(p);
return ObjectId.fromRaw(idxdata[levelOne], dataIdx);
}
@Override
+ long getOffset(long nthPosition) {
+ final int levelOne = findLevelOne(nthPosition);
+ final int levelTwo = getLevelTwo(nthPosition, levelOne);
+ final int p = (4 + Constants.OBJECT_ID_LENGTH) * levelTwo;
+ return NB.decodeUInt32(idxdata[levelOne], p);
+ }
+
+ @Override
public long findOffset(final AnyObjectId objId) {
final int levelOne = objId.getFirstByte();
byte[] data = idxdata[levelOne];
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java
index 9b1a5f3ce1..9d2caa2e88 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/file/PackIndexV2.java
@@ -170,15 +170,13 @@ class PackIndexV2 extends PackIndex {
return offset64.length / 8;
}
- @Override
- public ObjectId getObjectId(final long nthPosition) {
+ private int findLevelOne(final long nthPosition) {
int levelOne = Arrays.binarySearch(fanoutTable, nthPosition + 1);
- long base;
if (levelOne >= 0) {
// If we hit the bucket exactly the item is in the bucket, or
// any bucket before it which has the same object count.
//
- base = fanoutTable[levelOne];
+ long base = fanoutTable[levelOne];
while (levelOne > 0 && base == fanoutTable[levelOne - 1])
levelOne--;
} else {
@@ -186,19 +184,39 @@ class PackIndexV2 extends PackIndex {
//
levelOne = -(levelOne + 1);
}
+ return levelOne;
+ }
- base = levelOne > 0 ? fanoutTable[levelOne - 1] : 0;
- final int p = (int) (nthPosition - base);
+ private int getLevelTwo(final long nthPosition, final int levelOne) {
+ final long base = levelOne > 0 ? fanoutTable[levelOne - 1] : 0;
+ return (int) (nthPosition - base);
+ }
+
+ @Override
+ public ObjectId getObjectId(final long nthPosition) {
+ final int levelOne = findLevelOne(nthPosition);
+ final int p = getLevelTwo(nthPosition, levelOne);
final int p4 = p << 2;
return ObjectId.fromRaw(names[levelOne], p4 + p); // p * 5
}
@Override
+ public long getOffset(final long nthPosition) {
+ final int levelOne = findLevelOne(nthPosition);
+ final int levelTwo = getLevelTwo(nthPosition, levelOne);
+ return getOffset(levelOne, levelTwo);
+ }
+
+ @Override
public long findOffset(final AnyObjectId objId) {
final int levelOne = objId.getFirstByte();
final int levelTwo = binarySearchLevelTwo(objId, levelOne);
if (levelTwo == -1)
return -1;
+ return getOffset(levelOne, levelTwo);
+ }
+
+ private long getOffset(final int levelOne, final int levelTwo) {
final long p = NB.decodeUInt32(offset32[levelOne], levelTwo << 2);
if ((p & IS_O64) != 0)
return NB.decodeUInt64(offset64, (8 * (int) (p & ~IS_O64)));