Class KeyWatchTracker

java.lang.Object
io.permazen.kv.util.KeyWatchTracker
All Implemented Interfaces:
Closeable, AutoCloseable

@ThreadSafe public class KeyWatchTracker extends Object implements Closeable
Utility class used to track key watches.

To limit memory consumption, instances are configured with a maximum maximum number of key watches supported, as well as a maximum lifetime for each key watch. When these limits are exceeded, one or more key watches is evicted and a corresponding spurious notification occurs.

Instances can optionally be configured to only weakly reference the returned ListenableFuture's. This prevents memory leaks if the user of this class is sloppy and fails to cancel() them when no longer needed; however, it can also lead to missed notifications if the user of this class relies on the listener registration functionality provided in the ListenableFuture interface, because with a listener registration, there is no longer any need to directly reference the ListenableFuture, and so it may be reclaimed before firing. Therefore, by default strong references are used. In any case, ListenableFuture notifications are performed on a separate dedicated notification thread to avoid re-entrancy issues.

For space efficiency, this class does not track the original values associated with a key. Therefore, spurious notifications can also occur if a value is changed, and then changed back to its original value.

Instances are thread safe.

See Also:
  • Field Details

    • DEFAULT_CAPACITY

      public static final long DEFAULT_CAPACITY
      Default capacity (10000L).
      See Also:
    • DEFAULT_MAXIMUM_LIFETIME

      public static final long DEFAULT_MAXIMUM_LIFETIME
      Default maximum lifetime in seconds (2592000L).
      See Also:
    • DEFAULT_WEAK_REFERENCE

      public static final boolean DEFAULT_WEAK_REFERENCE
      Default for the weak reference option (false).
      See Also:
  • Constructor Details

    • KeyWatchTracker

      public KeyWatchTracker()
      Default constructor.

      Configures capacity 10000L, lifetime 2592000L seconds, and strong references.

    • KeyWatchTracker

      public KeyWatchTracker(long capacity, long maxLifetime, boolean weakReferences)
      Constructor.
      Parameters:
      capacity - maximum number of key watches allowed
      maxLifetime - maximum lifetime for a key watch in seconds
      weakReferences - true to only weakly reference registered ListenableFutures
      Throws:
      IllegalArgumentException - if capacity or maxLifetime is zero or negative
  • Method Details

    • register

      public ListenableFuture<Void> register(byte[] key)
      Register a new watch.

      If the returned Future is cancel()'ed, the watch is automatically unregistered.

      Parameters:
      key - the key to watch
      Returns:
      a ListenableFuture that returns key when the value associated with key is modified
      Throws:
      IllegalArgumentException - if key is null
    • getNumKeysWatched

      public int getNumKeysWatched()
      Count the number of keys being watched.

      Note that the same key can be watched more than once, so this only counts keys being watched, not total watches.

      Returns:
      number of keys being watched
    • trigger

      public boolean trigger(byte[] key)
      Trigger all watches associated with the given key.
      Parameters:
      key - the key that has been modified
      Returns:
      true if any watches were triggered, otherwise false
      Throws:
      IllegalArgumentException - if key is null
    • trigger

      public boolean trigger(Stream<byte[]> keys)
      Trigger all watches associated with the given keys.
      Parameters:
      keys - keys that have been modified
      Returns:
      true if any watches were triggered, otherwise false
      Throws:
      IllegalArgumentException - if keys is null
    • trigger

      public boolean trigger(KeyRange range)
      Trigger all watches associated with keys in the given range.
      Parameters:
      range - range of keys that have been modified
      Returns:
      true if any watches were triggered, otherwise false
      Throws:
      IllegalArgumentException - if range is null
    • trigger

      public boolean trigger(Mutations mutations)
      Trigger all watches associated with the given mutations.
      Parameters:
      mutations - mutations
      Returns:
      true if any watches were triggered, otherwise false
      Throws:
      IllegalArgumentException - if mutations is null
    • triggerAll

      public boolean triggerAll()
      Trigger all watches.
      Returns:
      true if any watches were triggered, otherwise false
    • failAll

      public void failAll(Exception e)
      Discard all outstanding key watches and fail them with the given exception.
      Parameters:
      e - failing exception
      Throws:
      IllegalArgumentException - if e is null
    • absorb

      public void absorb(KeyWatchTracker that)
      Absorb all of the watches from the given instance into this one. On return, this instance will contain all of the given instance's watches, and the given instance will be empty.
      Parameters:
      that - the instance to absorb into this one
    • close

      public void close()
      Close this instance.

      All outstanding key watches will be canceled as if by failAll().

      Specified by:
      close in interface AutoCloseable
      Specified by:
      close in interface Closeable