package com.alipay.bluewhale.core.cluster; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; import org.apache.log4j.Logger; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.Watcher.Event.EventType; import org.apache.zookeeper.Watcher.Event.KeeperState; import backtype.storm.Config; import com.alipay.bluewhale.core.utils.PathUtils; import com.alipay.bluewhale.core.zk.WatcherCallBack; import com.alipay.bluewhale.core.zk.Zookeeper; import com.netflix.curator.framework.CuratorFramework; public class DistributedClusterState implements ClusterState { private static Logger LOG = Logger.getLogger(DistributedClusterState.class); private Zookeeper zkobj = null; private ConcurrentHashMap<UUID, ClusterStateCallback> callbacks = new ConcurrentHashMap<UUID, ClusterStateCallback>(); private Map conf; private AtomicBoolean active; private CuratorFramework zk; private WatcherCallBack watcher; public DistributedClusterState(Map _conf) throws Exception { conf = _conf; zkobj = new Zookeeper(); CuratorFramework _zk = mkZk(); String path = String.valueOf(conf.get(Config.STORM_ZOOKEEPER_ROOT)); zkobj.mkdirs(_zk, path); _zk.close(); active = new AtomicBoolean(true); watcher = new WatcherCallBack() { @SuppressWarnings("unchecked") @Override public void execute(KeeperState state, EventType type, String path) { if (active.get()) { if (!(state.equals(KeeperState.SyncConnected))) { LOG.warn("Received event " + state + ":" + type + ":" + path + " with disconnected Zookeeper."); } if (!type.equals(EventType.None)) { for (Entry<UUID, ClusterStateCallback> e : callbacks .entrySet()) { ClusterStateCallback fn = e.getValue(); fn.execute(type, path); } } } } }; zk = null; zk = mkZk(watcher); } @SuppressWarnings("unchecked") private CuratorFramework mkZk() throws IOException { return zkobj.mkClient(conf, (List<String>) conf.get(Config.STORM_ZOOKEEPER_SERVERS), conf.get(Config.STORM_ZOOKEEPER_PORT), ""); } @SuppressWarnings("unchecked") private CuratorFramework mkZk(WatcherCallBack watcher) throws NumberFormatException, IOException { return zkobj.mkClient(conf, (List<String>) conf.get(Config.STORM_ZOOKEEPER_SERVERS), conf.get(Config.STORM_ZOOKEEPER_PORT), String.valueOf(conf.get(Config.STORM_ZOOKEEPER_ROOT)), watcher); } @Override public void close() { this.active.set(false); zk.close(); } @Override public void delete_node(String path) { try { zkobj.deletereRcursive(zk, path); } catch (Exception e) { LOG.error("delete_node", e); } } @Override public List<String> get_children(String path, boolean watch) { List<String> list = null; try { list = zkobj.getChildren(zk, path, watch); } catch (Exception e) { LOG.error("get_children", e); } return list; } @Override public byte[] get_data(String path, boolean watch) { byte[] bytes = null; try { bytes = zkobj.getData(zk, path, watch); } catch (Exception e) { LOG.error("get_data", e); } return bytes; } @Override public void mkdirs(String path) { try { zkobj.mkdirs(zk, path); } catch (Exception e) { LOG.error("mkdirs", e); } } @Override public UUID register(ClusterStateCallback callback) { UUID id = UUID.randomUUID(); this.callbacks.put(id, callback); return id; } @Override public void set_data(String path, byte[] data) { try { if (zkobj.exists(zk, path, false)) { zkobj.setData(zk, path, data); } else { zkobj.mkdirs(zk, PathUtils.parent_path(path)); zkobj.createNode(zk, path, data, CreateMode.PERSISTENT); } } catch (Exception e) { LOG.error("set_data", e); } } @Override public void set_ephemeral_node(String path, byte[] data) { try { zkobj.mkdirs(zk, PathUtils.parent_path(path)); if (zkobj.exists(zk, path, false)) { zkobj.setData(zk, path, data); } else { zkobj.createNode(zk, path, data, CreateMode.EPHEMERAL); } } catch (Exception e) { LOG.error("set_ephemeral_node", e); } } @Override public ClusterStateCallback unregister(UUID id) { return this.callbacks.remove(id); } }