use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.
the class RangeSet method rep.
@Nonnull
public CompletableFuture<String> rep(@Nonnull ReadTransactionContext tc) {
return tc.readAsync(tr -> {
StringBuilder sb = new StringBuilder();
AsyncIterable<KeyValue> iterable = tr.getRange(subspace.range());
return iterable.asList().thenApply((List<KeyValue> list) -> {
for (KeyValue kv : list) {
byte[] key = subspace.unpack(kv.getKey()).getBytes(0);
byte[] value = kv.getValue();
sb.append(ByteArrayUtil.printable(key));
sb.append(" -> ");
sb.append(ByteArrayUtil.printable(value));
sb.append('\n');
}
return sb.toString();
});
});
}
use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method loadIndexStatesAsync.
@Nonnull
private CompletableFuture<Map<String, IndexState>> loadIndexStatesAsync(@Nonnull IsolationLevel isolationLevel) {
Subspace isSubspace = getSubspace().subspace(Tuple.from(INDEX_STATE_SPACE_KEY));
KeyValueCursor cursor = KeyValueCursor.Builder.withSubspace(isSubspace).setContext(getContext()).setRange(TupleRange.ALL).setContinuation(null).setScanProperties(new ScanProperties(ExecuteProperties.newBuilder().setIsolationLevel(isolationLevel).setDefaultCursorStreamingMode(CursorStreamingMode.WANT_ALL).build())).build();
FDBStoreTimer timer = getTimer();
CompletableFuture<Map<String, IndexState>> result = cursor.asList().thenApply(list -> {
Map<String, IndexState> indexStateMap;
if (list.isEmpty()) {
indexStateMap = Collections.emptyMap();
} else {
ImmutableMap.Builder<String, IndexState> indexStateMapBuilder = ImmutableMap.builder();
for (KeyValue kv : list) {
String indexName = isSubspace.unpack(kv.getKey()).getString(0);
Object code = Tuple.fromBytes(kv.getValue()).get(0);
indexStateMapBuilder.put(indexName, IndexState.fromCode(code));
if (timer != null) {
timer.increment(FDBStoreTimer.Counts.LOAD_STORE_STATE_KEY);
timer.increment(FDBStoreTimer.Counts.LOAD_STORE_STATE_KEY_BYTES, kv.getKey().length);
timer.increment(FDBStoreTimer.Counts.LOAD_STORE_STATE_VALUE_BYTES, kv.getValue().length);
}
}
indexStateMap = indexStateMapBuilder.build();
}
return indexStateMap;
});
if (timer != null) {
result = timer.instrument(FDBStoreTimer.Events.LOAD_RECORD_STORE_INDEX_META_DATA, result, context.getExecutor());
}
return result;
}
use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method getPrimaryKeyBoundaries.
/**
* Return a cursor of boundaries separating the key ranges maintained by each FDB server. This information can be
* useful for splitting a large task (e.g., rebuilding an index for a large record store) into smaller tasks (e.g.,
* rebuilding the index for records in certain primary key ranges) more evenly so that they can be executed in a
* parallel fashion efficiently. The returned boundaries are an estimate from FDB's locality API and may not
* represent the exact boundary locations at any database version.
* <p>
* The boundaries are returned as a cursor which is sorted and does not contain any duplicates. The first element of
* the list is greater than or equal to <code>low</code>, and the last element is less than or equal to
* <code>high</code>.
* <p>
* This implementation may not work when there are too many shard boundaries to complete in a single transaction.
* <p>
* Note: the returned cursor is blocking and must not be used in an asynchronous context
*
* @param low low endpoint of primary key range (inclusive)
* @param high high endpoint of primary key range (exclusive)
* @return the list of boundary primary keys
*/
@API(API.Status.EXPERIMENTAL)
@Nonnull
public RecordCursor<Tuple> getPrimaryKeyBoundaries(@Nonnull Tuple low, @Nonnull Tuple high) {
final Transaction transaction = ensureContextActive();
byte[] rangeStart = recordsSubspace().pack(low);
byte[] rangeEnd = recordsSubspace().pack(high);
CloseableAsyncIterator<byte[]> cursor = context.getDatabase().getLocalityProvider().getBoundaryKeys(transaction, rangeStart, rangeEnd);
final boolean hasSplitRecordSuffix = hasSplitRecordSuffix();
DistinctFilterCursorClosure closure = new DistinctFilterCursorClosure();
return RecordCursor.flatMapPipelined(ignore -> RecordCursor.fromIterator(getExecutor(), cursor), (result, ignore) -> RecordCursor.fromIterator(getExecutor(), transaction.snapshot().getRange(result, rangeEnd, 1).iterator()), null, DEFAULT_PIPELINE_SIZE).map(keyValue -> {
Tuple recordKey = recordsSubspace().unpack(keyValue.getKey());
return hasSplitRecordSuffix ? recordKey.popBack() : recordKey;
}).filter(closure::pred);
}
use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.
the class FDBRecordStore method getSnapshotRecordCount.
@Override
public CompletableFuture<Long> getSnapshotRecordCount(@Nonnull KeyExpression key, @Nonnull Key.Evaluated value, @Nonnull IndexQueryabilityFilter indexQueryabilityFilter) {
if (getRecordMetaData().getRecordCountKey() != null) {
if (key.getColumnSize() != value.size()) {
throw recordCoreException("key and value are not the same size");
}
final ReadTransaction tr = context.readTransaction(true);
final Tuple subkey = Tuple.from(RECORD_COUNT_KEY).addAll(value.toTupleAppropriateList());
if (getRecordMetaData().getRecordCountKey().equals(key)) {
return tr.get(getSubspace().pack(subkey)).thenApply(FDBRecordStore::decodeRecordCount);
} else if (key.isPrefixKey(getRecordMetaData().getRecordCountKey())) {
AsyncIterable<KeyValue> kvs = tr.getRange(getSubspace().range(Tuple.from(RECORD_COUNT_KEY)));
return MoreAsyncUtil.reduce(getExecutor(), kvs.iterator(), 0L, (count, kv) -> count + decodeRecordCount(kv.getValue()));
}
}
return evaluateAggregateFunction(Collections.emptyList(), IndexFunctionHelper.count(key), TupleRange.allOf(value.toTuple()), IsolationLevel.SNAPSHOT, indexQueryabilityFilter).thenApply(tuple -> tuple.getLong(0));
}
use of com.apple.foundationdb.KeyValue in project fdb-record-layer by FoundationDB.
the class BunchedMapTest method inconsistentScan.
private static List<KeyValue> inconsistentScan(@Nonnull Database db, @Nonnull Subspace subspace) {
// Note that tr is mutated in the block, hence not using try-with-resources
Transaction tr = db.createTransaction();
try {
KeySelector begin = KeySelector.firstGreaterOrEqual(subspace.range().begin);
KeySelector end = KeySelector.firstGreaterOrEqual(subspace.range().end);
KeyValue lastSeen = null;
AsyncIterator<KeyValue> rangeIterator = tr.getRange(begin, end).iterator();
List<KeyValue> rangeKVs = new ArrayList<>();
boolean done = false;
while (!done) {
// Might loop if there are timeouts encountered within loop.
try {
while (rangeIterator.hasNext()) {
KeyValue next = rangeIterator.next();
rangeKVs.add(next);
lastSeen = next;
}
done = true;
} catch (RuntimeException e) {
FDBException fdbE = unwrapException(e);
if (fdbE == null || fdbE.getCode() != FDBError.TRANSACTION_TOO_OLD.code()) {
throw e;
} else {
// Timed out. Restart transaction and keep going.
tr.close();
tr = db.createTransaction();
if (lastSeen != null) {
// Update begin if we have any results.
begin = KeySelector.firstGreaterThan(lastSeen.getKey());
lastSeen = null;
}
rangeIterator = tr.getRange(begin, end).iterator();
}
}
}
return rangeKVs;
} finally {
tr.close();
}
}
Aggregations