zookeeper(9)ソース分析-イベントリスニングWatcher(2)


次の記事では、Watcherに関連するクラスのソースコードの分析を続けます.
ClientWatchManager
public Set materialize(Watcher.Event.KeeperState state,
        Watcher.Event.EventType type, String path);

このインタフェースは、実装する方法が1つしかありません.このメソッドは、イベントが発生したときに通知が必要なWatcherの集合を返し、空の集合である可能性があることを示します.
ZKWatchManager
1、ZKWatchManagerはZooKeeperの内部クラスであり、ClientWatchManagerを実現している.2、ZKWatchManagerは3つのMapキー値ペアを定義し、キーはノードパス、値はWatcherである.データが変化するWatcher,ノードが存在するかどうかのWatcher,サブノードが変化するWatcherにそれぞれ対応する.
static class ZKWatchManager implements ClientWatchManager {
        //     watchers
        private final Map> dataWatches =
            new HashMap>();
        //       watchers
        private final Map> existWatches =
            new HashMap>();
        //      watchers
        private final Map> childWatches =
            new HashMap>();

3、materialize方法
このメソッドは,イベント発生後に通知が必要なWatcher集合を返す.この方法では、まずEventTypeタイプに基づいて対応するイベントタイプを決定し、次にNoneタイプ、すなわちイベントがない場合、clientPath対応するWatcherを3つのキー値ペアから削除し、残りのWatcherセットを結果セットに追加するイベントタイプに応じて対応する操作を行う.NodeDataChangedおよびNodeCreatedイベントの場合、clientPathに対応するWatcherはdataWatchesおよびexistWatchesから削除され、残りのWatcherセットが結果セットに追加されます.
@Override
        public Set materialize(Watcher.Event.KeeperState state,
                                        Watcher.Event.EventType type,
                                        String clientPath)
        {
            //      
            Set result = new HashSet();

            switch (type) {//    
            case None://   
                //    watcher
                result.add(defaultWatcher);
                //  disableAutoWatchReset Zookeeper                  
                boolean clear = disableAutoWatchReset && state != Watcher.Event.KeeperState.SyncConnected;
                //  3    watcherMap    
                synchronized(dataWatches) {
                    for(Set ws: dataWatches.values()) {
                        //        
                        result.addAll(ws);
                    }
                    if (clear) { //       
                        dataWatches.clear();
                    }
                }

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

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

                return result;
            case NodeDataChanged://       
            case NodeCreated://     
                synchronized (dataWatches) {
                    //  clientPath   Watcher          
                    addTo(dataWatches.remove(clientPath), result);
                }
                synchronized (existWatches) {
                    //  clientPath   Watcher          
                    addTo(existWatches.remove(clientPath), result);
                }
                break;
            case NodeChildrenChanged: //        
                synchronized (childWatches) {
                    //   clientPath   Watcher          
                    addTo(childWatches.remove(clientPath), result);
                }
                break;
            case NodeDeleted://     
                synchronized (dataWatches) {
                    //   clientPath   Watcher          
                    addTo(dataWatches.remove(clientPath), result);
                }
                // XXX This shouldn't be needed, but just in case
                synchronized (existWatches) {
                    Set list = existWatches.remove(clientPath);
                    if (list != null) {
                        addTo(list, result);
                        LOG.warn("We are triggering an exists watch for delete! Shouldn't happen!");
                    }
                }
                synchronized (childWatches) {
                    //  clientPath   Watcher          
                    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;
        }
    }