Apache Zookeeper zkCli.sh命令及Java客户端连接测试
2017-03-28 10:21
465 查看
如题:Apache Zookeeper zkCli.sh命令及Java客户端连接测试,本文分两部分进行说明,第一部分是zkCli.sh命令行的使用,第二部分是Java客户端测试连接Zookeeper服务端。本文开始的前提是已安装Apache Zookeeper。
zkCli.sh命令使用
Linux的shell环境窗口操作:
zkCli.sh -server 127.0.0.1:2181 连接到 ZooKeeper 服务,连接成功后,系统会输出 ZooKeeper 的相关环境以及配置信息。
注:如果是本地单机情况,只需要输入 zkCli.sh 即可进入。
命令行工具的一些简单操作如下:
1. 显示根目录下、文件: ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容
2. 显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据
3. 创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode节点“ zk ”以及与它关联的字符串
4. 获取文件内容: get /zk 确认 znode 是否包含我们所创建的字符串
5. 修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置
6. 删除文件: delete /zk 将刚才创建的 znode 删除
7. 退出客户端: quit
8. 帮助命令: help
Java客户端连接测试
首先添加maven依赖配置
pom.xml
ZkWatcher.java
测试运行输出:
注:Zookeeper的用法基本上都可以在这个类里面找到。
import java.io.IOException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
/**
* Zookeeper构造参数类
*
* @package com.github.boonya.zookeeper.ZkZookeeper
* @date 2017年3月28日 上午10:48:24
* @author pengjunlin
* @comment
* @update
*/
public class ZkZookeeper extends ZooKeeper {
/**
*
* @param connectString
* ip:port
* @param sessionTimeout
* @param watcher
* @param sessionId
* @param sessionPasswd
* @param canBeReadOnly
* @throws IOException
*/
public ZkZookeeper(String connectString, int sessionTimeout,
Watcher watcher, long sessionId, byte[] sessionPasswd,
boolean canBeReadOnly) throws IOException {
super(connectString, sessionTimeout, watcher, sessionId, sessionPasswd,
canBeReadOnly);
// TODO Auto-generated constructor stub
}
/**
*
* @param connectString
* ip:port
* @param sessionTimeout
* @param watcher
* @param sessionId
* @param sessionPasswd
* @throws IOException
*/
public ZkZookeeper(String connectString, int sessionTimeout,
Watcher watcher, long sessionId, byte[] sessionPasswd)
throws IOException {
super(connectString, sessionTimeout, watcher, sessionId, sessionPasswd);
// TODO Auto-generated constructor stub
}
/**
*
* @param connectString
* ip:port
* @param sessionTimeout
* @param watcher
* @param canBeReadOnly
* @throws IOException
*/
public ZkZookeeper(String connectString, int sessionTimeout,
Watcher watcher, boolean canBeReadOnly) throws IOException {
super(connectString, sessionTimeout, watcher, canBeReadOnly);
// TODO Auto-generated constructor stub
}
/**
*
* @param connectString
* ip:port
* @param sessionTimeout
* @param watcher
* @throws IOException
*/
public ZkZookeeper(String connectString, int sessionTimeout, Watcher watcher)
throws IOException {
super(connectString, sessionTimeout, watcher);
// TODO Auto-generated constructor stub
}
}
Zookeeper支持四种构造实现。
Zookeeper客户端API之会话创建:http://blog.csdn.net/wo541075754/article/details/61190967
zkCli.sh命令使用
Linux的shell环境窗口操作:zkCli.sh -server 127.0.0.1:2181 连接到 ZooKeeper 服务,连接成功后,系统会输出 ZooKeeper 的相关环境以及配置信息。
注:如果是本地单机情况,只需要输入 zkCli.sh 即可进入。
命令行工具的一些简单操作如下:
1. 显示根目录下、文件: ls / 使用 ls 命令来查看当前 ZooKeeper 中所包含的内容
2. 显示根目录下、文件: ls2 / 查看当前节点数据并能看到更新次数等数据
3. 创建文件,并设置初始内容: create /zk "test" 创建一个新的 znode节点“ zk ”以及与它关联的字符串
4. 获取文件内容: get /zk 确认 znode 是否包含我们所创建的字符串
5. 修改文件内容: set /zk "zkbak" 对 zk 所关联的字符串进行设置
6. 删除文件: delete /zk 将刚才创建的 znode 删除
7. 退出客户端: quit
8. 帮助命令: help
Java客户端连接测试
首先添加maven依赖配置pom.xml
<dependency> <groupId>org.apache.zookeeper</groupId> <artifactId>zookeeper</artifactId> <version>3.4.9</version> </dependency>
ZkWatcher.java
package com.github.boonya.zookeeper; import java.io.IOException; import java.util.Date; import java.util.concurrent.CountDownLatch; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.WatchedEvent; import org.apache.zookeeper.Watcher; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; /** * 测试Zookeeper基本连接 * * @package com.github.boonya.zookeeper.ZkWatcher * @date 2017年3月28日 上午9:22:16 * @author pengjunlin * @comment * @update */ public class ZkWatcher implements Watcher{ private static CountDownLatch countDownLatch = new CountDownLatch(1); /** * 处理同步连接 */ public void process(WatchedEvent event) { System.out.println("Receive watcher event:" + event); if(Event.KeeperState.SyncConnected == event.getState()){ countDownLatch.countDown(); } } /** * 主函数入口 * * @MethodName: main * @Description: * @param args * @throws IOException * @throws KeeperException * @throws InterruptedException * @throws */ public static void main(String[] args) throws IOException, KeeperException, InterruptedException { Long startTime = new Date().getTime(); ZooKeeper zooKeeper = new ZooKeeper("192.168.234.128:2181",5000,new ZkWatcher()); try { countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("创建连接花费时间:" + (new Date().getTime() - startTime) + "ms"); System.out.println("连接状态:" + zooKeeper.getState()); System.out.println("sessionId:" + zooKeeper.getSessionId()); System.out.println("sessionPasswd:" + new String(zooKeeper.getSessionPasswd())); // 此时需要使用到zkCli.sh命令窗口 ,Zookeeper默认节点路径为/zookeeper //查看path: ls \ //创建path数据情况: create /zookeeper '默认内容' //查看path数据情况: get /zookeeper //version以节点的dataVersion = 2一致才能成功,否则抛出 KeeperErrorCode = BadVersion for /zookeeper zooKeeper.setData("/zookeeper", "Hello world! Hello Zookeeper!".getBytes(), 2); byte [] data=zooKeeper.getData("/zookeeper", new ZkWatcher(), new Stat()); System.out.println("/zookeeper data:"+new String(data)); } /* [zk: localhost:2181(CONNECTED) 4] get /zookeeper Hello world!Hello Zookeeper! cZxid = 0x0 ctime = Wed Dec 31 16:00:00 PST 1969 mZxid = 0xc mtime = Mon Mar 27 18:41:45 PDT 2017 pZxid = 0x0 cversion = -1 dataVersion = 1 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 28 numChildren = 1 [zk: localhost:2181(CONNECTED) 5] get /zookeeper Hello world! Hello Zookeeper! cZxid = 0x0 ctime = Wed Dec 31 16:00:00 PST 1969 mZxid = 0x15 mtime = Mon Mar 27 18:44:50 PDT 2017 pZxid = 0x0 cversion = -1 dataVersion = 2 aclVersion = 0 ephemeralOwner = 0x0 dataLength = 29 numChildren = 1*/ }
测试运行输出:
创建连接花费时间:227ms 连接状态:CONNECTED sessionId:97692145141547018 sessionPasswd:��W�DlRʼ�p��*� 09:45:14.301 [main-SendThread(192.168.234.128:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply sessionid:0x15b127d0882000a, packet:: clientPath:null serverPath:null finished:false header:: 1,5 replyHeader:: 1,28,0 request:: '/zookeeper,#48656c6c6f20776f726c64212048656c6c6f205a6f6f6b656570657221,2 response:: s{0,28,0,1490665711525,3,-1,0,0,29,1,0} 09:45:14.304 [main-SendThread(192.168.234.128:2181)] DEBUG org.apache.zookeeper.ClientCnxn - Reading reply sessionid:0x15b127d0882000a, packet:: clientPath:null serverPath:null finished:false header:: 2,4 replyHeader:: 2,28,0 request:: '/zookeeper,T response:: #48656c6c6f20776f726c64212048656c6c6f205a6f6f6b656570657221,s{0,28,0,1490665711525,3,-1,0,0,29,1,0} /zookeeper data:Hello world! Hello Zookeeper!
Zookeeper源代码工具类
* Licensed to the Apache Software Foundation (ASF) under one package org.apache.zookeeper; import org.apache.zookeeper.AsyncCallback.*; import org.apache.zookeeper.OpResult.ErrorResult; import org.apache.zookeeper.client.ConnectStringParser; import org.apache.zookeeper.client.HostProvider; import org.apache.zookeeper.client.StaticHostProvider; import org.apache.zookeeper.client.ZooKeeperSaslClient; import org.apache.zookeeper.common.PathUtils; import org.apache.zookeeper.data.ACL; import org.apache.zookeeper.data.Stat; import org.apache.zookeeper.proto.*; import org.apache.zookeeper.server.DataTree; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.net.SocketAddress; import java.util.*; /** * This is the main class of ZooKeeper client library. To use a ZooKeeper * service, an application must first instantiate an object of ZooKeeper class. * All the iterations will be done by calling the methods of ZooKeeper class. * The methods of this class are thread-safe unless otherwise noted. * <p> * Once a connection to a server is established, a session ID is assigned to the * client. The client will send heart beats to the server periodically to keep * the session valid. * <p> * The application can call ZooKeeper APIs through a client as long as the * session ID of the client remains valid. * <p> * If for some reason, the client fails to send heart beats to the server for a * prolonged period of time (exceeding the sessionTimeout value, for instance), * the server will expire the session, and the session ID will become invalid. * The client object will no longer be usable. To make ZooKeeper API calls, the * application must create a new client object. * <p> * If the ZooKeeper server the client currently connects to fails or otherwise * does not respond, the client will automatically try to connect to another * server before its session ID expires. If successful, the application can * continue to use the client. * <p> * The ZooKeeper API methods are either synchronous or asynchronous. Synchronous * methods blocks until the server has responded. Asynchronous methods just queue * the request for sending and return immediately. They take a callback object that * will be executed either on successful execution of the request or on error with * an appropriate return code (rc) indicating the error. * <p> * Some successful ZooKeeper API calls can leave watches on the "data nodes" in * the ZooKeeper server. Other successful ZooKeeper API calls can trigger those * watches. Once a watch is triggered, an event will be delivered to the client * which left the watch at the first place. Each watch can be triggered only * once. Thus, up to one event will be delivered to a client for every watch it * leaves. * <p> * A client needs an object of a class implementing Watcher interface for * processing the events delivered to the client. * * When a client drops current connection and re-connects to a server, all the * existing watches are considered as being triggered but the undelivered events * are lost. To emulate this, the client will generate a special event to tell * the event handler a connection has been dropped. This special event has type * EventNone and state sKeeperStateDisconnected. * */ public class ZooKeeper { public static final String ZOOKEEPER_CLIENT_CNXN_SOCKET = "zookeeper.clientCnxnSocket"; protected final ClientCnxn cnxn; private static final Logger LOG; static { //Keep these two lines together to keep the initialization order explicit LOG = LoggerFactory.getLogger(ZooKeeper.class); Environment.logEnv("Client environment:", LOG); } public ZooKeeperSaslClient getSaslClient() { return cnxn.zooKeeperSaslClient; } private final ZKWatchManager watchManager = new ZKWatchManager(); List<String> getDataWatches() { synchronized(watchManager.dataWatches) { List<String> rc = new ArrayList<String>(watchManager.dataWatches.keySet()); return rc; } } List<String> getExistWatches() { synchronized(watchManager.existWatches) { List<String> rc = new ArrayList<String>(watchManager.existWatches.keySet()); return rc; } } List<String> getChildWatches() { synchronized(watchManager.childWatches) { List<String> rc = new ArrayList<String>(watchManager.childWatches.keySet()); return rc; } } /** * Manage watchers & handle events generated by the ClientCnxn object. * * We are implementing this as a nested class of ZooKeeper so that * the public methods will not be exposed as part of the ZooKeeper client * API. */ private static class ZKWatchManager implements ClientWatchManager { private final Map<String, Set<Watcher>> dataWatches = new HashMap<String, Set<Watcher>>(); private final Map<String, Set<Watcher>> existWatches = new HashMap<String, Set<Watcher>>(); private final Map<String, Set<Watcher>> childWatches = new HashMap<String, Set<Watcher>>(); private volatile Watcher defaultWatcher; 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: result.add(defaultWatcher); 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: case NodeCreated: synchronized (dataWatches) { 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) { addTo(existWatches.remove(clientPath), 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; } } /** * Register a watcher for a particular path. */ abstract class WatchRegistration { private Watcher watcher; private String clientPath; public WatchRegistration(Watcher watcher, String clientPath) { this.watcher = watcher; this.clientPath = clientPath; } abstract protected Map<String, Set<Watcher>> getWatches(int rc); /** * Register the watcher with the set of watches on path. * @param rc the result code of the operation that attempted to * add the watch on the path. */ public void register(int rc) { if (shouldAddWatch(rc)) { Map<String, Set<Watcher>> watches = getWatches(rc); synchronized(watches) { Set<Watcher> watchers = watches.get(clientPath); if (watchers == null) { watchers = new HashSet<Watcher>(); watches.put(clientPath, watchers); } watchers.add(watcher); } } } /** * Determine whether the watch should be added based on return code. * @param rc the result code of the operation that attempted to add the * watch on the node * @return true if the watch should be added, otw false */ protected boolean shouldAddWatch(int rc) { return rc == 0; } } /** Handle the special case of exists watches - they add a watcher * even in the case where NONODE result code is returned. */ class ExistsWatchRegistration extends WatchRegistration { public ExistsWatchRegistration(Watcher watcher, String clientPath) { super(watcher, clientPath); } @Override protected Map<String, Set<Watcher>> getWatches(int rc) { return rc == 0 ? watchManager.dataWatches : watchManager.existWatches; } @Override protected boolean shouldAddWatch(int rc) { return rc == 0 || rc == KeeperException.Code.NONODE.intValue(); } } class DataWatchRegistration extends WatchRegistration { public DataWatchRegistration(Watcher watcher, String clientPath) { super(watcher, clientPath); } @Override protected Map<String, Set<Watcher>> getWatches(int rc) { return watchManager.dataWatches; } } class ChildWatchRegistration extends WatchRegistration { public ChildWatchRegistration(Watcher watcher, String clientPath) { super(watcher, clientPath); } @Override protected Map<String, Set<Watcher>> getWatches(int rc) { return watchManager.childWatches; } } public enum States { CONNECTING, ASSOCIATING, CONNECTED, CONNECTEDREADONLY, CLOSED, AUTH_FAILED, NOT_CONNECTED; public boolean isAlive() { return this != CLOSED && this != AUTH_FAILED; } /** * Returns whether we are connected to a server (which * could possibly be read-only, if this client is allowed * to go to read-only mode) * */ public boolean isConnected() { return this == CONNECTED || this == CONNECTEDREADONLY; } } /** * To create a ZooKeeper client object, the application needs to pass a * connection string containing a comma separated list of host:port pairs, * each corresponding to a ZooKeeper server. * <p> * Session establishment is asynchronous. This constructor will initiate * connection to the server and return immediately - potentially (usually) * before the session is fully established. The watcher argument specifies * the watcher that will be notified of any changes in state. This * notification can come at any point before or after the constructor call * has returned. * <p> * The instantiated ZooKeeper client object will pick an arbitrary server * from the connectString and attempt to connect to it. If establishment of * the connection fails, another server in the connect string will be tried * (the order is non-deterministic, as we random shuffle the list), until a * connection is established. The client will continue attempts until the * session is explicitly closed. * <p> * Added in 3.2.0: An optional "chroot" suffix may also be appended to the * connection string. This will run the client commands while interpreting * all paths relative to this root (similar to the unix chroot command). * * @param connectString * comma separated host:port pairs, each corresponding to a zk * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" If * the optional chroot suffix is used the example would look * like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a" * where the client would be rooted at "/app/a" and all paths * would be relative to this root - ie getting/setting/etc... * "/foo/bar" would result in operations being run on * "/app/a/foo/bar" (from the server perspective). * @param sessionTimeout * session timeout in milliseconds * @param watcher * a watcher object which will be notified of state changes, may * also be notified for node events * * @throws IOException * in cases of network failure * @throws IllegalArgumentException * if an invalid chroot path is specified */ public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher) throws IOException { this(connectString, sessionTimeout, watcher, false); } /** * To create a ZooKeeper client object, the application needs to pass a * connection string containing a comma separated list of host:port pairs, * each corresponding to a ZooKeeper server. * <p> * Session establishment is asynchronous. This constructor will initiate * connection to the server and return immediately - potentially (usually) * before the session is fully established. The watcher argument specifies * the watcher that will be notified of any changes in state. This * notification can come at any point before or after the constructor call * has returned. * <p> * The instantiated ZooKeeper client object will pick an arbitrary server * from the connectString and attempt to connect to it. If establishment of * the connection fails, another server in the connect string will be tried * (the order is non-deterministic, as we random shuffle the list), until a * connection is established. The client will continue attempts until the * session is explicitly closed. * <p> * Added in 3.2.0: An optional "chroot" suffix may also be appended to the * connection string. This will run the client commands while interpreting * all paths relative to this root (similar to the unix chroot command). * * @param connectString * comma separated host:port pairs, each corresponding to a zk * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" If * the optional chroot suffix is used the example would look * like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a" * where the client would be rooted at "/app/a" and all paths * would be relative to this root - ie getting/setting/etc... * "/foo/bar" would result in operations being run on * "/app/a/foo/bar" (from the server perspective). * @param sessionTimeout * session timeout in milliseconds * @param watcher * a watcher object which will be notified of state changes, may * also be notified for node events * @param canBeReadOnly * (added in 3.4) whether the created client is allowed to go to * read-only mode in case of partitioning. Read-only mode * basically means that if the client can't find any majority * servers but there's partitioned server it could reach, it * connects to one in read-only mode, i.e. read requests are * allowed while write requests are not. It continues seeking for * majority in the background. * * @throws IOException * in cases of network failure * @throws IllegalArgumentException * if an invalid chroot path is specified */ public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, boolean canBeReadOnly) throws IOException { LOG.info("Initiating client connection, connectString=" + connectString + " sessionTimeout=" + sessionTimeout + " watcher=" + watcher); watchManager.defaultWatcher = watcher; ConnectStringParser connectStringParser = new ConnectStringParser( connectString); HostProvider hostProvider = new StaticHostProvider( connectStringParser.getServerAddresses()); cnxn = new ClientCnxn(connectStringParser.getChrootPath(), hostProvider, sessionTimeout, this, watchManager, getClientCnxnSocket(), canBeReadOnly); cnxn.start(); } /** * To create a ZooKeeper client object, the application needs to pass a * connection string containing a comma separated list of host:port pairs, * each corresponding to a ZooKeeper server. * <p> * Session establishment is asynchronous. This constructor will initiate * connection to the server and return immediately - potentially (usually) * before the session is fully established. The watcher argument specifies * the watcher that will be notified of any changes in state. This * notification can come at any point before or after the constructor call * has returned. * <p> * The instantiated ZooKeeper client object will pick an arbitrary server * from the connectString and attempt to connect to it. If establishment of * the connection fails, another server in the connect string will be tried * (the order is non-deterministic, as we random shuffle the list), until a * connection is established. The client will continue attempts until the * session is explicitly closed (or the session is expired by the server). * <p> * Added in 3.2.0: An optional "chroot" suffix may also be appended to the * connection string. This will run the client commands while interpreting * all paths relative to this root (similar to the unix chroot command). * <p> * Use {@link #getSessionId} and {@link #getSessionPasswd} on an established * client connection, these values must be passed as sessionId and * sessionPasswd respectively if reconnecting. Otherwise, if not * reconnecting, use the other constructor which does not require these * parameters. * * @param connectString * comma separated host:port pairs, each corresponding to a zk * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" * If the optional chroot suffix is used the example would look * like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a" * where the client would be rooted at "/app/a" and all paths * would be relative to this root - ie getting/setting/etc... * "/foo/bar" would result in operations being run on * "/app/a/foo/bar" (from the server perspective). * @param sessionTimeout * session timeout in milliseconds * @param watcher * a watcher object which will be notified of state changes, may * also be notified for node events * @param sessionId * specific session id to use if reconnecting * @param sessionPasswd * password for this session * * @throws IOException in cases of network failure * @throws IllegalArgumentException if an invalid chroot path is specified * @throws IllegalArgumentException for an invalid list of ZooKeeper hosts */ public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd) throws IOException { this(connectString, sessionTimeout, watcher, sessionId, sessionPasswd, false); } /** * To create a ZooKeeper client object, the application needs to pass a * connection string containing a comma separated list of host:port pairs, * each corresponding to a ZooKeeper server. * <p> * Session establishment is asynchronous. This constructor will initiate * connection to the server and return immediately - potentially (usually) * before the session is fully established. The watcher argument specifies * the watcher that will be notified of any changes in state. This * notification can come at any point before or after the constructor call * has returned. * <p> * The instantiated ZooKeeper client object will pick an arbitrary server * from the connectString and attempt to connect to it. If establishment of * the connection fails, another server in the connect string will be tried * (the order is non-deterministic, as we random shuffle the list), until a * connection is established. The client will continue attempts until the * session is explicitly closed (or the session is expired by the server). * <p> * Added in 3.2.0: An optional "chroot" suffix may also be appended to the * connection string. This will run the client commands while interpreting * all paths relative to this root (similar to the unix chroot command). * <p> * Use {@link #getSessionId} and {@link #getSessionPasswd} on an established * client connection, these values must be passed as sessionId and * sessionPasswd respectively if reconnecting. Otherwise, if not * reconnecting, use the other constructor which does not require these * parameters. * * @param connectString * comma separated host:port pairs, each corresponding to a zk * server. e.g. "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002" * If the optional chroot suffix is used the example would look * like: "127.0.0.1:3000,127.0.0.1:3001,127.0.0.1:3002/app/a" * where the client would be rooted at "/app/a" and all paths * would be relative to this root - ie getting/setting/etc... * "/foo/bar" would result in operations being run on * "/app/a/foo/bar" (from the server perspective). * @param sessionTimeout * session timeout in milliseconds * @param watcher * a watcher object which will be notified of state changes, may * also be notified for node events * @param sessionId * specific session id to use if reconnecting * @param sessionPasswd * password for this session * @param canBeReadOnly * (added in 3.4) whether the created client is allowed to go to * read-only mode in case of partitioning. Read-only mode * basically means that if the client can't find any majority * servers but there's partitioned server it could reach, it * connects to one in read-only mode, i.e. read requests are * allowed while write requests are not. It continues seeking for * majority in the background. * * @throws IOException in cases of network failure * @throws IllegalArgumentException if an invalid chroot path is specified */ public ZooKeeper(String connectString, int sessionTimeout, Watcher watcher, long sessionId, byte[] sessionPasswd, boolean canBeReadOnly) throws IOException { LOG.info("Initiating client connection, connectString=" + connectString + " sessionTimeout=" + sessionTimeout + " watcher=" + watcher + " sessionId=" + Long.toHexString(sessionId) + " sessionPasswd=" + (sessionPasswd == null ? "<null>" : "<hidden>")); watchManager.defaultWatcher = watcher; ConnectStringParser connectStringParser = new ConnectStringParser( connectString); HostProvider hostProvider = new StaticHostProvider( connectStringParser.getServerAddresses()); cnxn = new ClientCnxn(connectStringParser.getChrootPath(), hostProvider, sessionTimeout, this, watchManager, getClientCnxnSocket(), sessionId, sessionPasswd, canBeReadOnly); cnxn.seenRwServerBefore = true; // since user has provided sessionId cnxn.start(); } /** * The session id for this ZooKeeper client instance. The value returned is * not valid until the client connects to a server and may change after a * re-connect. * * This method is NOT thread safe * * @return current session id */ public long getSessionId() { return cnxn.getSessionId(); } /** * The session password for this ZooKeeper client instance. The value * returned is not valid until the client connects to a server and may * change after a re-connect. * * This method is NOT thread safe * * @return current session password */ public byte[] getSessionPasswd() { return cnxn.getSessionPasswd(); } /** * The negotiated session timeout for this ZooKeeper client instance. The * value returned is not valid until the client connects to a server and * may change after a re-connect. * * This method is NOT thread safe * * @return current session timeout */ public int getSessionTimeout() { return cnxn.getSessionTimeout(); } /** * Add the specified scheme:auth information to this connection. * * This method is NOT thread safe * * @param scheme * @param auth */ public void addAuthInfo(String scheme, byte auth[]) { cnxn.addAuthInfo(scheme, auth); } /** * Specify the default watcher for the connection (overrides the one * specified during construction). * * @param watcher */ public synchronized void register(Watcher watcher) { watchManager.defaultWatcher = watcher; } /** * Close this client object. Once the client is closed, its session becomes * invalid. All the ephemeral nodes in the ZooKeeper server associated with * the session will be removed. The watches left on those nodes (and on * their parents) will be triggered. * * @throws InterruptedException */ public synchronized void close() throws InterruptedException { if (!cnxn.getState().isAlive()) { if (LOG.isDebugEnabled()) { LOG.debug("Close called on already closed client"); } return; } if (LOG.isDebugEnabled()) { LOG.debug("Closing session: 0x" + Long.toHexString(getSessionId())); } try { cnxn.close(); } catch (IOException e) { if (LOG.isDebugEnabled()) { LOG.debug("Ignoring unexpected exception during close", e); } } LOG.info("Session: 0x" + Long.toHexString(getSessionId()) + " closed"); } /** * Prepend the chroot to the client path (if present). The expectation of * this function is that the client path has been validated before this * function is called * @param clientPath path to the node * @return server view of the path (chroot prepended to client path) */ private String prependChroot(String clientPath) { if (cnxn.chrootPath != null) { // handle clientPath = "/" if (clientPath.length() == 1) { return cnxn.chrootPath; } return cnxn.chrootPath + clientPath; } else { return clientPath; } } /** * Create a node with the given path. The node data will be the given data, * and node acl will be the given acl. * <p> * The flags argument specifies whether the created node will be ephemeral * or not. * <p> * An ephemeral node will be removed by the ZooKeeper automatically when the * session associated with the creation of the node expires. * <p> * The flags argument can also specify to create a sequential node. The * actual path name of a sequential node will be the given path plus a * suffix "i" where i is the current sequential number of the node. The sequence * number is always fixed length of 10 digits, 0 padded. Once * such a node is created, the sequential number will be incremented by one. * <p> * If a node with the same actual path already exists in the ZooKeeper, a * KeeperException with error code KeeperException.NodeExists will be * thrown. Note that since a different actual path is used for each * invocation of creating sequential node with the same path argument, the * call will never throw "file exists" KeeperException. * <p> * If the parent node does not exist in the ZooKeeper, a KeeperException * with error code KeeperException.NoNode will be thrown. * <p> * An ephemeral node cannot have children. If the parent node of the given * path is ephemeral, a KeeperException with error code * KeeperException.NoChildrenForEphemerals will be thrown. * <p> * This operation, if successful, will trigger all the watches left on the * node of the given path by exists and getData API calls, and the watches * left on the parent node by getChildren API calls. * <p> * If a node is created successfully, the ZooKeeper server will trigger the * watches on the path left by exists calls, and the watches on the parent * of the node by getChildren calls. * <p> * The maximum allowable size of the data array is 1 MB (1,048,576 bytes). * Arrays larger than this will cause a KeeperExecption to be thrown. * * @param path * the path for the node * @param data * the initial data for the node * @param acl * the acl for the node * @param createMode * specifying whether the node to be created is ephemeral * and/or sequential * @return the actual path of the created node * @throws KeeperException if the server returns a non-zero error code * @throws KeeperException.InvalidACLException if the ACL is invalid, null, or empty * @throws InterruptedException if the transaction is interrupted * @throws IllegalArgumentException if an invalid path is specified */ public String create(final String path, byte data[], List<ACL> acl, CreateMode createMode) throws KeeperException, InterruptedException { final String clientPath = path; PathUtils.validatePath(clientPath, createMode.isSequential()); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.create); CreateRequest request = new CreateRequest(); CreateResponse response = new CreateResponse(); request.setData(data); request.setFlags(createMode.toFlag()); request.setPath(serverPath); if (acl != null && acl.size() == 0) { throw new KeeperException.InvalidACLException(); } request.setAcl(acl); ReplyHeader r = cnxn.submitRequest(h, request, response, null); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } if (cnxn.chrootPath == null) { return response.getPath(); } else { return response.getPath().substring(cnxn.chrootPath.length()); } } /** * The asynchronous version of create. * * @see #create(String, byte[], List, CreateMode) */ public void create(final String path, byte data[], List<ACL> acl, CreateMode createMode, StringCallback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath, createMode.isSequential()); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.create); CreateRequest request = new CreateRequest(); CreateResponse response = new CreateResponse(); ReplyHeader r = new ReplyHeader(); request.setData(data); request.setFlags(createMode.toFlag()); request.setPath(serverPath); request.setAcl(acl); cnxn.queuePacket(h, r, request, response, cb, clientPath, serverPath, ctx, null); } /** * Delete the node with the given path. The call will succeed if such a node * exists, and the given version matches the node's version (if the given * version is -1, it matches any node's versions). * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if the nodes does not exist. * <p> * A KeeperException with error code KeeperException.BadVersion will be * thrown if the given version does not match the node's version. * <p> * A KeeperException with error code KeeperException.NotEmpty will be thrown * if the node has children. * <p> * This operation, if successful, will trigger all the watches on the node * of the given path left by exists API calls, and the watches on the parent * node left by getChildren API calls. * * @param path * the path of the node to be deleted. * @param version * the expected node version. * @throws InterruptedException IF the server transaction is interrupted * @throws KeeperException If the server signals an error with a non-zero * return code. * @throws IllegalArgumentException if an invalid path is specified */ public void delete(final String path, int version) throws InterruptedException, KeeperException { final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath; // maintain semantics even in chroot case // specifically - root cannot be deleted // I think this makes sense even in chroot case. if (clientPath.equals("/")) { // a bit of a hack, but delete(/) will never succeed and ensures // that the same semantics are maintained serverPath = clientPath; } else { serverPath = prependChroot(clientPath); } RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.delete); DeleteRequest request = new DeleteRequest(); request.setPath(serverPath); request.setVersion(version); ReplyHeader r = cnxn.submitRequest(h, request, null, null); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } } /** * Executes multiple ZooKeeper operations or none of them. * <p> * On success, a list of results is returned. * On failure, an exception is raised which contains partial results and * error details, see {@link KeeperException#getResults} * <p> * Note: The maximum allowable size of all of the data arrays in all of * the setData operations in this single request is typically 1 MB * (1,048,576 bytes). This limit is specified on the server via * <a href="http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#Unsafe+Options">jute.maxbuffer</a>. * Requests larger than this will cause a KeeperException to be * thrown. * * @param ops An iterable that contains the operations to be done. * These should be created using the factory methods on {@link Op}. * @return A list of results, one for each input Op, the order of * which exactly matches the order of the <code>ops</code> input * operations. * @throws InterruptedException If the operation was interrupted. * The operation may or may not have succeeded, but will not have * partially succeeded if this exception is thrown. * @throws KeeperException If the operation could not be completed * due to some error in doing one of the specified ops. * @throws IllegalArgumentException if an invalid path is specified * * @since 3.4.0 */ public List<OpResult> multi(Iterable<Op> ops) throws InterruptedException, KeeperException { for (Op op : ops) { op.validate(); } return multiInternal(generateMultiTransaction(ops)); } /** * The asynchronous version of multi. * * @see #multi(Iterable) * @since 3.4.7 */ public void multi(Iterable<Op> ops, MultiCallback cb, Object ctx) { List<OpResult> results = validatePath(ops); if (results.size() > 0) { cb.processResult(KeeperException.Code.BADARGUMENTS.intValue(), null, ctx, results); return; } multiInternal(generateMultiTransaction(ops), cb, ctx); } private List<OpResult> validatePath(Iterable<Op> ops) { List<OpResult> results = new ArrayList<OpResult>(); boolean error = false; for (Op op : ops) { try { op.validate(); } catch (IllegalArgumentException iae) { LOG.error("IllegalArgumentException: " + iae.getMessage()); ErrorResult err = new ErrorResult( KeeperException.Code.BADARGUMENTS.intValue()); results.add(err); error = true; continue; } catch (KeeperException ke) { LOG.error("KeeperException: " + ke.getMessage()); ErrorResult err = new ErrorResult(ke.code().intValue()); results.add(err); error = true; continue; } ErrorResult err = new ErrorResult( KeeperException.Code.RUNTIMEINCONSISTENCY.intValue()); results.add(err); } if (false == error) { results.clear(); } return results; } private MultiTransactionRecord generateMultiTransaction(Iterable<Op> ops) { List<Op> transaction = new ArrayList<Op>(); for (Op op : ops) { transaction.add(withRootPrefix(op)); } return new MultiTransactionRecord(transaction); } private Op withRootPrefix(Op op) { if (null != op.getPath()) { final String serverPath = prependChroot(op.getPath()); if (!op.getPath().equals(serverPath)) { return op.withChroot(serverPath); } } return op; } protected void multiInternal(MultiTransactionRecord request, MultiCallback cb, Object ctx) { RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.multi); MultiResponse response = new MultiResponse(); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, null, null, ctx, null); } protected List<OpResult> multiInternal(MultiTransactionRecord request) throws InterruptedException, KeeperException { RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.multi); MultiResponse response = new MultiResponse(); ReplyHeader r = cnxn.submitRequest(h, request, response, null); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr())); } List<OpResult> results = response.getResultList(); ErrorResult fatalError = null; for (OpResult result : results) { if (result instanceof ErrorResult && ((ErrorResult)result).getErr() != KeeperException.Code.OK.intValue()) { fatalError = (ErrorResult) result; break; } } if (fatalError != null) { KeeperException ex = KeeperException.create(KeeperException.Code.get(fatalError.getErr())); ex.setMultiResults(results); throw ex; } return results; } /** * A Transaction is a thin wrapper on the {@link #multi} method * which provides a builder object that can be used to construct * and commit an atomic set of operations. * * @since 3.4.0 * * @return a Transaction builder object */ public Transaction transaction() { return new Transaction(this); } /** * The asynchronous version of delete. * * @see #delete(String, int) */ public void delete(final String path, int version, VoidCallback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath; // maintain semantics even in chroot case // specifically - root cannot be deleted // I think this makes sense even in chroot case. if (clientPath.equals("/")) { // a bit of a hack, but delete(/) will never succeed and ensures // that the same semantics are maintained serverPath = clientPath; } else { serverPath = prependChroot(clientPath); } RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.delete); DeleteRequest request = new DeleteRequest(); request.setPath(serverPath); request.setVersion(version); cnxn.queuePacket(h, new ReplyHeader(), request, null, cb, clientPath, serverPath, ctx, null); } /** * Return the stat of the node of the given path. Return null if no such a * node exists. * <p> * If the watch is non-null and the call is successful (no exception is thrown), * a watch will be left on the node with the given path. The watch will be * triggered by a successful operation that creates/delete the node or sets * the data on the node. * * @param path the node path * @param watcher explicit watcher * @return the stat of the node of the given path; return null if no such a * node exists. * @throws KeeperException If the server signals an error * @throws InterruptedException If the server transaction is interrupted. * @throws IllegalArgumentException if an invalid path is specified */ public Stat exists(final String path, Watcher watcher) throws KeeperException, InterruptedException { final String clientPath = path; PathUtils.validatePath(clientPath); // the watch contains the un-chroot path WatchRegistration wcb = null; if (watcher != null) { wcb = new ExistsWatchRegistration(watcher, clientPath); } final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.exists); ExistsRequest request = new ExistsRequest(); request.setPath(serverPath); request.setWatch(watcher != null); SetDataResponse response = new SetDataResponse(); ReplyHeader r = cnxn.submitRequest(h, request, response, wcb); if (r.getErr() != 0) { if (r.getErr() == KeeperException.Code.NONODE.intValue()) { return null; } throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } return response.getStat().getCzxid() == -1 ? null : response.getStat(); } /** * Return the stat of the node of the given path. Return null if no such a * node exists. * <p> * If the watch is true and the call is successful (no exception is thrown), * a watch will be left on the node with the given path. The watch will be * triggered by a successful operation that creates/delete the node or sets * the data on the node. * * @param path * the node path * @param watch * whether need to watch this node * @return the stat of the node of the given path; return null if no such a * node exists. * @throws KeeperException If the server signals an error * @throws InterruptedException If the server transaction is interrupted. */ public Stat exists(String path, boolean watch) throws KeeperException, InterruptedException { return exists(path, watch ? watchManager.defaultWatcher : null); } /** * The asynchronous version of exists. * * @see #exists(String, Watcher) */ public void exists(final String path, Watcher watcher, StatCallback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath); // the watch contains the un-chroot path WatchRegistration wcb = null; if (watcher != null) { wcb = new ExistsWatchRegistration(watcher, clientPath); } final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.exists); ExistsRequest request = new ExistsRequest(); request.setPath(serverPath); request.setWatch(watcher != null); SetDataResponse response = new SetDataResponse(); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, wcb); } /** * The asynchronous version of exists. * * @see #exists(String, boolean) */ public void exists(String path, boolean watch, StatCallback cb, Object ctx) { exists(path, watch ? watchManager.defaultWatcher : null, cb, ctx); } /** * Return the data and the stat of the node of the given path. * <p> * If the watch is non-null and the call is successful (no exception is * thrown), a watch will be left on the node with the given path. The watch * will be triggered by a successful operation that sets data on the node, or * deletes the node. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * * @param path the given path * @param watcher explicit watcher * @param stat the stat of the node * @return the data of the node * @throws KeeperException If the server signals an error with a non-zero error code * @throws InterruptedException If the server transaction is interrupted. * @throws IllegalArgumentException if an invalid path is specified */ public byte[] getData(final String path, Watcher watcher, Stat stat) throws KeeperException, InterruptedException { final String clientPath = path; PathUtils.validatePath(clientPath); // the watch contains the un-chroot path WatchRegistration wcb = null; if (watcher != null) { wcb = new DataWatchRegistration(watcher, clientPath); } final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getData); GetDataRequest request = new GetDataRequest(); request.setPath(serverPath); request.setWatch(watcher != null); GetDataResponse response = new GetDataResponse(); ReplyHeader r = cnxn.submitRequest(h, request, response, wcb); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } if (stat != null) { DataTree.copyStat(response.getStat(), stat); } return response.getData(); } /** * Return the data and the stat of the node of the given path. * <p> * If the watch is true and the call is successful (no exception is * thrown), a watch will be left on the node with the given path. The watch * will be triggered by a successful operation that sets data on the node, or * deletes the node. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * * @param path the given path * @param watch whether need to watch this node * @param stat the stat of the node * @return the data of the node * @throws KeeperException If the server signals an error with a non-zero error code * @throws InterruptedException If the server transaction is interrupted. */ public byte[] getData(String path, boolean watch, Stat stat) throws KeeperException, InterruptedException { return getData(path, watch ? watchManager.defaultWatcher : null, stat); } /** * The asynchronous version of getData. * * @see #getData(String, Watcher, Stat) */ public void getData(final String path, Watcher watcher, DataCallback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath); // the watch contains the un-chroot path WatchRegistration wcb = null; if (watcher != null) { wcb = new DataWatchRegistration(watcher, clientPath); } final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getData); GetDataRequest request = new GetDataRequest(); request.setPath(serverPath); request.setWatch(watcher != null); GetDataResponse response = new GetDataResponse(); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, wcb); } /** * The asynchronous version of getData. * * @see #getData(String, boolean, Stat) */ public void getData(String path, boolean watch, DataCallback cb, Object ctx) { getData(path, watch ? watchManager.defaultWatcher : null, cb, ctx); } /** * Set the data for the node of the given path if such a node exists and the * given version matches the version of the node (if the given version is * -1, it matches any node's versions). Return the stat of the node. * <p> * This operation, if successful, will trigger all the watches on the node * of the given path left by getData calls. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * <p> * A KeeperException with error code KeeperException.BadVersion will be * thrown if the given version does not match the node's version. * <p> * The maximum allowable size of the data array is 1 MB (1,048,576 bytes). * Arrays larger than this will cause a KeeperException to be thrown. * * @param path * the path of the node * @param data * the data to set * @param version * the expected matching version * @return the state of the node * @throws InterruptedException If the server transaction is interrupted. * @throws KeeperException If the server signals an error with a non-zero error code. * @throws IllegalArgumentException if an invalid path is specified */ public Stat setData(final String path, byte data[], int version) throws KeeperException, InterruptedException { final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.setData); SetDataRequest request = new SetDataRequest(); request.setPath(serverPath); request.setData(data); request.setVersion(version); SetDataResponse response = new SetDataResponse(); ReplyHeader r = cnxn.submitRequest(h, request, response, null); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } return response.getStat(); } /** * The asynchronous version of setData. * * @see #setData(String, byte[], int) */ public void setData(final String path, byte data[], int version, StatCallback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.setData); SetDataRequest request = new SetDataRequest(); request.setPath(serverPath); request.setData(data); request.setVersion(version); SetDataResponse response = new SetDataResponse(); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, null); } /** * Return the ACL and stat of the node of the given path. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * * @param path * the given path for the node * @param stat * the stat of the node will be copied to this parameter if * not null. * @return the ACL array of the given node. * @throws InterruptedException If the server transaction is interrupted. * @throws KeeperException If the server signals an error with a non-zero error code. * @throws IllegalArgumentException if an invalid path is specified */ public List<ACL> getACL(final String path, Stat stat) throws KeeperException, InterruptedException { final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getACL); GetACLRequest request = new GetACLRequest(); request.setPath(serverPath); GetACLResponse response = new GetACLResponse(); ReplyHeader r = cnxn.submitRequest(h, request, response, null); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } if (stat != null) { DataTree.copyStat(response.getStat(), stat); } return response.getAcl(); } /** * The asynchronous version of getACL. * * @see #getACL(String, Stat) */ public void getACL(final String path, Stat stat, ACLCallback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getACL); GetACLRequest request = new GetACLRequest(); request.setPath(serverPath); GetACLResponse response = new GetACLResponse(); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, null); } /** * Set the ACL for the node of the given path if such a node exists and the * given version matches the version of the node. Return the stat of the * node. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * <p> * A KeeperException with error code KeeperException.BadVersion will be * thrown if the given version does not match the node's version. * * @param path * @param acl * @param version * @return the stat of the node. * @throws InterruptedException If the server transaction is interrupted. * @throws KeeperException If the server signals an error with a non-zero error code. * @throws org.apache.zookeeper.KeeperException.InvalidACLException If the acl is invalide. * @throws IllegalArgumentException if an invalid path is specified */ public Stat setACL(final String path, List<ACL> acl, int version) throws KeeperException, InterruptedException { final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.setACL); SetACLRequest request = new SetACLRequest(); request.setPath(serverPath); if (acl != null && acl.size() == 0) { throw new KeeperException.InvalidACLException(clientPath); } request.setAcl(acl); request.setVersion(version); SetACLResponse response = new SetACLResponse(); ReplyHeader r = cnxn.submitRequest(h, request, response, null); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } return response.getStat(); } /** * The asynchronous version of setACL. * * @see #setACL(String, List, int) */ public void setACL(final String path, List<ACL> acl, int version, StatCallback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.setACL); SetACLRequest request = new SetACLRequest(); request.setPath(serverPath); request.setAcl(acl); request.setVersion(version); SetACLResponse response = new SetACLResponse(); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, null); } /** * Return the list of the children of the node of the given path. * <p> * If the watch is non-null and the call is successful (no exception is thrown), * a watch will be left on the node with the given path. The watch willbe * triggered by a successful operation that deletes the node of the given * path or creates/delete a child under the node. * <p> * The list of children returned is not sorted and no guarantee is provided * as to its natural or lexical order. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * * @param path * @param watcher explicit watcher * @return an unordered array of children of the node with the given path * @throws InterruptedException If the server transaction is interrupted. * @throws KeeperException If the server signals an error with a non-zero error code. * @throws IllegalArgumentException if an invalid path is specified */ public List<String> getChildren(final String path, Watcher watcher) throws KeeperException, InterruptedException { final String clientPath = path; PathUtils.validatePath(clientPath); // the watch contains the un-chroot path WatchRegistration wcb = null; if (watcher != null) { wcb = new ChildWatchRegistration(watcher, clientPath); } final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getChildren); GetChildrenRequest request = new GetChildrenRequest(); request.setPath(serverPath); request.setWatch(watcher != null); GetChildrenResponse response = new GetChildrenResponse(); ReplyHeader r = cnxn.submitRequest(h, request, response, wcb); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } return response.getChildren(); } /** * Return the list of the children of the node of the given path. * <p> * If the watch is true and the call is successful (no exception is thrown), * a watch will be left on the node with the given path. The watch willbe * triggered by a successful operation that deletes the node of the given * path or creates/delete a child under the node. * <p> * The list of children returned is not sorted and no guarantee is provided * as to its natural or lexical order. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * * @param path * @param watch * @return an unordered array of children of the node with the given path * @throws InterruptedException If the server transaction is interrupted. * @throws KeeperException If the server signals an error with a non-zero error code. */ public List<String> getChildren(String path, boolean watch) throws KeeperException, InterruptedException { return getChildren(path, watch ? watchManager.defaultWatcher : null); } /** * The asynchronous version of getChildren. * * @see #getChildren(String, Watcher) */ public void getChildren(final String path, Watcher watcher, ChildrenCallback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath); // the watch contains the un-chroot path WatchRegistration wcb = null; if (watcher != null) { wcb = new ChildWatchRegistration(watcher, clientPath); } final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getChildren); GetChildrenRequest request = new GetChildrenRequest(); request.setPath(serverPath); request.setWatch(watcher != null); GetChildrenResponse response = new GetChildrenResponse(); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, wcb); } /** * The asynchronous version of getChildren. * * @see #getChildren(String, boolean) */ public void getChildren(String path, boolean watch, ChildrenCallback cb, Object ctx) { getChildren(path, watch ? watchManager.defaultWatcher : null, cb, ctx); } /** * For the given znode path return the stat and children list. * <p> * If the watch is non-null and the call is successful (no exception is thrown), * a watch will be left on the node with the given path. The watch willbe * triggered by a successful operation that deletes the node of the given * path or creates/delete a child under the node. * <p> * The list of children returned is not sorted and no guarantee is provided * as to its natural or lexical order. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * * @since 3.3.0 * * @param path * @param watcher explicit watcher * @param stat stat of the znode designated by path * @return an unordered array of children of the node with the given path * @throws InterruptedException If the server transaction is interrupted. * @throws KeeperException If the server signals an error with a non-zero error code. * @throws IllegalArgumentException if an invalid path is specified */ public List<String> getChildren(final String path, Watcher watcher, Stat stat) throws KeeperException, InterruptedException { final String clientPath = path; PathUtils.validatePath(clientPath); // the watch contains the un-chroot path WatchRegistration wcb = null; if (watcher != null) { wcb = new ChildWatchRegistration(watcher, clientPath); } final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getChildren2); GetChildren2Request request = new GetChildren2Request(); request.setPath(serverPath); request.setWatch(watcher != null); GetChildren2Response response = new GetChildren2Response(); ReplyHeader r = cnxn.submitRequest(h, request, response, wcb); if (r.getErr() != 0) { throw KeeperException.create(KeeperException.Code.get(r.getErr()), clientPath); } if (stat != null) { DataTree.copyStat(response.getStat(), stat); } return response.getChildren(); } /** * For the given znode path return the stat and children list. * <p> * If the watch is true and the call is successful (no exception is thrown), * a watch will be left on the node with the given path. The watch willbe * triggered by a successful operation that deletes the node of the given * path or creates/delete a child under the node. * <p> * The list of children returned is not sorted and no guarantee is provided * as to its natural or lexical order. * <p> * A KeeperException with error code KeeperException.NoNode will be thrown * if no node with the given path exists. * * @since 3.3.0 * * @param path * @param watch * @param stat stat of the znode designated by path * @return an unordered array of children of the node with the given path * @throws InterruptedException If the server transaction is interrupted. * @throws KeeperException If the server signals an error with a non-zero * error code. */ public List<String> getChildren(String path, boolean watch, Stat stat) throws KeeperException, InterruptedException { return getChildren(path, watch ? watchManager.defaultWatcher : null, stat); } /** * The asynchronous version of getChildren. * * @since 3.3.0 * * @see #getChildren(String, Watcher, Stat) */ public void getChildren(final String path, Watcher watcher, Children2Callback cb, Object ctx) { final String clientPath = path; PathUtils.validatePath(clientPath); // the watch contains the un-chroot path WatchRegistration wcb = null; if (watcher != null) { wcb = new ChildWatchRegistration(watcher, clientPath); } final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.getChildren2); GetChildren2Request request = new GetChildren2Request(); request.setPath(serverPath); request.setWatch(watcher != null); GetChildren2Response response = new GetChildren2Response(); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, wcb); } /** * The asynchronous version of getChildren. * * @since 3.3.0 * * @see #getChildren(String, boolean, Stat) */ public void getChildren(String path, boolean watch, Children2Callback cb, Object ctx) { getChildren(path, watch ? watchManager.defaultWatcher : null, cb, ctx); } /** * Asynchronous sync. Flushes channel between process and leader. * @param path * @param cb a handler for the callback * @param ctx context to be provided to the callback * @throws IllegalArgumentException if an invalid path is specified */ public void sync(final String path, VoidCallback cb, Object ctx){ final String clientPath = path; PathUtils.validatePath(clientPath); final String serverPath = prependChroot(clientPath); RequestHeader h = new RequestHeader(); h.setType(ZooDefs.OpCode.sync); SyncRequest request = new SyncRequest(); SyncResponse response = new SyncResponse(); request.setPath(serverPath); cnxn.queuePacket(h, new ReplyHeader(), request, response, cb, clientPath, serverPath, ctx, null); } public States getState() { return cnxn.getState(); } /** * String representation of this ZooKeeper client. Suitable for things * like logging. * * Do NOT count on the format of this string, it may change without * warning. * * @since 3.3.0 */ @Override public String toString() { States state = getState(); return ("State:" + state.toString() + (state.isConnected() ? " Timeout:" + getSessionTimeout() + " " : " ") + cnxn); } /* * Methods to aid in testing follow. * * THESE METHODS ARE EXPECTED TO BE USED FOR TESTING ONLY!!! */ /** * Wait up to wait milliseconds for the underlying threads to shutdown. * THIS METHOD IS EXPECTED TO BE USED FOR TESTING ONLY!!! * * @since 3.3.0 * * @param wait max wait in milliseconds * @return true iff all threads are shutdown, otw false */ protected boolean testableWaitForShutdown(int wait) throws InterruptedException { cnxn.sendThread.join(wait); if (cnxn.sendThread.isAlive()) return false; cnxn.eventThread.join(wait); if (cnxn.eventThread.isAlive()) return false; return true; } /** * Returns the address to which the socket is connected. Useful for testing * against an ensemble - test client may need to know which server * to shutdown if interested in verifying that the code handles * disconnection/reconnection correctly. * THIS METHOD IS EXPECTED TO BE USED FOR TESTING ONLY!!! * * @since 3.3.0 * * @return ip address of the remote side of the connection or null if * not connected */ protected SocketAddress testableRemoteSocketAddress() { return cnxn.sendThread.getClientCnxnSocket().getRemoteSocketAddress(); } /** * Returns the local address to which the socket is bound. * THIS METHOD IS EXPECTED TO BE USED FOR TESTING ONLY!!! * * @since 3.3.0 * * @return ip address of the remote side of the connection or null if * not connected */ protected SocketAddress testableLocalSocketAddress() { return cnxn.sendThread.getClientCnxnSocket().getLocalSocketAddress(); } private static ClientCnxnSocket getClientCnxnSocket() throws IOException { String clientCnxnSocketName = System .getProperty(ZOOKEEPER_CLIENT_CNXN_SOCKET); if (clientCnxnSocketName == null) { clientCnxnSocketName = ClientCnxnSocketNIO.class.getName(); } try { return (ClientCnxnSocket) Class.forName(clientCnxnSocketName) .newInstance(); } catch (Exception e) { IOException ioe = new IOException("Couldn't instantiate " + clientCnxnSocketName); ioe.initCause(e); throw ioe; } } }
注:Zookeeper的用法基本上都可以在这个类里面找到。
Zookeeper构造函数实例
package com.github.boonya.zookeeper;import java.io.IOException;
import org.apache.zookeeper.Watcher;
import org.apache.zookeeper.ZooKeeper;
/**
* Zookeeper构造参数类
*
* @package com.github.boonya.zookeeper.ZkZookeeper
* @date 2017年3月28日 上午10:48:24
* @author pengjunlin
* @comment
* @update
*/
public class ZkZookeeper extends ZooKeeper {
/**
*
* @param connectString
* ip:port
* @param sessionTimeout
* @param watcher
* @param sessionId
* @param sessionPasswd
* @param canBeReadOnly
* @throws IOException
*/
public ZkZookeeper(String connectString, int sessionTimeout,
Watcher watcher, long sessionId, byte[] sessionPasswd,
boolean canBeReadOnly) throws IOException {
super(connectString, sessionTimeout, watcher, sessionId, sessionPasswd,
canBeReadOnly);
// TODO Auto-generated constructor stub
}
/**
*
* @param connectString
* ip:port
* @param sessionTimeout
* @param watcher
* @param sessionId
* @param sessionPasswd
* @throws IOException
*/
public ZkZookeeper(String connectString, int sessionTimeout,
Watcher watcher, long sessionId, byte[] sessionPasswd)
throws IOException {
super(connectString, sessionTimeout, watcher, sessionId, sessionPasswd);
// TODO Auto-generated constructor stub
}
/**
*
* @param connectString
* ip:port
* @param sessionTimeout
* @param watcher
* @param canBeReadOnly
* @throws IOException
*/
public ZkZookeeper(String connectString, int sessionTimeout,
Watcher watcher, boolean canBeReadOnly) throws IOException {
super(connectString, sessionTimeout, watcher, canBeReadOnly);
// TODO Auto-generated constructor stub
}
/**
*
* @param connectString
* ip:port
* @param sessionTimeout
* @param watcher
* @throws IOException
*/
public ZkZookeeper(String connectString, int sessionTimeout, Watcher watcher)
throws IOException {
super(connectString, sessionTimeout, watcher);
// TODO Auto-generated constructor stub
}
}
Zookeeper支持四种构造实现。
参考资料
Zookeeper系列之二Zookeeper常用命令:https://my.oschina.net/u/347386/blog/313037Zookeeper客户端API之会话创建:http://blog.csdn.net/wo541075754/article/details/61190967
相关文章推荐
- ZooKeeper 之 zkCli.sh客户端的命令使用
- zookeeper客户端zkCli.sh常用命令
- ZooKeeper 学习 (三) 客户端zkCli.sh以及相关操作命令
- java客户端测试连接zookeeper服务器
- zookeeper命令行(zkCli.sh&zkServer.sh)使用及四字命令
- Zookeeper客户端基本操作java实现——创建连接、创建节点、添加修改节点内容、获取子节点、获取节点数据、删除节点
- ZooKeeper客户端脚本zkCli.sh的节点操作
- Java编写Telnet客户端,连接到Windows的Telnet服务器,执行命令和批处理脚本
- zookeeper zkCli 客户端常用命令详解
- zookeeper命令行(zkCli.sh&zkServer.sh)使用及四字命令
- Zookeeper命令行操作(常用命令;客户端连接;查看znode路径;创建节点;获取znode数据,查看节点内容,设置节点内容,删除节点;监听znode事件;telnet连接zookeeper)
- RabbitMQ学习之Java客户端连接测试(二)
- zookeeper搭建以及Java连接zookeeper测试
- 分布式服务管理框架-Zookeeper客户端zkCli.sh使用详解
- zkCli.sh客户端其他命令简介
- zookeeper学习笔记1-zk简单安装及zkCli客户端命令
- Not a host:port pair: PBUF(用Java客户端(Eclipse平台)连接Hbase)&&apache官网Jar下载流程
- zookeeper 客户端 zkCli.sh 的使用 查看节点
- RabbitMQ/JAVA 客户端连接测试
- zookeeper命令行(zkCli.sh&zkServer.sh)使用及四字命令