use of com.thinkaurelius.titan.diskstorage.keycolumnvalue.StaticBufferEntry in project titan by thinkaurelius.
the class ConsistentKeyLockerTest method testCheckLocksInSimplestCase.
/**
* Test a single checking a single lock under optimal conditions (no
* timeouts, no errors)
*
* @throws StorageException shouldn't happen
* @throws InterruptedException shouldn't happen
*/
@Test
public void testCheckLocksInSimplestCase() throws StorageException, InterruptedException {
// Fake a pre-existing lock
final ConsistentKeyLockStatus ls = makeStatusNow();
expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, ls));
currentTimeNS += TimeUnit.NANOSECONDS.convert(10, TimeUnit.SECONDS);
// Checker should compare the fake lock's timestamp to the current time
expect(times.sleepUntil(ls.getWriteTimestamp(TimeUnit.NANOSECONDS) + defaultWaitNS)).andReturn(currentTimeNS);
// Expect a store getSlice() and return the fake lock's column and value
recordLockGetSliceAndReturnSingleEntry(new StaticBufferEntry(codec.toLockCol(ls.getWriteTimestamp(TimeUnit.NANOSECONDS), defaultLockRid), defaultLockVal));
ctrl.replay();
locker.checkLocks(defaultTx);
}
use of com.thinkaurelius.titan.diskstorage.keycolumnvalue.StaticBufferEntry in project titan by thinkaurelius.
the class ConsistentKeyLockerTest method recordExceptionLockWrite.
private StaticBuffer recordExceptionLockWrite(long duration, TimeUnit tu, StaticBuffer del, Throwable t) throws StorageException {
expect(times.getApproxNSSinceEpoch()).andReturn(++currentTimeNS);
StaticBuffer lockCol = codec.toLockCol(currentTimeNS, defaultLockRid);
Entry add = new StaticBufferEntry(lockCol, defaultLockVal);
StaticBuffer k = eq(defaultLockKey);
// assert null != add;
final List<Entry> adds = eq(Arrays.<Entry>asList(add));
// assert null != adds;
final List<StaticBuffer> dels;
if (null != del) {
dels = eq(Arrays.<StaticBuffer>asList(del));
} else {
dels = eq(ImmutableList.<StaticBuffer>of());
}
store.mutate(k, adds, dels, eq(defaultTx));
expectLastCall().andThrow(t);
currentTimeNS += TimeUnit.NANOSECONDS.convert(duration, tu);
expect(times.getApproxNSSinceEpoch()).andReturn(currentTimeNS);
return lockCol;
}
use of com.thinkaurelius.titan.diskstorage.keycolumnvalue.StaticBufferEntry 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.keycolumnvalue.StaticBufferEntry 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.keycolumnvalue.StaticBufferEntry in project titan by thinkaurelius.
the class ConsistentKeyLockerTest method testCheckLocksIgnoresSingleExpiredLock.
/**
* Lock checking should treat columns with timestamps older than the
* expiration period as though they were never read from the store (aside
* from logging them). This tests the checker with a single expired column.
*
* @throws StorageException shouldn't happen
* @throws InterruptedException
*/
@Test
public void testCheckLocksIgnoresSingleExpiredLock() throws StorageException, InterruptedException {
// Fake a pre-existing lock that's long since expired
final ConsistentKeyLockStatus expired = makeStatusNow();
expect(lockState.getLocksForTx(defaultTx)).andReturn(ImmutableMap.of(defaultLockID, expired));
// pretend a huge multiple of the expiration time has passed
currentTimeNS += TimeUnit.NANOSECONDS.convert(100, TimeUnit.DAYS);
// Checker should compare the fake lock's timestamp to the current time
expect(times.sleepUntil(expired.getWriteTimestamp(TimeUnit.NANOSECONDS) + defaultWaitNS)).andReturn(currentTimeNS);
// Checker must slice the store; we return the single expired lock column
recordLockGetSliceAndReturnSingleEntry(new StaticBufferEntry(codec.toLockCol(expired.getWriteTimestamp(TimeUnit.NANOSECONDS), defaultLockRid), defaultLockVal));
ctrl.replay();
TemporaryLockingException ple = null;
try {
locker.checkLocks(defaultTx);
} catch (TemporaryLockingException e) {
ple = e;
}
assertNotNull(ple);
}
Aggregations