use of com.palantir.atlasdb.keyvalue.api.RowResult in project atlasdb by palantir.
the class AbstractTransactionTest method testReadMyWritesAfterGetRange.
@Test
public void testReadMyWritesAfterGetRange() throws InterruptedException, ExecutionException {
Transaction t = startTransaction();
// this will come first in the range
put(t, "row0", "col1", "v0");
put(t, "row1", "col1", "v1");
put(t, "row1", "col2", "v2");
put(t, "row2", "col1", "v3");
put(t, "row4", "col1", "v4");
t.commit();
t = startTransaction();
assertEquals("v1", get(t, "row1", "col1"));
assertEquals("v2", get(t, "row1", "col2"));
assertEquals("v3", get(t, "row2", "col1"));
// we need a bunch of buffer writes so that we don't exhaust the local iterator right away
// because of peeking iterators looking ahead
put(t, "a0", "col2", "v0");
put(t, "b1", "col3", "v0");
put(t, "c2", "col3", "v0");
put(t, "d3", "col3", "v0");
final CountDownLatch latch = new CountDownLatch(1);
final CountDownLatch latch2 = new CountDownLatch(1);
final BatchingVisitable<RowResult<byte[]>> visitable = t.getRange(TEST_TABLE, RangeRequest.builder().build());
FutureTask<Void> futureTask = new FutureTask<Void>(() -> {
final Map<Cell, byte[]> vals = Maps.newHashMap();
try {
visitable.batchAccept(1, AbortingVisitors.batching((RowVisitor) item -> {
try {
latch.countDown();
latch2.await();
} catch (InterruptedException e) {
throw Throwables.throwUncheckedException(e);
}
MapEntries.putAll(vals, item.getCells());
if (Arrays.equals(item.getRowName(), "row1".getBytes())) {
assertEquals("v5", new String(item.getColumns().get("col1".getBytes())));
assertEquals(3, IterableView.of(item.getCells()).size());
}
return true;
}));
assertTrue(vals.containsKey(Cell.create("row1".getBytes(), "col1".getBytes())));
assertTrue(Arrays.equals("v5".getBytes(), vals.get(Cell.create("row1".getBytes(), "col1".getBytes()))));
assertFalse(vals.containsKey(Cell.create("row2".getBytes(), "col1".getBytes())));
return null;
} catch (Throwable t1) {
latch.countDown();
Throwables.throwIfInstance(t1, Exception.class);
throw Throwables.throwUncheckedException(t1);
}
});
Thread thread = new Thread(futureTask);
thread.setName("testReadMyWritesAfterGetRange");
thread.start();
latch.await();
// These puts will be seen by the range scan happening on the other thread
// this put is checked to exist
put(t, "row1", "col1", "v5");
// it is checked there are 3 cells for this
put(t, "row1", "col3", "v6");
put(t, "row3", "col1", "v7");
// this delete is checked
delete(t, "row2", "col1");
put(t, "row2", "col2", "v8");
latch2.countDown();
futureTask.get();
}
use of com.palantir.atlasdb.keyvalue.api.RowResult in project atlasdb by palantir.
the class TableMigratorTest method testMigrationToDifferentKvs.
// Table/IndexDefinition syntax
@SuppressWarnings({ "checkstyle:Indentation", "checkstyle:RightCurly" })
@Test
public void testMigrationToDifferentKvs() throws TableMappingNotFoundException {
final TableReference tableRef = TableReference.create(Namespace.DEFAULT_NAMESPACE, "table");
final TableReference namespacedTableRef = TableReference.createFromFullyQualifiedName("namespace." + tableRef.getTablename());
TableDefinition definition = new TableDefinition() {
{
rowName();
rowComponent("r", ValueType.BLOB);
columns();
column("c", "c", ValueType.BLOB);
}
};
keyValueService.createTable(tableRef, definition.toTableMetadata().persistToBytes());
keyValueService.createTable(namespacedTableRef, definition.toTableMetadata().persistToBytes());
keyValueService.putMetadataForTable(namespacedTableRef, definition.toTableMetadata().persistToBytes());
final Cell theCell = Cell.create(PtBytes.toBytes("r1"), PtBytes.toBytes("c"));
final byte[] theValue = PtBytes.toBytes("v1");
txManager.runTaskWithRetry((TransactionTask<Void, RuntimeException>) txn -> {
Map<Cell, byte[]> values = ImmutableMap.of(theCell, theValue);
txn.put(tableRef, values);
txn.put(namespacedTableRef, values);
return null;
});
final InMemoryKeyValueService kvs2 = new InMemoryKeyValueService(false);
final ConflictDetectionManager cdm2 = ConflictDetectionManagers.createWithNoConflictDetection();
final SweepStrategyManager ssm2 = SweepStrategyManagers.completelyConservative(kvs2);
final TestTransactionManagerImpl txManager2 = new TestTransactionManagerImpl(kvs2, timestampService, lockClient, lockService, transactionService, cdm2, ssm2, MultiTableSweepQueueWriter.NO_OP);
kvs2.createTable(tableRef, definition.toTableMetadata().persistToBytes());
kvs2.createTable(namespacedTableRef, definition.toTableMetadata().persistToBytes());
TableReference checkpointTable = TableReference.create(Namespace.DEFAULT_NAMESPACE, "checkpoint");
GeneralTaskCheckpointer checkpointer = new GeneralTaskCheckpointer(checkpointTable, kvs2, txManager2);
for (final TableReference name : Lists.newArrayList(tableRef, namespacedTableRef)) {
TransactionRangeMigrator rangeMigrator = new TransactionRangeMigratorBuilder().srcTable(name).readTxManager(txManager).txManager(txManager2).checkpointer(checkpointer).build();
TableMigratorBuilder builder = new TableMigratorBuilder().srcTable(name).partitions(1).executor(PTExecutors.newSingleThreadExecutor()).checkpointer(checkpointer).rangeMigrator(rangeMigrator);
TableMigrator migrator = builder.build();
migrator.migrate();
}
checkpointer.deleteCheckpoints();
final ConflictDetectionManager verifyCdm = ConflictDetectionManagers.createWithNoConflictDetection();
final SweepStrategyManager verifySsm = SweepStrategyManagers.completelyConservative(kvs2);
final TestTransactionManagerImpl verifyTxManager = new TestTransactionManagerImpl(kvs2, timestampService, lockClient, lockService, transactionService, verifyCdm, verifySsm, MultiTableSweepQueueWriter.NO_OP);
final MutableLong count = new MutableLong();
for (final TableReference name : Lists.newArrayList(tableRef, namespacedTableRef)) {
verifyTxManager.runTaskReadOnly((TransactionTask<Void, RuntimeException>) txn -> {
BatchingVisitable<RowResult<byte[]>> bv = txn.getRange(name, RangeRequest.all());
bv.batchAccept(1000, AbortingVisitors.batching(new AbortingVisitor<RowResult<byte[]>, RuntimeException>() {
@Override
public boolean visit(RowResult<byte[]> item) throws RuntimeException {
Iterable<Entry<Cell, byte[]>> cells = item.getCells();
Entry<Cell, byte[]> entry = Iterables.getOnlyElement(cells);
Assert.assertEquals(theCell, entry.getKey());
Assert.assertArrayEquals(theValue, entry.getValue());
count.increment();
return true;
}
}));
return null;
});
}
Assert.assertEquals(2L, count.longValue());
}
use of com.palantir.atlasdb.keyvalue.api.RowResult in project atlasdb by palantir.
the class InMemoryKeyValueService method getRangeInternal.
private <T> ClosableIterator<RowResult<T>> getRangeInternal(TableReference tableRef, final RangeRequest range, final ResultProducer<T> resultProducer) {
ConcurrentNavigableMap<Key, byte[]> tableMap = getTableMap(tableRef).entries;
if (range.isReverse()) {
tableMap = tableMap.descendingMap();
}
if (range.getStartInclusive().length != 0) {
if (range.isReverse()) {
Cell startCell = Cells.createLargestCellForRow(range.getStartInclusive());
tableMap = tableMap.tailMap(new Key(startCell, Long.MIN_VALUE));
} else {
Cell startCell = Cells.createSmallestCellForRow(range.getStartInclusive());
tableMap = tableMap.tailMap(new Key(startCell, Long.MIN_VALUE));
}
}
if (range.getEndExclusive().length != 0) {
if (range.isReverse()) {
Cell endCell = Cells.createLargestCellForRow(range.getEndExclusive());
tableMap = tableMap.headMap(new Key(endCell, Long.MAX_VALUE));
} else {
Cell endCell = Cells.createSmallestCellForRow(range.getEndExclusive());
tableMap = tableMap.headMap(new Key(endCell, Long.MAX_VALUE));
}
}
final PeekingIterator<Entry<Key, byte[]>> it = Iterators.peekingIterator(tableMap.entrySet().iterator());
return ClosableIterators.wrap(new AbstractIterator<RowResult<T>>() {
@Override
protected RowResult<T> computeNext() {
while (true) {
if (!it.hasNext()) {
return endOfData();
}
ImmutableSortedMap.Builder<byte[], T> result = ImmutableSortedMap.orderedBy(UnsignedBytes.lexicographicalComparator());
Key key = it.peek().getKey();
byte[] row = key.row;
Iterator<Entry<Key, byte[]>> cellIter = takeCell(it, key);
collectValueForTimestamp(key.col, cellIter, result, range, resultProducer);
while (it.hasNext()) {
if (!it.peek().getKey().matchesRow(row)) {
break;
}
key = it.peek().getKey();
cellIter = takeCell(it, key);
collectValueForTimestamp(key.col, cellIter, result, range, resultProducer);
}
SortedMap<byte[], T> columns = result.build();
if (!columns.isEmpty()) {
return RowResult.create(row, columns);
}
}
}
});
}
use of com.palantir.atlasdb.keyvalue.api.RowResult in project atlasdb by palantir.
the class KeyValueServices method getFirstBatchForRangeUsingGetRange.
public static void getFirstBatchForRangeUsingGetRange(KeyValueService kv, TableReference tableRef, RangeRequest request, long timestamp, @Output Map<RangeRequest, TokenBackedBasicResultsPage<RowResult<Value>, byte[]>> ret) {
if (ret.containsKey(request)) {
return;
}
RangeRequest requestWithHint = request;
if (request.getBatchHint() == null) {
requestWithHint = request.withBatchHint(100);
}
final ClosableIterator<RowResult<Value>> range = kv.getRange(tableRef, requestWithHint, timestamp);
try {
int batchSize = requestWithHint.getBatchHint();
final Iterator<RowResult<Value>> withLimit = Iterators.limit(range, batchSize);
ImmutableList<RowResult<Value>> results = ImmutableList.copyOf(withLimit);
if (results.size() != batchSize) {
ret.put(request, SimpleTokenBackedResultsPage.create(request.getEndExclusive(), results, false));
return;
}
RowResult<Value> last = results.get(results.size() - 1);
byte[] lastRowName = last.getRowName();
if (RangeRequests.isTerminalRow(request.isReverse(), lastRowName)) {
ret.put(request, SimpleTokenBackedResultsPage.create(lastRowName, results, false));
return;
}
byte[] nextStartRow = RangeRequests.getNextStartRow(request.isReverse(), lastRowName);
if (Arrays.equals(request.getEndExclusive(), nextStartRow)) {
ret.put(request, SimpleTokenBackedResultsPage.create(nextStartRow, results, false));
} else {
ret.put(request, SimpleTokenBackedResultsPage.create(nextStartRow, results, true));
}
} finally {
range.close();
}
}
use of com.palantir.atlasdb.keyvalue.api.RowResult in project atlasdb by palantir.
the class CleanTransactionRange method executeTimestampCommand.
@Override
protected int executeTimestampCommand(AtlasDbServices services) {
KeyValueService kvs = services.getKeyValueService();
ClosableIterator<RowResult<Value>> range = kvs.getRange(TransactionConstants.TRANSACTION_TABLE, RangeRequest.all(), Long.MAX_VALUE);
Multimap<Cell, Long> toDelete = HashMultimap.create();
while (range.hasNext()) {
RowResult<Value> row = range.next();
byte[] rowName = row.getRowName();
long startTs = TransactionConstants.getTimestampForValue(rowName);
Value value;
try {
value = row.getOnlyColumnValue();
} catch (IllegalStateException e) {
// this should never happen
printer.error("Found a row in the transactions table that didn't have 1" + " and only 1 column value: start={}", SafeArg.of("startTs", startTs));
continue;
}
long commitTs = TransactionConstants.getTimestampForValue(value.getContents());
if (commitTs <= timestamp) {
// this is a valid transaction
continue;
}
printer.info("Found and cleaning possibly inconsistent transaction: [start={}, commit={}]", SafeArg.of("startTs", startTs), SafeArg.of("commitTs", commitTs));
Cell key = Cell.create(rowName, TransactionConstants.COMMIT_TS_COLUMN);
// value.getTimestamp() should always be 0L
toDelete.put(key, value.getTimestamp());
}
if (!toDelete.isEmpty()) {
kvs.delete(TransactionConstants.TRANSACTION_TABLE, toDelete);
printer.info("Delete completed.");
} else {
printer.info("Found no transactions after the given timestamp to delete.");
}
return 0;
}
Aggregations