private long getCommitTimestampRollBackIfNecessary( long startTimestamp, Multimap<String, Cell> tableNameToCell) { Long commitTimestamp = transactionService.get(startTimestamp); if (commitTimestamp == null) { // Roll back this transaction (note that rolling back arbitrary transactions // can never cause correctness issues, only liveness issues) try { transactionService.putUnlessExists(startTimestamp, TransactionConstants.FAILED_COMMIT_TS); } catch (KeyAlreadyExistsException e) { String msg = "Could not roll back transaction with start timestamp " + startTimestamp + "; either" + " it was already rolled back (by a different transaction), or it committed successfully" + " before we could roll it back."; log.error( "This isn't a bug but it should be very infrequent. " + msg, new TransactionFailedRetriableException(msg, e)); } commitTimestamp = transactionService.get(startTimestamp); } if (commitTimestamp == null) { throw new RuntimeException( "expected commit timestamp to be non-null for startTs: " + startTimestamp); } if (commitTimestamp == TransactionConstants.FAILED_COMMIT_TS) { for (String table : tableNameToCell.keySet()) { Map<Cell, Long> toDelete = Maps2.createConstantValueMap(tableNameToCell.get(table), startTimestamp); keyValueService.delete(table, Multimaps.forMap(toDelete)); } } return commitTimestamp; }
private long ensureCommitTimestampExists( Long startTs, @Modified Map<Long, Long> startTsToCommitTs) { Long commitTs = startTsToCommitTs.get(startTs); if (commitTs == null) { // Roll back this transaction (note that rolling back arbitrary transactions // can never cause correctness issues, only liveness issues) try { // TODO: carrino: use the batched version of putUnlessExists when it is available. transactionService.putUnlessExists(startTs, TransactionConstants.FAILED_COMMIT_TS); } catch (KeyAlreadyExistsException e) { String msg = "Could not roll back transaction with start timestamp " + startTs + "; either" + " it was already rolled back (by a different transaction), or it committed successfully" + " before we could roll it back."; log.error( "This isn't a bug but it should be very infrequent. " + msg, new TransactionFailedRetriableException(msg, e)); } commitTs = transactionService.get(startTs); Validate.notNull(commitTs); startTsToCommitTs.put(startTs, commitTs); } return commitTs; }
private Multimap<Cell, Long> getCellTsPairsToSweep( Multimap<Cell, Long> cellTsMappings, PeekingIterator<RowResult<Value>> values, long sweepTimestamp, SweepStrategy sweepStrategy, @Output Set<Cell> sentinelsToAdd) { Multimap<Cell, Long> cellTsMappingsToSweep = HashMultimap.create(); Map<Long, Long> startTsToCommitTs = transactionService.get(cellTsMappings.values()); for (Map.Entry<Cell, Collection<Long>> entry : cellTsMappings.asMap().entrySet()) { Cell cell = entry.getKey(); Collection<Long> timestamps = entry.getValue(); boolean sweepLastCommitted = isLatestValueEmpty(cell, values); Iterable<? extends Long> timestampsToSweep = getTimestampsToSweep( cell, timestamps, startTsToCommitTs, sentinelsToAdd, sweepTimestamp, sweepLastCommitted, sweepStrategy); cellTsMappingsToSweep.putAll(entry.getKey(), timestampsToSweep); } return cellTsMappingsToSweep; }