use of com.thinkaurelius.titan.diskstorage.TemporaryStorageException in project titan by thinkaurelius.
the class AbstractLocker method checkLocks.
@Override
public void checkLocks(StoreTransaction tx) throws TemporaryLockingException, PermanentLockingException {
if (null != tx.getConfiguration().getMetricsPrefix()) {
MetricManager.INSTANCE.getCounter(tx.getConfiguration().getMetricsPrefix(), M_LOCKS, M_CHECK, M_CALLS).inc();
}
Map<KeyColumn, S> m = lockState.getLocksForTx(tx);
if (m.isEmpty()) {
// no locks for this tx
return;
}
// We never receive interrupts in normal operation; one can only appear
// during Thread.sleep(), and in that case it probably means the entire
// Titan process is shutting down; for this reason, we return ASAP on an
// interrupt
boolean ok = false;
try {
for (KeyColumn kc : m.keySet()) {
checkSingleLock(kc, m.get(kc), tx);
}
ok = true;
} catch (InterruptedException e) {
throw new TemporaryLockingException(e);
} catch (TemporaryStorageException tse) {
throw new TemporaryLockingException(tse);
} catch (AssertionError ae) {
// Concession to ease testing with mocks & behavior verification
throw ae;
} catch (Throwable t) {
throw new PermanentLockingException(t);
} finally {
if (!ok && null != tx.getConfiguration().getMetricsPrefix()) {
MetricManager.INSTANCE.getCounter(tx.getConfiguration().getMetricsPrefix(), M_LOCKS, M_CHECK, M_CALLS).inc();
}
}
}
use of com.thinkaurelius.titan.diskstorage.TemporaryStorageException in project titan by thinkaurelius.
the class ConsistentKeyLocker method writeSingleLock.
/**
* Try to write a lock record remotely up to
* {@link conf#getLockRetryCount()} 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 PermanentStorageException}, 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.getDurationNS() <= getLockWait(TimeUnit.NANOSECONDS)) {
// log.debug("Wrote lock {} to store {} using {}", new Object[] { lockID, store.getName(), txh });
return new ConsistentKeyLockStatus(wr.getBeforeNS(), TimeUnit.NANOSECONDS, wr.getBeforeNS() + lockExpireNS, TimeUnit.NANOSECONDS);
}
oldLockCol = wr.getLockCol();
handleMutationFailure(lockID, lockKey, wr, txh);
}
tryDeleteLockOnce(lockKey, oldLockCol, txh);
// TODO log exception or successful too-slow write here
throw new TemporaryStorageException("Lock write retry count exceeded");
}
use of com.thinkaurelius.titan.diskstorage.TemporaryStorageException in project titan by thinkaurelius.
the class CachedKeyColumnValueStore method getSlice.
@Override
public List<Entry> getSlice(final KeySliceQuery query, final StoreTransaction txh) throws StorageException {
if (query.isStatic()) {
try {
if (log.isDebugEnabled())
log.debug("Cache Retrieval on " + store.getName() + ". Attempts: {} | Misses: {}", CACHE_RETRIEVAL.getCount(), CACHE_MISS.getCount());
CACHE_RETRIEVAL.inc();
List<Entry> result = cache.get(query, new Callable<List<Entry>>() {
@Override
public List<Entry> call() throws StorageException {
CACHE_MISS.inc();
return store.getSlice(query, txh);
}
});
if (result.isEmpty())
cache.invalidate(query);
return result;
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (cause != null && cause instanceof StorageException) {
throw (StorageException) cause;
} else {
throw new TemporaryStorageException("Exception while accessing cache", e);
}
}
} else {
return store.getSlice(query, txh);
}
}
use of com.thinkaurelius.titan.diskstorage.TemporaryStorageException in project titan by thinkaurelius.
the class BackendOperation method execute.
public static final <V> V execute(Callable<V> exe, long maxTimeMS) throws TitanException {
long waitTime = BASE_REATTEMPT_TIME_MS;
long maxTime = System.currentTimeMillis() + maxTimeMS;
StorageException lastException = null;
do {
try {
return exe.call();
} catch (StorageException e) {
if (e instanceof TemporaryStorageException)
lastException = e;
else
// Its permanent
throw new TitanException("Permanent exception during backend operation", e);
} catch (Throwable e) {
throw new TitanException("Unexpected exception during backend operation", e);
}
// Wait and retry
Preconditions.checkNotNull(lastException);
if (System.currentTimeMillis() + waitTime < maxTime) {
log.info("Temporary storage exception during backend operation. Attempting backoff retry", exe.toString(), lastException);
try {
Thread.sleep(waitTime);
} catch (InterruptedException r) {
throw new TitanException("Interrupted while waiting to retry failed storage operation", r);
}
}
// Exponential backoff
waitTime *= 2;
} while (System.currentTimeMillis() < maxTime);
throw new TitanException("Could not successfully complete backend operation due to repeated temporary exceptions after " + maxTimeMS + " ms", lastException);
}
use of com.thinkaurelius.titan.diskstorage.TemporaryStorageException in project titan by thinkaurelius.
the class ConsistentKeyLockerTest method testDeleteLocksRetriesOnTemporaryStorageException.
/**
* Lock deletion should retry if the first store mutation throws a temporary
* exception.
*
* @throws StorageException shouldn't happen
*/
@Test
public void testDeleteLocksRetriesOnTemporaryStorageException() throws StorageException {
ConsistentKeyLockStatus defaultLS = makeStatusNow();
currentTimeNS++;
expect(lockState.getLocksForTx(defaultTx)).andReturn(Maps.newLinkedHashMap(ImmutableMap.of(defaultLockID, defaultLS)));
List<StaticBuffer> dels = ImmutableList.of(codec.toLockCol(defaultLS.getWriteTimestamp(TimeUnit.NANOSECONDS), defaultLockRid));
expect(times.getApproxNSSinceEpoch()).andReturn(currentTimeNS);
store.mutate(eq(defaultLockKey), eq(ImmutableList.<Entry>of()), eq(dels), eq(defaultTx));
expectLastCall().andThrow(new TemporaryStorageException("Storage cluster is backlogged"));
expect(times.getApproxNSSinceEpoch()).andReturn(currentTimeNS);
store.mutate(eq(defaultLockKey), eq(ImmutableList.<Entry>of()), eq(dels), eq(defaultTx));
expect(mediator.unlock(defaultLockID, defaultTx)).andReturn(true);
// lockState.release(defaultTx, defaultLockID);
ctrl.replay();
locker.deleteLocks(defaultTx);
}
Aggregations