/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.alibaba.dubbo.remoting.zookeeper.support; import com.alibaba.dubbo.common.URL; import com.alibaba.dubbo.common.logger.Logger; import com.alibaba.dubbo.common.logger.LoggerFactory; import com.alibaba.dubbo.remoting.zookeeper.ChildListener; import com.alibaba.dubbo.remoting.zookeeper.StateListener; import com.alibaba.dubbo.remoting.zookeeper.ZookeeperClient; import java.util.List; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.CopyOnWriteArraySet; // public abstract class AbstractZookeeperClient<TargetChildListener> implements ZookeeperClient { protected static final Logger logger = LoggerFactory.getLogger(AbstractZookeeperClient.class); private final URL url; private final Set<StateListener> stateListeners = new CopyOnWriteArraySet<StateListener>(); private final ConcurrentMap<String, ConcurrentMap<ChildListener, TargetChildListener>> childListeners = new ConcurrentHashMap<String, ConcurrentMap<ChildListener, TargetChildListener>>(); private volatile boolean closed = false; public AbstractZookeeperClient(URL url) { this.url = url; } @Override public URL getUrl() { return url; } @Override public void create(String path, boolean ephemeral) { if (!ephemeral) { if (checkExists(path)) { return; } } int i = path.lastIndexOf('/'); if (i > 0) { create(path.substring(0, i), false); } if (ephemeral) { // 创建zk临时节点=》 createEphemeral(path); } else { // 创建zk持久化节点=》 createPersistent(path); } } @Override public void addStateListener(StateListener listener) { stateListeners.add(listener); } @Override public void removeStateListener(StateListener listener) { stateListeners.remove(listener); } public Set<StateListener> getSessionListeners() { return stateListeners; } @Override public List<String> addChildListener(String path, final ChildListener listener) { ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path); if (listeners == null) { childListeners.putIfAbsent(path, new ConcurrentHashMap<ChildListener, TargetChildListener>()); listeners = childListeners.get(path); } TargetChildListener targetListener = listeners.get(listener); if (targetListener == null) { listeners.putIfAbsent(listener, createTargetChildListener(path, listener)); targetListener = listeners.get(listener); } // 添加节点监听器=》 return addTargetChildListener(path, targetListener); } @Override public void removeChildListener(String path, ChildListener listener) { ConcurrentMap<ChildListener, TargetChildListener> listeners = childListeners.get(path); if (listeners != null) { TargetChildListener targetListener = listeners.remove(listener); if (targetListener != null) { removeTargetChildListener(path, targetListener); } } } protected void stateChanged(int state) { for (StateListener sessionListener : getSessionListeners()) { sessionListener.stateChanged(state); } } @Override public void close() { if (closed) { return; } closed = true; try { doClose(); } catch (Throwable t) { logger.warn(t.getMessage(), t); } } protected abstract void doClose(); protected abstract void createPersistent(String path); protected abstract void createEphemeral(String path); protected abstract boolean checkExists(String path); protected abstract TargetChildListener createTargetChildListener(String path, ChildListener listener); protected abstract List<String> addTargetChildListener(String path, TargetChildListener listener); protected abstract void removeTargetChildListener(String path, TargetChildListener listener); }