@Override public void mutateMany(Map<ByteBuffer, Mutation> mutations, TransactionHandle txh) throws StorageException { // null txh means a Transaction is calling this method if (null != txh) { // non-null txh -> make sure locks are valid AstyanaxTransaction atxh = (AstyanaxTransaction) txh; if (!atxh.isMutationStarted()) { // This is the first mutate call in the transaction atxh.mutationStarted(); // Verify all blind lock claims now atxh.verifyAllLockClaims(); // throws GSE and unlocks everything on any lock failure } } MutationBatch m = keyspace .prepareMutationBatch() .setConsistencyLevel(writeLevel) .withRetryPolicy(retryPolicy.duplicate()); final long delTS = TimestampProvider.getApproxNSSinceEpoch(false); final long addTS = TimestampProvider.getApproxNSSinceEpoch(true); for (Map.Entry<ByteBuffer, Mutation> ent : mutations.entrySet()) { // The CLMs for additions and deletions are separated because // Astyanax's operation timestamp cannot be set on a per-delete // or per-addition basis. ColumnListMutation<ByteBuffer> dels = m.withRow(cf, ent.getKey()); dels.setTimestamp(delTS); ColumnListMutation<ByteBuffer> adds = m.withRow(cf, ent.getKey()); adds.setTimestamp(addTS); Mutation titanMutation = ent.getValue(); if (titanMutation.hasDeletions()) { for (ByteBuffer b : titanMutation.getDeletions()) { dels.deleteColumn(b); } } if (titanMutation.hasAdditions()) { for (Entry e : titanMutation.getAdditions()) { adds.putColumn(e.getColumn(), e.getValue(), null); } } } try { m.execute(); } catch (ConnectionException e) { throw new TemporaryStorageException(e); } }
@Override public void acquireLock( ByteBuffer key, ByteBuffer column, ByteBuffer expectedValue, TransactionHandle txh) throws StorageException { AstyanaxTransaction ctxh = (AstyanaxTransaction) txh; if (ctxh.isMutationStarted()) { throw new PermanentLockingException("Attempted to obtain a lock after one or more mutations"); } ctxh.writeBlindLockClaim(lockConfig, key, column, expectedValue); }