private static void rollback(Environment env, long startTs, PrimaryRowColumn prc, List<Entry<Key, Value>> value, Map<ByteSequence, Mutation> mutations) { for (Entry<Key, Value> entry : value) { if (isPrimary(prc, entry.getKey())) { continue; } long lockTs = entry.getKey().getTimestamp() & ColumnConstants.TIMESTAMP_MASK; Mutation mut = getMutation(entry.getKey().getRowData(), mutations); Key k = entry.getKey(); mut.put(k.getColumnFamilyData().toArray(), k.getColumnQualifierData().toArray(), k.getColumnVisibilityParsed(), ColumnConstants.DEL_LOCK_PREFIX | startTs, DelLockValue.encode(lockTs, false, true)); } }
Map<Bytes, Map<Column, Bytes>> scan() { long waitTime = SnapshotScanner.INITIAL_WAIT_TIME; long startTime = System.currentTimeMillis(); Map<Bytes, Map<Column, Bytes>> ret = new HashMap<>(); while (true) { List<Entry<Key, Value>> locks = new ArrayList<>(); scan(ret, locks); if (locks.size() > 0) { boolean resolvedAll = LockResolver.resolveLocks(env, startTs, stats, locks, startTime); if (!resolvedAll) { UtilWaitThread.sleep(waitTime); stats.incrementLockWaitTime(waitTime); waitTime = Math.min(SnapshotScanner.MAX_WAIT_TIME, waitTime * 2); } // TODO, could only rescan the row/cols that were locked instead of just the entire row // retain the rows that were locked for future scans HashSet<Bytes> lockedRows = new HashSet<>(); for (Entry<Key, Value> entry : locks) { lockedRows.add(ByteUtil.toBytes(entry.getKey().getRowData())); } unscannedRows.retainAll(lockedRows); continue; } for (Map<Column, Bytes> cols : ret.values()) { stats.incrementEntriesReturned(cols.size()); } return ret; } }
groupLocksByPrimary(locksToRecover); switch (txInfo.status) { case COMMITTED: commitColumns(env, group.getKey(), group.getValue(), txInfo.commitTs, mutations); numResolved += group.getValue().size(); break; case LOCKED: if (rollbackPrimary(env, startTs, group.getKey(), txInfo.lockValue)) { rollback(env, startTs, group.getKey(), group.getValue(), mutations); numResolved += group.getValue().size(); case ROLLED_BACK: rollback(env, startTs, group.getKey(), group.getValue(), mutations); numResolved += group.getValue().size(); break;
private static void commitColumns(Environment env, PrimaryRowColumn prc, List<Entry<Key, Value>> value, long commitTs, Map<ByteSequence, Mutation> mutations) { for (Entry<Key, Value> entry : value) { if (isPrimary(prc, entry.getKey())) { continue; } long lockTs = entry.getKey().getTimestamp() & ColumnConstants.TIMESTAMP_MASK; // TODO may be that a stronger sanity check that could be done here if (commitTs < lockTs) { throw new IllegalStateException("bad commitTs : " + entry.getKey() + " (" + commitTs + "<" + lockTs + ")"); } Mutation mut = getMutation(entry.getKey().getRowData(), mutations); Column col = SpanUtil.toRowColumn(entry.getKey()).getColumn(); LockValue lv = new LockValue(entry.getValue().get()); ColumnUtil.commitColumn(env, lv.isTrigger(), false, col, lv.isWrite(), lv.isDelete(), lockTs, commitTs, env.getObservers().keySet(), mut); } }
boolean resolvedLocks = LockResolver.resolveLocks(env, startTs, stats, locks, startTime);