Search in sources :

Example 11 with ConsistentKeyLockStatus

use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project janusgraph by JanusGraph.

the class ConsistentKeyLockerTest method testCheckLocksDiesOnPermanentStorageException.

/**
 * A single PermanentStorageException on getSlice() for a single lock is
 * sufficient to make the method return immediately (regardless of whether
 * other locks are waiting to be checked).
 *
 * @throws InterruptedException shouldn't happen
 * @throws org.janusgraph.diskstorage.BackendException     shouldn't happen
 */
@Test
public void testCheckLocksDiesOnPermanentStorageException() throws InterruptedException, BackendException {
    // Setup a LockStatus for defaultLockID
    ConsistentKeyLockStatus lockStatus = makeStatusNow();
    currentTimeNS = currentTimeNS.plusNanos(1);
    expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, lockStatus));
    expectSleepAfterWritingLock(lockStatus);
    // First and only getSlice call throws a PSE
    recordExceptionalLockGetSlice(new PermanentBackendException("Connection to storage cluster failed: peer is an IPv6 toaster"));
    ctrl.replay();
    PermanentBackendException pse = null;
    try {
        locker.checkLocks(defaultTx);
    } catch (PermanentBackendException e) {
        pse = e;
    }
    assertNotNull(pse);
}
Also used : PermanentBackendException(org.janusgraph.diskstorage.PermanentBackendException) ConsistentKeyLockStatus(org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus) Test(org.junit.jupiter.api.Test)

Example 12 with ConsistentKeyLockStatus

use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus 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 13 with ConsistentKeyLockStatus

use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project janusgraph by JanusGraph.

the class ConsistentKeyLockerTest method testCheckLocksSucceedsWithSeniorAndJuniorClaimsBySelf.

/**
 * If the checker retrieves a timestamp-ordered list of columns, where the
 * list starts with an unbroken series of columns with the checker's rid but
 * differing timestamps, then consider the lock successfully checked if the
 * checker's expected timestamp occurs anywhere in that series of columns.
 * <p/>
 * This relaxation of the normal checking rules only triggers when either
 * writeLock(...) issued mutate calls that appeared to fail client-side but
 * which actually succeeded (e.g. hinted handoff or timeout)
 *
 * @throws InterruptedException shouldn't happen
 * @throws org.janusgraph.diskstorage.BackendException     shouldn't happen
 */
@Test
public void testCheckLocksSucceedsWithSeniorAndJuniorClaimsBySelf() throws InterruptedException, BackendException {
    // Setup three lock columns differing only in timestamp
    StaticBuffer myFirstLockCol = codec.toLockCol(currentTimeNS, defaultLockRid, times);
    currentTimeNS = currentTimeNS.plusNanos(1);
    StaticBuffer mySecondLockCol = codec.toLockCol(currentTimeNS, defaultLockRid, times);
    ConsistentKeyLockStatus mySecondLS = makeStatusNow();
    currentTimeNS = currentTimeNS.plusNanos(1);
    StaticBuffer myThirdLockCol = codec.toLockCol(currentTimeNS, defaultLockRid, times);
    currentTimeNS = currentTimeNS.plusNanos(1);
    expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, mySecondLS));
    // Return defaultTx's second lock in a map when requested
    currentTimeNS = currentTimeNS.plusSeconds(10);
    expectSleepAfterWritingLock(mySecondLS);
    // When the checker slices the store, return the senior lock col by a
    // foreign tx and the junior lock col by defaultTx (in that order)
    recordLockGetSlice(StaticArrayEntryList.of(StaticArrayEntry.of(myFirstLockCol, defaultLockVal), StaticArrayEntry.of(mySecondLockCol, defaultLockVal), StaticArrayEntry.of(myThirdLockCol, defaultLockVal)));
    ctrl.replay();
    locker.checkLocks(defaultTx);
}
Also used : StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) ConsistentKeyLockStatus(org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus) Test(org.junit.jupiter.api.Test)

Example 14 with ConsistentKeyLockStatus

use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project janusgraph by JanusGraph.

the class ConsistentKeyLockerTest method testCheckLocksIdempotence.

/**
 * Each written lock should be checked at most once. Test this by faking a
 * single previously written lock using mocks and stubs and then calling
 * checkLocks() twice. The second call should have no effect.
 *
 * @throws InterruptedException shouldn't happen
 * @throws org.janusgraph.diskstorage.BackendException     shouldn't happen
 */
@Test
public void testCheckLocksIdempotence() throws InterruptedException, BackendException {
    // Fake a pre-existing valid lock
    final ConsistentKeyLockStatus ls = makeStatusNow();
    expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, ls));
    currentTimeNS = currentTimeNS.plusSeconds(10);
    expectSleepAfterWritingLock(ls);
    final StaticBuffer lc = codec.toLockCol(ls.getWriteTimestamp(), defaultLockRid, times);
    recordLockGetSliceAndReturnSingleEntry(StaticArrayEntry.of(lc, defaultLockVal));
    ctrl.replay();
    locker.checkLocks(defaultTx);
    ctrl.verify();
    ctrl.reset();
    // Return the faked lock in a map of size 1
    expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, ls));
    ctrl.replay();
    // At this point, checkLocks() should see that the single lock in the
    // map returned above has already been checked and return immediately
    locker.checkLocks(defaultTx);
}
Also used : StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) ConsistentKeyLockStatus(org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus) Test(org.junit.jupiter.api.Test)

Example 15 with ConsistentKeyLockStatus

use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus 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

ConsistentKeyLockStatus (org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus)19 Test (org.junit.jupiter.api.Test)18 StaticBuffer (org.janusgraph.diskstorage.StaticBuffer)7 TemporaryBackendException (org.janusgraph.diskstorage.TemporaryBackendException)4 PermanentBackendException (org.janusgraph.diskstorage.PermanentBackendException)2 KeyColumn (org.janusgraph.diskstorage.util.KeyColumn)2 Instant (java.time.Instant)1 HashMap (java.util.HashMap)1 Entry (org.janusgraph.diskstorage.Entry)1 ConsistentKeyLocker (org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLocker)1 ExpiredLockException (org.janusgraph.diskstorage.locking.consistentkey.ExpiredLockException)1 LockCleanerService (org.janusgraph.diskstorage.locking.consistentkey.LockCleanerService)1 StaticArrayEntry (org.janusgraph.diskstorage.util.StaticArrayEntry)1