use of com.thinkaurelius.titan.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project titan by thinkaurelius.
the class ConsistentKeyLockerTest method testDeleteLocksOnTwoLocks.
/**
* Delete two locks without any timeouts, errors, etc.
*
* @throws StorageException shouldn't happen
*/
@Test
public void testDeleteLocksOnTwoLocks() throws StorageException {
ConsistentKeyLockStatus defaultLS = makeStatusNow();
currentTimeNS++;
ConsistentKeyLockStatus otherLS = makeStatusNow();
currentTimeNS++;
// Expect a call for defaultTx's locks and return two
Map<KeyColumn, ConsistentKeyLockStatus> expectedMap = Maps.newLinkedHashMap();
expectedMap.put(defaultLockID, defaultLS);
expectedMap.put(otherLockID, otherLS);
expect(lockState.getLocksForTx(defaultTx)).andReturn(expectedMap);
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));
expect(mediator.unlock(defaultLockID, defaultTx)).andReturn(true);
dels = ImmutableList.of(codec.toLockCol(otherLS.getWriteTimestamp(TimeUnit.NANOSECONDS), defaultLockRid));
expect(times.getApproxNSSinceEpoch()).andReturn(currentTimeNS);
store.mutate(eq(otherLockKey), eq(ImmutableList.<Entry>of()), eq(dels), eq(defaultTx));
expect(mediator.unlock(otherLockID, defaultTx)).andReturn(true);
ctrl.replay();
locker.deleteLocks(defaultTx);
}
use of com.thinkaurelius.titan.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project titan by thinkaurelius.
the class ConsistentKeyLockerTest method testDeleteLocksIdempotence.
/**
* When delete is called multiple times with no intervening write or check
* calls, all calls after the first should have no effect.
*
* @throws StorageException shouldn't happen
*/
@Test
public void testDeleteLocksIdempotence() throws StorageException {
// Setup a LockStatus for defaultLockID
ConsistentKeyLockStatus lockStatus = makeStatusNow();
currentTimeNS += TimeUnit.NANOSECONDS.convert(1, TimeUnit.NANOSECONDS);
expect(lockState.getLocksForTx(defaultTx)).andReturn(Maps.newLinkedHashMap(ImmutableMap.of(defaultLockID, lockStatus)));
StaticBuffer del = codec.toLockCol(lockStatus.getWriteTimestamp(TimeUnit.NANOSECONDS), defaultLockRid);
expect(times.getApproxNSSinceEpoch()).andReturn(currentTimeNS);
store.mutate(eq(defaultLockKey), eq(ImmutableList.<Entry>of()), eq(Arrays.asList(del)), eq(defaultTx));
expect(mediator.unlock(defaultLockID, defaultTx)).andReturn(true);
// lockState.release(defaultTx, defaultLockID);
ctrl.replay();
locker.deleteLocks(defaultTx);
ctrl.verify();
ctrl.reset();
expect(lockState.getLocksForTx(defaultTx)).andReturn(Maps.newLinkedHashMap(ImmutableMap.<KeyColumn, ConsistentKeyLockStatus>of()));
ctrl.replay();
locker.deleteLocks(defaultTx);
}
use of com.thinkaurelius.titan.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project titan by thinkaurelius.
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 StorageException shouldn't happen
*/
@Test
public void testCheckLocksIdempotence() throws InterruptedException, StorageException {
// Fake a pre-existing valid lock
final ConsistentKeyLockStatus ls = makeStatusNow();
expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, ls));
currentTimeNS += TimeUnit.NANOSECONDS.convert(10, TimeUnit.SECONDS);
expect(times.sleepUntil(ls.getWriteTimestamp(TimeUnit.NANOSECONDS) + defaultWaitNS)).andReturn(currentTimeNS);
final StaticBuffer lc = codec.toLockCol(ls.getWriteTimestamp(TimeUnit.NANOSECONDS), defaultLockRid);
recordLockGetSliceAndReturnSingleEntry(new StaticBufferEntry(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);
}
use of com.thinkaurelius.titan.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project titan by thinkaurelius.
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 StorageException shouldn't happen
* @throws InterruptedException shouldn't happen
*/
@Test
public void testCheckLocksRetriesAfterSingleTemporaryStorageException() throws StorageException, InterruptedException {
// Setup one lock column
StaticBuffer lockCol = codec.toLockCol(currentTimeNS, defaultLockRid);
ConsistentKeyLockStatus lockStatus = makeStatusNow();
currentTimeNS += TimeUnit.NANOSECONDS.convert(1, TimeUnit.NANOSECONDS);
expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, lockStatus));
expect(times.sleepUntil(lockStatus.getWriteTimestamp(TimeUnit.NANOSECONDS) + defaultWaitNS)).andReturn(currentTimeNS);
// First getSlice will fail
TemporaryStorageException tse = new TemporaryStorageException("Storage cluster will be right back");
recordExceptionalLockGetSlice(tse);
// Second getSlice will succeed
recordLockGetSliceAndReturnSingleEntry(new StaticBufferEntry(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
}
use of com.thinkaurelius.titan.diskstorage.locking.consistentkey.ConsistentKeyLockStatus in project titan by thinkaurelius.
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 undeleted.
*
* @throws StorageException shouldn't happen
*/
@Test
public void testDeleteLocksSkipsToNextLockAfterMaxTemporaryStorageExceptions() 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 busy"));
expect(times.getApproxNSSinceEpoch()).andReturn(currentTimeNS);
store.mutate(eq(defaultLockKey), eq(ImmutableList.<Entry>of()), eq(dels), eq(defaultTx));
expectLastCall().andThrow(new TemporaryStorageException("Storage cluster is busier"));
expect(times.getApproxNSSinceEpoch()).andReturn(currentTimeNS);
store.mutate(eq(defaultLockKey), eq(ImmutableList.<Entry>of()), eq(dels), eq(defaultTx));
expectLastCall().andThrow(new TemporaryStorageException("Storage cluster has reached peak business"));
expect(mediator.unlock(defaultLockID, defaultTx)).andReturn(true);
// lockState.release(defaultTx, defaultLockID);
ctrl.replay();
locker.deleteLocks(defaultTx);
}
Aggregations