From 0eeed6ad2b93f9f9712803cfec288bb0f094dd17 Mon Sep 17 00:00:00 2001 From: Minh Thai Date: Thu, 19 Mar 2020 23:10:41 -0700 Subject: [PATCH] Scan through all merged reftables for max/min update indices Since reftables might have update index ranges that are overlapped. Change-Id: I8f8215b99a0a978d4dd0155dbaf33e5e06ea8202 Signed-off-by: Minh Thai (cherry picked from commit 06748c205c44bb4eaf6015387112de97f566c6a2) --- .../storage/reftable/MergedReftableTest.java | 117 ++++++++++++++++++ .../storage/reftable/MergedReftable.java | 24 +++- 2 files changed, 137 insertions(+), 4 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java index 2a2aeb592..a246ac9e9 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftable/MergedReftableTest.java @@ -286,6 +286,123 @@ public class MergedReftableTest { } } + @Test + public void nonOverlappedUpdateIndices() throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + ReftableWriter writer = new ReftableWriter(buf) + .setMinUpdateIndex(1) + .setMaxUpdateIndex(2) + .begin(); + writer.writeRef(ref("refs/heads/a", 1), 1); + writer.writeRef(ref("refs/heads/b", 2), 2); + writer.finish(); + byte[] base = buf.toByteArray(); + + buf = new ByteArrayOutputStream(); + writer = new ReftableWriter(buf) + .setMinUpdateIndex(3) + .setMaxUpdateIndex(4) + .begin(); + writer.writeRef(ref("refs/heads/a", 10), 3); + writer.writeRef(ref("refs/heads/b", 20), 4); + writer.finish(); + byte[] delta = buf.toByteArray(); + + MergedReftable mr = merge(base, delta); + assertEquals(1, mr.minUpdateIndex()); + assertEquals(4, mr.maxUpdateIndex()); + + try (RefCursor rc = mr.allRefs()) { + assertTrue(rc.next()); + assertEquals("refs/heads/a", rc.getRef().getName()); + assertEquals(id(10), rc.getRef().getObjectId()); + assertEquals(3, rc.getRef().getUpdateIndex()); + + assertTrue(rc.next()); + assertEquals("refs/heads/b", rc.getRef().getName()); + assertEquals(id(20), rc.getRef().getObjectId()); + assertEquals(4, rc.getRef().getUpdateIndex()); + } + } + + @Test + public void overlappedUpdateIndices() throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + ReftableWriter writer = new ReftableWriter(buf) + .setMinUpdateIndex(1) + .setMaxUpdateIndex(3) + .begin(); + writer.writeRef(ref("refs/heads/a", 1), 1); + writer.writeRef(ref("refs/heads/b", 2), 3); + writer.finish(); + byte[] base = buf.toByteArray(); + + buf = new ByteArrayOutputStream(); + writer = new ReftableWriter(buf) + .setMinUpdateIndex(2) + .setMaxUpdateIndex(4) + .begin(); + writer.writeRef(ref("refs/heads/a", 10), 2); + writer.writeRef(ref("refs/heads/b", 20), 4); + writer.finish(); + byte[] delta = buf.toByteArray(); + + MergedReftable mr = merge(base, delta); + assertEquals(1, mr.minUpdateIndex()); + assertEquals(4, mr.maxUpdateIndex()); + + try (RefCursor rc = mr.allRefs()) { + assertTrue(rc.next()); + assertEquals("refs/heads/a", rc.getRef().getName()); + assertEquals(id(10), rc.getRef().getObjectId()); + assertEquals(2, rc.getRef().getUpdateIndex()); + + assertTrue(rc.next()); + assertEquals("refs/heads/b", rc.getRef().getName()); + assertEquals(id(20), rc.getRef().getObjectId()); + assertEquals(4, rc.getRef().getUpdateIndex()); + } + } + + @Test + public void enclosedUpdateIndices() throws IOException { + ByteArrayOutputStream buf = new ByteArrayOutputStream(); + ReftableWriter writer = new ReftableWriter(buf) + .setMinUpdateIndex(1) + .setMaxUpdateIndex(4) + .begin(); + writer.writeRef(ref("refs/heads/a", 1), 1); + writer.writeRef(ref("refs/heads/b", 20), 4); + writer.finish(); + byte[] base = buf.toByteArray(); + + buf = new ByteArrayOutputStream(); + writer = new ReftableWriter(buf) + .setMinUpdateIndex(2) + .setMaxUpdateIndex(3) + .begin(); + writer.writeRef(ref("refs/heads/a", 10), 2); + writer.writeRef(ref("refs/heads/b", 2), 3); + writer.finish(); + byte[] delta = buf.toByteArray(); + + MergedReftable mr = merge(base, delta); + assertEquals(1, mr.minUpdateIndex()); + assertEquals(4, mr.maxUpdateIndex()); + + try (RefCursor rc = mr.allRefs()) { + assertTrue(rc.next()); + assertEquals("refs/heads/a", rc.getRef().getName()); + assertEquals(id(10), rc.getRef().getObjectId()); + assertEquals(2, rc.getRef().getUpdateIndex()); + + assertTrue(rc.next()); + assertEquals("refs/heads/b", rc.getRef().getName()); + assertEquals(id(20), rc.getRef().getObjectId()); + assertEquals(4, rc.getRef().getUpdateIndex()); + } + } + @Test public void compaction() throws IOException { List delta1 = Arrays.asList( diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java index 18c013fd8..36335153a 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftable/MergedReftable.java @@ -61,8 +61,16 @@ public class MergedReftable extends Reftable { */ @Override public long maxUpdateIndex() throws IOException { - return tables.length > 0 ? tables[tables.length - 1].maxUpdateIndex() - : 0; + if (tables.length == 0) { + return 0; + } + long maxUpdateIndex = tables[tables.length - 1].maxUpdateIndex(); + for (int i = tables.length - 2; i >= 0; i--) { + if (maxUpdateIndex < tables[i].maxUpdateIndex()) { + maxUpdateIndex = tables[i].maxUpdateIndex(); + } + } + return maxUpdateIndex; } /** @@ -70,8 +78,16 @@ public class MergedReftable extends Reftable { */ @Override public long minUpdateIndex() throws IOException { - return tables.length > 0 ? tables[0].minUpdateIndex() - : 0; + if (tables.length == 0) { + return 0; + } + long minUpdateIndex = tables[0].minUpdateIndex(); + for (int i = 0; i < tables.length - 1; i++) { + if (tables[i].minUpdateIndex() < minUpdateIndex) { + minUpdateIndex = tables[i].minUpdateIndex(); + } + } + return minUpdateIndex; } /** {@inheritDoc} */