@Override public LockImmutableTimestampResponse lockImmutableTimestamp(IdentifiedTimeLockRequest request) { LockImmutableTimestampResponse response = executeOnTimeLock(() -> delegate.lockImmutableTimestamp(request)); lockRefresher.registerLock(response.getLock()); return response; }
@Override public StartIdentifiedAtlasDbTransactionResponse startIdentifiedAtlasDbTransaction( StartIdentifiedAtlasDbTransactionRequest request) { StartIdentifiedAtlasDbTransactionResponse response = executeOnTimeLock( () -> delegate.startIdentifiedAtlasDbTransaction(request)); lockRefresher.registerLock(response.immutableTimestamp().getLock()); return response; }
@Override public StartAtlasDbTransactionResponse startAtlasDbTransaction(IdentifiedTimeLockRequest request) { StartAtlasDbTransactionResponse response = executeOnTimeLock(() -> delegate.startAtlasDbTransaction(request)); lockRefresher.registerLock(response.immutableTimestamp().getLock()); return response; }
@Override public TransactionAndImmutableTsLock setupRunTaskWithConditionThrowOnConflict(PreCommitCondition condition) { StartIdentifiedAtlasDbTransactionResponse transactionResponse = timelockService.startIdentifiedAtlasDbTransaction( StartIdentifiedAtlasDbTransactionRequest.createForRequestor(clientId)); try { LockToken immutableTsLock = transactionResponse.immutableTimestamp().getLock(); long immutableTs = transactionResponse.immutableTimestamp().getImmutableTimestamp(); recordImmutableTimestamp(immutableTs); cleaner.punch(transactionResponse.startTimestampAndPartition().timestamp()); Supplier<Long> startTimestampSupplier = Suppliers.ofInstance( transactionResponse.startTimestampAndPartition().timestamp()); SnapshotTransaction transaction = createTransaction(immutableTs, startTimestampSupplier, immutableTsLock, condition); return TransactionAndImmutableTsLock.of(transaction, immutableTsLock); } catch (Throwable e) { timelockService.tryUnlock(ImmutableSet.of(transactionResponse.immutableTimestamp().getLock())); throw Throwables.rewrapAndThrowUncheckedException(e); } }
@Test public void checkImmutableTsLockOnceIfThoroughlySwept_WithValidationOnReads() { TimelockService timelockService = spy(new LegacyTimelockService(timestampService, lockService, lockClient)); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction transaction = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP, true); transaction.get(TABLE_SWEPT_THOROUGH, ImmutableSet.of(TEST_CELL)); transaction.commit(); timelockService.unlock(ImmutableSet.of(res.getLock())); verify(timelockService).refreshLockLeases(ImmutableSet.of(res.getLock())); }
@Test public void checkImmutableTsLockOnceIfThoroughlySwept_WithoutValidationOnReads() { TimelockService timelockService = spy(new LegacyTimelockService(timestampService, lockService, lockClient)); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction transaction = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP, false); transaction.get(TABLE_SWEPT_THOROUGH, ImmutableSet.of(TEST_CELL)); transaction.commit(); timelockService.unlock(ImmutableSet.of(res.getLock())); verify(timelockService).refreshLockLeases(ImmutableSet.of(res.getLock())); }
SweepStrategyManagers.createDefault(keyValueService), lockImmutableTimestampResponse.getImmutableTimestamp(), Optional.of(lockImmutableTimestampResponse.getLock()), preCommitCondition, AtlasDbConstraintCheckingMode.NO_CONSTRAINT_CHECKING,
@Test public void validateLocksOnReadsIfThoroughlySwept() { TimelockService timelockService = new LegacyTimelockService(timestampService, lockService, lockClient); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction transaction = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP, true); timelockService.unlock(ImmutableSet.of(res.getLock())); assertThatExceptionOfType(TransactionLockTimeoutException.class).isThrownBy(() -> transaction.get(TABLE_SWEPT_THOROUGH, ImmutableSet.of(TEST_CELL))); }
@Test public void validateLocksOnlyOnCommitIfValidationFlagIsFalse() { TimelockService timelockService = new LegacyTimelockService(timestampService, lockService, lockClient); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction transaction = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP, false); timelockService.unlock(ImmutableSet.of(res.getLock())); transaction.get(TABLE_SWEPT_THOROUGH, ImmutableSet.of(TEST_CELL)); assertThatExceptionOfType(TransactionLockTimeoutException.class).isThrownBy(() -> transaction.commit()); }
@Test public void commitDoesNotThrowIfAlreadySuccessfullyCommitted() { final Cell cell = Cell.create(PtBytes.toBytes("row1"), PtBytes.toBytes("column1")); TimestampService timestampServiceSpy = spy(timestampService); TimelockService timelockService = new LegacyTimelockService(timestampServiceSpy, lockService, lockClient); long transactionTs = timelockService.getFreshTimestamp(); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); SnapshotTransaction snapshot = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP); when(timestampServiceSpy.getFreshTimestamp()).thenReturn(10000000L); //forcing to try to commit a transaction that is already committed transactionService.putUnlessExists(transactionTs, timelockService.getFreshTimestamp()); snapshot.put(TABLE, ImmutableMap.of(cell, PtBytes.toBytes("value"))); snapshot.commit(); timelockService.unlock(Collections.singleton(res.getLock())); }
@Test public void commitThrowsIfRolledBackAtCommitTime_expiredLocks() { final Cell cell = Cell.create(PtBytes.toBytes("row1"), PtBytes.toBytes("column1")); TimelockService timelockService = spy(new LegacyTimelockService(timestampService, lockService, lockClient)); // expire the locks when the pre-commit check happens - this is guaranteed to be after we've written the data PreCommitCondition condition = unused -> doReturn(ImmutableSet.of()).when(timelockService).refreshLockLeases(any()); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); long transactionTs = timelockService.getFreshTimestamp(); SnapshotTransaction snapshot = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, condition); //simulate roll back at commit time transactionService.putUnlessExists(snapshot.getTimestamp(), TransactionConstants.FAILED_COMMIT_TS); snapshot.put(TABLE, ImmutableMap.of(cell, PtBytes.toBytes("value"))); assertThatExceptionOfType(TransactionLockTimeoutException.class).isThrownBy(snapshot::commit); timelockService.unlock(ImmutableSet.of(res.getLock())); TransactionOutcomeMetricsAssert.assertThat(transactionOutcomeMetrics) .hasFailedCommits(1) .hasLocksExpired(1); }
@Test public void commitThrowsIfRolledBackAtCommitTime_alreadyAborted() { final Cell cell = Cell.create(PtBytes.toBytes("row1"), PtBytes.toBytes("column1")); TimelockService timelockService = new LegacyTimelockService(timestampService, lockService, lockClient); LockImmutableTimestampResponse res = timelockService.lockImmutableTimestamp(IdentifiedTimeLockRequest.create()); long transactionTs = timelockService.getFreshTimestamp(); SnapshotTransaction snapshot = getSnapshotTransactionWith( timelockService, () -> transactionTs, res, PreCommitConditions.NO_OP); //forcing to try to commit a transaction that is already committed transactionService.putUnlessExists(transactionTs, TransactionConstants.FAILED_COMMIT_TS); snapshot.put(TABLE, ImmutableMap.of(cell, PtBytes.toBytes("value"))); assertThatExceptionOfType(TransactionCommitFailedException.class).isThrownBy(snapshot::commit); timelockService.unlock(Collections.singleton(res.getLock())); }
@Override public LockImmutableTimestampResponse lockImmutableTimestamp(IdentifiedTimeLockRequest request) { LockImmutableTimestampResponse response = executeOnTimeLock(() -> delegate.lockImmutableTimestamp(request)); lockRefresher.registerLock(response.getLock()); return response; }
@Override public StartAtlasDbTransactionResponse startAtlasDbTransaction(IdentifiedTimeLockRequest request) { StartAtlasDbTransactionResponse response = executeOnTimeLock(() -> delegate.startAtlasDbTransaction(request)); lockRefresher.registerLock(response.immutableTimestamp().getLock()); return response; }
@Override public StartIdentifiedAtlasDbTransactionResponse startIdentifiedAtlasDbTransaction( StartIdentifiedAtlasDbTransactionRequest request) { StartIdentifiedAtlasDbTransactionResponse response = executeOnTimeLock( () -> delegate.startIdentifiedAtlasDbTransaction(request)); lockRefresher.registerLock(response.immutableTimestamp().getLock()); return response; }
@Override public TransactionAndImmutableTsLock setupRunTaskWithConditionThrowOnConflict(PreCommitCondition condition) { StartIdentifiedAtlasDbTransactionResponse transactionResponse = timelockService.startIdentifiedAtlasDbTransaction( StartIdentifiedAtlasDbTransactionRequest.createForRequestor(clientId)); try { LockToken immutableTsLock = transactionResponse.immutableTimestamp().getLock(); long immutableTs = transactionResponse.immutableTimestamp().getImmutableTimestamp(); recordImmutableTimestamp(immutableTs); cleaner.punch(transactionResponse.startTimestampAndPartition().timestamp()); Supplier<Long> startTimestampSupplier = Suppliers.ofInstance( transactionResponse.startTimestampAndPartition().timestamp()); SnapshotTransaction transaction = createTransaction(immutableTs, startTimestampSupplier, immutableTsLock, condition); return TransactionAndImmutableTsLock.of(transaction, immutableTsLock); } catch (Throwable e) { timelockService.tryUnlock(ImmutableSet.of(transactionResponse.immutableTimestamp().getLock())); throw Throwables.rewrapAndThrowUncheckedException(e); } }