Search in sources :

Example 26 with TemporaryBackendException

use of org.janusgraph.diskstorage.TemporaryBackendException 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");
}
Also used : TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) Instant(java.time.Instant) StaticBuffer(org.janusgraph.diskstorage.StaticBuffer)

Example 27 with TemporaryBackendException

use of org.janusgraph.diskstorage.TemporaryBackendException 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);
        }
    }
}
Also used : TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) StoreTransaction(org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction) StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) BackendException(org.janusgraph.diskstorage.BackendException) PermanentBackendException(org.janusgraph.diskstorage.PermanentBackendException)

Example 28 with TemporaryBackendException

use of org.janusgraph.diskstorage.TemporaryBackendException 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);
}
Also used : TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) BackendException(org.janusgraph.diskstorage.BackendException) PermanentBackendException(org.janusgraph.diskstorage.PermanentBackendException) Test(org.junit.jupiter.api.Test)

Example 29 with TemporaryBackendException

use of org.janusgraph.diskstorage.TemporaryBackendException in project janusgraph by JanusGraph.

the class ConsistentKeyLockerTest method testDeleteLocksSkipsToNextLockAfterMaxTemporaryStorageExceptions.

/**
 * If lock deletion exceeds the temporary exception retry count when trying
 * to delete a lock, it should move onto the next lock rather than returning
 * and potentially leaving the remaining locks alone (not deleted).
 *
 * @throws org.janusgraph.diskstorage.BackendException shouldn't happen
 */
@Test
public void testDeleteLocksSkipsToNextLockAfterMaxTemporaryStorageExceptions() throws BackendException {
    ConsistentKeyLockStatus defaultLS = makeStatusNow();
    currentTimeNS = currentTimeNS.plusNanos(1);
    expect(lockState.getLocksForTx(defaultTx)).andReturn(Maps.newLinkedHashMap(ImmutableMap.of(defaultLockID, defaultLS)));
    expectDeleteLock(defaultLockID, defaultLockKey, defaultLS, new TemporaryBackendException("Storage cluster is busy"), new TemporaryBackendException("Storage cluster is busier"), new TemporaryBackendException("Storage cluster has reached peak business"));
    ctrl.replay();
    locker.deleteLocks(defaultTx);
}
Also used : TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) ConsistentKeyLockStatus(org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus) Test(org.junit.jupiter.api.Test)

Example 30 with TemporaryBackendException

use of org.janusgraph.diskstorage.TemporaryBackendException in project janusgraph by JanusGraph.

the class ConsistentKeyLockerTest method testCheckLocksRetriesAfterSingleTemporaryStorageException.

/**
 * The checker should retry getSlice() in the face of a
 * TemporaryStorageException so long as the number of exceptional
 * getSlice()s is fewer than the lock retry count. The retry count applies
 * on a per-lock basis.
 *
 * @throws org.janusgraph.diskstorage.BackendException     shouldn't happen
 * @throws InterruptedException shouldn't happen
 */
@Test
public void testCheckLocksRetriesAfterSingleTemporaryStorageException() throws BackendException, InterruptedException {
    // Setup one lock column
    StaticBuffer lockCol = codec.toLockCol(currentTimeNS, defaultLockRid, times);
    ConsistentKeyLockStatus lockStatus = makeStatusNow();
    currentTimeNS = currentTimeNS.plusNanos(1);
    expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, lockStatus));
    expectSleepAfterWritingLock(lockStatus);
    // First getSlice will fail
    TemporaryBackendException tse = new TemporaryBackendException("Storage cluster will be right back");
    recordExceptionalLockGetSlice(tse);
    // Second getSlice will succeed
    recordLockGetSliceAndReturnSingleEntry(StaticArrayEntry.of(lockCol, defaultLockVal));
    ctrl.replay();
    locker.checkLocks(defaultTx);
// TODO run again with two locks instead of one and show that the retry count applies on a per-lock basis
}
Also used : TemporaryBackendException(org.janusgraph.diskstorage.TemporaryBackendException) StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) ConsistentKeyLockStatus(org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus) Test(org.junit.jupiter.api.Test)

Aggregations

TemporaryBackendException (org.janusgraph.diskstorage.TemporaryBackendException)32 IOException (java.io.IOException)13 PermanentBackendException (org.janusgraph.diskstorage.PermanentBackendException)13 StaticBuffer (org.janusgraph.diskstorage.StaticBuffer)11 ArrayList (java.util.ArrayList)8 BackendException (org.janusgraph.diskstorage.BackendException)7 List (java.util.List)6 Test (org.junit.jupiter.api.Test)6 ConnectionException (com.netflix.astyanax.connectionpool.exceptions.ConnectionException)5 HashMap (java.util.HashMap)5 IndexSearcher (org.apache.lucene.search.IndexSearcher)5 BaseTransaction (org.janusgraph.diskstorage.BaseTransaction)5 Duration (java.time.Duration)4 Map (java.util.Map)4 BooleanQuery (org.apache.lucene.search.BooleanQuery)4 DocValuesFieldExistsQuery (org.apache.lucene.search.DocValuesFieldExistsQuery)4 FuzzyQuery (org.apache.lucene.search.FuzzyQuery)4 MatchAllDocsQuery (org.apache.lucene.search.MatchAllDocsQuery)4 MatchNoDocsQuery (org.apache.lucene.search.MatchNoDocsQuery)4 NormsFieldExistsQuery (org.apache.lucene.search.NormsFieldExistsQuery)4