use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class TextIndexBunchedSerializerTest method serializeEntry.
@Test
public void serializeEntry() {
Tuple key = Tuple.from(1066L);
List<Integer> value = Arrays.asList(0, 1, 127 + 1, 128 + 1 + 127);
byte[] serialized = serializer.serializeEntry(key, value);
assertArrayEquals(ByteArrayUtil.join(new byte[] { 0x03 }, key.pack(), new byte[] { 0x05 }, new byte[] { 0x00, 0x01, 0x7f, (byte) 0x81, 0x00 }), serialized);
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class TextIndexBunchedSerializerTest method invalidDeserialization.
@Test
public void invalidDeserialization() {
final Tuple key = Tuple.from(1066L);
final List<byte[]> invalidDataArrays = Arrays.asList(// invalid prefix
new byte[] { 0x21, 0x04, 0x01, 0x02, 0x03, 0x04 }, // too few items in entry list
new byte[] { 0x20, 0x04, 0x01, 0x02, 0x03 }, // no final entry list
ByteArrayUtil.join(new byte[] { 0x20, 0x00, 0x03 }, Tuple.from(1415L).pack()));
for (byte[] data : invalidDataArrays) {
assertThrows(BunchedSerializationException.class, () -> serializer.deserializeEntries(key, data));
assertThrows(BunchedSerializationException.class, () -> serializer.deserializeKeys(key, data));
}
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class TextIndexBunchedSerializerTest method ratherLargeEntry.
@Test
public void ratherLargeEntry() {
Random r = new Random(0x5ca1ab1e);
Tuple t = Tuple.fromStream(LongStream.generate(r::nextLong).limit(100).boxed());
int last = 0;
List<Integer> list = new ArrayList<>(500);
for (int i = 0; i < 500; i++) {
int bytes = r.nextInt(4);
int bound = 1 << (7 * bytes);
int next = last + r.nextInt(bound);
list.add(next);
last = next;
}
byte[] serialized = serializer.serializeEntries(Arrays.asList(entryOf(TupleHelpers.EMPTY, Collections.emptyList()), entryOf(t, list)));
byte[] serializedTuple = t.pack();
int tupleStart = (Integer.SIZE - Integer.numberOfLeadingZeros(serializedTuple.length) + 6) / 7 + 2;
assertArrayEquals(serializedTuple, Arrays.copyOfRange(serialized, tupleStart, tupleStart + serializedTuple.length));
List<Map.Entry<Tuple, List<Integer>>> deserializedEntries = serializer.deserializeEntries(TupleHelpers.EMPTY, serialized);
Map.Entry<Tuple, List<Integer>> entry = deserializedEntries.get(1);
assertEquals(t, entry.getKey());
assertEquals(list, entry.getValue());
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class TextIndexTest method scanMulti.
@Nonnull
private List<BunchedMapScanEntry<Tuple, List<Integer>, String>> scanMulti(@Nonnull FDBRecordStore store, @Nonnull Subspace mapSubspace) throws ExecutionException, InterruptedException {
SubspaceSplitter<String> splitter = new SubspaceSplitter<String>() {
@Nonnull
@Override
public Subspace subspaceOf(@Nonnull byte[] keyBytes) {
Tuple t = mapSubspace.unpack(keyBytes);
return mapSubspace.subspace(TupleHelpers.subTuple(t, 0, 1));
}
@Nonnull
@Override
public String subspaceTag(@Nonnull Subspace subspace) {
return mapSubspace.unpack(subspace.getKey()).getString(0);
}
};
BunchedMapMultiIterator<Tuple, List<Integer>, String> iterator = BUNCHED_MAP.scanMulti(store.ensureContextActive(), mapSubspace, splitter);
return AsyncUtil.collectRemaining(iterator).get();
}
use of com.apple.foundationdb.tuple.Tuple in project fdb-record-layer by FoundationDB.
the class FDBRecordStoreIndexTest method testIndexMissingValidation.
@Test
public void testIndexMissingValidation() throws Exception {
final int nRecords = 10;
try (FDBRecordContext context = openContext()) {
openSimpleRecordStore(context);
for (int i = 0; i < nRecords; i++) {
TestRecords1Proto.MySimpleRecord.Builder recBuilder = TestRecords1Proto.MySimpleRecord.newBuilder();
recBuilder.setRecNo(i);
recBuilder.setStrValueIndexed(Integer.toString(i));
// nRecords is not larger than 10, so the indexes (sorted by the string version of recNo) are in the
// same order as the records. This can make the test easy.
recordStore.saveRecord(recBuilder.build());
}
commit(context);
}
// Delete the indexes of some records.
Set<InvalidIndexEntry> expectedInvalidEntries = new HashSet<>();
try (FDBRecordContext context = openContext()) {
final Index index = recordStore.getRecordMetaData().getIndex("MySimpleRecord$str_value_indexed");
openSimpleRecordStore(context);
List<FDBStoredRecord<Message>> savedRecords = recordStore.scanRecords(TupleRange.ALL, null, ScanProperties.FORWARD_SCAN).asList().get();
List<IndexEntry> indexEntries = recordStore.scanIndex(index, IndexScanType.BY_VALUE, TupleRange.ALL, null, ScanProperties.FORWARD_SCAN).asList().get();
for (int i = 0; i < nRecords; i += 2) {
IndexEntry indexEntry = indexEntries.get(i);
FDBStoredRecord<Message> record = savedRecords.get(i);
final Tuple valueKey = indexEntry.getKey();
final Tuple entryKey = indexEntryKey(index, valueKey, record.getPrimaryKey());
final byte[] keyBytes = recordStore.indexSubspace(index).pack(valueKey);
byte[] v0 = recordStore.getContext().ensureActive().get(keyBytes).get();
recordStore.getContext().ensureActive().clear(keyBytes);
byte[] v = recordStore.getContext().ensureActive().get(keyBytes).get();
expectedInvalidEntries.add(InvalidIndexEntry.newMissing(indexEntry, record));
}
commit(context);
}
try (FDBDatabaseRunner runner = fdb.newRunner()) {
AtomicInteger generatorCount = new AtomicInteger();
// Set a scanned records limit to mock when the NoNextReason is out of band.
RecordCursorIterator<InvalidIndexEntry> cursor = new AutoContinuingCursor<>(runner, (context, continuation) -> new LazyCursor<>(FDBRecordStore.newBuilder().setContext(context).setKeySpacePath(path).setMetaDataProvider(simpleMetaData(NO_HOOK)).openAsync().thenApply(currentRecordStore -> {
generatorCount.getAndIncrement();
final Index index = currentRecordStore.getRecordMetaData().getIndex("MySimpleRecord$str_value_indexed");
ScanProperties scanProperties = new ScanProperties(ExecuteProperties.newBuilder().setReturnedRowLimit(Integer.MAX_VALUE).setIsolationLevel(IsolationLevel.SNAPSHOT).setScannedRecordsLimit(4).build());
return currentRecordStore.getIndexMaintainer(index).validateEntries(continuation, scanProperties);
}))).asIterator();
Set<InvalidIndexEntry> results = new HashSet<>();
cursor.forEachRemaining(results::add);
assertEquals(expectedInvalidEntries, results);
// The number of scans is about the number of index entries (orphan validation) plus the number of records
// (missing validation).
assertThat(generatorCount.get(), greaterThanOrEqualTo((5 + 10) / 4));
}
}
Aggregations