/**
   * 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());
    }
  }
예제 #2
0
  /**
   * 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);
    }
  }