@Override public LockToken lock(String client, String lockName) throws InterruptedException { LockRequest lockRequest = LockRequest.of( ImmutableSet.of(StringLockDescriptor.of(lockName)), Long.MAX_VALUE, client); LockResponse lockResponse = timelockService.lock(lockRequest); Preconditions.checkState(lockResponse.wasSuccessful(), "Jepsen failed to lock a lock, but it would wait for Long.MAX_VALUE, so this is unexpected."); return lockResponse.getToken(); }
@Override public LockResponse lock(LockRequest request) { LockRefreshToken legacyToken = lockAnonymous(toLegacyLockRequest(request)); if (legacyToken == null) { return LockResponse.timedOut(); } else { return LockResponse.successful(LockTokenConverter.toTokenV2(legacyToken)); } }
@JsonIgnore default LockToken getToken() { if (!wasSuccessful()) { throw new IllegalStateException("This lock response was not successful"); } return getTokenOrEmpty().get(); }
@Theory public void shouldAcquireRowAndCellLockIfRequiresBoth(ConflictHandler conflictHandler) { Assume.assumeTrue(conflictHandler.lockCellsForConflicts() && conflictHandler.lockRowsForConflicts()); PreCommitCondition cellAndRowLockAcquired = (ignored) -> { LockResponse cellLockResponse = acquireCellLock(ROW, COLUMN); LockResponse rowLockResponse = acquireRowLock(ROW); assertFalse(cellLockResponse.wasSuccessful()); assertFalse(rowLockResponse.wasSuccessful()); }; commitWriteWith(cellAndRowLockAcquired, conflictHandler); }
@Override protected void performOneCall() { LockToken token = timelock.lock(nextRequest()).getToken(); boolean wasUnlocked = timelock.unlock(ImmutableSet.of(token)).contains(token); Preconditions.checkState(wasUnlocked, "unlock returned false"); }
@JsonIgnore default boolean wasSuccessful() { return getTokenOrEmpty().isPresent(); }
@Test public void registersLocks() { LockRequest request = LockRequest.of(LOCKS, TIMEOUT); when(delegate.lock(request)).thenReturn(LockResponse.successful(TOKEN_1)); timelock.lock(request); verify(refresher).registerLock(TOKEN_1); }
@Theory public void shouldNotAcquireCellLockIfDoesNotLockAtCellLevel(ConflictHandler conflictHandler) { Assume.assumeFalse(conflictHandler.lockCellsForConflicts()); PreCommitCondition canAcquireCellLock = (ignored) -> { LockResponse response = acquireCellLock(ROW, COLUMN); //current lock implementation allows you to get a cell lock on a row that is already locked assertTrue(response.wasSuccessful()); }; commitWriteWith(canAcquireCellLock, conflictHandler); }
public static Optional<TargetedSweeperLock> tryAcquire(int shard, TableMetadataPersistence.SweepStrategy strategy, TimelockService timeLock) { ShardAndStrategy shardStrategy = ShardAndStrategy.of(shard, strategy); LockDescriptor lock = StringLockDescriptor.of(shardStrategy.toText()); // We do not want the timeout to be too low to avoid a race condition where we give up too soon LockRequest request = LockRequest.of(ImmutableSet.of(lock), 100L); return timeLock.lock(request) .getTokenOrEmpty() .map(lockToken -> new TargetedSweeperLock(shardStrategy, timeLock, lockToken)); }
@Test public void lockDelegatesToLockService() throws InterruptedException { com.palantir.lock.LockRequest legacyRequest = com.palantir.lock.LockRequest.builder(buildLockMap(LockMode.WRITE)) .blockForAtMost(SimpleTimeDuration.of(TIMEOUT, TimeUnit.MILLISECONDS)) .build(); when(lockService.lock(LockClient.ANONYMOUS.getClientId(), legacyRequest)).thenReturn(LOCK_REFRESH_TOKEN); assertEquals(LockResponse.successful(LOCK_TOKEN_V2), timelock.lock( LockRequest.of(ImmutableSet.of(LOCK_A, LOCK_B), TIMEOUT))); verify(lockService).lock(LockClient.ANONYMOUS.getClientId(), legacyRequest); }
@Override public LockResponse lock(LockRequest request) { LockResponse response = executeOnTimeLock(() -> delegate.lock(request)); if (response.wasSuccessful()) { lockRefresher.registerLock(response.getToken()); } return response; }
@Theory public void shouldNotAcquireRowLockIfDoesNotLockAtRowLevel(ConflictHandler conflictHandler) { Assume.assumeFalse(conflictHandler.lockRowsForConflicts()); PreCommitCondition canAcquireRowLock = (ignored) -> { LockResponse response = acquireRowLock(ROW); assertTrue(response.wasSuccessful()); }; commitWriteWith(canAcquireRowLock, conflictHandler); }
@JsonIgnore default LockToken getToken() { if (!wasSuccessful()) { throw new IllegalStateException("This lock response was not successful"); } return getTokenOrEmpty().get(); }
@POST @Path("lock") public void lock(@Suspended final AsyncResponse response, LockRequest request) { AsyncResult<LockToken> result = timelock.lock(request); lockLog.registerRequest(request, result); result.onComplete(() -> { if (result.isFailed()) { response.resume(result.getError()); } else if (result.isTimedOut()) { response.resume(LockResponse.timedOut()); } else { response.resume(LockResponse.successful(result.get())); } }); }
@JsonIgnore default boolean wasSuccessful() { return getTokenOrEmpty().isPresent(); }
/** * This method should acquire any locks needed to do proper concurrency control at commit time. */ protected LockToken acquireLocksForCommit() { Set<LockDescriptor> lockDescriptors = getLocksForWrites(); LockRequest request = LockRequest.of(lockDescriptors, transactionConfig.get().getLockAcquireTimeoutMillis()); LockResponse lockResponse = timelockService.lock(request); if (!lockResponse.wasSuccessful()) { log.error("Timed out waiting while acquiring commit locks. Request id was {}. Timeout was {} ms. " + "First ten required locks were {}.", SafeArg.of("requestId", request.getRequestId()), SafeArg.of("acquireTimeoutMs", transactionConfig.get().getLockAcquireTimeoutMillis()), UnsafeArg.of("firstTenLockDescriptors", Iterables.limit(lockDescriptors, 10))); throw new TransactionLockAcquisitionTimeoutException("Timed out while acquiring commit locks."); } return lockResponse.getToken(); }
@Theory public void shouldAcquireRowLockIfLocksAtRowLevel(ConflictHandler conflictHandler) { Assume.assumeTrue(conflictHandler.lockRowsForConflicts()); PreCommitCondition rowLocksAcquired = (ignored) -> { LockResponse response = acquireRowLock(ROW); assertFalse(response.wasSuccessful()); }; commitWriteWith(rowLocksAcquired, conflictHandler); }
@POST @Path("lock") public void lock(@Suspended final AsyncResponse response, LockRequest request) { AsyncResult<LockToken> result = timelock.lock(request); lockLog.registerRequest(request, result); result.onComplete(() -> { if (result.isFailed()) { response.resume(result.getError()); } else if (result.isTimedOut()) { response.resume(LockResponse.timedOut()); } else { response.resume(LockResponse.successful(result.get())); } }); }
public static Optional<TargetedSweeperLock> tryAcquire(int shard, TableMetadataPersistence.SweepStrategy strategy, TimelockService timeLock) { ShardAndStrategy shardStrategy = ShardAndStrategy.of(shard, strategy); LockDescriptor lock = StringLockDescriptor.of(shardStrategy.toText()); // We do not want the timeout to be too low to avoid a race condition where we give up too soon LockRequest request = LockRequest.of(ImmutableSet.of(lock), 100L); return timeLock.lock(request) .getTokenOrEmpty() .map(lockToken -> new TargetedSweeperLock(shardStrategy, timeLock, lockToken)); }
@Override public LockResponse lock(LockRequest request) { LockResponse response = executeOnTimeLock(() -> delegate.lock(request)); if (response.wasSuccessful()) { lockRefresher.registerLock(response.getToken()); } return response; }