private List<ServerNode> doNodesDiscovery() throws Exception { if (logger_ != null) { if (logger_.isInfoEnabled()) logger_.info("nodes discovery start..."); } List<String> serverNodes = registerPathNodeDataChangeWatcher(zkNodePath_); if (serverNodes == null) serverNodes = new ArrayList<>(); List<ServerNode> newestServerNodes = new ArrayList<>(); for (final String nodeKey : serverNodes) { final byte[] nodeValueBytes = zkClient_.getData().forPath(String.format("%s/%s", zkNodePath_, nodeKey)); if (nodeValueBytes == null || nodeValueBytes.length <= 0) continue; final String nodeValueInfo = new String(nodeValueBytes, ZK_CHAR_SET); final ServerNodeInfo serverNode = JSONObject.parseObject(nodeValueInfo, ServerNodeInfo.class); newestServerNodes.add(serverNode); } if (serverNodes != null) serverNodes.clear(); synchronized (this.serverNodes_) { this.serverNodes_.clear(); this.serverNodes_.addAll(newestServerNodes); if (logger_ != null) { if (logger_.isInfoEnabled()) logger_.info( String.format( "current discovery's server nodes count (%d)", this.serverNodes_.size())); } } if (logger_ != null) { if (logger_.isInfoEnabled()) logger_.info("nodes discovery end..."); } return this.nodes(); }
@Test public void testBasic() throws Exception { CuratorFramework client = CuratorFrameworkFactory.newClient(server.getConnectString(), new RetryOneTime(1)); client.start(); try { Collection<CuratorTransactionResult> results = client .inTransaction() .create() .forPath("/foo") .and() .create() .forPath("/foo/bar", "snafu".getBytes()) .and() .commit(); Assert.assertTrue(client.checkExists().forPath("/foo/bar") != null); Assert.assertEquals(client.getData().forPath("/foo/bar"), "snafu".getBytes()); CuratorTransactionResult fooResult = Iterables.find( results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo")); CuratorTransactionResult fooBarResult = Iterables.find( results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/foo/bar")); Assert.assertNotNull(fooResult); Assert.assertNotNull(fooBarResult); Assert.assertNotSame(fooResult, fooBarResult); Assert.assertEquals(fooResult.getResultPath(), "/foo"); Assert.assertEquals(fooBarResult.getResultPath(), "/foo/bar"); } finally { client.close(); } }
@Test public void testUpdateShuffleNode() throws Exception { JobId jobId = JobId.newJobId(createTestAppId(), 123456); DragonZooKeeper.NodeData node = new DragonZooKeeper.NodeData(); node.nodeId = createTestNodeId(); node.taskId = TaskId.newTaskId(jobId, 34565, TaskType.MAP); dragonZK.createShufflePath(jobId); dragonZK.createShuffleNode(jobId, newArrayList(node)); node.nodeId.setHost("NewServerHost"); dragonZK.updateShuffleNode(jobId, newArrayList(node)); Stat stat = zkClient .checkExists() .forPath( "/dragon/job_458495849584_89894985_123456/shuffle/task_458495849584_89894985_123456_m_34565"); assertNotNull(stat); byte[] data = zkClient .getData() .forPath( "/dragon/job_458495849584_89894985_123456/shuffle/task_458495849584_89894985_123456_m_34565"); assertEquals("NewServerHost:2345", new String(data)); }
/** * Try to atomically update a node in ZooKeeper, creating it if it doesn't exist. This is meant to * be used within an optimistic concurrency model. * * @param pathSuffix suffix to use to build path in ZooKeeper. * @param f function used to initialize the node, or transform the data already there. * @return true if node was created/updated, false if a concurrent modification occurred and * succeeded while trying to update/create the node. * @throws Exception */ private boolean tryAtomicUpdate(final String pathSuffix, final NodeFunction f) throws Exception { final String path = buildZookeeperPath(pathSuffix); final Stat stat = zk.checkExists().forPath(path); if (stat == null) { try { zk.create() .creatingParentsIfNeeded() .withMode(CreateMode.PERSISTENT) .forPath(path, f.initialize()); } catch (KeeperException.NodeExistsException e) { LOG.debug("Concurrent creation of " + path + ", retrying", e); return false; } } else { Mod<byte[]> newVal = f.apply(zk.getData().forPath(path)); if (newVal.hasModification()) { try { zk.setData().withVersion(stat.getVersion()).forPath(path, newVal.get()); } catch (KeeperException.BadVersionException e) { LOG.debug("Concurrent update to " + path + ", retrying.", e); return false; } } } return true; }
private boolean getCurrentValue(MutableAtomicValue<byte[]> result, Stat stat) throws Exception { boolean createIt = false; try { result.preValue = client.getData().storingStatIn(stat).forPath(path); } catch (KeeperException.NoNodeException e) { result.preValue = null; createIt = true; } return createIt; }
private boolean internalLockLoop(long startMillis, Long millisToWait, String ourPath) throws Exception { if (revocable.get() != null) { client.getData().usingWatcher(revocableWatcher).forPath(ourPath); } boolean haveTheLock = false; boolean doDelete = false; try { while (client.isStarted() && !haveTheLock) { List<String> children = getSortedChildren(); String sequenceNodeName = ourPath.substring(basePath.length() + 1); // +1 to include the slash PredicateResults predicateResults = driver.getsTheLock(client, children, sequenceNodeName, maxLeases); if (predicateResults.getsTheLock()) { haveTheLock = true; } else { String previousSequencePath = basePath + "/" + predicateResults.getPathToWatch(); synchronized (this) { Stat stat = client.checkExists().usingWatcher(watcher).forPath(previousSequencePath); if (stat != null) { if (millisToWait != null) { millisToWait -= (System.currentTimeMillis() - startMillis); startMillis = System.currentTimeMillis(); if (millisToWait <= 0) { doDelete = true; // timed out - delete our node break; } wait(millisToWait); } else { wait(); } } } // else it may have been deleted (i.e. lock released). Try to acquire again } } } catch (KeeperException e) { // ignore this and let the retry policy handle it throw e; } catch (Exception e) { doDelete = true; throw e; } finally { if (doDelete) { client.delete().guaranteed().forPath(ourPath); } } return haveTheLock; }
private void checkRevocableWatcher(String path) throws Exception { RevocationSpec entry = revocable.get(); if (entry != null) { try { byte[] bytes = client.getData().usingWatcher(revocableWatcher).forPath(path); if (Arrays.equals(bytes, REVOKE_MESSAGE)) { entry.getExecutor().execute(entry.getRunnable()); } } catch (KeeperException.NoNodeException ignore) { // ignore } } }
@Test public void testWithNamespace() throws Exception { CuratorFramework client = CuratorFrameworkFactory.builder() .connectString(server.getConnectString()) .retryPolicy(new RetryOneTime(1)) .namespace("galt") .build(); client.start(); try { Collection<CuratorTransactionResult> results = client .inTransaction() .create() .forPath("/foo", "one".getBytes()) .and() .create() .withMode(CreateMode.PERSISTENT_SEQUENTIAL) .forPath("/test-", "one".getBytes()) .and() .setData() .forPath("/foo", "two".getBytes()) .and() .create() .forPath("/foo/bar") .and() .delete() .forPath("/foo/bar") .and() .commit(); Assert.assertTrue(client.checkExists().forPath("/foo") != null); Assert.assertTrue(client.nonNamespaceView().checkExists().forPath("/galt/foo") != null); Assert.assertEquals(client.getData().forPath("/foo"), "two".getBytes()); Assert.assertTrue(client.checkExists().forPath("/foo/bar") == null); CuratorTransactionResult ephemeralResult = Iterables.find( results, CuratorTransactionResult.ofTypeAndPath(OperationType.CREATE, "/test-")); Assert.assertNotNull(ephemeralResult); Assert.assertNotEquals(ephemeralResult.getResultPath(), "/test-"); Assert.assertTrue(ephemeralResult.getResultPath().startsWith("/test-")); } finally { client.close(); } }
private synchronized void readValue() throws Exception { Stat localStat = new Stat(); byte[] bytes = client.getData().storingStatIn(localStat).usingWatcher(watcher).forPath(path); stat = localStat; value = bytes; }