/** construct a Transaction for use in an offline operation */
 public static LifecycleTransaction offline(
     OperationType operationType, Iterable<SSTableReader> readers) {
   // if offline, for simplicity we just use a dummy tracker
   Tracker dummy = new Tracker(null, false);
   dummy.addInitialSSTables(readers);
   dummy.apply(updateCompacting(emptySet(), readers));
   return new LifecycleTransaction(dummy, operationType, readers);
 }
 private Throwable unmarkCompacting(Set<SSTableReader> unmark, Throwable accumulate) {
   accumulate = tracker.apply(updateCompacting(unmark, emptySet()), accumulate);
   // when the CFS is invalidated, it will call unreferenceSSTables().  However,
   // unreferenceSSTables only deals
   // with sstables that aren't currently being compacted.  If there are ongoing compactions that
   // finish or are
   // interrupted after the CFS is invalidated, those sstables need to be unreferenced as well, so
   // we do that here.
   accumulate = tracker.dropSSTablesIfInvalid(accumulate);
   return accumulate;
 }
  private Throwable checkpoint(Throwable accumulate) {
    if (logger.isDebugEnabled())
      logger.debug("Checkpointing update:{}, obsolete:{}", staged.update, staged.obsolete);

    if (staged.isEmpty()) return accumulate;

    Set<SSTableReader> toUpdate = toUpdate();
    Set<SSTableReader> fresh = copyOf(fresh());

    // check the current versions of the readers we're replacing haven't somehow been replaced by
    // someone else
    checkNotReplaced(filterIn(toUpdate, staged.update));

    // ensure any new readers are in the compacting set, since we aren't done with them yet
    // and don't want anyone else messing with them
    // apply atomically along with updating the live set of readers
    tracker.apply(
        compose(updateCompacting(emptySet(), fresh), updateLiveSet(toUpdate, staged.update)));

    // log the staged changes and our newly marked readers
    marked.addAll(fresh);
    logged.log(staged);

    // setup our tracker, and mark our prior versions replaced, also releasing our references to
    // them
    // we do not replace/release obsoleted readers, since we may need to restore them on rollback
    accumulate = setReplaced(filterOut(toUpdate, staged.obsolete), accumulate);
    accumulate = release(selfRefs(filterOut(toUpdate, staged.obsolete)), accumulate);

    staged.clear();
    return accumulate;
  }
  /** point of no return: commit all changes, but leave all readers marked as compacting */
  public Throwable doCommit(Throwable accumulate) {
    assert staged.isEmpty() : "must be no actions introduced between prepareToCommit and a commit";

    logger.debug("Committing update:{}, obsolete:{}", staged.update, staged.obsolete);

    // this is now the point of no return; we cannot safely rollback, so we ignore exceptions until
    // we're done
    // we restore state by obsoleting our obsolete files, releasing our references to them, and
    // updating our size
    // and notification status for the obsolete and new files
    accumulate = markObsolete(tracker, logged.obsolete, accumulate);
    accumulate = tracker.updateSizeTracking(logged.obsolete, logged.update, accumulate);
    accumulate = release(selfRefs(logged.obsolete), accumulate);
    accumulate = tracker.notifySSTablesChanged(originals, logged.update, operationType, accumulate);
    return accumulate;
  }
  /** undo all of the changes made by this transaction, resetting the state to its original form */
  public Throwable doAbort(Throwable accumulate) {
    if (logger.isDebugEnabled())
      logger.debug(
          "Aborting transaction over {}, with ({},{}) logged and ({},{}) staged",
          originals,
          logged.update,
          logged.obsolete,
          staged.update,
          staged.obsolete);

    if (logged.isEmpty() && staged.isEmpty()) return accumulate;

    // mark obsolete all readers that are not versions of those present in the original set
    Iterable<SSTableReader> obsolete =
        filterOut(concatUniq(staged.update, logged.update), originals);
    logger.debug("Obsoleting {}", obsolete);
    // we don't pass the tracker in for the obsoletion, since these readers have never been notified
    // externally
    // nor had their size accounting affected
    accumulate = markObsolete(null, obsolete, accumulate);

    // replace all updated readers with a version restored to its original state
    accumulate = tracker.apply(updateLiveSet(logged.update, restoreUpdatedOriginals()), accumulate);
    // setReplaced immediately preceding versions that have not been obsoleted
    accumulate = setReplaced(logged.update, accumulate);
    // we have replaced all of logged.update and never made visible staged.update,
    // and the files we have logged as obsolete we clone fresh versions of, so they are no longer
    // needed either
    // any _staged_ obsoletes should either be in staged.update already, and dealt with there,
    // or is still in its original form (so left as is); in either case no extra action is needed
    accumulate =
        release(selfRefs(concat(staged.update, logged.update, logged.obsolete)), accumulate);
    logged.clear();
    staged.clear();
    return accumulate;
  }
 public boolean isOffline() {
   return tracker.isDummy();
 }