RangeSet { @Nonnull public CompletableFuture<List<Range>> missingRanges(@Nonnull ReadTransactionContext tc) { return tc.readAsync(tr -> { AsyncIterable<Range> ranges = missingRanges(tr); return ranges.asList(); }); } RangeSet(@Nonnull Subspace subspace); @Nonnull CompletableFuture<Boolean> contains(@Nonnull TransactionContext tc, @Nonnull byte[] key); @Nonnull CompletableFuture<Boolean> insertRange(@Nonnull TransactionContext tc, @Nonnull Range r); @Nonnull CompletableFuture<Boolean> insertRange(@Nonnull TransactionContext tc, @Nonnull Range r, boolean requireEmpty); @Nonnull CompletableFuture<Boolean> insertRange(@Nonnull TransactionContext tc, @Nullable byte[] begin, @Nullable byte[] end); @Nonnull CompletableFuture<Boolean> insertRange(@Nonnull TransactionContext tc, @Nullable byte[] begin, @Nullable byte[] end, boolean requireEmpty); @Nonnull CompletableFuture<List<Range>> missingRanges(@Nonnull ReadTransactionContext tc); @Nonnull AsyncIterable<Range> missingRanges(@Nonnull ReadTransaction tr); @Nonnull CompletableFuture<List<Range>> missingRanges(@Nonnull ReadTransactionContext tc, @Nonnull Range superRange); @Nonnull AsyncIterable<Range> missingRanges(@Nonnull ReadTransaction tr, @Nonnull Range superRange); @Nonnull CompletableFuture<List<Range>> missingRanges(@Nonnull ReadTransactionContext tc, @Nullable byte[] begin, @Nullable byte[] end); @Nonnull AsyncIterable<Range> missingRanges(@Nonnull ReadTransaction tr, @Nullable byte[] begin, @Nullable byte[] end); @Nonnull CompletableFuture<List<Range>> missingRanges(@Nonnull ReadTransactionContext tc, @Nullable byte[] begin, @Nullable byte[] end, int limit); @Nonnull AsyncIterable<Range> missingRanges(@Nonnull ReadTransaction tr, @Nullable byte[] begin, @Nullable byte[] end, int limit); @Nonnull CompletableFuture<Void> clear(@Nonnull TransactionContext tc); @Nonnull CompletableFuture<String> rep(@Nonnull ReadTransactionContext tc); static final int UNLIMITED; }
@Test public void missingRanges() { List<Range> ranges = db.readAsync(tr -> rs.missingRanges(tr).asList()).join(); assertEquals(1, ranges.size()); Range r1 = ranges.get(0); assertArrayEquals(new byte[]{0x00}, r1.begin); assertArrayEquals(new byte[]{(byte)0xff}, r1.end); List<Range> toAdd = Arrays.asList( new Range(new byte[]{0x10}, new byte[]{0x20}), new Range(new byte[]{0x20}, new byte[]{0x20,0x00}), new Range(new byte[]{0x30}, new byte[]{0x40}), new Range(new byte[]{0x40,0x00}, new byte[]{0x50}), new Range(new byte[]{0x60}, new byte[]{0x6a}), new Range(new byte[]{0x62}, new byte[]{0x70}), new Range(new byte[]{0x71}, new byte[]{0x72}), new Range(new byte[]{0x72}, new byte[]{0x7f}) ); List<Range> expected = Arrays.asList( new Range(new byte[]{0x00}, new byte[]{0x10}), new Range(new byte[]{0x20,0x00}, new byte[]{0x30}), new Range(new byte[]{0x40}, new byte[]{0x40,0x00}), new Range(new byte[]{0x50}, new byte[]{0x60}), new Range(new byte[]{0x70}, new byte[]{0x71}), new Range(new byte[]{0x7f}, new byte[]{(byte)0xff}) ); List<Boolean> added = db.runAsync(tr -> { List<CompletableFuture<Boolean>> futures = new ArrayList<>(); for (Range range : toAdd) { futures.add(rs.insertRange(tr, range)); } return AsyncUtil.getAll(futures); }).join(); assertTrue(added.stream().allMatch(b -> b), "Some of the insertions didn't change things"); ranges = rs.missingRanges(db).join(); assertEquals(6, ranges.size()); for (int i = 0; i < ranges.size(); i++) { assertArrayEquals(expected.get(i).begin, ranges.get(i).begin); assertArrayEquals(expected.get(i).end, ranges.get(i).end); } ranges = rs.missingRanges(db, new byte[]{0x00}, new byte[]{0x60}).join(); assertEquals(4, ranges.size()); for (int i = 0; i < ranges.size(); i++) { assertArrayEquals(expected.get(i).begin, ranges.get(i).begin); assertArrayEquals(expected.get(i).end, ranges.get(i).end); } ranges = rs.missingRanges(db, new Range(new byte[]{0x00}, new byte[]{0x60})).join(); assertEquals(4, ranges.size()); for (int i = 0; i < ranges.size(); i++) { assertArrayEquals(expected.get(i).begin, ranges.get(i).begin); assertArrayEquals(expected.get(i).end, ranges.get(i).end); } ranges = rs.missingRanges(db, new byte[]{0x00}, new byte[]{0x60}, 2).join(); assertEquals(2, ranges.size()); for (int i = 0; i < ranges.size(); i++) { assertArrayEquals(expected.get(i).begin, ranges.get(i).begin); assertArrayEquals(expected.get(i).end, ranges.get(i).end); } ranges = rs.missingRanges(db, new byte[]{0x00}, new byte[]{0x60}, 1).join(); assertEquals(1, ranges.size()); for (int i = 0; i < ranges.size(); i++) { assertArrayEquals(expected.get(i).begin, ranges.get(i).begin); assertArrayEquals(expected.get(i).end, ranges.get(i).end); } }