use of org.janusgraph.diskstorage.StaticBuffer in project janusgraph by JanusGraph.
the class ConsistentKeyLocker method writeSingleLock.
/**
* Try to write a lock record remotely up to the configured number of
* times. If the store produces
* {@link TemporaryLockingException}, then we'll call mutate again to add a
* new column with an updated timestamp and to delete the column that tried
* to write when the store threw an exception. We continue like that up to
* the retry limit. If the store throws anything else, such as an unchecked
* exception or a {@link org.janusgraph.diskstorage.PermanentBackendException}, then we'll try to
* delete whatever we added and return without further retries.
*
* @param lockID lock to acquire
* @param txh transaction
* @return the timestamp, in nanoseconds since UNIX Epoch, on the lock
* column that we successfully wrote to the store
* @throws TemporaryLockingException if the lock retry count is exceeded without successfully
* writing the lock in less than the wait limit
* @throws Throwable if the storage layer throws anything else
*/
@Override
protected ConsistentKeyLockStatus writeSingleLock(KeyColumn lockID, StoreTransaction txh) throws Throwable {
final StaticBuffer lockKey = serializer.toLockKey(lockID.getKey(), lockID.getColumn());
StaticBuffer oldLockCol = null;
for (int i = 0; i < lockRetryCount; i++) {
WriteResult wr = tryWriteLockOnce(lockKey, oldLockCol, txh);
if (wr.isSuccessful() && wr.getDuration().compareTo(lockWait) <= 0) {
final Instant writeInstant = wr.getWriteTimestamp();
final Instant expireInstant = writeInstant.plus(lockExpire);
return new ConsistentKeyLockStatus(writeInstant, expireInstant);
}
oldLockCol = wr.getLockCol();
handleMutationFailure(lockID, lockKey, wr, txh);
}
tryDeleteLockOnce(lockKey, oldLockCol, txh);
// TODO log exception or successful too-slow write here
throw new TemporaryBackendException("Lock write retry count exceeded");
}
use of org.janusgraph.diskstorage.StaticBuffer in project janusgraph by JanusGraph.
the class ConsistentKeyLocker method deleteSingleLock.
@Override
protected void deleteSingleLock(KeyColumn kc, ConsistentKeyLockStatus ls, StoreTransaction tx) {
List<StaticBuffer> deletions = Collections.singletonList(serializer.toLockCol(ls.getWriteTimestamp(), rid, times));
for (int i = 0; i < lockRetryCount; i++) {
StoreTransaction newTx = null;
try {
newTx = overrideTimestamp(tx, times.getTime());
store.mutate(serializer.toLockKey(kc.getKey(), kc.getColumn()), Collections.emptyList(), deletions, newTx);
newTx.commit();
newTx = null;
return;
} catch (TemporaryBackendException e) {
log.warn("Temporary storage exception while deleting lock", e);
// don't return -- iterate and retry
} catch (BackendException e) {
log.error("Storage exception while deleting lock", e);
// give up on this lock
return;
} finally {
rollbackIfNotNull(newTx);
}
}
}
use of org.janusgraph.diskstorage.StaticBuffer in project janusgraph by JanusGraph.
the class BufferUtil method readEntry.
public static Entry readEntry(ReadBuffer in, Serializer serializer) {
long valuePosition = VariableLong.readPositive(in);
Preconditions.checkArgument(valuePosition > 0 && valuePosition <= Integer.MAX_VALUE);
StaticBuffer buffer = readBuffer(in);
StaticArrayEntry entry = new StaticArrayEntry(buffer, (int) valuePosition);
int metaSize = in.getByte();
for (int i = 0; i < metaSize; i++) {
EntryMetaData meta = EntryMetaData.values()[in.getByte()];
entry.setMetaData(meta, serializer.readObjectNotNull(in, meta.getDataType()));
}
return entry;
}
use of org.janusgraph.diskstorage.StaticBuffer in project janusgraph by JanusGraph.
the class ConsistentKeyLockerTest method expectDeleteLock.
private void expectDeleteLock(KeyColumn lockID, StaticBuffer lockKey, ConsistentKeyLockStatus lockStatus, BackendException... backendFailures) throws BackendException {
List<StaticBuffer> deletions = ImmutableList.of(codec.toLockCol(lockStatus.getWriteTimestamp(), defaultLockRid, times));
expect(times.getTime()).andReturn(currentTimeNS);
store.mutate(eq(lockKey), eq(ImmutableList.of()), eq(deletions), eq(defaultTx));
int backendExceptionsThrown = 0;
for (BackendException e : backendFailures) {
expectLastCall().andThrow(e);
if (e instanceof PermanentBackendException) {
break;
}
backendExceptionsThrown++;
int maxTemporaryStorageExceptions = 3;
if (backendExceptionsThrown < maxTemporaryStorageExceptions) {
expect(times.getTime()).andReturn(currentTimeNS);
store.mutate(eq(lockKey), eq(ImmutableList.of()), eq(deletions), eq(defaultTx));
}
}
expect(mediator.unlock(lockID, defaultTx)).andReturn(true);
}
use of org.janusgraph.diskstorage.StaticBuffer in project janusgraph by JanusGraph.
the class ConsistentKeyLockerTest method testWriteLockThrowsExceptionAfterMaxStoreTimeouts.
/**
* Test locker when all three attempts to write a lock succeed but take
* longer than the wait limit. We expect the locker to delete all three
* columns that it wrote and locally unlock the KeyColumn, then emit an
* exception.
*
* @throws org.janusgraph.diskstorage.BackendException shouldn't happen
*/
@Test
public void testWriteLockThrowsExceptionAfterMaxStoreTimeouts() throws BackendException {
expect(lockState.has(defaultTx, defaultLockID)).andReturn(false);
recordSuccessfulLocalLock();
StaticBuffer firstCol = recordSuccessfulLockWrite(5, ChronoUnit.SECONDS, null).col;
StaticBuffer secondCol = recordSuccessfulLockWrite(5, ChronoUnit.SECONDS, firstCol).col;
StaticBuffer thirdCol = recordSuccessfulLockWrite(5, ChronoUnit.SECONDS, secondCol).col;
recordSuccessfulLockDelete(thirdCol);
recordSuccessfulLocalUnlock();
ctrl.replay();
BackendException expected = null;
try {
// SUT
locker.writeLock(defaultLockID, defaultTx);
} catch (TemporaryBackendException e) {
expected = e;
}
assertNotNull(expected);
}
Aggregations