Search in sources :

Example 91 with StaticBuffer

use of org.janusgraph.diskstorage.StaticBuffer 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 92 with StaticBuffer

use of org.janusgraph.diskstorage.StaticBuffer 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 93 with StaticBuffer

use of org.janusgraph.diskstorage.StaticBuffer 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)

Example 94 with StaticBuffer

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

the class ConsistentKeyLockerTest method recordSuccessfulLockWrite.

private LockInfo recordSuccessfulLockWrite(StoreTransaction tx, long duration, TemporalUnit tu, StaticBuffer del) throws BackendException {
    currentTimeNS = currentTimeNS.plusNanos(1);
    expect(times.getTime()).andReturn(currentTimeNS);
    final Instant lockNS = currentTimeNS;
    StaticBuffer lockCol = codec.toLockCol(lockNS, defaultLockRid, times);
    Entry add = StaticArrayEntry.of(lockCol, defaultLockVal);
    StaticBuffer k = eq(defaultLockKey);
    final List<Entry> adds = eq(Collections.singletonList(add));
    final List<StaticBuffer> deletions;
    if (null != del) {
        deletions = eq(Collections.singletonList(del));
    } else {
        deletions = eq(ImmutableList.of());
    }
    store.mutate(k, adds, deletions, eq(tx));
    expectLastCall().once();
    currentTimeNS = currentTimeNS.plus(duration, tu);
    expect(times.getTime()).andReturn(currentTimeNS);
    ConsistentKeyLockStatus status = new ConsistentKeyLockStatus(lockNS, lockNS.plus(defaultExpireNS));
    return new LockInfo(lockNS, status, lockCol);
}
Also used : Entry(org.janusgraph.diskstorage.Entry) StaticArrayEntry(org.janusgraph.diskstorage.util.StaticArrayEntry) Instant(java.time.Instant) StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) ConsistentKeyLockStatus(org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus)

Example 95 with StaticBuffer

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

the class ConsistentKeyLockerTest method testWriteLockRetriesAfterOneStoreTimeout.

/**
 * Test locker when first attempt to write to the store takes too long (but
 * succeeds). Expected behavior is to call mutate on the store, adding a
 * column with a new timestamp and deleting the column with the old
 * (too-slow-to-write) timestamp.
 *
 * @throws org.janusgraph.diskstorage.BackendException shouldn't happen
 */
@Test
public void testWriteLockRetriesAfterOneStoreTimeout() throws BackendException {
    expect(lockState.has(defaultTx, defaultLockID)).andReturn(false);
    recordSuccessfulLocalLock();
    // too slow
    StaticBuffer firstCol = recordSuccessfulLockWrite(5, ChronoUnit.SECONDS, null).col;
    // plenty fast
    LockInfo secondLI = recordSuccessfulLockWrite(1, ChronoUnit.NANOS, firstCol);
    recordSuccessfulLocalLock(secondLI.tsNS);
    lockState.take(eq(defaultTx), eq(defaultLockID), eq(secondLI.stat));
    ctrl.replay();
    // SUT
    locker.writeLock(defaultLockID, defaultTx);
}
Also used : StaticBuffer(org.janusgraph.diskstorage.StaticBuffer) Test(org.junit.jupiter.api.Test)

Aggregations

StaticBuffer (org.janusgraph.diskstorage.StaticBuffer)101 Entry (org.janusgraph.diskstorage.Entry)36 Test (org.junit.jupiter.api.Test)36 ArrayList (java.util.ArrayList)27 HashMap (java.util.HashMap)20 Map (java.util.Map)19 StoreTransaction (org.janusgraph.diskstorage.keycolumnvalue.StoreTransaction)17 KeySliceQuery (org.janusgraph.diskstorage.keycolumnvalue.KeySliceQuery)16 StaticArrayEntry (org.janusgraph.diskstorage.util.StaticArrayEntry)16 BackendException (org.janusgraph.diskstorage.BackendException)15 List (java.util.List)14 EntryList (org.janusgraph.diskstorage.EntryList)14 TemporaryBackendException (org.janusgraph.diskstorage.TemporaryBackendException)14 KCVMutation (org.janusgraph.diskstorage.keycolumnvalue.KCVMutation)13 PermanentBackendException (org.janusgraph.diskstorage.PermanentBackendException)12 Instant (java.time.Instant)11 DataOutput (org.janusgraph.graphdb.database.serialize.DataOutput)10 ReadBuffer (org.janusgraph.diskstorage.ReadBuffer)8 ConsistentKeyLockStatus (org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus)7 BackendOperation (org.janusgraph.diskstorage.util.BackendOperation)7