WatchManagerOptimized (Apache ZooKeeper - Server 3.7.0 API)
Date: 2021-03-17

org.apache.zookeeper.server.watch

## Class WatchManagerOptimized

- java.lang.Object
- - org.apache.zookeeper.server.watch.WatchManagerOptimized

- All Implemented Interfaces:
    IDeadWatcherListener, IWatchManager

      public class WatchManagerOptimized
      extends Object
      implements IWatchManager, IDeadWatcherListener

  Optimized in memory and time complexity, compared to WatchManager, both the memory consumption and time complexity improved a lot, but it cannot efficiently remove the watcher when the session or socket is closed, for majority use case this is not a problem. Changed made compared to WatchManager: - Use HashSet and BitSet to store the watchers to find a balance between memory usage and time complexity - Use ReadWriteLock instead of synchronized to reduce lock retention - Lazily clean up the closed watchers

- - ### Constructor Summary

    Constructors
    Constructor and Description
    `WatchManagerOptimized()`

  - ### Method Summary

    All Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `boolean` | `addWatch(String path, Watcher watcher)` Add watch to specific path.
    `boolean` | `containsWatcher(String path, Watcher watcher)` Used in the OpCode.checkWatches, which is a read operation, since read and write requests are exclusively processed, we don't need to hold lock here.
    `void` | `dumpWatches(PrintWriter pwriter, boolean byPath)` String representation of watches.
    `Map<Watcher,Set<String>>` | `getWatcher2PathesMap()` May cause OOM if there are lots of watches, might better to forbid it in this class.
    `WatchesReport` | `getWatches()` Returns a watch report.
    `WatchesPathReport` | `getWatchesByPath()` Iterate through ConcurrentHashMap is 'safe', it will reflect the state of the map at the time iteration began, may miss update while iterating, given this is used in the commands to get a general idea of the watches state, we don't care about missing some update.
    `WatchesSummary` | `getWatchesSummary()` Returns a watch summary.
    `void` | `processDeadWatchers(Set<Integer> deadWatchers)` Entry for WatcherCleaner to remove dead watchers
    `boolean` | `removeWatcher(String path, Watcher watcher)` Removes the specified watcher for the given path.
    `void` | `removeWatcher(Watcher watcher)` The entry to remove the watcher when the cnxn is closed.
    `void` | `shutdown()` Clean up the watch manager.
    `int` | `size()` Get the size of watchers.
    `String` | `toString()`
    `WatcherOrBitSet` | `triggerWatch(String path, Watcher.Event.EventType type)` Distribute the watch event for the given path.
    `WatcherOrBitSet` | `triggerWatch(String path, Watcher.Event.EventType type, WatcherOrBitSet suppress)` Distribute the watch event for the given path, but ignore those suppressed ones.

    - ### Methods inherited from class java.lang.Object

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

    - ### Methods inherited from interface org.apache.zookeeper.server.watch.IWatchManager

      `addWatch, getRecursiveWatchQty`

