You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@accumulo.apache.org by ct...@apache.org on 2022/04/27 19:52:14 UTC
[accumulo] 02/02: Minor enhancements to ZK utilities
This is an automated email from the ASF dual-hosted git repository.
ctubbsii pushed a commit to branch single-node-props
in repository https://gitbox.apache.org/repos/asf/accumulo.git
commit 292453bf49eb4053c300aa634d6bf061726f30de
Author: Christopher Tubbs <ct...@apache.org>
AuthorDate: Wed Apr 27 15:51:56 2022 -0400
Minor enhancements to ZK utilities
---
.../apache/accumulo/fate/zookeeper/ZooReader.java | 15 ++++++
.../accumulo/fate/zookeeper/ZooReaderWriter.java | 56 ++++++++++++++++++----
.../apache/accumulo/fate/zookeeper/ZooUtil.java | 38 +++++++++++++++
3 files changed, 101 insertions(+), 8 deletions(-)
diff --git a/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReader.java b/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReader.java
index 4165d3faa7..2aa996b613 100644
--- a/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReader.java
+++ b/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReader.java
@@ -66,6 +66,16 @@ public class ZooReader {
return RETRY_FACTORY;
}
+ /**
+ * Returns the requested ZooKeeper client session timeout. The client may negotiate a different
+ * value and the actual negotiated value may change after a re-connect.
+ *
+ * @return the timeout in milliseconds
+ */
+ public int getSessionTimeout() {
+ return timeout;
+ }
+
public byte[] getData(String zPath) throws KeeperException, InterruptedException {
return retryLoop(zk -> zk.getData(zPath, null, null));
}
@@ -79,6 +89,11 @@ public class ZooReader {
return retryLoop(zk -> zk.getData(zPath, requireNonNull(watcher), null));
}
+ public byte[] getData(String zPath, Watcher watcher, Stat stat)
+ throws KeeperException, InterruptedException {
+ return retryLoop(zk -> zk.getData(zPath, requireNonNull(watcher), requireNonNull(stat)));
+ }
+
public Stat getStatus(String zPath) throws KeeperException, InterruptedException {
return retryLoop(zk -> zk.exists(zPath, null));
}
diff --git a/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReaderWriter.java b/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReaderWriter.java
index 8e79007cc1..58c5671f50 100644
--- a/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReaderWriter.java
+++ b/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooReaderWriter.java
@@ -134,6 +134,33 @@ public class ZooReaderWriter extends ZooReader {
e -> e.code() == Code.NONODE && policy == NodeExistsPolicy.OVERWRITE);
}
+ /**
+ * Overwrite a persistent node if the data version matches.
+ *
+ * @param zPath
+ * the zookeeper path
+ * @param data
+ * the byte array data
+ * @param expectedVersion
+ * the expected data version of the zookeeper node.
+ * @return true if the data was set, false if the version does not match expected.
+ * @throws KeeperException
+ * if a KeeperException occurs (no node most likely)
+ * @throws InterruptedException
+ * if the zookeeper write is interrupted.
+ */
+ public boolean overwritePersistentData(String zPath, byte[] data, final int expectedVersion)
+ throws KeeperException, InterruptedException {
+ return retryLoop(zk -> {
+ try {
+ zk.setData(zPath, data, expectedVersion);
+ return true;
+ } catch (KeeperException.BadVersionException ex) {
+ return false;
+ }
+ });
+ }
+
/**
* Create a persistent sequential node with the default ACL
*
@@ -242,15 +269,28 @@ public class ZooReaderWriter extends ZooReader {
* Delete the specified node, and ignore NONODE exceptions.
*/
public void delete(String path) throws KeeperException, InterruptedException {
- retryLoop(zk -> {
- try {
- zk.delete(path, -1);
- } catch (KeeperException e) {
- // ignore the case where the node doesn't exist
- if (e.code() != Code.NONODE) {
- throw e;
- }
+ try {
+ deleteStrict(path, -1);
+ } catch (KeeperException e) {
+ if (e.code() != Code.NONODE) {
+ throw e;
}
+ }
+ }
+
+ /**
+ * Delete the specified node if the version matches the provided version. All underlying
+ * exceptions are thrown back to the caller.
+ *
+ * @param path
+ * the path of the ZooKeeper node.
+ * @param version
+ * the expected version of the ZooKeeper node.
+ */
+ public void deleteStrict(final String path, final int version)
+ throws KeeperException, InterruptedException {
+ retryLoop(zk -> {
+ zk.delete(path, version);
return null;
});
}
diff --git a/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooUtil.java b/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooUtil.java
index 82c3a1658b..6f6431ede1 100644
--- a/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooUtil.java
+++ b/core/src/main/java/org/apache/accumulo/fate/zookeeper/ZooUtil.java
@@ -21,6 +21,10 @@ package org.apache.accumulo.fate.zookeeper;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.math.BigInteger;
+import java.time.Instant;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@@ -32,6 +36,7 @@ import org.apache.zookeeper.ZooDefs.Ids;
import org.apache.zookeeper.ZooDefs.Perms;
import org.apache.zookeeper.ZooKeeper;
import org.apache.zookeeper.data.ACL;
+import org.apache.zookeeper.data.Stat;
public class ZooUtil {
@@ -43,6 +48,10 @@ public class ZooUtil {
SKIP, CREATE, FAIL
}
+ // used for zookeeper stat print formatting
+ private static final DateTimeFormatter fmt =
+ DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss 'UTC' yyyy");
+
public static class LockID {
public long eid;
public String path;
@@ -124,6 +133,35 @@ public class ZooUtil {
}
}
+ /**
+ * For debug: print the ZooKeeper Stat with value labels for a more user friendly string. The
+ * format matches the zookeeper cli stat command.
+ *
+ * @param stat
+ * Zookeeper Stat structure
+ * @return a formatted string.
+ */
+ public static String printStat(final Stat stat) {
+
+ if (stat == null) {
+ return "null";
+ }
+
+ return "\ncZxid = " + String.format("0x%x", stat.getCzxid()) + "\nctime = "
+ + getFmtTime(stat.getCtime()) + "\nmZxid = " + String.format("0x%x", stat.getMzxid())
+ + "\nmtime = " + getFmtTime(stat.getMtime()) + "\npZxid = "
+ + String.format("0x%x", stat.getPzxid()) + "\ncversion = " + stat.getCversion()
+ + "\ndataVersion = " + stat.getVersion() + "\naclVersion = " + stat.getAversion()
+ + "\nephemeralOwner = " + String.format("0x%x", stat.getEphemeralOwner())
+ + "\ndataLength = " + stat.getDataLength() + "\nnumChildren = " + stat.getNumChildren();
+ }
+
+ private static String getFmtTime(final long epoch) {
+ OffsetDateTime timestamp =
+ OffsetDateTime.ofInstant(Instant.ofEpochMilli(epoch), ZoneOffset.UTC);
+ return fmt.format(timestamp);
+ }
+
public static void digestAuth(ZooKeeper zoo, String secret) {
auth(zoo, "digest", ("accumulo:" + secret).getBytes(UTF_8));
}