use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method minMaxTupleRepeatConcatenated.
@Test
public void minMaxTupleRepeatConcatenated() throws Exception {
final FieldKeyExpression fieldKey = field("repeater", FanType.Concatenate);
final GroupingKeyExpression indexKey = fieldKey.ungrouped();
final RecordMetaDataHook hook = md -> {
RecordTypeBuilder type = md.getRecordType("MySimpleRecord");
md.addIndex(type, new Index("min", indexKey, IndexTypes.MIN_EVER_TUPLE));
md.addIndex(type, new Index("max", indexKey, IndexTypes.MAX_EVER_TUPLE));
};
final IndexAggregateFunction min = new IndexAggregateFunction(FunctionNames.MIN_EVER, indexKey, null);
final IndexAggregateFunction max = new IndexAggregateFunction(FunctionNames.MAX_EVER, indexKey, null);
List<String> types = Collections.singletonList("MySimpleRecord");
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertNull(recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(1);
recordStore.saveRecord(recBuilder.build());
assertEquals(Tuple.from(Tuple.from()), recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from(Tuple.from()), recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
recBuilder.addRepeater(1);
recordStore.saveRecord(recBuilder.build());
assertEquals(Tuple.from(Tuple.from()), recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from(Tuple.from(1L)), recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
recBuilder.addRepeater(1);
recordStore.saveRecord(recBuilder.build());
assertEquals(Tuple.from(Tuple.from()), recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from(Tuple.from(1L, 1L)), recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
recBuilder.clearRepeater();
recBuilder.addRepeater(2);
recordStore.saveRecord(recBuilder.build());
assertEquals(Tuple.from(Tuple.from()), recordStore.evaluateAggregateFunction(types, min, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertEquals(Tuple.from(Tuple.from(2L)), recordStore.evaluateAggregateFunction(types, max, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
commit(context);
}
}
use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method isAbsentBuildable.
@Test
public void isAbsentBuildable() throws Exception {
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
assertThrows(MetaDataException.class, () -> recordStore.firstUnbuiltRange(new Index("this_index_doesn't_exist", Key.Expressions.field("str_value_indexed"))).get());
}
}
use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method markManyDisabled.
@Test
public void markManyDisabled() throws Exception {
final Index[] indexes = new Index[100];
for (int i = 0; i < indexes.length; i++) {
indexes[i] = new Index(String.format("index-%d", i), "str_value_indexed");
}
final RecordMetaDataHook hook = metaData -> {
final RecordTypeBuilder recordType = metaData.getRecordType("MySimpleRecord");
for (int i = 0; i < indexes.length; i++) {
metaData.addIndex(recordType, indexes[i]);
}
};
// Such timing problems take several tries to show up.
for (int j = 0; j < 10; j++) {
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
List<CompletableFuture<Boolean>> futures = new ArrayList<>();
List<Index> shouldBeDisabled = new ArrayList<>();
// Expected contract: only use isIndexXXX and markIndexXXX and wait for all futures when done.
for (int i = 0; i < indexes.length; i++) {
if ((i % 2 == 0) || (i == 99 && recordStore.isIndexDisabled(indexes[i]))) {
futures.add(recordStore.markIndexDisabled(indexes[i]));
shouldBeDisabled.add(indexes[i]);
}
}
AsyncUtil.whenAll(futures).join();
for (Index index : shouldBeDisabled) {
assertThat(index, new TypeSafeMatcher<Index>() {
@Override
protected boolean matchesSafely(Index item) {
return recordStore.isIndexDisabled(index);
}
@Override
public void describeTo(Description description) {
description.appendText("a disabled index");
}
});
}
}
}
}
use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method getIndexStates.
@Test
public void getIndexStates() throws Exception {
final String indexName = "MySimpleRecord$str_value_indexed";
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
final Index index = recordStore.getRecordMetaData().getIndex(indexName);
assertThat(recordStore.getAllIndexStates(), hasEntry(index, IndexState.READABLE));
recordStore.markIndexWriteOnly(indexName).get();
assertThat(recordStore.getAllIndexStates(), hasEntry(index, IndexState.WRITE_ONLY));
context.commit();
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
final Index index = recordStore.getRecordMetaData().getIndex(indexName);
assertThat(recordStore.getAllIndexStates(), hasEntry(index, IndexState.WRITE_ONLY));
recordStore.markIndexDisabled(indexName).get();
assertThat(recordStore.getAllIndexStates(), hasEntry(index, IndexState.DISABLED));
// does not commit
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
final Index index = recordStore.getRecordMetaData().getIndex(indexName);
assertThat(recordStore.getAllIndexStates(), hasEntry(index, IndexState.WRITE_ONLY));
recordStore.saveRecord(TestRecords1Proto.MyOtherRecord.newBuilder().setRecNo(2).build());
try (FDBRecordContext context2 = openContext()) {
openSimpleRecordStore(context2);
recordStore.markIndexReadable(indexName).get();
context2.commit();
}
assertThrows(FDBExceptions.FDBStoreTransactionConflictException.class, context::commit);
}
}
use of com.apple.foundationdb.record.metadata.Index in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreOpeningTest method storeExistenceChecksWithNoRecords.
@Test
public void storeExistenceChecksWithNoRecords() throws Exception {
RecordMetaData metaData = RecordMetaData.build(TestRecords1Proto.getDescriptor());
FDBRecordStore.Builder storeBuilder;
try (FDBRecordContext context = openContext()) {
storeBuilder = storeBuilder(context, metaData);
FDBRecordStore store = storeBuilder.create();
// delete the header
store.ensureContextActive().clear(getStoreInfoKey(store));
commit(context);
}
// Should be able to recover from a completely empty record store
try (FDBRecordContext context = openContext()) {
storeBuilder.setContext(context);
FDBRecordStore store = storeBuilder.createOrOpen();
// put a range subspace in for an index so that a future store opening can see it
store.ensureContextActive().clear(getStoreInfoKey(store));
Index foundIndex = metaData.getAllIndexes().stream().findAny().orElseGet(() -> fail("no indexes defined in meta-data"));
new RangeSet(store.indexRangeSubspace(foundIndex)).insertRange(context.ensureActive(), null, null).get();
// re-delete the header
store.ensureContextActive().clear(getStoreInfoKey(store));
commit(context);
}
// should be recoverable using ERROR_IF_NO_INFO_AND_HAS_RECORDS_OR_INDEXES
try (FDBRecordContext context = openContext()) {
storeBuilder.setContext(context);
assertThrows(RecordStoreNoInfoAndNotEmptyException.class, storeBuilder::createOrOpen);
commit(context);
}
try (FDBRecordContext context = openContext()) {
storeBuilder.setContext(context);
// do not perform checkVersion yet
FDBRecordStore store = storeBuilder.build();
assertNull(context.ensureActive().get(getStoreInfoKey(store)).get());
assertTrue(store.checkVersion(null, FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NO_INFO_AND_HAS_RECORDS_OR_INDEXES).get());
commit(context);
}
// Delete everything except a value in the index build space
try (FDBRecordContext context = openContext()) {
FDBRecordStore store = storeBuilder.setContext(context).open();
final Subspace subspace = OnlineIndexer.indexBuildScannedRecordsSubspace(store, metaData.getIndex("MySimpleRecord$str_value_indexed"));
// set a key in the INDEX_BUILD_SPACE
context.ensureActive().set(subspace.getKey(), FDBRecordStore.encodeRecordCount(1215));
context.ensureActive().clear(store.getSubspace().getKey(), subspace.getKey());
commit(context);
}
try (FDBRecordContext context = openContext()) {
storeBuilder.setContext(context);
assertThrows(RecordStoreNoInfoAndNotEmptyException.class, storeBuilder::createOrOpen);
}
try (FDBRecordContext context = openContext()) {
storeBuilder.setContext(context).createOrOpen(FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NO_INFO_AND_HAS_RECORDS_OR_INDEXES);
commit(context);
}
// Insert a record, then delete the store header
try (FDBRecordContext context = openContext()) {
// open as the previous open with the relaxed existence check should have fixed the store header
FDBRecordStore store = storeBuilder.setContext(context).open();
store.saveRecord(TestRecords1Proto.MySimpleRecord.newBuilder().setRecNo(1066L).build());
store.ensureContextActive().clear(getStoreInfoKey(store));
commit(context);
}
try (FDBRecordContext context = openContext()) {
storeBuilder.setContext(context);
assertThrows(RecordStoreNoInfoAndNotEmptyException.class, storeBuilder::createOrOpen);
assertThrows(RecordStoreNoInfoAndNotEmptyException.class, () -> storeBuilder.createOrOpen(FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NO_INFO_AND_HAS_RECORDS_OR_INDEXES));
commit(context);
}
// Delete the record store, then insert a key at an unknown keyspace
try (FDBRecordContext context = openContext()) {
FDBRecordStore.deleteStore(context, path);
Subspace subspace = path.toSubspace(context);
context.ensureActive().set(subspace.pack("unknown_keyspace"), Tuple.from("doesn't matter").pack());
commit(context);
}
try (FDBRecordContext context = openContext()) {
storeBuilder.setContext(context);
assertThrows(RecordStoreNoInfoAndNotEmptyException.class, storeBuilder::createOrOpen);
RecordCoreException err = assertThrows(RecordCoreException.class, () -> storeBuilder.createOrOpen(FDBRecordStoreBase.StoreExistenceCheck.ERROR_IF_NO_INFO_AND_HAS_RECORDS_OR_INDEXES));
assertEquals("Unrecognized keyspace: unknown_keyspace", err.getMessage());
commit(context);
}
}
Aggregations