use of com.apple.foundationdb.record.ValueRange in project fdb-record-layer by FoundationDB.
the class KeySpaceDirectory method listSubdirectoryAsync.
@Nonnull
// SonarQube doesn't realize that the cursor is wrapped and returned
@SuppressWarnings("squid:S2095")
protected RecordCursor<ResolvedKeySpacePath> listSubdirectoryAsync(@Nullable KeySpacePath listFrom, @Nonnull FDBRecordContext context, @Nonnull String subdirName, @Nullable ValueRange<?> valueRange, @Nullable byte[] continuation, @Nonnull ScanProperties scanProperties) {
if (listFrom != null && listFrom.getDirectory() != this) {
throw new RecordCoreException("Provided path does not belong to this directory").addLogInfo("path", listFrom, "directory", this.getName());
}
final KeySpaceDirectory subdir = getSubdirectory(subdirName);
final CompletableFuture<ResolvedKeySpacePath> resolvedFromFuture = listFrom == null ? CompletableFuture.completedFuture(null) : listFrom.toResolvedPathAsync(context);
// The chained cursor cannot implement reverse scan, so we implement it by having the
// inner key value cursor do the reversing but telling the chained cursor we are moving
// forward.
final ScanProperties chainedCursorScanProperties;
if (scanProperties.isReverse()) {
chainedCursorScanProperties = scanProperties.setReverse(false);
} else {
chainedCursorScanProperties = scanProperties;
}
// For the read of the individual row keys, we only want to read a single key. In addition,
// the ChainedCursor is going to do counting of our reads to apply any limits that were specified
// on the ScanProperties. We don't want the inner KeyValueCursor in nextTuple() to ALSO count those
// same reads so we clear out its limits.
final ScanProperties keyReadScanProperties = scanProperties.with(props -> props.clearState().setReturnedRowLimit(1));
return new LazyCursor<>(resolvedFromFuture.thenCompose(resolvedFrom -> {
final Subspace subspace = resolvedFrom == null ? new Subspace() : resolvedFrom.toSubspace();
return subdir.getValueRange(context, valueRange, subspace).thenApply(range -> {
final RecordCursor<Tuple> cursor = new ChainedCursor<>(context, lastKey -> nextTuple(context, subspace, range, lastKey, keyReadScanProperties), Tuple::pack, Tuple::fromBytes, continuation, chainedCursorScanProperties);
return cursor.mapPipelined(tuple -> {
final Tuple key = Tuple.fromList(tuple.getItems());
return findChildForKey(context, resolvedFrom, key, 1, 0);
}, 1);
});
}), context.getExecutor());
}
use of com.apple.foundationdb.record.ValueRange in project fdb-record-layer by FoundationDB.
the class KeySpaceDirectoryTest method testListAnyValue.
@Test
public void testListAnyValue() throws Exception {
// Create a root directory called "a" with subdirs of every type (no constants for now)
Long rootValue = random.nextLong();
KeySpaceDirectory dirA = new KeySpaceDirectory("a", KeyType.LONG, rootValue);
for (KeyTypeValue kv : valueOfEveryType) {
dirA.addSubdirectory(new KeySpaceDirectory(kv.keyType.toString(), kv.keyType));
}
KeySpace root = new KeySpace(dirA);
final FDBDatabase database = FDBDatabaseFactory.instance().getDatabase();
final Map<KeyType, List<Tuple>> valuesForType = new HashMap<>();
// Create an entry in the keyspace with a row for every type that we support
try (FDBRecordContext context = database.openContext()) {
Transaction tr = context.ensureActive();
for (KeyTypeValue kv : valueOfEveryType) {
List<Tuple> values = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Object value = kv.generator.get();
Tuple tupleValue = Tuple.from(value);
if (!values.contains(tupleValue)) {
values.add(tupleValue);
// final results.
for (int j = 0; j < 5; j++) {
tr.set(Tuple.from(rootValue, value, j).pack(), Tuple.from(i).pack());
}
}
}
valuesForType.put(kv.keyType, values);
}
context.commit();
}
try (FDBRecordContext context = database.openContext()) {
for (KeyTypeValue kv : valueOfEveryType) {
if (kv.keyType != KeyType.NULL) {
List<Tuple> values = valuesForType.get(kv.keyType);
for (Pair<ValueRange<Object>, List<Tuple>> testCase : listRangeTestCases(values)) {
testListRange(testCase.getLeft(), testCase.getRight(), context, root, kv.keyType);
}
}
}
}
}
use of com.apple.foundationdb.record.ValueRange in project fdb-record-layer by FoundationDB.
the class KeySpaceDirectoryTest method testInvalidListRange.
@Test
public void testInvalidListRange() throws Exception {
final String rootDir = "root_dir";
final String stringDir = "string_dir";
final String longConstDir = "long_const_dir";
KeySpaceDirectory dirA = new KeySpaceDirectory(rootDir, KeyType.LONG, random.nextLong()).addSubdirectory(new KeySpaceDirectory(stringDir, KeyType.STRING)).addSubdirectory(new KeySpaceDirectory(longConstDir, KeyType.LONG, 100));
KeySpace root = new KeySpace(dirA);
final FDBDatabase database = FDBDatabaseFactory.instance().getDatabase();
try (FDBRecordContext context = database.openContext()) {
// Positive example.
root.path(rootDir).listSubdirectory(context, stringDir, new ValueRange<>("A", "B", EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_EXCLUSIVE), null, ScanProperties.FORWARD_SCAN);
// The range value should be in the same type.
assertThrows(RecordCoreArgumentException.class, () -> root.path(rootDir).listSubdirectory(context, stringDir, new ValueRange<>(100, 200, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_EXCLUSIVE), null, ScanProperties.FORWARD_SCAN));
// PREFIX_STRING should not be used as a endpoint type.
assertThrows(RecordCoreArgumentException.class, () -> root.path(rootDir).listSubdirectory(context, stringDir, new ValueRange<>("A", "B", EndpointType.PREFIX_STRING, EndpointType.RANGE_EXCLUSIVE), null, ScanProperties.FORWARD_SCAN));
// Range should be null when the subdirectory has a value.
assertThrows(RecordCoreArgumentException.class, () -> root.path(rootDir).listSubdirectory(context, longConstDir, new ValueRange<>(100, 200, EndpointType.RANGE_INCLUSIVE, EndpointType.RANGE_EXCLUSIVE), null, ScanProperties.FORWARD_SCAN));
}
}
Aggregations