void createClient() throws Exception { PathBasedZkSerializer zkSerializer = ChainedPathZkSerializer.builder(new ZNRecordStreamingSerializer()).build(); _zkclient = new ZkClient( _zkAddress, _sessionTimeout, ZkClient.DEFAULT_CONNECTION_TIMEOUT, zkSerializer); _baseDataAccessor = createBaseDataAccessor(); _dataAccessor = new ZKHelixDataAccessor(_clusterName, _instanceType, _baseDataAccessor); _configAccessor = new ConfigAccessor(_zkclient); int retryCount = 0; _zkclient.subscribeStateChanges(this); while (retryCount < 3) { try { _zkclient.waitUntilConnected(_sessionTimeout, TimeUnit.MILLISECONDS); handleStateChanged(KeeperState.SyncConnected); handleNewSession(); break; } catch (HelixException e) { LOG.error("fail to createClient.", e); throw e; } catch (Exception e) { retryCount++; LOG.error("fail to createClient. retry " + retryCount, e); if (retryCount == 3) { throw e; } } } }
/** sync remove */ @Override public boolean remove(String path, int options) { try { // optimize on common path _zkClient.delete(path); } catch (ZkException e) { _zkClient.deleteRecursive(path); } return true; }
/** * sync update * * @return: updatedData on success, or null on fail */ public T update( String path, DataUpdater<T> updater, List<String> createPaths, Stat stat, int options) { CreateMode mode = AccessOption.getMode(options); if (mode == null) { LOG.error("Invalid update mode. options: " + options); return null; } boolean retry; T updatedData = null; do { retry = false; try { Stat readStat = new Stat(); T oldData = (T) _zkClient.readData(path, readStat); T newData = updater.update(oldData); Stat setStat = _zkClient.writeDataGetStat(path, newData, readStat.getVersion()); if (stat != null) { DataTree.copyStat(setStat, stat); } updatedData = newData; } catch (ZkBadVersionException e) { retry = true; } catch (ZkNoNodeException e) { // node not exist, try create try { T newData = updater.update(null); RetCode rc = create(path, newData, createPaths, options); switch (rc) { case OK: updatedData = newData; break; case NODE_EXISTS: retry = true; break; default: LOG.error("Fail to update path by creating: " + path); return null; } } catch (Exception e1) { LOG.error("Exception while updating path by creating: " + path, e1); return null; } } catch (Exception e) { LOG.error("Exception while updating path: " + path, e); return null; } } while (retry); return updatedData; }
@Override public void disconnect() { if (_zkclient == null) { LOG.info("instanceName: " + _instanceName + " already disconnected"); return; } LOG.info("disconnect " + _instanceName + "(" + _instanceType + ") from " + _clusterName); try { /** stop all timer tasks */ stopTimerTasks(); /** * shutdown thread pool first to avoid reset() being invoked in the middle of state transition */ _messagingService.getExecutor().shutdown(); // TODO reset user defined handlers only resetHandlers(); _dataAccessor.shutdown(); if (_leaderElectionHandler != null) { _leaderElectionHandler.reset(); } } finally { _zkclient.close(); _zkclient = null; LOG.info("Cluster manager: " + _instanceName + " disconnected"); } }
public boolean offer(T element) { try { _zkClient.createPersistentSequential(_root + "/" + ELEMENT_NAME + "-", element); } catch (Exception e) { throw ExceptionUtil.convertToRuntimeException(e); } return true; }
/** * sync getChildNames * * @return null if parentPath doesn't exist */ @Override public List<String> getChildNames(String parentPath, int options) { try { List<String> childNames = _zkClient.getChildren(parentPath); Collections.sort(childNames); return childNames; } catch (ZkNoNodeException e) { return null; } }
/** sync get */ @Override public T get(String path, Stat stat, int options) { T data = null; try { data = (T) _zkClient.readData(path, stat); } catch (ZkNoNodeException e) { if (AccessOption.isThrowExceptionIfNotExist(options)) { throw e; } } return data; }
@Override public boolean isConnected() { if (_zkclient == null) { return false; } ZkConnection zkconnection = (ZkConnection) _zkclient.getConnection(); if (zkconnection != null) { States state = zkconnection.getZookeeperState(); return state == States.CONNECTED; } return false; }
@SuppressWarnings("unchecked") private Element<T> getFirstElement() { try { while (true) { List<String> list = _zkClient.getChildren(_root); if (list.size() == 0) { return null; } String elementName = getSmallestElement(list); try { return new Element<T>( _root + "/" + elementName, (T) _zkClient.readData(_root + "/" + elementName)); } catch (ZkNoNodeException e) { // somebody else picked up the element first, so we have to // retry with the new first element } } } catch (Exception e) { throw ExceptionUtil.convertToRuntimeException(e); } }
/** * wait until we get a non-zero session-id. note that we might lose zkconnection right after we * read session-id. but it's ok to get stale session-id and we will have another * handle-new-session callback to correct this. */ void waitUntilConnected() { boolean isConnected; do { isConnected = _zkclient.waitUntilConnected(ZkClient.DEFAULT_CONNECTION_TIMEOUT, TimeUnit.MILLISECONDS); if (!isConnected) { LOG.error( "fail to connect zkserver: " + _zkAddress + " in " + ZkClient.DEFAULT_CONNECTION_TIMEOUT + "ms. expiredSessionId: " + _sessionId + ", clusterName: " + _clusterName); continue; } ZkConnection zkConnection = ((ZkConnection) _zkclient.getConnection()); _sessionId = Long.toHexString(zkConnection.getZookeeper().getSessionId()); /** * at the time we read session-id, zkconnection might be lost again wait until we get a * non-zero session-id */ } while ("0".equals(_sessionId)); LOG.info( "Handling new session, session id: " + _sessionId + ", instance: " + _instanceName + ", instanceTye: " + _instanceType + ", cluster: " + _clusterName + ", zkconnection: " + ((ZkConnection) _zkclient.getConnection()).getZookeeper()); }
@Override public void handleStateChanged(KeeperState state) throws Exception { switch (state) { case SyncConnected: ZkConnection zkConnection = (ZkConnection) _zkclient.getConnection(); LOG.info("KeeperState: " + state + ", zookeeper:" + zkConnection.getZookeeper()); break; case Disconnected: LOG.info( "KeeperState:" + state + ", disconnectedSessionId: " + _sessionId + ", instance: " + _instanceName + ", type: " + _instanceType); /** * Track the time stamp that the disconnected happens, then check history and see if we * should disconnect the helix-manager */ _disconnectTimeHistory.add(System.currentTimeMillis()); if (isFlapping()) { LOG.error( "instanceName: " + _instanceName + " is flapping. diconnect it. " + " maxDisconnectThreshold: " + _maxDisconnectThreshold + " disconnects in " + _flappingTimeWindowMs + "ms."); disconnect(); } break; case Expired: LOG.info( "KeeperState:" + state + ", expiredSessionId: " + _sessionId + ", instance: " + _instanceName + ", type: " + _instanceType); break; default: break; } }
/** * sync set * * @param setstat : if node is created instead of set, stat will NOT be set */ public boolean set( String path, T record, List<String> pathsCreated, Stat setstat, int expectVersion, int options) { CreateMode mode = AccessOption.getMode(options); if (mode == null) { LOG.error("Invalid set mode. options: " + options); return false; } boolean retry; do { retry = false; try { // _zkClient.writeData(path, record); Stat setStat = _zkClient.writeDataGetStat(path, record, expectVersion); if (setstat != null) DataTree.copyStat(setStat, setstat); } catch (ZkNoNodeException e) { // node not exists, try create. in this case, stat will not be set try { RetCode rc = create(path, record, pathsCreated, options); // if (rc == RetCode.OK || rc == RetCode.NODE_EXISTS) // retry = true; switch (rc) { case OK: // not set stat if node is created (instead of set) break; case NODE_EXISTS: retry = true; break; default: LOG.error("Fail to set path by creating: " + path); return false; } } catch (Exception e1) { LOG.error("Exception while setting path by creating: " + path, e); return false; } } catch (ZkBadVersionException e) { throw e; } catch (Exception e) { LOG.error("Exception while setting path: " + path, e); return false; } } while (retry); return true; }
public T poll() { while (true) { Element<T> element = getFirstElement(); if (element == null) { return null; } try { _zkClient.delete(element.getName()); return element.getData(); } catch (ZkNoNodeException e) { // somebody else picked up the element first, so we have to // retry with the new first element } catch (Exception e) { throw ExceptionUtil.convertToRuntimeException(e); } } }
/** async getStat */ @Override public Stat[] getStats(List<String> paths, int options) { if (paths == null || paths.size() == 0) { LOG.error("paths is null or empty"); return new Stat[0]; } Stat[] stats = new Stat[paths.size()]; long startT = System.nanoTime(); try { ExistsCallbackHandler[] cbList = new ExistsCallbackHandler[paths.size()]; for (int i = 0; i < paths.size(); i++) { String path = paths.get(i); cbList[i] = new ExistsCallbackHandler(); _zkClient.asyncExists(path, cbList[i]); } for (int i = 0; i < cbList.length; i++) { ExistsCallbackHandler cb = cbList[i]; cb.waitForSuccess(); stats[i] = cb._stat; } return stats; } finally { long endT = System.nanoTime(); if (LOG.isDebugEnabled()) { LOG.debug( "exists_async, size: " + paths.size() + ", paths: " + paths.get(0) + ",... time: " + (endT - startT) + " ns"); } } }
/** async remove */ @Override public boolean[] remove(List<String> paths, int options) { if (paths == null || paths.size() == 0) { return new boolean[0]; } boolean[] success = new boolean[paths.size()]; DeleteCallbackHandler[] cbList = new DeleteCallbackHandler[paths.size()]; long startT = System.nanoTime(); try { for (int i = 0; i < paths.size(); i++) { String path = paths.get(i); cbList[i] = new DeleteCallbackHandler(); _zkClient.asyncDelete(path, cbList[i]); } for (int i = 0; i < cbList.length; i++) { DeleteCallbackHandler cb = cbList[i]; cb.waitForSuccess(); success[i] = (cb.getRc() == 0); } return success; } finally { long endT = System.nanoTime(); if (LOG.isDebugEnabled()) { LOG.debug( "delete_async, size: " + paths.size() + ", paths: " + paths.get(0) + ",... time: " + (endT - startT) + " ns"); } } }
/** sync create */ public RetCode create(String path, T record, List<String> pathCreated, int options) { CreateMode mode = AccessOption.getMode(options); if (mode == null) { LOG.error("Invalid create mode. options: " + options); return RetCode.ERROR; } boolean retry; do { retry = false; try { _zkClient.create(path, record, mode); if (pathCreated != null) pathCreated.add(path); return RetCode.OK; } catch (ZkNoNodeException e) { // this will happen if parent node does not exist String parentPath = new File(path).getParent(); try { RetCode rc = create(parentPath, null, pathCreated, AccessOption.PERSISTENT); if (rc == RetCode.OK || rc == RetCode.NODE_EXISTS) { // if parent node created/exists, retry retry = true; } } catch (Exception e1) { LOG.error("Exception while creating path: " + parentPath, e1); return RetCode.ERROR; } } catch (ZkNodeExistsException e) { LOG.warn("Node already exists. path: " + path); return RetCode.NODE_EXISTS; } catch (Exception e) { LOG.error("Exception while creating path: " + path, e); return RetCode.ERROR; } } while (retry); return RetCode.OK; }
@Override public void process(WatchedEvent event) { if (!asnycConnection && event.getState() == Event.KeeperState.SyncConnected) { connectionLock.release(); // 连接成功 } else if (event.getState() == Event.KeeperState.Disconnected) { // 连接断开 log.warn("zookeeper 连接断开......"); } else if (event.getState() == Event.KeeperState.Expired) { // 连接超时 log.warn("zookeeper session timeout......"); try { zkClient.reconnect(); process.relisten(); process.recreate(); } catch (Exception e) { log.error("reconnection to zookeeper error.", e); } } if (event.getType() == Event.EventType.NodeChildrenChanged) { // 子节点变化 process.clientNodeChanged(event.getPath()); } else if (event.getType() == Event.EventType.NodeDataChanged) { // 节点数据变化 process.nodeDataChanged(event.getPath()); } }
// simple test public static void main(String[] args) { ZkClient zkclient = new ZkClient("localhost:2191"); zkclient.setZkSerializer(new ZNRecordSerializer()); ZkBaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(zkclient); // test async create List<String> createPaths = Arrays.asList("/test/child1/child1", "/test/child2/child2"); List<ZNRecord> createRecords = Arrays.asList(new ZNRecord("child1"), new ZNRecord("child2")); boolean[] needCreate = new boolean[createPaths.size()]; Arrays.fill(needCreate, true); List<List<String>> pathsCreated = new ArrayList<List<String>>(Collections.<List<String>>nCopies(createPaths.size(), null)); accessor.create(createPaths, createRecords, needCreate, pathsCreated, AccessOption.PERSISTENT); System.out.println("pathsCreated: " + pathsCreated); // test async set List<String> setPaths = Arrays.asList("/test/setChild1/setChild1", "/test/setChild2/setChild2"); List<ZNRecord> setRecords = Arrays.asList(new ZNRecord("setChild1"), new ZNRecord("setChild2")); pathsCreated = new ArrayList<List<String>>(Collections.<List<String>>nCopies(setPaths.size(), null)); boolean[] success = accessor.set(setPaths, setRecords, pathsCreated, null, AccessOption.PERSISTENT); System.out.println("pathsCreated: " + pathsCreated); System.out.println("setSuccess: " + Arrays.toString(success)); // test async update List<String> updatePaths = Arrays.asList("/test/updateChild1/updateChild1", "/test/setChild2/setChild2"); class TestUpdater implements DataUpdater<ZNRecord> { final ZNRecord _newData; public TestUpdater(ZNRecord newData) { _newData = newData; } @Override public ZNRecord update(ZNRecord currentData) { return _newData; } } List<DataUpdater<ZNRecord>> updaters = Arrays.asList( (DataUpdater<ZNRecord>) new TestUpdater(new ZNRecord("updateChild1")), (DataUpdater<ZNRecord>) new TestUpdater(new ZNRecord("updateChild2"))); pathsCreated = new ArrayList<List<String>>(Collections.<List<String>>nCopies(updatePaths.size(), null)); List<ZNRecord> updateRecords = accessor.update(updatePaths, updaters, pathsCreated, null, AccessOption.PERSISTENT); for (int i = 0; i < updatePaths.size(); i++) { success[i] = updateRecords.get(i) != null; } System.out.println("pathsCreated: " + pathsCreated); System.out.println("updateSuccess: " + Arrays.toString(success)); System.out.println("CLOSING"); zkclient.close(); }
/** async get */ List<T> get(List<String> paths, List<Stat> stats, boolean[] needRead) { if (paths == null || paths.size() == 0) { return Collections.emptyList(); } // init stats if (stats != null) { stats.clear(); stats.addAll(Collections.<Stat>nCopies(paths.size(), null)); } long startT = System.nanoTime(); try { // issue asyn get requests GetDataCallbackHandler[] cbList = new GetDataCallbackHandler[paths.size()]; for (int i = 0; i < paths.size(); i++) { if (!needRead[i]) continue; String path = paths.get(i); cbList[i] = new GetDataCallbackHandler(); _zkClient.asyncGetData(path, cbList[i]); } // wait for completion for (int i = 0; i < cbList.length; i++) { if (!needRead[i]) continue; GetDataCallbackHandler cb = cbList[i]; cb.waitForSuccess(); } // construct return results List<T> records = new ArrayList<T>(Collections.<T>nCopies(paths.size(), null)); for (int i = 0; i < paths.size(); i++) { if (!needRead[i]) continue; GetDataCallbackHandler cb = cbList[i]; if (Code.get(cb.getRc()) == Code.OK) { @SuppressWarnings("unchecked") T record = (T) _zkClient.deserialize(cb._data, paths.get(i)); records.set(i, record); if (stats != null) { stats.set(i, cb._stat); } } } return records; } finally { long endT = System.nanoTime(); if (LOG.isDebugEnabled()) { LOG.debug( "getData_async, size: " + paths.size() + ", paths: " + paths.get(0) + ",... time: " + (endT - startT) + " ns"); } } }
/** sync exists */ @Override public boolean exists(String path, int options) { return _zkClient.exists(path); }
/** sync getStat */ @Override public Stat getStat(String path, int options) { return _zkClient.getStat(path); }
public boolean isEmpty() { return _zkClient.getChildren(_root).size() == 0; }
/** async set, give up on error other than NoNode */ boolean[] set( List<String> paths, List<T> records, List<List<String>> pathsCreated, List<Stat> stats, int options) { if (paths == null || paths.size() == 0) { return new boolean[0]; } if ((records != null && records.size() != paths.size()) || (pathsCreated != null && pathsCreated.size() != paths.size())) { throw new IllegalArgumentException("paths, records, and pathsCreated should be of same size"); } boolean[] success = new boolean[paths.size()]; CreateMode mode = AccessOption.getMode(options); if (mode == null) { LOG.error("Invalid async set mode. options: " + options); return success; } List<Stat> setStats = new ArrayList<Stat>(Collections.<Stat>nCopies(paths.size(), null)); SetDataCallbackHandler[] cbList = new SetDataCallbackHandler[paths.size()]; CreateCallbackHandler[] createCbList = null; boolean[] needSet = new boolean[paths.size()]; Arrays.fill(needSet, true); long startT = System.nanoTime(); try { boolean retry; do { retry = false; for (int i = 0; i < paths.size(); i++) { if (!needSet[i]) continue; String path = paths.get(i); T record = records.get(i); cbList[i] = new SetDataCallbackHandler(); _zkClient.asyncSetData(path, record, -1, cbList[i]); } boolean failOnNoNode = false; for (int i = 0; i < cbList.length; i++) { SetDataCallbackHandler cb = cbList[i]; cb.waitForSuccess(); Code rc = Code.get(cb.getRc()); switch (rc) { case OK: setStats.set(i, cb.getStat()); needSet[i] = false; break; case NONODE: // if fail on NoNode, try create the node failOnNoNode = true; break; default: // if fail on error other than NoNode, give up needSet[i] = false; break; } } // if failOnNoNode, try create if (failOnNoNode) { boolean[] needCreate = Arrays.copyOf(needSet, needSet.length); createCbList = create(paths, records, needCreate, pathsCreated, options); for (int i = 0; i < createCbList.length; i++) { CreateCallbackHandler createCb = createCbList[i]; if (createCb == null) { continue; } Code rc = Code.get(createCb.getRc()); switch (rc) { case OK: setStats.set(i, ZNode.ZERO_STAT); needSet[i] = false; break; case NODEEXISTS: retry = true; break; default: // if creation fails on error other than NodeExists // no need to retry set needSet[i] = false; break; } } } } while (retry); // construct return results for (int i = 0; i < cbList.length; i++) { SetDataCallbackHandler cb = cbList[i]; Code rc = Code.get(cb.getRc()); if (rc == Code.OK) { success[i] = true; } else if (rc == Code.NONODE) { CreateCallbackHandler createCb = createCbList[i]; if (Code.get(createCb.getRc()) == Code.OK) { success[i] = true; } } } if (stats != null) { stats.clear(); stats.addAll(setStats); } return success; } finally { long endT = System.nanoTime(); if (LOG.isDebugEnabled()) { LOG.debug( "setData_async, size: " + paths.size() + ", paths: " + paths.get(0) + ",... time: " + (endT - startT) + " ns"); } } }
/** async create. give up on error other than NONODE */ CreateCallbackHandler[] create( List<String> paths, List<T> records, boolean[] needCreate, List<List<String>> pathsCreated, int options) { if ((records != null && records.size() != paths.size()) || needCreate.length != paths.size() || (pathsCreated != null && pathsCreated.size() != paths.size())) { throw new IllegalArgumentException( "paths, records, needCreate, and pathsCreated should be of same size"); } CreateCallbackHandler[] cbList = new CreateCallbackHandler[paths.size()]; CreateMode mode = AccessOption.getMode(options); if (mode == null) { LOG.error("Invalid async set mode. options: " + options); return cbList; } boolean retry; do { retry = false; for (int i = 0; i < paths.size(); i++) { if (!needCreate[i]) continue; String path = paths.get(i); T record = records == null ? null : records.get(i); cbList[i] = new CreateCallbackHandler(); _zkClient.asyncCreate(path, record, mode, cbList[i]); } List<String> parentPaths = new ArrayList<String>(Collections.<String>nCopies(paths.size(), null)); boolean failOnNoNode = false; for (int i = 0; i < paths.size(); i++) { if (!needCreate[i]) continue; CreateCallbackHandler cb = cbList[i]; cb.waitForSuccess(); String path = paths.get(i); if (Code.get(cb.getRc()) == Code.NONODE) { String parentPath = new File(path).getParent(); parentPaths.set(i, parentPath); failOnNoNode = true; } else { // if create succeed or fail on error other than NONODE, // give up needCreate[i] = false; // if succeeds, record what paths we've created if (Code.get(cb.getRc()) == Code.OK && pathsCreated != null) { if (pathsCreated.get(i) == null) { pathsCreated.set(i, new ArrayList<String>()); } pathsCreated.get(i).add(path); } } } if (failOnNoNode) { boolean[] needCreateParent = Arrays.copyOf(needCreate, needCreate.length); CreateCallbackHandler[] parentCbList = create(parentPaths, null, needCreateParent, pathsCreated, AccessOption.PERSISTENT); for (int i = 0; i < parentCbList.length; i++) { CreateCallbackHandler parentCb = parentCbList[i]; if (parentCb == null) continue; Code rc = Code.get(parentCb.getRc()); // if parent is created, retry create child if (rc == Code.OK || rc == Code.NODEEXISTS) { retry = true; break; } } } } while (retry); return cbList; }
/** * async update * * <p>return: updatedData on success or null on fail */ List<T> update( List<String> paths, List<DataUpdater<T>> updaters, List<List<String>> pathsCreated, List<Stat> stats, int options) { if (paths == null || paths.size() == 0) { LOG.error("paths is null or empty"); return Collections.emptyList(); } if (updaters.size() != paths.size() || (pathsCreated != null && pathsCreated.size() != paths.size())) { throw new IllegalArgumentException( "paths, updaters, and pathsCreated should be of same size"); } List<Stat> setStats = new ArrayList<Stat>(Collections.<Stat>nCopies(paths.size(), null)); List<T> updateData = new ArrayList<T>(Collections.<T>nCopies(paths.size(), null)); CreateMode mode = AccessOption.getMode(options); if (mode == null) { LOG.error("Invalid update mode. options: " + options); return updateData; } SetDataCallbackHandler[] cbList = new SetDataCallbackHandler[paths.size()]; CreateCallbackHandler[] createCbList = null; boolean[] needUpdate = new boolean[paths.size()]; Arrays.fill(needUpdate, true); long startT = System.nanoTime(); try { boolean retry; do { retry = false; boolean[] needCreate = new boolean[paths.size()]; // init'ed with false boolean failOnNoNode = false; // asycn read all data List<Stat> curStats = new ArrayList<Stat>(); List<T> curDataList = get(paths, curStats, Arrays.copyOf(needUpdate, needUpdate.length)); // async update List<T> newDataList = new ArrayList<T>(); for (int i = 0; i < paths.size(); i++) { if (!needUpdate[i]) { newDataList.add(null); continue; } String path = paths.get(i); DataUpdater<T> updater = updaters.get(i); T newData = updater.update(curDataList.get(i)); newDataList.add(newData); Stat curStat = curStats.get(i); if (curStat == null) { // node not exists failOnNoNode = true; needCreate[i] = true; } else { cbList[i] = new SetDataCallbackHandler(); _zkClient.asyncSetData(path, newData, curStat.getVersion(), cbList[i]); } } // wait for completion boolean failOnBadVersion = false; for (int i = 0; i < paths.size(); i++) { SetDataCallbackHandler cb = cbList[i]; if (cb == null) continue; cb.waitForSuccess(); switch (Code.get(cb.getRc())) { case OK: updateData.set(i, newDataList.get(i)); setStats.set(i, cb.getStat()); needUpdate[i] = false; break; case NONODE: failOnNoNode = true; needCreate[i] = true; break; case BADVERSION: failOnBadVersion = true; break; default: // if fail on error other than NoNode or BadVersion // will not retry needUpdate[i] = false; break; } } // if failOnNoNode, try create if (failOnNoNode) { createCbList = create(paths, newDataList, needCreate, pathsCreated, options); for (int i = 0; i < paths.size(); i++) { CreateCallbackHandler createCb = createCbList[i]; if (createCb == null) { continue; } switch (Code.get(createCb.getRc())) { case OK: needUpdate[i] = false; updateData.set(i, newDataList.get(i)); setStats.set(i, ZNode.ZERO_STAT); break; case NODEEXISTS: retry = true; break; default: // if fail on error other than NodeExists // will not retry needUpdate[i] = false; break; } } } // if failOnBadVersion, retry if (failOnBadVersion) { retry = true; } } while (retry); if (stats != null) { stats.clear(); stats.addAll(setStats); } return updateData; } finally { long endT = System.nanoTime(); if (LOG.isDebugEnabled()) { LOG.debug( "setData_async, size: " + paths.size() + ", paths: " + paths.get(0) + ",... time: " + (endT - startT) + " ns"); } } }
/** Unsubscrie to zookeeper data changes */ @Override public void unsubscribeChildChanges(String path, IZkChildListener childListener) { _zkClient.unsubscribeChildChanges(path, childListener); }
/** Subscrie to zookeeper data changes */ @Override public List<String> subscribeChildChanges(String path, IZkChildListener listener) { return _zkClient.subscribeChildChanges(path, listener); }
/** Unsubscribe to zookeeper data changes */ @Override public void unsubscribeDataChanges(String path, IZkDataListener dataListener) { _zkClient.unsubscribeDataChanges(path, dataListener); }
/** Subscribe to zookeeper data changes */ @Override public void subscribeDataChanges(String path, IZkDataListener listener) { _zkClient.subscribeDataChanges(path, listener); }
@Test public void testAsyncZkBaseDataAccessor() { System.out.println( "START TestZkBaseDataAccessor.async at " + new Date(System.currentTimeMillis())); String root = "TestZkBaseDataAccessor_asyn"; ZkClient zkClient = new ZkClient(ZK_ADDR); zkClient.setZkSerializer(new ZNRecordSerializer()); zkClient.deleteRecursive("/" + root); ZkBaseDataAccessor<ZNRecord> accessor = new ZkBaseDataAccessor<ZNRecord>(zkClient); // test async createChildren String parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); List<ZNRecord> records = new ArrayList<ZNRecord>(); List<String> paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); records.add(new ZNRecord(msgId)); } boolean[] success = accessor.createChildren(paths, records, AccessOption.PERSISTENT); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(success[i], "Should succeed in create " + msgId); } // test get what we created for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId); ZNRecord record = zkClient.readData(path); Assert.assertEquals(record.getId(), msgId, "Should get what we created"); } // test async setChildren parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); records = new ArrayList<ZNRecord>(); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); ZNRecord newRecord = new ZNRecord(msgId); newRecord.setSimpleField("key1", "value1"); records.add(newRecord); } success = accessor.setChildren(paths, records, AccessOption.PERSISTENT); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(success[i], "Should succeed in set " + msgId); } // test get what we set for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId); ZNRecord record = zkClient.readData(path); Assert.assertEquals(record.getSimpleFields().size(), 1, "Should have 1 simple field set"); Assert.assertEquals(record.getSimpleField("key1"), "value1", "Should have value1 set"); } // test async updateChildren parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); // records = new ArrayList<ZNRecord>(); List<DataUpdater<ZNRecord>> znrecordUpdaters = new ArrayList<DataUpdater<ZNRecord>>(); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); ZNRecord newRecord = new ZNRecord(msgId); newRecord.setSimpleField("key2", "value2"); // records.add(newRecord); znrecordUpdaters.add(new ZNRecordUpdater(newRecord)); } success = accessor.updateChildren(paths, znrecordUpdaters, AccessOption.PERSISTENT); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(success[i], "Should succeed in update " + msgId); } // test get what we updated for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId); ZNRecord record = zkClient.readData(path); Assert.assertEquals(record.getSimpleFields().size(), 2, "Should have 2 simple fields set"); Assert.assertEquals(record.getSimpleField("key2"), "value2", "Should have value2 set"); } // test async getChildren parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); records = accessor.getChildren(parentPath, null, 0); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; ZNRecord record = records.get(i); Assert.assertEquals(record.getId(), msgId, "Should get what we updated"); Assert.assertEquals(record.getSimpleFields().size(), 2, "Should have 2 simple fields set"); Assert.assertEquals(record.getSimpleField("key2"), "value2", "Should have value2 set"); } // test async exists parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); } boolean[] exists = accessor.exists(paths, 0); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(exists[i], "Should exist " + msgId); } // test async getStats parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); } Stat[] stats = accessor.getStats(paths, 0); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertNotNull(stats[i], "Stat should exist for " + msgId); Assert.assertEquals( stats[i].getVersion(), 2, "DataVersion should be 2, since we set 1 and update 1 for " + msgId); } // test async remove parentPath = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1"); paths = new ArrayList<String>(); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; paths.add(PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId)); } success = accessor.remove(paths, 0); for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; Assert.assertTrue(success[i], "Should succeed in remove " + msgId); } // test get what we removed for (int i = 0; i < 10; i++) { String msgId = "msg_" + i; String path = PropertyPathConfig.getPath(PropertyType.MESSAGES, root, "host_1", msgId); boolean pathExists = zkClient.exists(path); Assert.assertFalse(pathExists, "Should be removed " + msgId); } zkClient.close(); System.out.println( "END TestZkBaseDataAccessor.async at " + new Date(System.currentTimeMillis())); }