@Override public Set<LockRefreshToken> unlock(Set<LockRefreshToken> lockRefreshTokens) throws InterruptedException { Set<LockRefreshToken> tokensUnlocked = Sets.newHashSet(); lockRefreshTokens.forEach(token -> { if (lockService.unlock(token)) { tokensUnlocked.add(token); } }); return tokensUnlocked; }
@Override public Set<LockToken> unlock(Set<LockToken> tokens) { Set<LockToken> unlocked = Sets.newHashSet(); for (LockToken tokenV2 : tokens) { LockRefreshToken legacyToken = LockTokenConverter.toLegacyToken(tokenV2); if (lockService.unlock(legacyToken)) { unlocked.add(tokenV2); } } return unlocked; }
@Override public void cleanup() { PreCommitConditions.runCleanupTask(() -> lockService.unlock(heldLock.getLockRefreshToken())); }
@Test public void unlockDelegatesToLockService() { timelock.unlock(ImmutableSet.of(LOCK_TOKEN_V2)); verify(lockService).unlock(LOCK_REFRESH_TOKEN); }
@Test public void unlockReturnsEmptySetIfTokensWereAlreadyUnlocked() throws InterruptedException { when(LOCK_SERVICE.unlock(any(LockRefreshToken.class))).thenReturn(false); assertThat(LOCK_CLIENT.unlock(ImmutableSet.of(TOKEN_1, TOKEN_2)), empty()); }
@Test public void transactionLocksCondition_cleanUpReleasesLock() { transactionLocksCondition.cleanup(); verify(lockService).unlock(TRANSACTION_LOCK_REFRESH_TOKEN); }
@Test public void unlockSingleReturnsTrueIfTokenCanBeUnlocked() throws InterruptedException { when(LOCK_SERVICE.unlock(eq(TOKEN_1))).thenReturn(true); assertTrue(LOCK_CLIENT.unlockSingle(TOKEN_1)); }
@Test public void closeUnlocksToken() throws InterruptedException { LockRefreshToken token = new LockRefreshToken(BigInteger.ONE, 10000000000L); when(mockLockService.lock(anyString(), any())).thenReturn(token); lockService.lockOrRefresh(); lockService.close(); verify(mockLockService, atLeastOnce()).unlock(token); } }
@Test public void unlockReturnsSubsetThatWereUnlocked() { LockToken tokenA = randomLockToken(); LockToken tokenB = randomLockToken(); when(lockService.unlock(toLegacyToken(tokenA))).thenReturn(true); when(lockService.unlock(toLegacyToken(tokenB))).thenReturn(false); Set<LockToken> expected = ImmutableSet.of(tokenA); assertEquals(expected, timelock.unlock(ImmutableSet.of(tokenA, tokenB))); }
/** Tests lockAndRelease with perf optimization */ @Test public void testLockAndRelease2() throws Exception { LockRequest hasLock1 = LockRequest.builder(ImmutableSortedMap.of(lock1, LockMode.WRITE)).build(); LockRequest hasLock2 = LockRequest.builder(ImmutableSortedMap.of(lock2, LockMode.WRITE)).build(); final LockRequest request = LockRequest.builder(ImmutableSortedMap.of(lock1, LockMode.WRITE, lock2, LockMode.WRITE)).lockAndRelease().build(); LockResponse resp2 = server.lockWithFullLockResponse(LockClient.ANONYMOUS, hasLock2); Assert.assertTrue(resp2.success()); Future<?> future = executor.submit((Callable<Void>) () -> { LockResponse resp = server.lockWithFullLockResponse(LockClient.ANONYMOUS, request); Assert.assertNotNull(resp); Assert.assertTrue(resp.success()); return null; }); Thread.sleep(10); try { future.get(1, TimeUnit.MILLISECONDS); Assert.fail(); } catch (TimeoutException e) { // good } LockResponse resp1 = server.lockWithFullLockResponse(client, hasLock1); server.unlock(resp2.getToken()); future.get(150, TimeUnit.SECONDS); server.unlock(resp1.getToken()); resp2 = server.lockWithFullLockResponse(LockClient.ANONYMOUS, hasLock2); server.unlock(resp2.getToken()); }
/** Tests lockAndRelease */ @Test public void testLockAndRelease() throws Exception { LockRequest hasLock2 = LockRequest.builder(ImmutableSortedMap.of(lock2, LockMode.WRITE)).build(); final LockRequest request = LockRequest.builder(ImmutableSortedMap.of(lock1, LockMode.WRITE, lock2, LockMode.WRITE)).lockAndRelease().build(); LockResponse resp2 = server.lockWithFullLockResponse(LockClient.ANONYMOUS, hasLock2); Assert.assertTrue(resp2.success()); Future<?> future = executor.submit((Callable<Void>) () -> { LockResponse resp = server.lockWithFullLockResponse(LockClient.ANONYMOUS, request); Assert.assertNotNull(resp); Assert.assertTrue(resp.success()); return null; }); try { future.get(1, TimeUnit.MILLISECONDS); Assert.fail(); } catch (TimeoutException e) { // good } server.unlock(resp2.getToken()); future.get(150, TimeUnit.SECONDS); resp2 = server.lockWithFullLockResponse(LockClient.ANONYMOUS, hasLock2); server.unlock(resp2.getToken()); }
@Override public LockImmutableTimestampResponse lockImmutableTimestamp(IdentifiedTimeLockRequest request) { long immutableLockTs = timestampService.getFreshTimestamp(); LockDescriptor lockDesc = AtlasTimestampLockDescriptor.of(immutableLockTs); com.palantir.lock.LockRequest lockRequest = com.palantir.lock.LockRequest.builder( ImmutableSortedMap.of(lockDesc, LockMode.READ)) .withLockedInVersionId(immutableLockTs).build(); LockRefreshToken lock; try { lock = lockService.lock(immutableTsLockClient.getClientId(), lockRequest); } catch (InterruptedException e) { throw Throwables.throwUncheckedException(e); } try { return LockImmutableTimestampResponse.of( getImmutableTimestampInternal(immutableLockTs), LockTokenConverter.toTokenV2(lock)); } catch (Throwable e) { if (lock != null) { lockService.unlock(lock); } throw Throwables.rewrapAndThrowUncheckedException(e); } }
/** Convert a write lock to a read lock */ @Test public void testConvertWriteToRead() throws Exception { final LockRequest request1 = LockRequest.builder(ImmutableSortedMap.of(lock1, LockMode.WRITE)) .build(); final LockRequest request2 = LockRequest.builder(ImmutableSortedMap.of(lock1, LockMode.READ)) .build(); HeldLocksToken token1 = server.lockWithFullLockResponse(client, request1).getToken(); Assert.assertNotNull(token1); Assert.assertEquals(client, token1.getClient()); Assert.assertEquals(request1.getLockDescriptors(), token1.getLockDescriptors()); Future<?> future = executor.submit((Callable<Void>) () -> { barrier.await(); HeldLocksToken validToken = server.lockWithFullLockResponse(LockClient.ANONYMOUS, request2).getToken(); Assert.assertNotNull(validToken); Assert.assertEquals(LockClient.ANONYMOUS, validToken.getClient()); Assert.assertEquals(request2.getLockDescriptors(), validToken.getLockDescriptors()); Assert.assertTrue(server.unlock(validToken)); return null; }); barrier.await(); Thread.sleep(50); HeldLocksToken token2 = server.lockWithFullLockResponse(client, request2).getToken(); Assert.assertNotNull(token2); Assert.assertEquals(client, token2.getClient()); Assert.assertEquals(request2.getLockDescriptors(), token2.getLockDescriptors()); Assert.assertTrue(server.unlock(token1)); future.get(); Assert.assertTrue(server.unlock(token2)); Assert.assertTrue(server.getTokens(client).isEmpty()); }
server.unlock(token2); server.unlock(token3); Assert.assertNotNull(validToken); Assert.assertEquals(client2, validToken.getClient()); server.unlock(validToken); Assert.assertNotNull(validToken1); Assert.assertEquals(LockClient.ANONYMOUS, validToken1.getClient()); server.unlock(validToken1); server.unlock(validToken); future.get(); Assert.assertTrue(server.getTokens(client).isEmpty());
/** Tests that RemoteLockService api (that internal forwards to LockService api) passes a sanity check. */ @Test public void testRemoteLockServiceApi() throws InterruptedException { LockRequest request = LockRequest.builder(ImmutableSortedMap.of( lock1, LockMode.READ, lock2, LockMode.WRITE)) .withLockedInVersionId(10).doNotBlock().build(); Assert.assertNull(server.getMinLockedInVersionId(LockClient.ANONYMOUS.getClientId())); LockRefreshToken token = server.lock(LockClient.ANONYMOUS.getClientId(), request); Assert.assertEquals(10, (long) server.getMinLockedInVersionId(LockClient.ANONYMOUS.getClientId())); Assert.assertNull(server.lock(LockClient.ANONYMOUS.getClientId(), request)); server.unlock(token); Assert.assertNull(server.getMinLockedInVersionId(LockClient.ANONYMOUS.getClientId())); HeldLocksToken heldToken = server.lockAndGetHeldLocks(LockClient.ANONYMOUS.getClientId(), request); Assert.assertEquals(10, (long) server.getMinLockedInVersionId(LockClient.ANONYMOUS.getClientId())); Assert.assertNull(server.lockAndGetHeldLocks(LockClient.ANONYMOUS.getClientId(), request)); server.unlock(heldToken.getLockRefreshToken()); }
.doNotBlock().build()).getToken(); Assert.assertNotNull(anonymousReadToken); server.unlock(anonymousReadToken); Assert.assertEquals(5, server.getMinLockedInVersionId(client).longValue()); server.unlock(token2); Assert.assertEquals(ImmutableSet.of(token1, token3), server.getTokens(client)); Assert.assertEquals(10, server.getMinLockedInVersionId(client).longValue()); server.unlock(token1); Assert.assertEquals(ImmutableSet.of(token3), server.refreshTokens(ImmutableSet.of(token1, token2, token3))); Assert.assertNull(server.getMinLockedInVersionId(client)); server.unlock(token3); Assert.assertTrue(server.getTokens(client).isEmpty()); Assert.assertNull(server.getMinLockedInVersionId(client));
Assert.assertEquals(client, token.getClient()); Assert.assertEquals(request.getLockDescriptors(), token.getLockDescriptors()); server.unlock(token); Assert.assertTrue(server.getTokens(client).isEmpty());
private void runAndVerifyCli(Verifier verifier) throws Exception { try (SingleBackendCliTestRunner runner = makeRunner(cliArgs.toArray(new String[0]))) { TestAtlasDbServices services = runner.connect(moduleFactory); LockService lockService = services.getLockService(); TimestampService tss = services.getTimestampService(); LockClient client = services.getTestLockClient(); Clock clock = GlobalClock.create(lockService); long prePunch = clock.getTimeMillis(); punch(services, tss, clock); long postPunch = clock.getTimeMillis(); long immutableTs = tss.getFreshTimestamp(); LockRequest request = LockRequest.builder(ImmutableSortedMap.of(lock, LockMode.WRITE)) .withLockedInVersionId(immutableTs) .doNotBlock() .build(); LockRefreshToken token = lockService.lock(client.getClientId(), request); long lastFreshTs = tss.getFreshTimestamps(1000).getUpperBound(); verifier.verify(runner, tss, immutableTs, prePunch, postPunch, lastFreshTs, true); lockService.unlock(token); lastFreshTs = tss.getFreshTimestamps(1000).getUpperBound(); // there are no locks so we now expect immutable to just be a fresh runner.freshCommand(); verifier.verify(runner, tss, immutableTs, prePunch, postPunch, lastFreshTs, false); } }