use of org.apache.cassandra.thrift.CASResult in project atlasdb by palantir.
the class Heartbeat method beat.
private Void beat(CassandraClient client) throws TException {
Column ourUpdate = SchemaMutationLock.lockColumnFromIdAndHeartbeat(lockId, heartbeatCount + 1);
List<Column> expected = ImmutableList.of(SchemaMutationLock.lockColumnFromIdAndHeartbeat(lockId, heartbeatCount));
if (Thread.currentThread().isInterrupted()) {
log.debug("Cancelled {}", this);
return null;
}
CASResult casResult = writeDdlLockWithCas(client, ourUpdate, expected);
if (casResult.isSuccess()) {
heartbeatCount++;
} else {
log.warn("Unable to update lock for {}", this);
SchemaMutationLock.handleForcedLockClear(casResult, lockId, heartbeatCount);
}
log.debug("Completed {}", this);
return null;
}
use of org.apache.cassandra.thrift.CASResult in project atlasdb by palantir.
the class CassandraKeyValueServiceImpl method putUnlessExists.
/**
* Puts values into the key-value store. This call <i>does not</i> guarantee
* atomicity across cells. On failure, it is possible that some of the requests will
* have succeeded (without having been rolled back). Similarly, concurrent batched requests may
* interleave. However, concurrent writes to the same Cell will not both report success.
* One of them will throw {@link KeyAlreadyExistsException}.
* <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 put values into.
* @param values map containing the key-value entries to put.
*
* @throws KeyAlreadyExistsException If you are putting a Cell with the same timestamp as one that already exists.
*/
@Override
public void putUnlessExists(final TableReference tableRef, final Map<Cell, byte[]> values) throws KeyAlreadyExistsException {
try {
clientPool.runWithRetry(client -> {
for (Entry<Cell, byte[]> e : values.entrySet()) {
CheckAndSetRequest request = CheckAndSetRequest.newCell(tableRef, e.getKey(), e.getValue());
CASResult casResult = executeCheckAndSet(client, request);
if (!casResult.isSuccess()) {
throw new KeyAlreadyExistsException(String.format("The row in table %s already exists.", tableRef.getQualifiedName()), ImmutableList.of(e.getKey()));
}
}
clientPool.markWritesForTable(values, tableRef);
return null;
});
} catch (Exception e) {
throw QosAwareThrowables.unwrapAndThrowRateLimitExceededOrAtlasDbDependencyException(e);
}
}
use of org.apache.cassandra.thrift.CASResult in project atlasdb by palantir.
the class CassandraTimestampBoundStore method cas.
@GuardedBy("this")
private void cas(CassandraClient client, Long oldVal, long newVal) {
final CASResult result;
try {
DebugLogger.logger.info("[CAS] Trying to set upper limit from {} to {}.", oldVal, newVal);
result = client.cas(AtlasDbConstants.TIMESTAMP_TABLE, getRowName(), oldVal == null ? ImmutableList.of() : ImmutableList.of(makeColumn(oldVal)), ImmutableList.of(makeColumn(newVal)), ConsistencyLevel.SERIAL, ConsistencyLevel.EACH_QUORUM);
} catch (Exception e) {
log.error("[CAS] Error trying to set from {} to {}", SafeArg.of("oldValue", oldVal), SafeArg.of("newValue", newVal), e);
DebugLogger.logger.error("[CAS] Error trying to set from {} to {}", SafeArg.of("oldValue", oldVal), SafeArg.of("newValue", newVal), e);
throw Throwables.throwUncheckedException(e);
}
if (!result.isSuccess()) {
final String msg = "Unable to CAS from {} to {}." + " Timestamp limit changed underneath us (limit in memory: {}, stored in DB: {})." + " This may indicate that another timestamp service is running against this cassandra keyspace." + " This is likely caused by multiple copies of a service running without a configured set of" + " leaders or a CLI being run with an embedded timestamp service against an already running" + " service.";
MultipleRunningTimestampServiceError err = new MultipleRunningTimestampServiceError(String.format(replaceBracesWithStringFormatSpecifier(msg), oldVal, newVal, currentLimit, getCurrentTimestampValues(result)));
log.error(msg, SafeArg.of("oldValue", oldVal), SafeArg.of("newValue", newVal), SafeArg.of("inMemoryLimit", currentLimit), SafeArg.of("dbLimit", getCurrentTimestampValues(result)), err);
DebugLogger.logger.error(msg, SafeArg.of("oldValue", oldVal), SafeArg.of("newValue", newVal), SafeArg.of("inMemoryLimit", currentLimit), SafeArg.of("dbLimit", getCurrentTimestampValues(result)), err);
DebugLogger.logger.error("Thread dump: {}", SafeArg.of("threadDump", ThreadDumps.programmaticThreadDump()));
throw err;
} else {
DebugLogger.logger.debug("[CAS] Setting cached limit to {}.", newVal);
currentLimit = newVal;
}
}
use of org.apache.cassandra.thrift.CASResult in project atlasdb by palantir.
the class SchemaMutationLock method trySchemaMutationUnlockOnce.
private boolean trySchemaMutationUnlockOnce(long perOperationNodeId) {
try {
return clientPool.runWithRetry(client -> {
Column clearedLock = lockColumnWithValue(GLOBAL_DDL_LOCK_CLEARED_VALUE);
Column existingColumn = queryExistingLockColumn(client).orElse(clearedLock);
long existingLockId = getLockIdFromColumn(existingColumn);
if (existingLockId == GLOBAL_DDL_LOCK_CLEARED_ID) {
return true;
}
Preconditions.checkState(existingLockId == perOperationNodeId, "Trying to unlock lock [%s] but a different lock [%s] is taken out.", perOperationNodeId, existingLockId);
List<Column> ourExpectedLock = ImmutableList.of(existingColumn);
CASResult casResult = writeDdlLockWithCas(client, ourExpectedLock, clearedLock);
if (casResult.isSuccess()) {
log.info("Successfully released schema mutation lock with id [{}]", SafeArg.of("lockId", existingLockId));
}
return casResult.isSuccess();
});
} catch (TException e) {
throw Throwables.throwUncheckedException(e);
}
}
Aggregations