Interface KVStore

All Known Subinterfaces:
AtomicKVStore, CloseableKVStore, DeltaKVStore, KVTransaction
All Known Implementing Classes:
AbstractKVStore, ArrayKVStore, ArrayKVTransaction, AtomicArrayKVStore, AtomicKVDatabase, BerkeleyKVTransaction, BranchedKVTransaction, ByteArrayLMDBKVStore, ByteArrayLMDBKVTransaction, CachingKVStore, CachingKVTransaction, CloseableForwardingKVStore, FallbackKVTransaction, ForwardingKVStore, FoundationKVStore, FoundationKVTransaction, LevelDBAtomicKVStore, LevelDBKVStore, LevelDBKVTransaction, LMDBKVStore, LMDBKVTransaction, MemoryAtomicKVStore, MemoryKVStore, MutableView, MVMapKVStore, MVMapSnapshot, MVStoreAtomicKVStore, MVStoreKVTransaction, PrefixKVStore, PrefixKVTransaction, RaftKVTransaction, ReadOnlySpannerView, ReadWriteSpannerView, SimpleKVTransaction, SnapshotKVTransaction, SnapshotLevelDBKVStore, SpannerKVTransaction, SQLKVTransaction, UnmodifiableKVStore, XMLKVTransaction, XodusKVStore, XodusKVTransaction

public interface KVStore
General API into a key/value store where the keys are sorted lexicographically as unsigned bytes.

Implementations are not required to support accessing keys that start with 0xff, and if not may throw IllegalArgumentException if such keys are accessed.

Thread Safety

Instances must be thread safe, in the sense that multi-threaded operations never lead to a behavior that is inconsisitent with some consistent total ordering of those operations. So for example if thread A invokes removeRange() while thread B does a put to some key in the range, then afterwards either the range is empty or it contains only the key, but in any case no other outcome is possible.

With respect to thread safety, the set of possible "operations" includes accessing the CloseableIterator returned by getRange(); see getRange() for details.

Lock-free Counters

Implementations are encouraged to include support for encoding a 64 bit counter in a key/value pair such that the counter can be efficiently adjusted by concurrent transactions without conflict. In practice this means no locking is required to increment or decrement the counter by some amount, as long as it's not necessary to actually directly read or write the counter value in the same transaction. Whether counter adjustments are actually lock-free is implementation dependent, however, the counter methods encodeCounter(), decodeCounter(), and adjustCounter() must function correctly as specified in all cases.

