@Test public void testMagicVersionNumberAllowsUnconditionalUpdate() throws Exception { String nodePath = "/foo"; ZooKeeperClient zkClient = createZkClient(); zkClient.get().create(nodePath, "init".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT); Stat initStat = new Stat(); byte[] initialData = zkClient.get().getData(nodePath, false, initStat); assertArrayEquals("init".getBytes(), initialData); // bump the version Stat rev1Stat = zkClient.get().setData(nodePath, "rev1".getBytes(), initStat.getVersion()); try { zkClient.get().setData(nodePath, "rev2".getBytes(), initStat.getVersion()); fail("expected correct version to be required"); } catch (BadVersionException e) { // expected } // expect using the correct version to work Stat rev2Stat = zkClient.get().setData(nodePath, "rev2".getBytes(), rev1Stat.getVersion()); assertNotEquals(ZooKeeperUtils.ANY_VERSION, rev2Stat.getVersion()); zkClient.get().setData(nodePath, "force-write".getBytes(), ZooKeeperUtils.ANY_VERSION); Stat forceWriteStat = new Stat(); byte[] forceWriteData = zkClient.get().getData(nodePath, false, forceWriteStat); assertArrayEquals("force-write".getBytes(), forceWriteData); assertTrue(forceWriteStat.getVersion() > rev2Stat.getVersion()); assertNotEquals(ZooKeeperUtils.ANY_VERSION, forceWriteStat.getVersion()); }
@Override public Future<Boolean> expunge(final Variable variable) { checkNotNull(variable, "variable is null"); checkState(!closed.get(), "already closed"); checkState(variable instanceof ZookeeperVariable, "can not process native variable, use ZookeeperVariable"); final ZookeeperVariable v = (ZookeeperVariable) variable; final String fullName = getFullPath(v.getName()); return executor.submit(new Callable<Boolean>() { @Override public Boolean call() throws Exception { ZookeeperVariable current = load(fullName); while (true) { if (current == null) { return false; } if (!current.getUuid().equals(v.getUuid())) { return false; } checkState(current.getZookeeperVersion() != null, "expunge with unknown zookeeper version (%s)", current.getEntry()); try { client.delete(fullName, current.getZookeeperVersion()); return true; } catch (BadVersionException | NoNodeException e) { // Version has changed under us or the node has disappeared. Retry (which will probably fail unless it was deleted). LOG.debug("Could not change version %d, retry expunging", current.getZookeeperVersion()); } // Current could be null here if the node was deleted while we were not looking. current = load(fullName); } } }); }