use of com.apple.foundationdb.record.provider.foundationdb.FDBDatabase in project fdb-record-layer by FoundationDB.
the class KeySpaceDirectoryTest method testPathWrapperExample.
/*
* This isn't specifically just a test, but is also here to demonstrate how you can use the KeySpacePath
* wrapping facility to work with paths in a type safe manner.
*/
@Test
public void testPathWrapperExample() throws Exception {
EnvironmentKeySpace keySpace = new EnvironmentKeySpace("production");
final FDBDatabase database = FDBDatabaseFactory.instance().getDatabase();
// Create a tuple to represent a path to a user's main store. This will trigger the creation of the
// necessary directory layer entries.
final Tuple dataStoreTuple;
final Tuple metadataStoreTuple;
try (FDBRecordContext context = database.openContext()) {
ApplicationPath application = keySpace.root().userid(123).application("myApplication");
dataStoreTuple = application.dataStore().toTuple(context);
metadataStoreTuple = application.metadataStore().toTuple(context);
context.commit();
}
try (FDBRecordContext context = database.openContext()) {
List<Long> entries = resolveBatch(context, keySpace.getRootName(), "myApplication");
// Validate the entries created above look like what we expect
assertEquals(Tuple.from(entries.get(0), 123L, entries.get(1), EnvironmentKeySpace.DATA_VALUE), dataStoreTuple);
assertEquals(Tuple.from(entries.get(0), 123L, entries.get(1), EnvironmentKeySpace.METADATA_VALUE), metadataStoreTuple);
ResolvedKeySpacePath path = keySpace.fromKey(context, dataStoreTuple);
assertThat(path.toPath(), instanceOf(DataPath.class));
DataPath mainStorePath = (DataPath) path.toPath();
assertEquals(EnvironmentKeySpace.DATA_VALUE, mainStorePath.getValue());
assertEquals(EnvironmentKeySpace.DATA_VALUE, mainStorePath.resolveAsync(context).get().getResolvedValue());
assertEquals(entries.get(1), mainStorePath.parent().resolveAsync(context).get().getResolvedValue());
assertEquals("myApplication", mainStorePath.parent().getValue());
assertEquals(123L, mainStorePath.parent().parent().getValue());
assertEquals(entries.get(0), mainStorePath.parent().parent().parent().resolveAsync(context).get().getResolvedValue());
assertEquals("production", mainStorePath.parent().parent().parent().getValue());
assertEquals(null, mainStorePath.parent().parent().parent().parent());
assertThat(keySpace.fromKey(context, TupleHelpers.subTuple(dataStoreTuple, 0, 1)).toPath(), instanceOf(EnvironmentRoot.class));
assertThat(keySpace.fromKey(context, TupleHelpers.subTuple(dataStoreTuple, 0, 2)).toPath(), instanceOf(UserPath.class));
assertThat(keySpace.fromKey(context, TupleHelpers.subTuple(dataStoreTuple, 0, 3)).toPath(), instanceOf(ApplicationPath.class));
path = keySpace.fromKey(context, metadataStoreTuple);
assertThat(path.toPath(), instanceOf(MetadataPath.class));
MetadataPath metadataPath = (MetadataPath) path.toPath();
assertEquals(EnvironmentKeySpace.METADATA_VALUE, metadataPath.getValue());
assertEquals(EnvironmentKeySpace.METADATA_VALUE, metadataPath.resolveAsync(context).get().getResolvedValue());
assertEquals(entries.get(1), metadataPath.parent().resolveAsync(context).get().getResolvedValue());
assertEquals("myApplication", metadataPath.parent().getValue());
assertEquals(123L, metadataPath.parent().parent().getValue());
assertEquals(entries.get(0), metadataPath.parent().parent().parent().resolveAsync(context).get().getResolvedValue());
assertEquals("production", metadataPath.parent().parent().parent().getValue());
assertEquals(null, metadataPath.parent().parent().parent().parent());
assertThat(keySpace.fromKey(context, TupleHelpers.subTuple(dataStoreTuple, 0, 1)).toPath(), instanceOf(EnvironmentRoot.class));
assertThat(keySpace.fromKey(context, TupleHelpers.subTuple(dataStoreTuple, 0, 2)).toPath(), instanceOf(UserPath.class));
assertThat(keySpace.fromKey(context, TupleHelpers.subTuple(dataStoreTuple, 0, 3)).toPath(), instanceOf(ApplicationPath.class));
// Create a fake main store "record" key to demonstrate that we can get the key as the remainder
// 1=record space, record id, 0=unsplit record
Tuple recordTuple = dataStoreTuple.add(1L).add("someStr").add(0L);
path = keySpace.fromKey(context, recordTuple);
assertThat(path.toPath(), instanceOf(DataPath.class));
assertEquals(Tuple.from(1L, "someStr", 0L), path.getRemainder());
assertEquals(dataStoreTuple, path.toTuple());
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBDatabase in project fdb-record-layer by FoundationDB.
the class KeySpaceDirectoryTest method testListDoesNotGoTooDeep.
@Test
public void testListDoesNotGoTooDeep() throws Exception {
KeySpace root = new KeySpace(new KeySpaceDirectory("a", KeyType.LONG, random.nextLong()).addSubdirectory(new DirectoryLayerDirectory("b").addSubdirectory(new KeySpaceDirectory("c", KeyType.STRING).addSubdirectory(new KeySpaceDirectory("d", KeyType.BYTES).addSubdirectory(new KeySpaceDirectory("e", KeyType.LONG))))));
final FDBDatabase database = FDBDatabaseFactory.instance().getDatabase();
try (FDBRecordContext context = database.openContext()) {
Transaction tr = context.ensureActive();
for (int i = 0; i < 5; i++) {
tr.set(root.path("a").add("b", "foo_" + i).add("c", "hi_" + i).add("d", new byte[] { (byte) i }).toTuple(context).pack(), Tuple.from(i).pack());
}
context.commit();
}
// remainder on the "b" path entry.
try (FDBRecordContext context = database.openContext()) {
List<ResolvedKeySpacePath> paths;
// Check listing from the root
paths = root.listDirectory(context, "a");
assertThat("Number of paths in 'a'", paths.size(), is(1));
assertThat("Value of subdirectory 'a'", paths.get(0).getLogicalValue(), is(root.getDirectory("a").getValue()));
assertThat("Remainder size of 'a'", paths.get(0).getRemainder().size(), is(3));
// List from "b"
paths = root.path("a").listSubdirectory(context, "b");
assertThat("Number of paths in 'b'", paths.size(), is(5));
for (ResolvedKeySpacePath path : paths) {
assertThat("Listing of 'b' directory", path.getDirectoryName(), is("b"));
Tuple remainder = path.getRemainder();
assertThat("Remainder of 'b'", remainder.size(), is(2));
assertThat("Remainder of 'b', first tuple value", remainder.getString(0), startsWith("hi_"));
assertThat("Remainder of 'b', second tuple value", remainder.getBytes(1), instanceOf(new byte[0].getClass()));
}
// List from "c"
paths = root.path("a").add("b", "foo_0").listSubdirectory(context, "c");
assertThat("Number of paths in 'c'", paths.size(), is(1));
for (ResolvedKeySpacePath path : paths) {
assertThat("Listing of 'c' directory", path.getDirectoryName(), is("c"));
final Tuple remainder = path.getRemainder();
assertThat("Remainder of 'c'", remainder.size(), is(1));
assertThat("Remainder of 'c', first tuple value", remainder.getBytes(0), instanceOf(new byte[0].getClass()));
}
// List from "d"
paths = root.path("a").add("b", "foo_0").add("c", "hi_0").listSubdirectory(context, "d");
assertThat("Number of paths in 'd'", paths.size(), is(1));
ResolvedKeySpacePath path = paths.get(0);
assertThat("Remainder of 'd'", path.getRemainder(), is((Tuple) null));
// List from "e" (which has no data)
paths = root.path("a").add("b", "foo_0").add("c", "hi_0").add("d", new byte[] { 0x00 }).listSubdirectory(context, "e");
assertThat("Number of paths in 'e'", paths.size(), is(0));
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBDatabase in project fdb-record-layer by FoundationDB.
the class LocatableResolverTest method testWriteLockCaching.
@Test
public void testWriteLockCaching() {
FDBStoreTimer timer = new FDBStoreTimer();
try (FDBRecordContext context = database.openContext()) {
context.setTimer(timer);
globalScope.resolve(context.getTimer(), "something").join();
int initialCount = timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ);
assertThat("first read must check the lock in the database", initialCount, greaterThanOrEqualTo(1));
timer.reset();
int oldCount = timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ);
for (int i = 0; i < 10; i++) {
globalScope.resolve(context.getTimer(), "something-" + i).join();
// depending on the nature of the write safety check we may need to read the key multiple times
// so assert that we do at least one read on each resolve
int currentCount = timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ);
assertThat("subsequent writes must also check the key", currentCount, is(greaterThan(oldCount)));
oldCount = currentCount;
}
timer.reset();
for (int i = 0; i < 10; i++) {
globalScope.resolve(context.getTimer(), "something-" + i).join();
}
assertThat("reads do not need to check the key", timer.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(0));
}
FDBDatabaseFactory.instance().clear();
FDBDatabase newDatabase = FDBDatabaseFactory.instance().getDatabase();
FDBStoreTimer timer2 = new FDBStoreTimer();
try (FDBRecordContext context = newDatabase.openContext()) {
context.setTimer(timer2);
globalScope.resolve(context.getTimer(), "something").join();
assertThat("state is loaded from the new database", timer2.getCount(FDBStoreTimer.DetailEvents.RESOLVER_STATE_READ), is(1));
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBDatabase in project fdb-record-layer by FoundationDB.
the class KeySpaceDirectoryTest method testAllTypesConstValues.
@Test
public void testAllTypesConstValues() throws Exception {
KeySpaceDirectory rootDir = new KeySpaceDirectory("root", KeyType.LONG, 1L);
for (KeyTypeValue kv : valueOfEveryType) {
rootDir.addSubdirectory(new KeySpaceDirectory(kv.keyType.toString(), kv.keyType, kv.value));
}
KeySpace root = new KeySpace(rootDir);
final FDBDatabase database = FDBDatabaseFactory.instance().getDatabase();
try (FDBRecordContext context = database.openContext()) {
// Test all constants that match the ones we created with
for (KeyTypeValue kv : valueOfEveryType) {
assertEquals(Tuple.from(1L, kv.value), root.path("root").add(kv.keyType.toString()).toTuple(context));
assertEquals(Tuple.from(1L, kv.value), root.path("root").add(kv.keyType.toString(), kv.value).toTuple(context));
// Try a different value of the same type and make sure that fails
if (kv.keyType != KeyType.NULL) {
assertThrows(RecordCoreArgumentException.class, () -> root.path("root").add(kv.keyType.toString(), kv.value2).toTuple(context));
}
// Try a completely different type and make sure that fails
final Object badValue = pickDifferentType(kv.keyType).generator.get();
assertThrows(RecordCoreArgumentException.class, () -> root.path("root").add(kv.keyType.toString(), badValue).toTuple(context));
}
}
}
use of com.apple.foundationdb.record.provider.foundationdb.FDBDatabase in project fdb-record-layer by FoundationDB.
the class KeySpaceDirectoryTest method testListDirectoryLayer.
@Test
public void testListDirectoryLayer() throws Exception {
KeySpace root = new KeySpace(new KeySpaceDirectory("a", KeyType.LONG, random.nextLong()).addSubdirectory(new DirectoryLayerDirectory("b")).addSubdirectory(new KeySpaceDirectory("c", KeyType.STRING, "c").addSubdirectory(new DirectoryLayerDirectory("d", "d")).addSubdirectory(new DirectoryLayerDirectory("e", "e")).addSubdirectory(new DirectoryLayerDirectory("f", "f"))));
final FDBDatabase database = FDBDatabaseFactory.instance().getDatabase();
try (FDBRecordContext context = database.openContext()) {
Transaction tr = context.ensureActive();
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 5; j++) {
Tuple key = root.path("a").add("b", "value_" + i).toTuple(context).add(i).add(j);
tr.set(key.pack(), Tuple.from(i).pack());
}
}
for (int i = 0; i < 5; i++) {
tr.set(root.path("a").add("c").add("d").toTuple(context).add(i).pack(), Tuple.from(i).pack());
tr.set(root.path("a").add("c").add("e").toTuple(context).add(i).pack(), Tuple.from(i).pack());
tr.set(root.path("a").add("c").add("f").toTuple(context).add(i).pack(), Tuple.from(i).pack());
}
context.commit();
}
try (FDBRecordContext context = database.openContext()) {
List<ResolvedKeySpacePath> paths = root.path("a").listSubdirectory(context, "b");
assertEquals(10, paths.size());
for (ResolvedKeySpacePath path : paths) {
// The first part of the remainder was the index
final long index = path.getRemainder().getLong(0);
// We should always get the "first" key for the value in the directory
assertEquals(0, path.getRemainder().getLong(1));
assertTrue(index >= 0 && index < 10);
assertEquals("a", path.getParent().getDirectoryName());
assertEquals(root.getDirectory("a").getValue(), path.getParent().getLogicalValue());
assertEquals("value_" + index, path.getLogicalValue());
}
for (String subdir : ImmutableList.of("d", "e", "f")) {
paths = root.path("a").add("c").listSubdirectory(context, subdir);
assertEquals(1, paths.size());
assertEquals(subdir, paths.get(0).getLogicalValue());
assertEquals(0L, paths.get(0).getRemainder().getLong(0));
assertEquals("c", paths.get(0).getParent().getDirectoryName());
assertEquals("a", paths.get(0).getParent().getParent().getDirectoryName());
}
}
}
Aggregations