- - ### Constructor Detail

    - #### WatchManagerOptimized

          public WatchManagerOptimized()

  - ### Method Detail

    - #### addWatch

          public boolean addWatch(String path,
                                  Watcher watcher)

      Description copied from interface: `IWatchManager`
      Add watch to specific path.
      Specified by:
        `addWatch` in interface `IWatchManager`
      Parameters:
        `path` - znode path
        `watcher` - watcher object reference
      Returns:
        true if the watcher added is not already present

    - #### containsWatcher

          public boolean containsWatcher(String path,
                                         Watcher watcher)

      Used in the OpCode.checkWatches, which is a read operation, since read and write requests are exclusively processed, we don't need to hold lock here. Different from addWatch this method doesn't mutate any state, so we don't need to hold read lock to avoid dead watcher (cnxn closed) being added to the watcher manager. It's possible that before we lazily clean up the dead watcher, this will return true, but since the cnxn is closed, the response will dropped as well, so it doesn't matter.
      Specified by:
        `containsWatcher` in interface `IWatchManager`
      Parameters:
        `path` - znode path
        `watcher` - watcher object reference
      Returns:
        true if the watcher exists, false otherwise

    - #### removeWatcher

          public boolean removeWatcher(String path,
                                       Watcher watcher)

      Description copied from interface: `IWatchManager`
      Removes the specified watcher for the given path.
      Specified by:
        `removeWatcher` in interface `IWatchManager`
      Parameters:
        `path` - znode path
        `watcher` - watcher object reference
      Returns:
        true if the watcher successfully removed, false otherwise

    - #### removeWatcher

          public void removeWatcher(Watcher watcher)

      Description copied from interface: `IWatchManager`
      The entry to remove the watcher when the cnxn is closed.
      Specified by:
        `removeWatcher` in interface `IWatchManager`
      Parameters:
        `watcher` - watcher object reference

    - #### processDeadWatchers

          public void processDeadWatchers(Set<Integer> deadWatchers)

      Entry for WatcherCleaner to remove dead watchers
      Specified by:
        `processDeadWatchers` in interface `IDeadWatcherListener`
      Parameters:
        `deadWatchers` - the watchers need to be removed

    - #### triggerWatch

          public WatcherOrBitSet triggerWatch(String path,
                                              Watcher.Event.EventType type)

      Description copied from interface: `IWatchManager`
      Distribute the watch event for the given path.
      Specified by:
        `triggerWatch` in interface `IWatchManager`
      Parameters:
        `path` - znode path
        `type` - the watch event type
      Returns:
        the watchers have been notified

    - #### triggerWatch

          public WatcherOrBitSet triggerWatch(String path,
                                              Watcher.Event.EventType type,
                                              WatcherOrBitSet suppress)

      Description copied from interface: `IWatchManager`
      Distribute the watch event for the given path, but ignore those suppressed ones.
      Specified by:
        `triggerWatch` in interface `IWatchManager`
      Parameters:
        `path` - znode path
        `type` - the watch event type
        `suppress` - the suppressed watcher set
      Returns:
        the watchers have been notified

    - #### size

          public int size()

      Description copied from interface: `IWatchManager`
      Get the size of watchers.
      Specified by:
        `size` in interface `IWatchManager`
      Returns:
        the watchers number managed in this class.

    - #### shutdown

          public void shutdown()

      Description copied from interface: `IWatchManager`
      Clean up the watch manager.
      Specified by:
        `shutdown` in interface `IWatchManager`

    - #### getWatchesSummary

          public WatchesSummary getWatchesSummary()

      Description copied from interface: `IWatchManager`
      Returns a watch summary.
      Specified by:
        `getWatchesSummary` in interface `IWatchManager`
      Returns:
        watch summary
      See Also:
        `WatchesSummary`

    - #### getWatches

          public WatchesReport getWatches()

      Description copied from interface: `IWatchManager`
      Returns a watch report.
      Specified by:
        `getWatches` in interface `IWatchManager`
      Returns:
        watch report
      See Also:
        `WatchesReport`

    - #### getWatchesByPath

          public WatchesPathReport getWatchesByPath()

      Iterate through ConcurrentHashMap is 'safe', it will reflect the state of the map at the time iteration began, may miss update while iterating, given this is used in the commands to get a general idea of the watches state, we don't care about missing some update.
      Specified by:
        `getWatchesByPath` in interface `IWatchManager`
      Returns:
        watch report
      See Also:
        `WatchesPathReport`

    - #### getWatcher2PathesMap

          public Map<Watcher,Set<String>> getWatcher2PathesMap()

      May cause OOM if there are lots of watches, might better to forbid it in this class.

    - #### dumpWatches

          public void dumpWatches(PrintWriter pwriter,
                                  boolean byPath)

      Description copied from interface: `IWatchManager`
      String representation of watches. Warning, may be large!
      Specified by:
        `dumpWatches` in interface `IWatchManager`
      Parameters:
        `pwriter` - the writer to dump the watches
        `byPath` - iff true output watches by paths, otw output watches by connection

    - #### toString

          public String toString()

      Overrides:
        `toString` in class `Object`

Copyright © 2008–2021 The Apache Software Foundation. All rights reserved.