Class AtomicKVDatabase

java.lang.Object
io.permazen.kv.AbstractKVStore
io.permazen.kv.mvcc.AtomicKVDatabase
All Implemented Interfaces:
KVStore, AtomicKVStore

public class AtomicKVDatabase extends AbstractKVStore implements AtomicKVStore
Wrapper class that presents an AtomicKVStore view of a KVDatabase, using individual transactions for each operation.

Warning: this class is only appropriate for use with KVDatabases that implement some form of MVCC; KVDatabases that use locking will likely generate conflicts if readOnlySnapshot() is used concurrently with other methods.

See Also:
  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    protected final KVDatabase
     
  • Constructor Summary

    Constructors
    Constructor
    Description
    Constructor.
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    adjustCounter(byte[] key, long amount)
    Adjust the counter at the given key by the given amount.
    void
    apply(Mutations mutations, boolean sync)
    Apply a set of mutations to this instance atomically.
    long
    decodeCounter(byte[] bytes)
    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, boolean reverse)
    Iterate the key/value pairs in the specified range.
    void
    put(byte[] key, byte[] value)
    Set the value associated with the given key.
    Create a read-only "snapshot" view of this instance equal to its current state.
    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.
    void
    Start this instance.
    void
    Stop this instance.
     

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait

    Methods inherited from interface io.permazen.kv.mvcc.AtomicKVStore

    apply

    Methods inherited from interface io.permazen.kv.KVStore

    getRange, getRange, removeRange
  • Field Details

  • Constructor Details

  • Method Details

    • get

      public byte[] get(byte[] key)
      Description copied from interface: KVStore
      Get the value associated with the given key, if any.

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

      Specified by:
      get in interface KVStore
      Overrides:
      get in class AbstractKVStore
      Parameters:
      key - key
      Returns:
      value associated with key, or null if not found
    • getAtLeast

      public KVPair getAtLeast(byte[] minKey, byte[] maxKey)
      Description copied from interface: KVStore
      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.

      Specified by:
      getAtLeast in interface KVStore
      Overrides:
      getAtLeast in class AbstractKVStore
      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
    • getAtMost

      public KVPair getAtMost(byte[] maxKey, byte[] minKey)
      Description copied from interface: KVStore
      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.

      Specified by:
      getAtMost in interface KVStore
      Overrides:
      getAtMost in class AbstractKVStore
      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
    • getRange

      public KVPairIterator getRange(byte[] minKey, byte[] maxKey, boolean reverse)
      Description copied from interface: KVStore
      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.

      Specified by:
      getRange in interface KVStore
      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)
    • put

      public void put(byte[] key, byte[] value)
      Description copied from interface: KVStore
      Set the value associated with the given key.
      Specified by:
      put in interface KVStore
      Overrides:
      put in class AbstractKVStore
      Parameters:
      key - key
      value - value
    • remove

      public void remove(byte[] key)
      Description copied from interface: KVStore
      Remove the key/value pair with the given key, if it exists.
      Specified by:
      remove in interface KVStore
      Overrides:
      remove in class AbstractKVStore
      Parameters:
      key - key
    • removeRange

      public void removeRange(byte[] minKey, byte[] maxKey)
      Description copied from interface: KVStore
      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
      Specified by:
      removeRange in interface KVStore
      Overrides:
      removeRange in class AbstractKVStore
      Parameters:
      minKey - minimum key (inclusive), or null for no minimum
      maxKey - maximum key (exclusive), or null for no maximum
    • adjustCounter

      public void adjustCounter(byte[] key, long amount)
      Description copied from interface: KVStore
      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.

      Specified by:
      adjustCounter in interface KVStore
      Overrides:
      adjustCounter in class AbstractKVStore
      Parameters:
      key - key
      amount - amount to adjust counter value by
    • encodeCounter

      public byte[] encodeCounter(long value)
      Description copied from interface: KVStore
      Encode a counter value into a byte[] value suitable for use with decodeCounter() and/or adjustCounter().
      Specified by:
      encodeCounter in interface KVStore
      Overrides:
      encodeCounter in class AbstractKVStore
      Parameters:
      value - desired counter value
      Returns:
      encoded counter value
    • decodeCounter

      public long decodeCounter(byte[] bytes)
      Description copied from interface: KVStore
      Decode a counter value previously encoded by encodeCounter().
      Specified by:
      decodeCounter in interface KVStore
      Overrides:
      decodeCounter in class AbstractKVStore
      Parameters:
      bytes - encoded counter value
      Returns:
      decoded counter value
    • start

      @PostConstruct public void start()
      Description copied from interface: AtomicKVStore
      Start this instance. This method must be called prior to creating any transactions.

      This method is idempotent: if this instance is already started, nothing happens.

      Whether an instance that has been started and stopped can be restarted is implementation-dependent.

      Specified by:
      start in interface AtomicKVStore
    • stop

      @PreDestroy public void stop()
      Description copied from interface: AtomicKVStore
      Stop this instance.

      Any open AtomicKVStore.readOnlySnapshot()'s should be close()'d before invoking this method; the behavior of those that are not is undefined.

      This method is idempotent: if this instance has not been started, or is already stopped, nothing happens.

      Specified by:
      stop in interface AtomicKVStore
    • readOnlySnapshot

      public CloseableKVStore readOnlySnapshot()
      Description copied from interface: AtomicKVStore
      Create a read-only "snapshot" view of this instance equal to its current state.

      The returned CloseableKVStore should be treated as read-only. It may not actually be read-only, but if it's not, then any changes should have no effect on this instance. The returned CloseableKVStore must be completely independent from this instance (subsequent changes to either one do not affect the other).

      The returned CloseableKVStore should be promply close()'d when no longer needed to release any underlying resources.

      Specified by:
      readOnlySnapshot in interface AtomicKVStore
      Returns:
      read-only, snapshot view of this instance
    • apply

      public void apply(Mutations mutations, boolean sync)
      Description copied from interface: AtomicKVStore
      Apply a set of mutations to this instance atomically.

      If this method returns normally, all of the given mutations will have been applied. If this method returns abnormally, then none of the given mutations will have been applied.

      In any case, other threads observing this instance will never see a partial application of the given mutations.

      This method is required to apply the mutations in this order: removes, puts, adjusts.

      If sync is true, the implementation must durably persist the changes before returning.

      Specified by:
      apply in interface AtomicKVStore
      Parameters:
      mutations - the mutations to apply
      sync - if true, caller requires that the changes be durably persisted
    • toString

      public String toString()
      Overrides:
      toString in class Object