Interface DeltaKVStore

All Superinterfaces:
KVStore
All Known Implementing Classes:
MutableView, ReadWriteSpannerView

public interface DeltaKVStore extends KVStore
Presents a mutable view of an underlying read-only KVStore and records the mutations in memory.

Instances intercept all operations to the underlying KVStore, recording mutations in a Writes instance instead of applying them to the KVStore. Instances provide a view of the mutated KVStore based those mutations which is always up-to-date, i.e., mutations that overwrite previous mutations are consolidated, etc.

The resulting Writes represent the delta between the underlying KVStore and this KVStore. This delta can be applied later to another KVStore via KVStore.apply().

Reads are passed through to the underlying KVStore except where they intersect a previous write.

Instances ensure that counter adjustment mutations are atomic, so they never overlap put or remove mutations.

In all cases, the underlying KVStore is never modified.

Read Tracking

Instances may optionally be configured to track and record all keys read in a Reads object. When reads are being tracked, tracking may be temporarily suspended in the current thread via withoutReadTracking(). Read tracking may also be permanently disabled (and any recorded reads discarded) via disableReadTracking().

Thread Safety

Instances are thread safe and always present an up-to-date view even in the face of multiple threads making changes, and all operations are atomic. However, directly accessing the associated Reads or Writes is not safe without first locking the DeltaKVStore that owns them.

  • Method Details

    • getBaseKVStore

      KVStore getBaseKVStore()
      Get the KVStore that underlies this instance.

      Note that in some implementations the returned object and/or its contents may change over time, for example, if this instance gets "rebased" on a newer underlying KVStore.

      Returns:
      underlying KVStore
    • getReads

      Reads getReads()
      Get the Reads associated with this instance.

      This includes all keys explicitly or implicitly read by calls to get(), getAtLeast(), getAtMost(), and getRange().

      The returned object is "live" and should only be accessed while synchronized on this instance.

      The read tracking may be imprecise, as long as all actual reads are included. For example, if keys 10001, 100002, and 100003 were read, the returned Reads may contain those three keys, or it may contain the entire range 10001-10003, even though some keys in that range were not actually read in order to save memory. This optimization is acceptable as long as the keys that were actually read are always included.

      Returns:
      reads recorded, or null if this instance is not configured to record reads or read tracking has been permanently disabled via disableReadTracking()
    • getWrites

      Writes getWrites()
      Get the Writes associated with this instance.

      The returned object is "live" and should only be accessed while synchronized on this instance.

      Returns:
      writes recorded
    • isReadOnly

      boolean isReadOnly()
      Determine if this instance is read-only.
      Returns:
      true if this instance is read-only, otherwise false
    • setReadOnly

      void setReadOnly()
      Configure this instance as read-only.

      Any subsequent write attempts will result in an IllegalStateException.

      This operation cannot be un-done.

    • disableReadTracking

      void disableReadTracking()
      Permanently disable read tracking and discard the Reads associated with this instance.

      This can be used to save some memory when read tracking information is no longer needed.

      Does nothing if read tracking is already disabled.

    • withoutReadTracking

      void withoutReadTracking(boolean allowWrites, Runnable action)
      Temporarily disable read tracking in the current thread while performing the given action.

      If allowWrites is false, then any write attempts by action will provoke an IllegalStateException.

      Read tracking is disabled only for the current thread, and it ends when this method returns.

      Parameters:
      allowWrites - whether to allow writes (usually this is a bad idea)
      action - the action to perform
      Throws:
      IllegalArgumentException - if action is null