use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class BunchedMapScanTest method testScanMulti.
private void testScanMulti(int limit, boolean reverse, List<List<Tuple>> keyLists, @Nonnull BiFunction<Transaction, byte[], BunchedMapMultiIterator<Tuple, Tuple, Long>> iteratorFunction) {
try (Transaction tr = db.createTransaction()) {
byte[] continuation = null;
List<BunchedMapScanEntry<Tuple, Tuple, Long>> entryList = new ArrayList<>();
BunchedMapScanEntry<Tuple, Tuple, Long> lastEntry = null;
do {
BunchedMapMultiIterator<Tuple, Tuple, Long> iterator = iteratorFunction.apply(tr, continuation);
int returned = 0;
while (iterator.hasNext()) {
BunchedMapScanEntry<Tuple, Tuple, Long> toAdd = iterator.peek();
assertEquals(toAdd, iterator.next());
if (lastEntry != null) {
if (toAdd.getSubspaceTag().equals(lastEntry.getSubspaceTag())) {
assertEquals(reverse ? 1 : -1, Integer.signum(lastEntry.getKey().compareTo(toAdd.getKey())));
} else {
assertEquals(reverse ? 1 : -1, Integer.signum(lastEntry.getSubspaceTag().compareTo(toAdd.getSubspaceTag())));
}
}
entryList.add(toAdd);
lastEntry = toAdd;
returned++;
}
continuation = iterator.getContinuation();
if (limit == ReadTransaction.ROW_LIMIT_UNLIMITED || returned < limit) {
assertNull(continuation);
} else {
assertNotNull(continuation);
}
} while (continuation != null);
if (reverse) {
entryList = Lists.reverse(entryList);
}
Long tag = null;
int pos = 0;
int totalRead = 0;
for (BunchedMapScanEntry<Tuple, Tuple, Long> entry : entryList) {
if (tag == null || !tag.equals(entry.getSubspaceTag())) {
if (tag != null) {
assertEquals(tag + 1, entry.getSubspaceTag().longValue());
}
tag = entry.getSubspaceTag();
pos = 0;
}
assertEquals(keyLists.get(tag.intValue()).get(pos), entry.getKey());
assertEquals(value, entry.getValue());
assertEquals(subSubspaces.get(tag.intValue()), entry.getSubspace());
pos++;
totalRead++;
}
int totalToSee = keyLists.stream().mapToInt(List::size).sum();
assertEquals(totalToSee, totalRead);
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class BunchedMapScanTest method continuationWithDeletes.
private void continuationWithDeletes(int limit, boolean reverse) {
try (Transaction tr = db.createTransaction()) {
byte[] continuation = null;
List<Tuple> readKeys = new ArrayList<>();
do {
List<Tuple> mostRecentReadKeys = new ArrayList<>();
int returned = 0;
BunchedMapIterator<Tuple, Tuple> bunchedMapIterator = map.scan(tr, subSubspaces.get(1), continuation, limit, reverse);
while (bunchedMapIterator.hasNext()) {
Tuple toAdd = bunchedMapIterator.peek().getKey();
assertEquals(toAdd, bunchedMapIterator.next().getKey());
mostRecentReadKeys.add(toAdd);
returned += 1;
}
assertFalse(bunchedMapIterator.hasNext());
assertThrows(NoSuchElementException.class, bunchedMapIterator::peek);
assertThrows(NoSuchElementException.class, bunchedMapIterator::next);
continuation = bunchedMapIterator.getContinuation();
if (returned != limit) {
assertNull(continuation);
} else {
assertNotNull(continuation);
}
// Remove all of the keys that were most recently read.
mostRecentReadKeys.forEach(k -> map.remove(tr, subSubspaces.get(1), k).join());
readKeys.addAll(mostRecentReadKeys);
} while (continuation != null);
if (reverse) {
readKeys = Lists.reverse(readKeys);
}
List<Tuple> expectedKeys = IntStream.range(0, keys.size()).filter(i -> i % subSubspaces.size() == 1).mapToObj(keys::get).collect(Collectors.toList());
assertEquals(expectedKeys, readKeys);
tr.cancel();
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class BunchedMapScanTest method scanWithConflict.
@Test
public void scanWithConflict() throws InterruptedException, ExecutionException {
clearAndPopulate();
try (Transaction tr1 = db.createTransaction();
Transaction tr2 = db.createTransaction()) {
CompletableFuture.allOf(tr1.getReadVersion(), tr2.getReadVersion()).get();
BunchedMapIterator<Tuple, Tuple> iterator = map.scan(tr1, bmSubspace);
int count = MoreAsyncUtil.reduce(iterator, 0, (oldCount, item) -> oldCount + 1).get();
assertEquals(keys.size(), count);
tr1.addWriteConflictKey(Tuple.from(count).pack());
assertFalse(map.put(tr2, bmSubspace, Tuple.from(keys.get(keys.size() - 1).getLong(0) + 1), value).get().isPresent());
tr2.commit().get();
CompletionException e = assertThrows(CompletionException.class, () -> tr1.commit().join());
assertNotNull(e.getCause());
assertTrue(e.getCause() instanceof FDBException);
FDBException fdbE = (FDBException) e.getCause();
assertEquals(FDBError.NOT_COMMITTED.code(), fdbE.getCode());
}
byte[] continuation = null;
for (int i = 0; i < keys.size(); i++) {
}
try (Transaction tr1 = db.createTransaction();
Transaction tr2 = db.createTransaction()) {
CompletableFuture.allOf(tr1.getReadVersion(), tr2.getReadVersion()).get();
BunchedMapIterator<Tuple, Tuple> iterator = map.scan(tr1, bmSubspace);
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class BunchedMapTest method concurrentIllegalUpdates.
@Test
public void concurrentIllegalUpdates() throws ExecutionException, InterruptedException {
final Tuple value = Tuple.from(Tuple.from((Object) null));
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(0L), value).join();
map.put(tr1, bmSubspace, Tuple.from(5L), value).join();
map.put(tr2, bmSubspace, Tuple.from(3L), value).join();
}, false, Collections.singletonList(Tuple.from(0L)));
try (Transaction tr = db.createTransaction()) {
tr.clear(bmSubspace.range());
tr.commit().get();
}
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(5L), value).join();
map.put(tr1, bmSubspace, Tuple.from(0L), value).join();
map.put(tr2, bmSubspace, Tuple.from(3L), value).join();
}, false, Collections.singletonList(Tuple.from(0L)));
try (Transaction tr = db.createTransaction()) {
tr.clear(bmSubspace.range());
tr.commit().get();
}
final List<Tuple> tuples = LongStream.range(100L, 115L).boxed().map(Tuple::from).collect(Collectors.toList());
db.run(tr -> {
tr.clear(bmSubspace.range());
tuples.forEach(t -> map.put(tr, bmSubspace, t, value).join());
return null;
});
// Case 1: Transaction reads the value of a boundary key while
// that boundary is updated.
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(116L), value).join();
assertEquals(value, map.get(tr2, bmSubspace, Tuple.from(110L)).join().get());
}, false, Arrays.asList(Tuple.from(100L), Tuple.from(110L)));
// Case 2: Transaction reads the same key while
// a put goes onto the same key and changes the value.
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(105L), value.add(3.14d)).join();
assertEquals(value, map.get(tr2, bmSubspace, Tuple.from(105L)).join().get());
}, false, Arrays.asList(Tuple.from(100L), Tuple.from(110L)));
assertEquals(value.add(3.14d), map.get(db, bmSubspace, Tuple.from(105L)).get().get());
// Case 3: One put changes a value while another put tries to set it to
// the same value.
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(105L), value).join();
map.put(tr2, bmSubspace, Tuple.from(105L), value.add(3.14d)).join();
}, false, Arrays.asList(Tuple.from(100L), Tuple.from(110L)));
assertEquals(value, map.get(db, bmSubspace, Tuple.from(105L)).get().get());
// Case 4: Two puts happen at the same value at the same time.
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(105L), value.add(3.14d)).join();
map.put(tr2, bmSubspace, Tuple.from(105L), value.add(2.72d)).join();
}, false, Arrays.asList(Tuple.from(100L), Tuple.from(110L)));
assertEquals(value.add(3.14d), map.get(db, bmSubspace, Tuple.from(105L)).get().get());
// Case 5: Something attempts to re-write something in the
// interior of the boundary while writing
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(116L), value.add(3.14d)).join();
map.put(tr2, bmSubspace, Tuple.from(117L), value).join();
}, false, Arrays.asList(Tuple.from(100L), Tuple.from(110L)));
assertFalse(map.containsKey(db, bmSubspace, Tuple.from(117L)).get());
// Case 6: Write a value that would end up being overwritten in a split
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(102L, null), value).join();
map.put(tr2, bmSubspace, Tuple.from(107L), value.add(3.14d)).join();
}, false, Arrays.asList(Tuple.from(100L), Tuple.from(104L), Tuple.from(110L)));
assertEquals(value, map.get(db, bmSubspace, Tuple.from(107L)).get().get());
// Case 7: Write a key before the current value that eats the value
// from a boundary key while another transaction does the same thing
// (Note that this test fails if the read conflict ranges are added
// after the writes, so this tests to make sure that that is done
// properly.)
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(98L), value).join();
map.put(tr2, bmSubspace, Tuple.from(99L), value).join();
}, false, Arrays.asList(Tuple.from(98L), Tuple.from(104L), Tuple.from(110L)));
// Case 8: The same as case 7, but the greater key wins instead of
// the smaller key
runWithTwoTrs((tr1, tr2) -> {
map.put(tr1, bmSubspace, Tuple.from(97L), value).join();
map.put(tr2, bmSubspace, Tuple.from(96L), value).join();
}, false, Arrays.asList(Tuple.from(97L), Tuple.from(104L), Tuple.from(110L)));
try (Transaction tr = db.createTransaction()) {
List<Map.Entry<Tuple, Tuple>> entryList = AsyncUtil.collectRemaining(map.scan(tr, bmSubspace)).get();
System.out.println(entryList);
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class BunchedMapTest method insertSingleKey.
@Test
public void insertSingleKey() {
List<Tuple> testTuples = Stream.of(1066L, 1776L, 1415L, 800L).map(Tuple::from).collect(Collectors.toList());
Tuple value = Tuple.from(1415L);
db.run(tr -> {
Tuple minSoFar = null;
for (int i = 0; i < testTuples.size(); i++) {
Tuple key = testTuples.get(i);
minSoFar = (minSoFar == null || key.compareTo(minSoFar) < 0) ? key : minSoFar;
map.put(tr, bmSubspace, key, value).join();
for (int j = 0; j < testTuples.size(); j++) {
assertEquals(j <= i, map.containsKey(tr, bmSubspace, testTuples.get(j)).join());
}
List<KeyValue> rangeKVs = tr.getRange(bmSubspace.range()).asList().join();
assertEquals(1, rangeKVs.size());
assertArrayEquals(bmSubspace.pack(minSoFar), rangeKVs.get(0).getKey());
List<Map.Entry<Tuple, Tuple>> entryList = testTuples.subList(0, i + 1).stream().sorted().map(t -> new AbstractMap.SimpleImmutableEntry<>(t, value)).collect(Collectors.toList());
assertArrayEquals(serializer.serializeEntries(entryList), rangeKVs.get(0).getValue());
}
return null;
});
}
Aggregations