/**
  * update a reader: if !original, this is a reader that is being introduced by this transaction;
  * otherwise it must be in the originals() set, i.e. a reader guarded by this transaction
  */
 public void update(SSTableReader reader, boolean original) {
   assert !staged.update.contains(reader)
       : "each reader may only be updated once per checkpoint: " + reader;
   assert !identities.contains(reader.instanceId)
       : "each reader instance may only be provided as an update once: " + reader;
   // check it isn't obsolete, and that it matches the original flag
   assert !(logged.obsolete.contains(reader) || staged.obsolete.contains(reader))
       : "may not update a reader that has been obsoleted";
   assert original == originals.contains(reader)
       : String.format(
           "the 'original' indicator was incorrect (%s provided): %s", original, reader);
   staged.update.add(reader);
   identities.add(reader.instanceId);
   if (!isOffline()) reader.setupKeyCache();
 }
 /**
  * mark this reader as for obsoletion. this does not actually obsolete the reader until commit()
  * is called, but on checkpoint() the reader will be removed from the live set
  */
 public void obsolete(SSTableReader reader) {
   logger.debug("Staging for obsolescence {}", reader);
   // check this is: a reader guarded by the transaction, an instance we have already worked with
   // and that we haven't already obsoleted it, nor do we have other changes staged for it
   assert identities.contains(reader.instanceId)
       : "only reader instances that have previously been provided may be obsoleted: " + reader;
   assert originals.contains(reader)
       : "only readers in the 'original' set may be obsoleted: " + reader + " vs " + originals;
   assert !(logged.obsolete.contains(reader) || staged.obsolete.contains(reader))
       : "may not obsolete a reader that has already been obsoleted: " + reader;
   assert !staged.update.contains(reader)
       : "may not obsolete a reader that has a staged update (must checkpoint first): " + reader;
   assert current(reader) == reader
       : "may only obsolete the latest version of the reader: " + reader;
   staged.obsolete.add(reader);
 }
 /**
  * return the current version of the provided reader, whether or not it is visible or staged; i.e.
  * returns the first version present by testing staged, logged and originals in order.
  */
 public SSTableReader current(SSTableReader reader) {
   Set<SSTableReader> container;
   if (staged.contains(reader))
     container = staged.update.contains(reader) ? staged.update : staged.obsolete;
   else if (logged.contains(reader))
     container = logged.update.contains(reader) ? logged.update : logged.obsolete;
   else if (originals.contains(reader)) container = originals;
   else throw new AssertionError();
   return select(reader, container);
 }
 /** remove the reader from the set we're modifying */
 public void cancel(SSTableReader cancel) {
   logger.debug("Cancelling {} from transaction", cancel);
   assert originals.contains(cancel)
       : "may only cancel a reader in the 'original' set: " + cancel + " vs " + originals;
   assert !(staged.contains(cancel) || logged.contains(cancel))
       : "may only cancel a reader that has not been updated or obsoleted in this transaction: "
           + cancel;
   originals.remove(cancel);
   marked.remove(cancel);
   maybeFail(unmarkCompacting(singleton(cancel), null));
 }
  /**
   * remove the provided readers from this Transaction, and return a new Transaction to manage them
   * only permitted to be called if the current Transaction has never been used
   */
  public LifecycleTransaction split(Collection<SSTableReader> readers) {
    logger.debug("Splitting {} into new transaction", readers);
    checkUnused();
    for (SSTableReader reader : readers)
      assert identities.contains(reader.instanceId)
          : "may only split the same reader instance the transaction was opened with: " + reader;

    for (SSTableReader reader : readers) {
      identities.remove(reader.instanceId);
      originals.remove(reader);
      marked.remove(reader);
    }
    return new LifecycleTransaction(tracker, operationType, readers);
  }
 @VisibleForTesting
 public ReaderState state(SSTableReader reader) {
   SSTableReader currentlyVisible =
       ReaderState.visible(reader, in(logged.obsolete), logged.update, originals);
   SSTableReader nextVisible =
       ReaderState.visible(
           reader,
           orIn(staged.obsolete, logged.obsolete),
           staged.update,
           logged.update,
           originals);
   return new ReaderState(
       ReaderState.Action.get(logged.update.contains(reader), logged.obsolete.contains(reader)),
       ReaderState.Action.get(staged.update.contains(reader), staged.obsolete.contains(reader)),
       currentlyVisible,
       nextVisible,
       originals.contains(reader));
 }
 boolean contains(SSTableReader reader) {
   return update.contains(reader) || obsolete.contains(reader);
 }