From 3728918d72e3ff2e7540becadf719957d8d75d70 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 4 Nov 2010 18:46:19 -0700 Subject: [PATCH] Add internal API for note iteration Some algorithms need to be able to iterate through all notes within a particular bucket, such as when splitting or combining a bucket. Exposing an Iterator makes this traversal possible. For a LeafBucket the iteration is simple, its over the sorted array of elements. For FanoutBucket its a bit more complex as the iteration needs to union the iterators of each fanout bucket, lazily loading any buckets that aren't already in-memory. Change-Id: I3d5279b11984f44dcf0ddb14a82a4b4e51d4632d Signed-off-by: Shawn O. Pearce --- .../org/eclipse/jgit/notes/FanoutBucket.java | 57 +++++++++++++++++++ .../org/eclipse/jgit/notes/LeafBucket.java | 24 ++++++++ .../org/eclipse/jgit/notes/NoteBucket.java | 4 ++ 3 files changed, 85 insertions(+) diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java index 208567690..5d35355ba 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/FanoutBucket.java @@ -46,9 +46,12 @@ package org.eclipse.jgit.notes; import static org.eclipse.jgit.lib.FileMode.TREE; import java.io.IOException; +import java.util.Iterator; +import java.util.NoSuchElementException; import org.eclipse.jgit.lib.AbbreviatedObjectId; import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.MutableObjectId; import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectInserter; import org.eclipse.jgit.lib.ObjectReader; @@ -107,6 +110,54 @@ class FanoutBucket extends InMemoryNoteBucket { return b != null ? b.get(objId, or) : null; } + @Override + Iterator iterator(AnyObjectId objId, final ObjectReader reader) + throws IOException { + final MutableObjectId id = new MutableObjectId(); + id.fromObjectId(objId); + + return new Iterator() { + private int cell; + + private Iterator itr; + + public boolean hasNext() { + if (itr != null && itr.hasNext()) + return true; + + for (; cell < table.length; cell++) { + NoteBucket b = table[cell]; + if (b == null) + continue; + + try { + id.setByte(prefixLen >> 1, cell); + itr = b.iterator(id, reader); + } catch (IOException err) { + throw new RuntimeException(err); + } + + if (itr.hasNext()) { + cell++; + return true; + } + } + return false; + } + + public Note next() { + if (hasNext()) + return itr.next(); + else + throw new NoSuchElementException(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + @Override InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData, ObjectReader or) throws IOException { @@ -193,6 +244,12 @@ class FanoutBucket extends InMemoryNoteBucket { return load(objId, or).get(objId, or); } + @Override + Iterator iterator(AnyObjectId objId, ObjectReader reader) + throws IOException { + return load(objId, reader).iterator(objId, reader); + } + @Override InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData, ObjectReader or) throws IOException { diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java index 40be45f43..67bb3c8a0 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/LeafBucket.java @@ -47,6 +47,8 @@ import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH; import static org.eclipse.jgit.lib.FileMode.REGULAR_FILE; import java.io.IOException; +import java.util.Iterator; +import java.util.NoSuchElementException; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ObjectId; @@ -103,6 +105,28 @@ class LeafBucket extends InMemoryNoteBucket { return 0 <= idx ? notes[idx].getData() : null; } + @Override + Iterator iterator(AnyObjectId objId, ObjectReader reader) { + return new Iterator() { + private int idx; + + public boolean hasNext() { + return idx < cnt; + } + + public Note next() { + if (hasNext()) + return notes[idx++]; + else + throw new NoSuchElementException(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + }; + } + InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData, ObjectReader or) throws IOException { int p = search(noteOn); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java b/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java index f5465148a..e13067cc1 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/notes/NoteBucket.java @@ -44,6 +44,7 @@ package org.eclipse.jgit.notes; import java.io.IOException; +import java.util.Iterator; import org.eclipse.jgit.lib.AnyObjectId; import org.eclipse.jgit.lib.ObjectId; @@ -60,6 +61,9 @@ abstract class NoteBucket { abstract ObjectId get(AnyObjectId objId, ObjectReader reader) throws IOException; + abstract Iterator iterator(AnyObjectId objId, ObjectReader reader) + throws IOException; + abstract InMemoryNoteBucket set(AnyObjectId noteOn, AnyObjectId noteData, ObjectReader reader) throws IOException;