How counters are encoded is specific to the implementation. Clients needing to read or write counter values directly should use decodeCounter() and encodeCounter(), respectively. Counters are removed using the normal methods (i.e., remove() and removeRange()).

  • Method Summary

    Modifier and Type
    Method
    Description
    void
    adjustCounter(byte[] key, long amount)
    Adjust the counter at the given key by the given amount.
    default void
    apply(Mutations mutations)
    Apply all the given Mutations to this instance.
    long
    decodeCounter(byte[] value)
    Decode a counter value previously encoded by encodeCounter().
    byte[]
    encodeCounter(long value)
    Encode a counter value into a byte[] value suitable for use with decodeCounter() and/or adjustCounter().
    byte[]
    get(byte[] key)
    Get the value associated with the given key, if any.
    getAtLeast(byte[] minKey, byte[] maxKey)
    Get the key/value pair having the smallest key greater than or equal to the given minimum, if any.
    getAtMost(byte[] maxKey, byte[] minKey)
    Get the key/value pair having the largest key strictly less than the given maximum, if any.
    getRange(byte[] minKey, byte[] maxKey)
    Iterate the key/value pairs in the specified range in the forward direction.
    getRange(byte[] minKey, byte[] maxKey, boolean reverse)
    Iterate the key/value pairs in the specified range.
    Iterate the key/value pairs in the specified range in the forward direction.
    void
    put(byte[] key, byte[] value)
    Set the value associated with the given key.
    void
    remove(byte[] key)
    Remove the key/value pair with the given key, if it exists.
    void
    removeRange(byte[] minKey, byte[] maxKey)
    Remove all key/value pairs whose keys are in a given range.
    default void
    Remove all key/value pairs whose keys are in a given range.
  • Method Details

    • get

      byte[] get(byte[] key)
      Get the value associated with the given key, if any.

      Modifications to the returned byte[] array do not affect this instance.

      Parameters:
      key - key
      Returns:
      value associated with key, or null if not found
      Throws:
      IllegalArgumentException - if key starts with 0xff and such keys are not supported
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
      NullPointerException - if key is null
    • getAtLeast

      KVPair getAtLeast(byte[] minKey, byte[] maxKey)
      Get the key/value pair having the smallest key greater than or equal to the given minimum, if any.

      An optional (exclusive) maximum key may also be specified; if maxKey is null, there is no upper bound; if maxKey <= minKey, null is always returned.

      If keys starting with 0xff are not supported by this instance, and minKey starts with 0xff, then this method returns null.

      Modifications to the returned byte[] arrays do not affect this instance.

      Parameters:
      minKey - minimum key (inclusive), or null for no minimum (get the smallest key)
      maxKey - maximum key (exclusive), or null for no maximum (no upper bound)
      Returns:
      smallest key/value pair with key >= minKey and key < maxKey, or null if none exists
      Throws:
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
    • getAtMost

      KVPair getAtMost(byte[] maxKey, byte[] minKey)
      Get the key/value pair having the largest key strictly less than the given maximum, if any.

      An optional (inclusive) minimum key may also be specified; if minKey is null, there is no lower bound (equivalent to a lower bound of the empty byte array); if minKey >= maxKey, null is always returned.

      If keys starting with 0xff are not supported by this instance, and maxKey starts with 0xff, then this method behaves as if maxKey were null.

      Modifications to the returned byte[] arrays do not affect this instance.

      Parameters:
      maxKey - maximum key (exclusive), or null for no maximum (get the largest key)
      minKey - minimum key (inclusive), or null for no minimum (no lower bound)
      Returns:
      largest key/value pair with key < maxKey and key >= minKey, or null if none exists
      Throws:
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
    • getRange

      CloseableIterator<KVPair> getRange(byte[] minKey, byte[] maxKey, boolean reverse)
      Iterate the key/value pairs in the specified range. The returned CloseableIterator's remove() method must be supported and should have the same effect as invoking remove() on the corresponding key.

      If keys starting with 0xff are not supported by this instance, and minKey starts with 0xff, then this method returns an empty iteration.

      If keys starting with 0xff are not supported by this instance, and maxKey starts with 0xff, then this method behaves as if maxKey were null.

      The returned CloseableIterator is weakly consistent (see java.util.concurrent). In short, the returned CloseableIterator must not throw ConcurrentModificationException; however, whether or not a "live" CloseableIterator reflects any modifications made after its creation is implementation dependent. Implementations that do make post-creation updates visible in the CloseableIterator, even if the update occurs after some delay, must preserve the order in which the modifications actually occurred.

      The returned CloseableIterator itself is not guaranteed to be thread safe; is should only be used in the thread that created it.

      Invokers of this method are encouraged to close() the returned iterators, though this is not required for correct behavior.

      Modifications to the returned KVPair key and value byte[] arrays do not affect this instance.

      Parameters:
      minKey - minimum key (inclusive), or null for no minimum (start at the smallest key)
      maxKey - maximum key (exclusive), or null for no maximum (end at the largest key)
      reverse - true to return key/value pairs in reverse order (i.e., keys descending)
      Returns:
      iteration of key/value pairs in the range minKey (inclusive) to maxKey (exclusive)
      Throws:
      IllegalArgumentException - if minKey > maxKey
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
    • getRange

      default CloseableIterator<KVPair> getRange(byte[] minKey, byte[] maxKey)
      Iterate the key/value pairs in the specified range in the forward direction.

      This is a convenience method, equivalent to: getRange(minKey, maxKey, false).

      Parameters:
      minKey - minimum key (inclusive), or null for no minimum (start at the smallest key)
      maxKey - maximum key (exclusive), or null for no maximum (end at the largest key)
      Returns:
      iteration of key/value pairs in the range minKey (inclusive) to maxKey (exclusive)
      Throws:
      IllegalArgumentException - if minKey > maxKey
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
    • getRange

      default CloseableIterator<KVPair> getRange(KeyRange range)
      Iterate the key/value pairs in the specified range in the forward direction.

      This is a convenience method, equivalent to: getRange(range.getMin(), range.getMax(), false).

      Parameters:
      range - range of keys to iterate
      Returns:
      iteration of key/value pairs in range
      Throws:
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
      IllegalArgumentException - if range is null
    • put

      void put(byte[] key, byte[] value)
      Set the value associated with the given key.
      Parameters:
      key - key
      value - value
      Throws:
      IllegalArgumentException - if key starts with 0xff and such keys are not supported
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
      NullPointerException - if key or value is null
    • remove

      void remove(byte[] key)
      Remove the key/value pair with the given key, if it exists.
      Parameters:
      key - key
      Throws:
      IllegalArgumentException - if key starts with 0xff and such keys are not supported
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
      NullPointerException - if key is null
    • removeRange

      void removeRange(byte[] minKey, byte[] maxKey)
      Remove all key/value pairs whose keys are in a given range.

      The minKey must be less than or equal to maxKey; if they equal (and not null) then nothing happens; if they are both null then all entries are deleted.

      If keys starting with 0xff are not supported by this instance, then:

      • If minKey starts with 0xff, then no change occurs
      • If maxKey starts with 0xff, then this method behaves as if maxKey were null
      Parameters:
      minKey - minimum key (inclusive), or null for no minimum
      maxKey - maximum key (exclusive), or null for no maximum
      Throws:
      IllegalArgumentException - if minKey > maxKey
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
    • removeRange

      default void removeRange(KeyRange range)
      Remove all key/value pairs whose keys are in a given range.

      Equivalent to: removeRange(range.getMin(), range.getMax()).

      Parameters:
      range - range to remove
      Throws:
      IllegalArgumentException - if range is null
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
    • encodeCounter

      byte[] encodeCounter(long value)
      Encode a counter value into a byte[] value suitable for use with decodeCounter() and/or adjustCounter().
      Parameters:
      value - desired counter value
      Returns:
      encoded counter value
      Throws:
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
    • decodeCounter

      long decodeCounter(byte[] value)
      Decode a counter value previously encoded by encodeCounter().
      Parameters:
      value - encoded counter value
      Returns:
      decoded counter value
      Throws:
      IllegalArgumentException - if value is not a valid counter value
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
      NullPointerException - if value is null
    • adjustCounter

      void adjustCounter(byte[] key, long amount)
      Adjust the counter at the given key by the given amount.

      Ideally this operation should behave in a lock-free manner, so that concurrent transactions can invoke it without conflict. However, when lock-free behavior occurs (if at all) depends on the implementation.

      If there is no value associated with key, or key's value is not a valid counter encoding as would be acceptable to decodeCounter(), then how this operation affects key's value is undefined.

      Parameters:
      key - key
      amount - amount to adjust counter value by
      Throws:
      StaleTransactionException - if an underlying transaction is no longer usable
      RetryTransactionException - if an underlying transaction must be retried and is no longer usable
      NullPointerException - if key is null
    • apply

      default void apply(Mutations mutations)
      Apply all the given Mutations to this instance.

      Mutations are always to be applied in this order: removes, puts, counter adjustments.

      The implementation in KVStore simply iterates over the individual changes and applies them via remove() (for removals of a single key), removeRange(), put(), and/or adjustCounter(). Implementations that can process batch updates more efficiently are encouraged to override this method.

      Unlike AtomicKVStore.apply(), this method is not required to apply the mutations atomically.

      Parameters:
      mutations - mutations to apply
      Throws:
      IllegalArgumentException - if mutations is null
      UnsupportedOperationException - if this instance is immutable