//接口的唯一方法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表示什么意思呢?研究了才来更新