[Zookeeper学习笔记之8]Zookeeper源代码分析之Zookeeper.ZKWatchManager

[Zookeeper学习笔记之八]Zookeeper源代码分析之Zookeeper.ZKWatchManager

ClientWatchManager接口

//接口的唯一方法materialize用于确定那些Watcher需要被通知
//确定Watcher需要三方面的因素1.事件状态 2.事件类型 3.znode的path
public interface ClientWatchManager {
    /**
     * Return a set of watchers that should be notified of the event. The 
     * manager must not notify the watcher(s), however it will update it's 
     * internal structure as if the watches had triggered. The intent being 
     * that the callee is now responsible for notifying the watchers of the 
     * event, possibly at some later time.
     * 
     * @param state event state
     * @param type event type
     * @param path event path
     * @return may be empty set but must not be null
     */
    public Set<Watcher> materialize(Watcher.Event.KeeperState state,
        Watcher.Event.EventType type, String path);
}

 

 

 

   ZKWatchManager类

private static class ZKWatchManager implements ClientWatchManager {
        //znode数据更新Watcher     
        private final Map<String, Set<Watcher>> dataWatches =
            new HashMap<String, Set<Watcher>>();
        //znode存在Watcher,即使znode不存在,这个Watcher也可以设置到这个不存在的znode上
        private final Map<String, Set<Watcher>> existWatches =
            new HashMap<String, Set<Watcher>>();
       //znode的子znodes个数变化Watcher
       private final Map<String, Set<Watcher>> childWatches =
            new HashMap<String, Set<Watcher>>();
        //默认的Watcher,如果构造Zookeeper没有显式指定Watcher,则使用这个watcher
        private volatile Watcher defaultWatcher;

        //把from中的watcher添加到集合to中
        final private void addTo(Set<Watcher> from, Set<Watcher> to) {
            if (from != null) {
                to.addAll(from);
            }
        }

        /* (non-Javadoc)
         * @see org.apache.zookeeper.ClientWatchManager#materialize(Event.KeeperState, 
         *                                                        Event.EventType, java.lang.String)
         */
        @Override
        public Set<Watcher> materialize(Watcher.Event.KeeperState state,
                                        Watcher.Event.EventType type,
                                        String clientPath)
        {
            Set<Watcher> result = new HashSet<Watcher>();

            switch (type) {
            case None://事件类型为None,表示???,把dataWatches,existWatches,childWatches所有的watch都返回
                //添加默认的Watcher,只有在类型为None的情况下,才会添加这个默认的Watcher
                result.add(defaultWatcher);
                //满足两种情况则清空dataWatches,existWatches,childWatches
                //1.状态不是SyncConnected(客户端与服务器端已建立链接)
                //2.设置了System property:zookeepr.disableAutoWatchReset 为true
/*
zookeeper.disableAutoWatchReset用于控制是否启动Watch自动reset,Clients automatically reset watches during session reconnect
*/                      
                boolean clear = ClientCnxn.getDisableAutoResetWatch() &&
                        state != Watcher.Event.KeeperState.SyncConnected;

                synchronized(dataWatches) {
                    for(Set<Watcher> ws: dataWatches.values()) {
                        result.addAll(ws);
                    }
                    if (clear) {
                        dataWatches.clear();
                    }
                }

                synchronized(existWatches) {
                    for(Set<Watcher> ws: existWatches.values()) {
                        result.addAll(ws);
                    }
                    if (clear) {
                        existWatches.clear();
                    }
                }

                synchronized(childWatches) {
                    for(Set<Watcher> ws: childWatches.values()) {
                        result.addAll(ws);
                    }
                    if (clear) {
                        childWatches.clear();
                    }
                }

                return result;
            case NodeDataChanged://如果是单节点发生变化,znode数据变化,znode创建
            case NodeCreated:
                synchronized (dataWatches) {
                   //把clientPath从dataWatches删除掉,加入到result中
                    addTo(dataWatches.remove(clientPath), result);
                }
                synchronized (existWatches) {
                    addTo(existWatches.remove(clientPath), result);
                }
                break;
            case NodeChildrenChanged://子节点发生数目改变
                synchronized (childWatches) {
                    addTo(childWatches.remove(clientPath), result);
                }
                break;
            case NodeDeleted://删除节点
                synchronized (dataWatches) {
                    addTo(dataWatches.remove(clientPath), result);
                }
                // XXX This shouldn't be needed, but just in case
                synchronized (existWatches) {
                    Set<Watcher> list = existWatches.remove(clientPath);
                    if (list != null) {//list应该
                        addTo(existWatches.remove(clientPath), result);//只是将clientPath对应的existWatches删除掉,不会加入到result上
                        LOG.warn("We are triggering an exists watch for delete! Shouldn't happen!");
                    }
                }
                synchronized (childWatches) {//如果一个节点存在子节点,则这个子节点不能被删掉,所以,这地方的逻辑是否会有问题?
                    addTo(childWatches.remove(clientPath), result);
                }
                break;
            default:
                String msg = "Unhandled watch event type " + type
                    + " with state " + state + " on path " + clientPath;
                LOG.error(msg);
                throw new RuntimeException(msg);
            }

            return result;
        }
    }

 

 默认的Watcher只有事件类型为None的情况下才会设置上,事件类型为Nonde表示什么意思呢?研究了才来更新