use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreFormatVersionTest method testAccessUserFieldAtOldFormatVersion.
/**
* Test that accessing the header user fields at earlier format versions is disallowed.
*/
@Test
public void testAccessUserFieldAtOldFormatVersion() {
final String expectedErrMsg = "cannot access header user fields at current format version";
final RecordMetaData metaData = RecordMetaData.build(TestRecords1Proto.getDescriptor());
FDBRecordStore.Builder storeBuilder = FDBRecordStore.newBuilder().setKeySpacePath(path).setMetaDataProvider(metaData).setFormatVersion(FDBRecordStore.HEADER_USER_FIELDS_FORMAT_VERSION - 1);
try (FDBRecordContext context = openContext()) {
recordStore = storeBuilder.setContext(context).create();
RecordCoreException err = assertThrows(RecordCoreException.class, () -> recordStore.getHeaderUserField("foo"));
assertEquals(expectedErrMsg, err.getMessage());
commit(context);
}
try (FDBRecordContext context = openContext()) {
recordStore = storeBuilder.setContext(context).open();
RecordCoreException err = assertThrows(RecordCoreException.class, () -> recordStore.setHeaderUserField("foo", "bar".getBytes(Charsets.UTF_8)));
assertEquals(expectedErrMsg, err.getMessage());
commit(context);
}
try (FDBRecordContext context = openContext()) {
recordStore = storeBuilder.setFormatVersion(FDBRecordStore.INFO_ADDED_FORMAT_VERSION).setContext(context).open();
assertEquals(FDBRecordStore.HEADER_USER_FIELDS_FORMAT_VERSION - 1, recordStore.getFormatVersion());
RecordCoreException err = assertThrows(RecordCoreException.class, () -> recordStore.clearHeaderUserField("foo"));
assertEquals(expectedErrMsg, err.getMessage());
commit(context);
}
// Now try upgrading the format version and validate that the fields can be read
try (FDBRecordContext context = openContext()) {
recordStore = storeBuilder.setFormatVersion(FDBRecordStore.HEADER_USER_FIELDS_FORMAT_VERSION).setContext(context).open();
assertEquals(FDBRecordStore.HEADER_USER_FIELDS_FORMAT_VERSION, recordStore.getFormatVersion());
recordStore.setHeaderUserField("foo", "bar".getBytes(Charsets.UTF_8));
String val = recordStore.getHeaderUserField("foo").toStringUtf8();
assertEquals("bar", val);
recordStore.clearHeaderUserField("foo");
assertNull(recordStore.getHeaderUserField("foo"));
commit(context);
}
}
use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method minMaxIndex.
@ParameterizedTest(name = "minMaxIndex({0})")
@EnumSource(MinMaxIndexTypes.class)
public void minMaxIndex(MinMaxIndexTypes indexTypes) throws Exception {
final FieldKeyExpression recno = field("rec_no");
final GroupingKeyExpression byKey = recno.groupBy(field("num_value_3_indexed"));
final RecordMetaDataHook hook = md -> {
RecordTypeBuilder type = md.getRecordType("MySimpleRecord");
md.addIndex(type, new Index("min", byKey, indexTypes.min()));
md.addIndex(type, new Index("max", byKey, indexTypes.max()));
};
final IndexAggregateFunction minOverall = new IndexAggregateFunction(FunctionNames.MIN_EVER, recno, null);
final IndexAggregateFunction maxOverall = new IndexAggregateFunction(FunctionNames.MAX_EVER, recno, null);
final IndexAggregateFunction minByKey = new IndexAggregateFunction(FunctionNames.MIN_EVER, byKey, null);
final IndexAggregateFunction maxByKey = new IndexAggregateFunction(FunctionNames.MAX_EVER, byKey, null);
List<String> types = Collections.singletonList("MySimpleRecord");
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertNull(recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, minByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join());
assertNull(recordStore.evaluateAggregateFunction(types, maxByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join());
for (int i = 0; i < 100; i++) {
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(i);
recBuilder.setNumValue3Indexed(i % 5);
recordStore.saveRecord(recBuilder.build());
}
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
assertEquals(0, recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(99, recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(1, recordStore.evaluateAggregateFunction(types, minByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(96, recordStore.evaluateAggregateFunction(types, maxByKey, Key.Evaluated.scalar(1), IsolationLevel.SNAPSHOT).join().getLong(0));
commit(context);
}
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
recordStore.deleteRecord(Tuple.from(0));
recordStore.deleteRecord(Tuple.from(99));
assertEquals(0, recordStore.evaluateAggregateFunction(types, minOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join().getLong(0));
assertEquals(99, recordStore.evaluateAggregateFunction(types, maxOverall, Key.Evaluated.EMPTY, IsolationLevel.SNAPSHOT).join().getLong(0));
commit(context);
}
// verify that negatives do not appear in min/max
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context, hook);
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(-1);
recBuilder.setNumValue3Indexed(1);
recordStore.saveRecord(recBuilder.build());
if (!indexTypes.shouldAllowNegative()) {
fail("should have thrown exception");
}
} catch (RecordCoreException e) {
if (indexTypes.shouldAllowNegative()) {
throw e;
}
assertEquals(e.getMessage(), "Attempted update of MAX_EVER_LONG or MIN_EVER_LONG index with negative value");
}
}
use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class OnlineIndexerBuildRankIndexTest method rankRebuild.
private void rankRebuild(@Nonnull List<TestRecords1Proto.MySimpleRecord> records, @Nullable List<TestRecords1Proto.MySimpleRecord> recordsWhileBuilding, int agents, boolean overlap) {
final Index index = new Index("newRankIndex", field("num_value_2").ungrouped(), IndexTypes.RANK);
final IndexRecordFunction<Long> recordFunction = (IndexRecordFunction<Long>) Query.rank("num_value_2").getFunction();
final Runnable beforeBuild = new Runnable() {
@SuppressWarnings("try")
@Override
public void run() {
try (FDBRecordContext context = openContext()) {
for (TestRecords1Proto.MySimpleRecord record : records) {
try {
recordStore.evaluateRecordFunction(recordFunction, createStoredMessage(record)).join();
fail("Somehow evaluated rank");
} catch (RecordCoreException e) {
assertEquals("Record function rank(Field { 'num_value_2' None} group 1) requires appropriate index on MySimpleRecord", e.getMessage());
}
}
// Either we get an exception, or the record store is empty.
try {
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.rank("num_value_2").equalsValue(0L)).build();
RecordQueryPlan plan = planner.plan(query);
assertEquals("Scan(<,>) | [MySimpleRecord] | rank(Field { 'num_value_2' None} group 1) EQUALS 0", plan.toString());
Optional<?> first = recordStore.executeQuery(plan).first().join();
assertTrue(!first.isPresent(), "non-empty range with rank rebuild");
} catch (CompletionException e) {
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(RecordCoreException.class));
assertEquals("Record function rank(Field { 'num_value_2' None} group 1) requires appropriate index on MySimpleRecord", e.getCause().getMessage());
}
}
}
};
List<TestRecords1Proto.MySimpleRecord> updatedRecords;
if (recordsWhileBuilding == null || recordsWhileBuilding.size() == 0) {
updatedRecords = records;
} else {
updatedRecords = updated(records, recordsWhileBuilding);
}
final Runnable afterBuild = new Runnable() {
@SuppressWarnings("try")
@Override
public void run() {
try (FDBRecordContext context = openContext()) {
for (TestRecords1Proto.MySimpleRecord record : updatedRecords) {
try {
recordStore.evaluateRecordFunction(recordFunction, createStoredMessage(record)).join();
fail("Somehow evaluated rank");
} catch (RecordCoreException e) {
assertEquals("Record function rank(Field { 'num_value_2' None} group 1) requires appropriate index on MySimpleRecord", e.getMessage());
}
}
// Either we get an exception, or the record store is empty.
try {
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.rank("num_value_2").equalsValue(0L)).build();
RecordQueryPlan plan = planner.plan(query);
assertEquals("Scan(<,>) | [MySimpleRecord] | rank(Field { 'num_value_2' None} group 1) EQUALS 0", plan.toString());
Optional<?> first = recordStore.executeQuery(plan).first().join();
assertTrue(!first.isPresent(), "non-empty range with rank rebuild");
} catch (CompletionException e) {
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(RecordCoreException.class));
assertEquals("Record function rank(Field { 'num_value_2' None} group 1) requires appropriate index on MySimpleRecord", e.getCause().getMessage());
}
}
}
};
TreeSet<Integer> values = new TreeSet<>();
boolean hasNull = false;
for (TestRecords1Proto.MySimpleRecord record : updatedRecords) {
if (!record.hasNumValue2()) {
hasNull = true;
} else {
values.add(record.getNumValue2());
}
}
long curr = 0;
Map<Integer, Long> ranks = new HashMap<>();
if (hasNull) {
curr += 1;
}
for (Integer value : values) {
ranks.put(value, curr);
curr += 1;
}
final Runnable afterReadable = new Runnable() {
@SuppressWarnings("try")
@Override
public void run() {
try (FDBRecordContext context = openContext()) {
for (TestRecords1Proto.MySimpleRecord record : updatedRecords) {
Long rank = recordStore.evaluateRecordFunction(recordFunction, createStoredMessage(record)).join();
if (!record.hasNumValue2()) {
assertEquals(0L, rank.longValue());
} else {
assertEquals(ranks.get(record.getNumValue2()), rank);
}
RecordQuery query = RecordQuery.newBuilder().setRecordType("MySimpleRecord").setFilter(Query.rank("num_value_2").equalsValue(rank)).build();
RecordQueryPlan plan = planner.plan(query);
assertEquals("Index(newRankIndex [[" + rank + "],[" + rank + "]] BY_RANK)", plan.toString());
Optional<TestRecords1Proto.MySimpleRecord> retrieved = recordStore.executeQuery(plan).map(rec -> TestRecords1Proto.MySimpleRecord.newBuilder().mergeFrom(rec.getRecord()).build()).filter(rec -> rec.getRecNo() == record.getRecNo()).first().join();
assertTrue(retrieved.isPresent(), "empty range after rank index build");
assertEquals(record, retrieved.get());
}
}
}
};
singleRebuild(records, recordsWhileBuilding, agents, overlap, false, index, beforeBuild, afterBuild, afterReadable);
}
use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class OnlineIndexerSimpleTest method notReincreaseLimit.
@Test
void notReincreaseLimit() {
// Non-retriable error that is in lessen work codes.
Supplier<RuntimeException> createException = () -> new RecordCoreException("Non-retriable", new FDBException("transaction_too_large", 2101));
Queue<Pair<Integer, Supplier<RuntimeException>>> queue = new LinkedList<>();
// failures until it hits 42
for (int i = 100; i > 42; i = (3 * i) / 4) {
queue.add(Pair.of(i, createException));
}
// a whole bunch of successes
for (int i = 0; i < 100; i++) {
queue.add(Pair.of(42, null));
}
reincreaseLimit(queue, index -> OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).setLimit(100).setMaxRetries(queue.size() + 3).setRecordsPerSecond(10000).setMdcContext(ImmutableMap.of("mdcKey", "my cool mdc value")).setMaxAttempts(3).build());
}
use of com.apple.foundationdb.record.RecordCoreException in project fdb-record-layer by FoundationDB.
the class OnlineIndexerSimpleTest method run.
@Test
public void run() {
Index index = runAsyncSetup();
try (OnlineIndexer indexBuilder = OnlineIndexer.newBuilder().setDatabase(fdb).setMetaData(metaData).setIndex(index).setSubspace(subspace).setLimit(100).setMaxRetries(3).setRecordsPerSecond(10000).setMdcContext(ImmutableMap.of("mdcKey", "my cool mdc value")).setMaxAttempts(2).build()) {
AtomicInteger attempts = new AtomicInteger();
// Non-FDB error
attempts.set(0);
runAndHandleLessenWorkCodes(indexBuilder, store -> {
attempts.incrementAndGet();
throw new IllegalStateException("illegal state");
}).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(IllegalStateException.class));
assertEquals("illegal state", e.getMessage());
assertNull(e.getCause());
assertEquals(1, attempts.get());
assertEquals("my cool mdc value", ThreadContext.get("mdcKey"));
return null;
}).join();
// Retriable error that is not in lessen work codes.
attempts.set(0);
runAndHandleLessenWorkCodes(indexBuilder, store -> {
attempts.incrementAndGet();
throw new RecordCoreRetriableTransactionException("Retriable", new FDBException("commit_unknown_result", 1021));
}).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(RecordCoreRetriableTransactionException.class));
assertEquals("Retriable", e.getMessage());
assertThat(e.getCause(), instanceOf(FDBException.class));
assertEquals("commit_unknown_result", e.getCause().getMessage());
assertEquals(FDBError.COMMIT_UNKNOWN_RESULT.code(), ((FDBException) e.getCause()).getCode());
assertEquals(2, attempts.get());
assertEquals("my cool mdc value", ThreadContext.get("mdcKey"));
return null;
}).join();
// Non-retriable error that is in lessen work codes.
attempts.set(0);
runAndHandleLessenWorkCodes(indexBuilder, store -> {
attempts.incrementAndGet();
throw new RecordCoreException("Non-retriable", new FDBException("transaction_too_large", 2101));
}).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(RecordCoreException.class));
assertEquals("Non-retriable", e.getMessage());
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(FDBException.class));
assertEquals("transaction_too_large", e.getCause().getMessage());
assertEquals(FDBError.TRANSACTION_TOO_LARGE.code(), ((FDBException) e.getCause()).getCode());
// lessenWorkCodes is maxRetries
assertEquals(4, attempts.get());
assertEquals("my cool mdc value", ThreadContext.get("mdcKey"));
return null;
}).join();
// Retriable error that is in lessen work codes.
attempts.set(0);
runAndHandleLessenWorkCodes(indexBuilder, store -> {
attempts.incrementAndGet();
throw new RecordCoreRetriableTransactionException("Retriable and lessener", new FDBException("not_committed", 1020));
}).handle((val, e) -> {
assertNotNull(e);
assertThat(e, instanceOf(RecordCoreRetriableTransactionException.class));
assertEquals("Retriable and lessener", e.getMessage());
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(FDBException.class));
assertEquals("not_committed", e.getCause().getMessage());
assertEquals(FDBError.NOT_COMMITTED.code(), ((FDBException) e.getCause()).getCode());
assertEquals(8, attempts.get());
assertEquals("my cool mdc value", ThreadContext.get("mdcKey"));
return null;
}).join();
}
}
Aggregations