Java tutorial
/** *Copyright 2016 zhaojie * *Licensed under the Apache License, Version 2.0 (the "License"); *you may not use this file except in compliance with the License. *You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * *Unless required by applicable law or agreed to in writing, software *distributed under the License is distributed on an "AS IS" BASIS, *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *See the License for the specific language governing permissions and *limitations under the License. */ package com.api6.zkclient.watcher; import java.util.List; import java.util.Map.Entry; import java.util.Set; import java.util.concurrent.CopyOnWriteArraySet; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher.Event.EventType; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.api6.zkclient.ZKClient; import com.api6.zkclient.event.ZKEvent; import com.api6.zkclient.event.ZKEventThreadPool; import com.api6.zkclient.exception.ZKNoNodeException; import com.api6.zkclient.listener.ZKChildDataListener; import com.api6.zkclient.listener.ZKListener; import com.api6.zkclient.listener.ZKNodeListener; import com.api6.zkclient.listener.ZKStateListener; /** * ??? * @author: zhaojie/zh_jie@163.com.com */ public class ZKWatcherProcess { private static Logger LOG = LoggerFactory.getLogger(ZKWatcherProcess.class); private final ZKEventThreadPool eventThreadPool; private final ZKClient client; public ZKWatcherProcess(ZKClient zkClient) { this.client = zkClient; //? eventThreadPool = new ZKEventThreadPool(zkClient.getEventThreadPoolSize()); } /** * ?? * @return void */ public void stop() { eventThreadPool.destory(); } public void processStateChanged(WatchedEvent event) { final KeeperState keeperState = event.getState(); LOG.info("ZooKeeper state is changed [" + keeperState + "] ."); //?ZooKeeper? client.setCurrentState(keeperState); if (client.getShutdownTrigger()) { return; } //?? Set<ZKStateListener> listeners = client.getStateListenerSet(); //??? for (final ZKStateListener stateListener : listeners) { eventThreadPool.submit(new ZKEvent("State changed to " + keeperState + " sent to " + stateListener) { @Override public void run() throws Exception { stateListener.handleStateChanged(keeperState); } }); } //???? if (event.getState() == KeeperState.Expired) { try { //?? client.reconnect(); //?? for (final ZKStateListener stateListener : listeners) { ZKEvent zkEvent = new ZKEvent("New session event sent to " + stateListener) { @Override public void run() throws Exception { stateListener.handleNewSession(); } }; eventThreadPool.submit(zkEvent); } } catch (final Exception e) { LOG.info("Unable to re-establish connection. Notifying consumer of the following exception: ", e); //???? for (final ZKStateListener stateListener : listeners) { eventThreadPool .submit(new ZKEvent("Session establishment error[" + e + "] sent to " + stateListener) { @Override public void run() throws Exception { stateListener.handleSessionError(e); } }); } } } } /** * ??? * @param event * @return void */ public void processChildChanged(final WatchedEvent event) { final String path = event.getPath(); final Set<ZKListener> listeners = client.getChildListenerMap().get(path); //???? submitChildEvent(listeners, path, event.getType()); } /** * ??? * @param event * @return void */ public void processNodeChanged(final WatchedEvent event) { final String path = event.getPath(); final EventType eventType = event.getType(); final Set<ZKListener> listeners = client.getNodeListenerMap().get(path); if (listeners == null || listeners.isEmpty()) { return; } //listenersZKChildDataListener? //?????? //????ZKChildDataListener final Set<ZKListener> childDataChangeListners = new CopyOnWriteArraySet<>(); final Set<ZKListener> nodeListners = new CopyOnWriteArraySet<>(); classifyListeners(listeners, nodeListners, childDataChangeListners); //???? submitNodeEvent(nodeListners, childDataChangeListners, path, eventType); //???? if (eventType == EventType.NodeDataChanged) { //???? submitChildDataEvent(childDataChangeListners, path, eventType); } } /** * ???? * ????watch * ???????? * ?????????? * @param eventType * @return void * @author: zhaojie/zh_jie@163.com */ public void processAllNodeAndChildListeners(final WatchedEvent event) { LOG.debug("processAllNodeAndChildListeners...."); //??? for (Entry<String, CopyOnWriteArraySet<ZKListener>> entry : client.getNodeListenerMap().entrySet()) { Set<ZKListener> nodeListners = new CopyOnWriteArraySet<ZKListener>(); Set<ZKListener> childDataChangeListners = new CopyOnWriteArraySet<ZKListener>(); Set<ZKListener> listeners = entry.getValue(); classifyListeners(listeners, nodeListners, childDataChangeListners); //???? submitNodeEvent(nodeListners, childDataChangeListners, entry.getKey(), event.getType()); } //??? for (Entry<String, CopyOnWriteArraySet<ZKListener>> entry : client.getChildListenerMap().entrySet()) { //???? submitChildEvent(entry.getValue(), entry.getKey(), event.getType()); } } /** * listeners?{@link ZKNodeListener}nodeListeners{@link ZKChildDataListener} childDataChangeListeners * @param listeners * @param nodeListeners * @param childDataChangeListeners * @return void */ private void classifyListeners(Set<ZKListener> listeners, Set<ZKListener> nodeListeners, Set<ZKListener> childDataChangeListeners) { for (ZKListener listener : listeners) { if (listener instanceof ZKChildDataListener) { if (!childDataChangeListeners.contains(listener)) { childDataChangeListeners.add(listener); } } else { if (!nodeListeners.contains(listener)) { nodeListeners.add(listener); } } } } /** * ???? * @param listeners * @param childDataChangeListners * @param path * @param eventType * @return void */ private void submitNodeEvent(final Set<ZKListener> listeners, final Set<ZKListener> childDataChangeListners, final String path, final EventType eventType) { if (listeners != null && !listeners.isEmpty()) { for (final ZKListener listener : listeners) { ZKEvent zkEvent = new ZKEvent("Node of " + path + " changed sent to " + listener) { @Override public void run() throws Exception { //zookeeper ???? LOG.debug("Rewatch the path [" + path + "] by exists method"); boolean flag = client.exists(path, true); LOG.debug("Rewatched the path [" + path + "] by exists method"); try { LOG.debug("Rewatch and get changed data [path:" + path + " | EventType:" + eventType + "] by getData method"); Object data = client.getData(path, null); LOG.debug("Rewatched and return data [" + path + " | " + data + " | EventType:" + eventType + "] by getData method"); listener.handle(path, eventType, data); //??????? //? if (eventType == EventType.NodeDeleted && flag) { listener.handle(path, EventType.NodeCreated, data); } } catch (ZKNoNodeException e) { //??ZKChildDataListener? client.unlistenNodeChanges(path, childDataChangeListners); //?client.getData(path,null) listener.handle(path, eventType, null); //?????? //????? //?? if (eventType == EventType.NodeCreated && !flag) { listener.handle(path, EventType.NodeDeleted, null); } } } }; eventThreadPool.submit(zkEvent); } } } /** * ????? * @param listeners * @param path * @param eventType * @return void */ private void submitChildEvent(final Set<ZKListener> listeners, final String path, final EventType eventType) { if (listeners != null && !listeners.isEmpty()) { try { for (final ZKListener listener : listeners) { //? ZKEvent zkEvent = new ZKEvent("Children of " + path + " changed sent to " + listener) { @Override public void run() throws Exception { //zookeeper ????? LOG.debug("Rewatch the path [" + path + "] by exists method"); client.exists(path); LOG.debug("Rewatched the path [" + path + "] by exists method"); try { LOG.debug("Rewatch and get chilldren [path:" + path + " | EventType:" + eventType + "] by getChildren method"); //?????? List<String> children = client.getChildren(path); LOG.debug("Rewatched and return children [children:" + children + " | EventType:" + eventType + "] by getChildren method"); //????pathZKChildDataListener //?????? client.listenNewChildPathWithData(path, children); listener.handle(path, eventType, children); } catch (ZKNoNodeException e) { //?client.getChildren(path) listener.handle(path, eventType, null); } } }; eventThreadPool.submit(zkEvent); } } catch (Exception e) { LOG.error("Failed to fire child changed event. Unable to getChildren. ", e); } } } /** * ?????? * @param listeners * @param path * @param eventType * @return void */ private void submitChildDataEvent(final Set<ZKListener> listeners, final String path, final EventType eventType) { if (listeners != null && !listeners.isEmpty()) { for (final ZKListener listener : listeners) { ZKEvent zkEvent = new ZKEvent("Children of " + path + " changed sent to " + listener) { @Override public void run() throws Exception { //zookeeper ???? LOG.debug("rewatch the path [" + path + "]"); client.exists(path, true); LOG.debug("rewatched the path [" + path + "]"); try { LOG.debug("Try to get child changed data [path:" + path + " | EventType:" + eventType + "]"); //?????? //????? //??? Object data = client.getData(path, null); LOG.debug("Child changed data is [path:" + path + " | data:" + data + " | EventType:" + eventType + "]"); listener.handle(path, eventType, data); } catch (ZKNoNodeException e) { //ignore } } }; eventThreadPool.submit(zkEvent); } } } }