private void executeCheckAndSet(CheckAndSetRequest request) { Preconditions.checkArgument(request.oldValue().isPresent()); runWrite(request.table(), table -> { //noinspection OptionalGetWithoutIsPresent table.update(request.cell(), AtlasDbConstants.TRANSACTION_TS, request.oldValue().get(), request.newValue()); return null; }); }
private CheckAndSetRequest casProgressRequest(Cell cell, Map<Cell, Value> storedProgress, SweepProgress newProgress) throws JsonProcessingException { if (storedProgress.isEmpty()) { // Progress for this thread has never been stored return CheckAndSetRequest.newCell(AtlasDbConstants.SWEEP_PROGRESS_TABLE, cell, progressToBytes(newProgress)); } Value storedValue = Iterables.getOnlyElement(storedProgress.values()); if (isFinishedTablePlaceholder(storedValue)) { // Last iteration, this thread finished a table return CheckAndSetRequest.singleCell(AtlasDbConstants.SWEEP_PROGRESS_TABLE, cell, FINISHED_TABLE, progressToBytes(newProgress)); } else { return CheckAndSetRequest.singleCell(AtlasDbConstants.SWEEP_PROGRESS_TABLE, cell, progressToBytes(hydrateProgress(storedProgress).get()), progressToBytes(newProgress)); } }
private void executePutUnlessExists(CheckAndSetRequest checkAndSetRequest) { try { Map<Cell, byte[]> value = ImmutableMap.of(checkAndSetRequest.cell(), checkAndSetRequest.newValue()); putUnlessExists(checkAndSetRequest.table(), value); } catch (KeyAlreadyExistsException e) { throw new CheckAndSetException("Value unexpectedly present when running check and set", e); } }
CheckAndSetRequest createNewCellRequest(ShardAndStrategy shardAndStrategy, byte[] colValNew) { return CheckAndSetRequest.newCell(TABLE_REF, cellForShard(shardAndStrategy), colValNew); }
@Override public void checkAndSet(CheckAndSetRequest request) { tablesWrittenTo.add(request.table()); super.checkAndSet(request); }
private void clearProgressFromCell(SweepProgress progress, Cell cell) { try { CheckAndSetRequest request = CheckAndSetRequest.singleCell( AtlasDbConstants.SWEEP_PROGRESS_TABLE, cell, progressToBytes(progress), FINISHED_TABLE); kvs.checkAndSet(request); } catch (JsonProcessingException e) { log.warn("Exception trying to clear sweep progress. " + "Sweep may continue examining the same range if the problem persists.", e); } }
@Override public void checkAndSet(CheckAndSetRequest checkAndSetRequest) throws CheckAndSetException { if (checkAndSetRequest.oldValue().isPresent()) { executeCheckAndSet(checkAndSetRequest); } else { executePutUnlessExists(checkAndSetRequest); } }
@Override public void checkAndSet(CheckAndSetRequest request) { TableStats s = timeOperation(request.table(), () -> super.checkAndSet(request)); // Only update stats after put was successful. s.totalPutCells.incrementAndGet(); // can only CAS one value incrementPutBytes(s, request.cell(), request.newValue()); }
void populate() { CheckAndSetRequest request = CheckAndSetRequest.newCell( AtlasDbConstants.PERSISTED_LOCKS_TABLE, LOCK_OPEN.cell(), LOCK_OPEN.value()); try { kvs.checkAndSet(request); } catch (CheckAndSetException e) { // This can happen if multiple LockStores are started at once. We don't actually mind. // All we care about is that we're in the state machine of "LOCK_OPEN"/"LOCK_TAKEN". // It still might be interesting, so we'll log it. List<String> values = getActualValues(e); log.debug("Encountered a CheckAndSetException when creating the LockStore. This means that two " + "LockStore objects were created near-simultaneously, and is probably not a problem. " + "For the record, we observed these values: {}", values); } }
@Override public void checkAndSet(CheckAndSetRequest checkAndSetRequest) { getDelegate(checkAndSetRequest.table()).checkAndSet(checkAndSetRequest); }
private CheckAndSetRequest createSingleCellRequest(ShardAndStrategy shardAndStrategy, long oldVal, byte[] colValNew) { byte[] colValOld = createColumnValue(oldVal); return CheckAndSetRequest.singleCell(TABLE_REF, cellForShard(shardAndStrategy), colValOld, colValNew); } }
static CqlQuery getQueryForRequest(CheckAndSetRequest request) { return request.oldValue().map(unused -> updateIfMatching(request)).orElseGet(() -> insertIfNotExists(request)); }
private static CqlQuery updateIfMatching(CheckAndSetRequest request) { Preconditions.checkState(request.oldValue().isPresent(), "updateIfMatching queries should only be made if we do have an old value"); return ImmutableCqlQuery.builder() .safeQueryFormat("UPDATE \"%s\" SET value=%s WHERE key=%s AND column1=%s AND column2=%s IF value=%s;") .addArgs( LoggingArgs.internalTableName(request.table()), UnsafeArg.of("newValue", encodeCassandraHexString(request.newValue())), UnsafeArg.of("row", encodeCassandraHexString(request.cell().getRowName())), UnsafeArg.of("column", encodeCassandraHexString(request.cell().getColumnName())), SafeArg.of("cassandraTimestamp", CASSANDRA_TIMESTAMP), UnsafeArg.of("oldValue", encodeCassandraHexString(request.oldValue().get()))) .build(); }
private void executePutUnlessExists(CheckAndSetRequest checkAndSetRequest) { try { Map<Cell, byte[]> value = ImmutableMap.of(checkAndSetRequest.cell(), checkAndSetRequest.newValue()); putUnlessExists(checkAndSetRequest.table(), value); } catch (KeyAlreadyExistsException e) { throw new CheckAndSetException("Value unexpectedly present when running check and set", e); } }
private void updateWatermarkForTable(long newWatermark, TableReference table) { while (true) { Cell cell = cell(table); Optional<Value> currentValue = Optional.ofNullable( kvs.get(CLEARS, ImmutableMap.of(cell, Long.MAX_VALUE)).get(cell)); Optional<Long> currentWatermark = currentValue.map(value -> RowResult.of(cell, value.getContents())) .map(TableClearsRowResult::of) .map(TableClearsRowResult::getLastClearedTimestamp); if (currentWatermark.isPresent() && currentWatermark.get() > newWatermark) { return; } CheckAndSetRequest request = currentWatermark .map(watermark -> CheckAndSetRequest.singleCell( CLEARS, cell, EncodingUtils.encodeVarLong(watermark), EncodingUtils.encodeVarLong(newWatermark))) .orElseGet(() -> CheckAndSetRequest.newCell( CLEARS, cell, EncodingUtils.encodeVarLong(newWatermark))); try { kvs.checkAndSet(request); return; } catch (CheckAndSetException e) { // do nothing, we spin } } }
Optional<KeyAlreadyExistsException> failure = clientPool.runWithRetry(client -> { for (Entry<Cell, byte[]> e : values.entrySet()) { CheckAndSetRequest request = CheckAndSetRequest.newCell(tableRef, e.getKey(), e.getValue()); CheckAndSetResult casResult = checkAndSetRunner.executeCheckAndSet(client, request); if (!casResult.successful()) {