Github user Randgalt commented on a diff in the pull request:
https://github.com/apache/zookeeper/pull/136#discussion_r140815418
--- Diff: src/java/main/org/apache/zookeeper/server/WatchManager.java ---
@@ -40,50 +40,110 @@
class WatchManager {
private static final Logger LOG =
LoggerFactory.getLogger(WatchManager.class);
- private final HashMap<String, HashSet<Watcher>> watchTable =
- new HashMap<String, HashSet<Watcher>>();
+ enum Type {
+ STANDARD() {
+ @Override
+ boolean isPersistent() {
+ return false;
+ }
+
+ @Override
+ boolean isRecursive() {
+ return false;
+ }
+ },
+ PERSISTENT() {
+ @Override
+ boolean isPersistent() {
+ return true;
+ }
+
+ @Override
+ boolean isRecursive() {
+ return false;
+ }
+ },
+ PERSISTENT_RECURSIVE() {
+ @Override
+ boolean isPersistent() {
+ return true;
+ }
+
+ @Override
+ boolean isRecursive() {
+ return true;
+ }
+ }
+ ;
+
+ abstract boolean isPersistent();
+ abstract boolean isRecursive();
+ }
+
+ private final Map<String, Map<Watcher, Type>> watchTable =
+ new HashMap<>();
+
+ private final Map<Watcher, Set<String>> watch2Paths =
+ new HashMap<>();
- private final HashMap<Watcher, HashSet<String>> watch2Paths =
- new HashMap<Watcher, HashSet<String>>();
+ private int recursiveWatchQty = 0; // guarded by sync
+
+ // visible for testing
+ synchronized int getRecursiveWatchQty() {
+ return recursiveWatchQty;
+ }
synchronized int size(){
int result = 0;
- for(Set<Watcher> watches : watchTable.values()) {
+ for(Map<Watcher, Type> watches : watchTable.values()) {
result += watches.size();
}
return result;
}
- synchronized void addWatch(String path, Watcher watcher) {
- HashSet<Watcher> list = watchTable.get(path);
+ synchronized void addWatch(String path, Watcher watcher,
WatchManager.Type type) {
+ Map<Watcher, Type> list = watchTable.get(path);
if (list == null) {
// don't waste memory if there are few watches on a node
// rehash when the 4th entry is added, doubling size thereafter
// seems like a good compromise
- list = new HashSet<Watcher>(4);
+ list = new HashMap<>(4);
--- End diff --
Good point - this was just cargo-cult coding on my part. However,
internally `HashSet` uses a `HashMap` so the implementation is the same.
---