/** * Reverses the operations detailed in the list of deltas on the given wavelet. * * @param wavelet {@link ObservableWaveletData} to apply operations to * @param deltas the {@link WaveletDelta} containing the operations which we should revert on the * given wavelet. * @throws OperationException if the operations can not be rolled back. */ private static void rollback(ObservableWaveletData wavelet, List<TransformedWaveletDelta> deltas) throws OperationException { List<WaveletOperation> inverseOps = Lists.newArrayList(); // Go through everything in reverse order for (int i = deltas.size() - 1; i >= 0; i--) { TransformedWaveletDelta delta = deltas.get(i); // Metadata such as the last modified ts will change due to the rollback // of operations. for (int j = delta.size() - 1; j >= 0; j--) { WaveletOperation op = delta.get(j); WaveletOperation inverseOp = WaveletOperationInverter.invert(op); inverseOps.add(inverseOp); } } long startVersion = wavelet.getVersion(); int opCount = 0; for (WaveletOperation inverseOp : inverseOps) { inverseOp.apply(wavelet); opCount++; } if (wavelet.getVersion() != startVersion - opCount) { throw new OperationException( "Expected end version " + (startVersion - opCount) + " doesn't match the version of the wavelet " + wavelet.getVersion()); } }
/** * Apply a list of operations from a single delta to the wavelet container. * * @param ops to apply */ protected void applyWaveletOperations(List<WaveletOperation> ops) throws OperationException, EmptyDeltaException { if (ops.isEmpty()) { LOG.warning("No operations to apply at version " + currentVersion); throw new EmptyDeltaException(); } WaveletOperation lastOp = null; int opsApplied = 0; try { for (WaveletOperation op : ops) { lastOp = op; op.apply(waveletData); opsApplied++; } } catch (OperationException e) { LOG.warning( "Only applied " + opsApplied + " of " + ops.size() + " operations at version " + currentVersion + ", rolling back, failed op was " + lastOp, e); // Deltas are atomic, so roll back all operations that were successful rollbackWaveletOperations(ops.subList(0, opsApplied)); throw new OperationException("Failed to apply all operations, none were applied", e); } }