use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.
the class StatsTrackingKeyValueService method get.
@Override
public Map<Cell, Value> get(TableReference tableRef, Map<Cell, Long> timestampByCell) {
long start = System.currentTimeMillis();
Map<Cell, Value> r = super.get(tableRef, timestampByCell);
long finish = System.currentTimeMillis();
// Update stats only after successful get.
TableStats s = getTableStats(tableRef);
long cellBytes = 0;
for (Cell cell : timestampByCell.keySet()) {
cellBytes += cell.getRowName().length;
cellBytes += cell.getColumnName().length;
}
s.totalGetCellBytes.addAndGet(cellBytes);
s.totalGetMillis.addAndGet(finish - start);
s.totalGetCalls.incrementAndGet();
updateGetStats(s, r);
return r;
}
use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.
the class SweepStatsKeyValueService method flushWrites.
private void flushWrites(Multiset<TableReference> writes, Set<TableReference> clears) {
if (writes.isEmpty() && clears.isEmpty()) {
log.info("No writes to flush");
return;
}
log.info("Flushing stats for {} writes and {} clears", SafeArg.of("writes", writes.size()), SafeArg.of("clears", clears.size()));
log.trace("Flushing writes: {}", UnsafeArg.of("writes", writes));
log.trace("Flushing clears: {}", UnsafeArg.of("clears", clears));
try {
Set<TableReference> tableNames = Sets.difference(writes.elementSet(), clears);
Collection<byte[]> rows = Collections2.transform(Collections2.transform(tableNames, t -> t.getQualifiedName()), Functions.compose(Persistables.persistToBytesFunction(), SweepPriorityRow.fromFullTableNameFun()));
Map<Cell, Value> oldWriteCounts = delegate().getRows(SWEEP_PRIORITY_TABLE, rows, SweepPriorityTable.getColumnSelection(SweepPriorityNamedColumn.WRITE_COUNT), Long.MAX_VALUE);
Map<Cell, byte[]> newWriteCounts = Maps.newHashMapWithExpectedSize(writes.elementSet().size());
byte[] col = SweepPriorityNamedColumn.WRITE_COUNT.getShortName();
for (TableReference tableRef : tableNames) {
Preconditions.checkState(!tableRef.getQualifiedName().startsWith(AtlasDbConstants.NAMESPACE_PREFIX), "The sweep stats kvs should wrap the namespace mapping kvs, not the other way around.");
byte[] row = SweepPriorityRow.of(tableRef.getQualifiedName()).persistToBytes();
Cell cell = Cell.create(row, col);
Value oldValue = oldWriteCounts.get(cell);
long oldCount = oldValue == null || oldValue.getContents().length == 0 ? 0 : SweepPriorityTable.WriteCount.BYTES_HYDRATOR.hydrateFromBytes(oldValue.getContents()).getValue();
long newValue = clears.contains(tableRef) ? writes.count(tableRef) : oldCount + writes.count(tableRef);
log.debug("Sweep priority for {} has {} writes (was {})", tableRef, newValue, oldCount);
newWriteCounts.put(cell, SweepPriorityTable.WriteCount.of(newValue).persistValue());
}
long timestamp = timestampService.getFreshTimestamp();
// Committing before writing is intentional, we want the start timestamp to
// show up in the transaction table before we write do our writes.
commit(timestamp);
delegate().put(SWEEP_PRIORITY_TABLE, newWriteCounts, timestamp);
} catch (RuntimeException e) {
if (Thread.interrupted()) {
return;
}
Set<TableReference> allTableNames = delegate().getAllTableNames();
if (!allTableNames.contains(SWEEP_PRIORITY_TABLE) || !allTableNames.contains(TransactionConstants.TRANSACTION_TABLE)) {
// ignore problems when sweep or transaction tables don't exist
log.warn("Ignoring failed sweep stats flush due to ", e);
}
log.error("Unable to flush sweep stats for writes {} and clears {}: ", writes, clears, e);
throw e;
}
}
use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.
the class ValidatingQueryRewritingKeyValueService method putWithTimestamps.
@Override
public void putWithTimestamps(TableReference tableRef, Multimap<Cell, Value> cellValues) throws KeyAlreadyExistsException {
if (cellValues.isEmpty()) {
return;
}
Validate.isTrue(!tableRef.equals(TransactionConstants.TRANSACTION_TABLE), TRANSACTION_ERROR);
long lastTimestamp = -1;
boolean allAtSameTimestamp = true;
for (Value value : cellValues.values()) {
long timestamp = value.getTimestamp();
Validate.isTrue(timestamp != Long.MAX_VALUE);
Validate.isTrue(timestamp >= 0);
if (lastTimestamp != -1 && timestamp != lastTimestamp) {
allAtSameTimestamp = false;
}
lastTimestamp = timestamp;
}
if (allAtSameTimestamp) {
Multimap<Cell, byte[]> cellValuesWithStrippedTimestamp = Multimaps.transformValues(cellValues, Value.GET_VALUE);
Map<Cell, byte[]> putMap = Maps.transformValues(cellValuesWithStrippedTimestamp.asMap(), input -> {
try {
return Iterables.getOnlyElement(input);
} catch (IllegalArgumentException e) {
log.error("Application tried to put multiple same-cell values in at same timestamp; attempting to perform last-write-wins, but ordering is not guaranteed.");
return Iterables.getLast(input);
}
});
put(tableRef, putMap, lastTimestamp);
return;
}
delegate.putWithTimestamps(tableRef, cellValues);
}
use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.
the class CassandraKeyValueServiceTableCreationIntegrationTest method testCreateTableCanRestoreLostMetadata.
@Test
public void testCreateTableCanRestoreLostMetadata() {
// setup a basic table
TableReference missingMetadataTable = TableReference.createFromFullyQualifiedName("test.metadata_missing");
byte[] initialMetadata = new TableDefinition() {
{
rowName();
rowComponent("blob", ValueType.BLOB);
columns();
column("bar", "b", ValueType.BLOB);
conflictHandler(ConflictHandler.IGNORE_ALL);
sweepStrategy(TableMetadataPersistence.SweepStrategy.NOTHING);
}
}.toTableMetadata().persistToBytes();
kvs.createTable(missingMetadataTable, initialMetadata);
// retrieve the metadata and see that it's the same as what we just put in
byte[] existingMetadata = kvs.getMetadataForTable(missingMetadataTable);
assertThat(initialMetadata, is(existingMetadata));
// Directly get and delete the metadata (`get` necessary to get the fake timestamp putMetadataForTables used)
Cell cell = Cell.create(missingMetadataTable.getQualifiedName().getBytes(StandardCharsets.UTF_8), "m".getBytes(StandardCharsets.UTF_8));
Value persistedMetadata = Iterables.getLast(kvs.get(AtlasDbConstants.DEFAULT_METADATA_TABLE, ImmutableMap.of(cell, Long.MAX_VALUE)).values());
kvs.delete(AtlasDbConstants.DEFAULT_METADATA_TABLE, ImmutableMultimap.of(cell, persistedMetadata.getTimestamp()));
// pretend we started up again and did a createTable() for our existing table, that no longer has metadata
kvs.createTable(missingMetadataTable, initialMetadata);
// retrieve the metadata again and see that it's the same as what we just put in
existingMetadata = kvs.getMetadataForTable(missingMetadataTable);
assertThat(initialMetadata, is(existingMetadata));
}
use of com.palantir.atlasdb.keyvalue.api.Value in project atlasdb by palantir.
the class CassandraKeyValueServiceImpl method get.
/**
* Gets values from the key-value store.
* <p>
* Does not require all Cassandra nodes to be up and available, works as long as quorum is achieved.
*
* @param tableRef the name of the table to retrieve values from.
* @param timestampByCell specifies, for each row, the maximum timestamp (exclusive) at which to
* retrieve that rows's value.
*
* @return map of retrieved values. Values which do not exist (either
* because they were deleted or never created in the first place)
* are simply not returned.
*
* @throws IllegalArgumentException if any of the requests were invalid
* (e.g., attempting to retrieve values from a non-existent table).
*/
@Override
public Map<Cell, Value> get(TableReference tableRef, Map<Cell, Long> timestampByCell) {
if (timestampByCell.isEmpty()) {
log.info("Attempted get on '{}' table with empty cells", LoggingArgs.tableRef(tableRef));
return ImmutableMap.of();
}
try {
Long firstTs = timestampByCell.values().iterator().next();
if (Iterables.all(timestampByCell.values(), Predicates.equalTo(firstTs))) {
return get("get", tableRef, timestampByCell.keySet(), firstTs);
}
SetMultimap<Long, Cell> cellsByTs = Multimaps.invertFrom(Multimaps.forMap(timestampByCell), HashMultimap.<Long, Cell>create());
Builder<Cell, Value> builder = ImmutableMap.builder();
for (long ts : cellsByTs.keySet()) {
StartTsResultsCollector collector = new StartTsResultsCollector(ts);
cellLoader.loadWithTs("get", tableRef, cellsByTs.get(ts), ts, false, collector, readConsistency);
builder.putAll(collector.getCollectedResults());
}
return builder.build();
} catch (Exception e) {
throw QosAwareThrowables.unwrapAndThrowRateLimitExceededOrAtlasDbDependencyException(e);
}
}
Aggregations