use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project janusgraph by JanusGraph.
the class ConsistentKeyLockerTest method testDeleteLocksSkipsToNextLockOnPermanentStorageException.
/**
* Same as
* {@link #testDeleteLocksSkipsToNextLockAfterMaxTemporaryStorageExceptions()}
* , except instead of exceeding the temporary exception retry count on a
* lock, that lock throws a single permanent exception.
*
* @throws org.janusgraph.diskstorage.BackendException should not happen
*/
@Test
public void testDeleteLocksSkipsToNextLockOnPermanentStorageException() 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 PermanentBackendException("Storage cluster has been destroyed by a tornado"));
ctrl.replay();
locker.deleteLocks(defaultTx);
}
use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project janusgraph by JanusGraph.
the class ConsistentKeyLockerTest method testCheckLocksFailsWithSeniorClaimsByOthers.
/**
* If the checker reads its own lock column preceded by a lock column from
* another rid with an earlier timestamp and the timestamps on both columns
* are unexpired, then the checker must throw a TemporaryLockingException.
*
* @throws InterruptedException shouldn't happen
* @throws org.janusgraph.diskstorage.BackendException
* shouldn't happen (we expect a TemporaryLockingException but we catch and swallow it)
*/
@Test
public void testCheckLocksFailsWithSeniorClaimsByOthers() throws InterruptedException, BackendException {
// Make a pre-existing valid lock by some other tx (written by another process)
StaticBuffer otherSeniorLockCol = codec.toLockCol(currentTimeNS, otherLockRid, times);
currentTimeNS = currentTimeNS.plusNanos(1);
// Expect checker to fetch locks for defaultTx; return just our own lock (not the other guy's)
StaticBuffer ownJuniorLockCol = codec.toLockCol(currentTimeNS, defaultLockRid, times);
ConsistentKeyLockStatus ownJuniorLS = makeStatusNow();
expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, ownJuniorLS));
currentTimeNS = currentTimeNS.plusSeconds(10);
// Return defaultTx's lock in a map when requested
expectSleepAfterWritingLock(ownJuniorLS);
// 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(otherSeniorLockCol, defaultLockVal), StaticArrayEntry.of(ownJuniorLockCol, defaultLockVal)));
ctrl.replay();
TemporaryLockingException tle = null;
try {
locker.checkLocks(defaultTx);
} catch (TemporaryLockingException e) {
tle = e;
}
assertNotNull(tle);
}
use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project janusgraph by JanusGraph.
the class ConsistentKeyLockerTest method testCheckLocksSucceedsWithJuniorClaimsByOthers.
/**
* When the checker retrieves its own lock column followed by a lock column
* with a later timestamp (both with unexpired timestamps), it should
* consider the lock successfully checked.
*
* @throws InterruptedException shouldn't happen
* @throws org.janusgraph.diskstorage.BackendException shouldn't happen
*/
@Test
public void testCheckLocksSucceedsWithJuniorClaimsByOthers() throws InterruptedException, BackendException {
// Expect checker to fetch locks for defaultTx; return just our own lock (not the other guy's)
StaticBuffer ownSeniorLockCol = codec.toLockCol(currentTimeNS, defaultLockRid, times);
ConsistentKeyLockStatus ownSeniorLS = makeStatusNow();
currentTimeNS = currentTimeNS.plusNanos(1);
// Make junior lock
StaticBuffer otherJuniorLockCol = codec.toLockCol(currentTimeNS, otherLockRid, times);
expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, ownSeniorLS));
currentTimeNS = currentTimeNS.plusSeconds(10);
// Return defaultTx's lock in a map when requested
expectSleepAfterWritingLock(ownSeniorLS);
// 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(ownSeniorLockCol, defaultLockVal), StaticArrayEntry.of(otherJuniorLockCol, defaultLockVal)));
ctrl.replay();
locker.checkLocks(defaultTx);
}
use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project janusgraph by JanusGraph.
the class ConsistentKeyLockerTest method testCheckLocksIgnoresOtherExpiredLocks.
/**
* A transaction that detects expired locks from other transactions, or from
* its own transaction but with a different timestamp than the one currently
* stored in memory by the transaction (presumably from an earlier attempt),
* should be ignored.
*
* @throws org.janusgraph.diskstorage.BackendException shouldn't happen
* @throws InterruptedException
*/
@Test
public void testCheckLocksIgnoresOtherExpiredLocks() throws BackendException, InterruptedException {
// Fake a pre-existing lock from a different tx that's long since expired
final ConsistentKeyLockStatus otherExpired = makeStatusNow();
// Fake a pre-existing lock from our tx
final ConsistentKeyLockStatus ownExpired = makeStatusNow();
// pretend a huge multiple of the expiration time has passed
currentTimeNS = currentTimeNS.plus(100, ChronoUnit.DAYS);
// Create a still-valid lock belonging to the default tx
final ConsistentKeyLockStatus recent = makeStatusNow();
expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, recent));
currentTimeNS = currentTimeNS.plusMillis(1);
expectSleepAfterWritingLock(recent);
// Checker must slice the store; return both of the expired claims and the one active claim
recordLockGetSlice(StaticArrayEntryList.of(StaticArrayEntry.of(codec.toLockCol(otherExpired.getWriteTimestamp(), otherLockRid, times), defaultLockVal), StaticArrayEntry.of(codec.toLockCol(ownExpired.getWriteTimestamp(), defaultLockRid, times), defaultLockVal), StaticArrayEntry.of(codec.toLockCol(recent.getWriteTimestamp(), defaultLockRid, times), defaultLockVal)));
ctrl.replay();
locker.checkLocks(defaultTx);
}
use of org.janusgraph.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project janusgraph by JanusGraph.
the class ConsistentKeyLockerTest method testCleanExpiredLock.
/**
* Checking locks when the expired lock cleaner is enabled should trigger
* one call to the LockCleanerService.
*
* @throws org.janusgraph.diskstorage.BackendException shouldn't happen
*/
@Test
public void testCleanExpiredLock() throws BackendException, InterruptedException {
LockCleanerService mockCleaner = ctrl.createMock(LockCleanerService.class);
ctrl.replay();
Locker altLocker = getDefaultBuilder().customCleaner(mockCleaner).build();
ctrl.verify();
ctrl.reset();
final ConsistentKeyLockStatus expired = makeStatusNow();
expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, expired));
// pretend a huge multiple of the expiration time has passed
currentTimeNS = currentTimeNS.plus(100, ChronoUnit.DAYS);
// Checker should compare the fake lock's timestamp to the current time
expect(times.sleepPast(expired.getWriteTimestamp().plus(defaultWaitNS))).andReturn(currentTimeNS);
// Checker must slice the store; we return the single expired lock column
recordLockGetSliceAndReturnSingleEntry(StaticArrayEntry.of(codec.toLockCol(expired.getWriteTimestamp(), defaultLockRid, times), defaultLockVal));
// Checker must attempt to cleanup expired lock
mockCleaner.clean(eq(defaultLockID), eq(currentTimeNS.minus(defaultExpireNS)), eq(defaultTx));
expectLastCall().once();
ctrl.replay();
TemporaryLockingException ple = null;
try {
altLocker.checkLocks(defaultTx);
} catch (TemporaryLockingException e) {
ple = e;
}
assertNotNull(ple);
}
Aggregations