use of com.palantir.atlasdb.transaction.api.TransactionConflictException.CellConflict in project atlasdb by palantir.
the class SnapshotTransaction method throwIfValueChangedConflict.
/**
* This will throw if we have a value changed conflict. This means that either we changed the
* value and anyone did a write after our start timestamp, or we just touched the value (put the
* same value as before) and a changed value was written after our start time.
*/
private void throwIfValueChangedConflict(TableReference table, Map<Cell, byte[]> writes, Set<CellConflict> spanningWrites, Set<CellConflict> dominatingWrites, LockToken commitLocksToken) {
Map<Cell, CellConflict> cellToConflict = Maps.newHashMap();
Map<Cell, Long> cellToTs = Maps.newHashMap();
for (CellConflict c : Sets.union(spanningWrites, dominatingWrites)) {
cellToConflict.put(c.getCell(), c);
cellToTs.put(c.getCell(), c.getTheirStart() + 1);
}
Map<Cell, byte[]> oldValues = getIgnoringLocalWrites(table, cellToTs.keySet());
Map<Cell, Value> conflictingValues = keyValueService.get(table, cellToTs);
Set<Cell> conflictingCells = Sets.newHashSet();
for (Entry<Cell, Long> cellEntry : cellToTs.entrySet()) {
Cell cell = cellEntry.getKey();
if (!writes.containsKey(cell)) {
Validate.isTrue(false, "Missing write for cell: %s for table %s", cellToConflict.get(cell), table);
}
if (!conflictingValues.containsKey(cell)) {
// This error case could happen if our locks expired.
throwIfPreCommitRequirementsNotMet(commitLocksToken, getStartTimestamp());
Validate.isTrue(false, "Missing conflicting value for cell: %s for table %s", cellToConflict.get(cell), table);
}
if (conflictingValues.get(cell).getTimestamp() != (cellEntry.getValue() - 1)) {
// This error case could happen if our locks expired.
throwIfPreCommitRequirementsNotMet(commitLocksToken, getStartTimestamp());
Validate.isTrue(false, "Wrong timestamp for cell in table %s Expected: %s Actual: %s", table, cellToConflict.get(cell), conflictingValues.get(cell));
}
@Nullable byte[] oldVal = oldValues.get(cell);
byte[] writeVal = writes.get(cell);
byte[] conflictingVal = conflictingValues.get(cell).getContents();
if (!Transactions.cellValuesEqual(oldVal, writeVal) || !Arrays.equals(writeVal, conflictingVal)) {
conflictingCells.add(cell);
} else if (log.isInfoEnabled()) {
log.info("Another transaction committed to the same cell before us but their value was the same." + " Cell: {} Table: {}", UnsafeArg.of("cell", cell), LoggingArgs.tableRef(table));
}
}
if (conflictingCells.isEmpty()) {
return;
}
Predicate<CellConflict> conflicting = Predicates.compose(Predicates.in(conflictingCells), CellConflict.getCellFunction());
getTransactionConflictsMeter().mark();
throw TransactionConflictException.create(table, getStartTimestamp(), Sets.filter(spanningWrites, conflicting), Sets.filter(dominatingWrites, conflicting), System.currentTimeMillis() - timeCreated);
}
Aggregations