This is an automated email from the ASF dual-hosted git repository.

hulee pushed a commit to branch zookeeper-api-ttlcontainer
in repository https://gitbox.apache.org/repos/asf/helix.git


The following commit(s) were added to refs/heads/zookeeper-api-ttlcontainer by 
this push:
     new 450c47f77 Add TTL and Container modes to sync create API in ZkClient 
and ZkConnection (#2090)
450c47f77 is described below

commit 450c47f77020f35dfae06e85dab31809a71f37fb
Author: Ramin Bashizade <[email protected]>
AuthorDate: Wed May 18 05:44:15 2022 -0700

    Add TTL and Container modes to sync create API in ZkClient and ZkConnection 
(#2090)
    
    This PR adds methods that support creating persistent nodes with Container 
and TTL modes synchronously to ZkClient and ZkConnection classes.
---
 .../helix/zookeeper/zkclient/IZkConnection.java    |   2 +
 .../apache/helix/zookeeper/zkclient/ZkClient.java  | 327 ++++++++++++++++++++-
 .../helix/zookeeper/zkclient/ZkConnection.java     |   6 +
 .../zookeeper/impl/client/TestRawZkClient.java     | 129 ++++++++
 4 files changed, 455 insertions(+), 9 deletions(-)

diff --git 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/IZkConnection.java
 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/IZkConnection.java
index 6fc040fd8..e766bf7d9 100644
--- 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/IZkConnection.java
+++ 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/IZkConnection.java
@@ -40,6 +40,8 @@ public interface IZkConnection {
 
     public String create(String path, byte[] data, List<ACL> acl, CreateMode 
mode) throws KeeperException, InterruptedException;
 
+    public String create(String path, byte[] data, List<ACL> acl, CreateMode 
mode, long ttl) throws KeeperException, InterruptedException;
+
     public void delete(String path) throws InterruptedException, 
KeeperException;
 
     boolean exists(final String path, final boolean watch) throws 
KeeperException, InterruptedException;
diff --git 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/ZkClient.java 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/ZkClient.java
index c6b74239b..e4832656b 100644
--- 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/ZkClient.java
+++ 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/ZkClient.java
@@ -438,6 +438,41 @@ public class ZkClient implements Watcher {
     createPersistent(path, false);
   }
 
+  /**
+   * Create a persistent node with TTL.
+   * @param path the path where you want the node to be created
+   * @param ttl TTL of the node in milliseconds
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createPersistentWithTTL(String path, long ttl)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    createPersistentWithTTL(path, false, ttl);
+  }
+
+  /**
+   * Create a container node.
+   * @param path the path where you want the node to be created
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createContainer(String path)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    createContainer(path, false);
+  }
+
   /**
    * Create a persistent node and set its ACLs.
    * @param path
@@ -459,6 +494,45 @@ public class ZkClient implements Watcher {
     createPersistent(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE);
   }
 
+  /**
+   * Create a persistent node with TTL and set its ACLs.
+   * @param path the path where you want the node to be created
+   * @param createParents if true all parent dirs are created as well and no
+   *                      {@link ZkNodeExistsException} is thrown in case the 
path already exists
+   * @param ttl TTL of the node in milliseconds
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createPersistentWithTTL(String path, boolean createParents, long 
ttl)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    createPersistentWithTTL(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE, 
ttl);
+  }
+
+  /**
+   * Create a container node and set its ACLs.
+   * @param path the path where you want the node to be created
+   * @param createParents if true all parent dirs are created as well and no
+   *                      {@link ZkNodeExistsException} is thrown in case the 
path already exists
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createContainer(String path, boolean createParents)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    createContainer(path, createParents, ZooDefs.Ids.OPEN_ACL_UNSAFE);
+  }
+
   /**
    * Create a persistent node and set its ACLs.
    * @param path
@@ -495,6 +569,73 @@ public class ZkClient implements Watcher {
     }
   }
 
+  /**
+   * Create a persistent node with TTL and set its ACLs.
+   * @param path the path where you want the node to be created
+   * @param createParents if true all parent dirs are created as well and no
+   *                      {@link ZkNodeExistsException} is thrown in case the 
path already exists
+   * @param acl List of ACL permissions to assign to the node
+   * @param ttl TTL of the node in milliseconds
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createPersistentWithTTL(String path, boolean createParents, 
List<ACL> acl, long ttl)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    try {
+      create(path, null, acl, CreateMode.PERSISTENT_WITH_TTL, ttl);
+    } catch (ZkNodeExistsException e) {
+      if (!createParents) {
+        throw e;
+      }
+    } catch (ZkNoNodeException e) {
+      if (!createParents) {
+        throw e;
+      }
+      String parentDir = path.substring(0, path.lastIndexOf('/'));
+      createPersistentWithTTL(parentDir, createParents, acl, ttl);
+      createPersistentWithTTL(path, createParents, acl, ttl);
+    }
+  }
+
+  /**
+   * Create a container node and set its ACLs.
+   * @param path the path where you want the node to be created
+   * @param createParents if true all parent dirs are created as well and no
+   *                      {@link ZkNodeExistsException} is thrown in case the 
path already exists
+   * @param acl List of ACL permissions to assign to the node
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createContainer(String path, boolean createParents, List<ACL> 
acl)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    try {
+      create(path, null, acl, CreateMode.CONTAINER);
+    } catch (ZkNodeExistsException e) {
+      if (!createParents) {
+        throw e;
+      }
+    } catch (ZkNoNodeException e) {
+      if (!createParents) {
+        throw e;
+      }
+      String parentDir = path.substring(0, path.lastIndexOf('/'));
+      createContainer(parentDir, createParents, acl);
+      createContainer(path, createParents, acl);
+    }
+  }
+
   /**
    * Create a persistent node.
    * @param path
@@ -513,6 +654,43 @@ public class ZkClient implements Watcher {
     create(path, data, CreateMode.PERSISTENT);
   }
 
+  /**
+   * Create a persistent node with TTL.
+   * @param path the path where you want the node to be created
+   * @param data data of the node
+   * @param ttl TTL of the node in milliseconds
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createPersistentWithTTL(String path, Object data, long ttl)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    create(path, data, CreateMode.PERSISTENT_WITH_TTL, ttl);
+  }
+
+  /**
+   * Create a container node.
+   * @param path the path where you want the node to be created
+   * @param data data of the node
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createContainer(String path, Object data)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    create(path, data, CreateMode.CONTAINER);
+  }
+
   /**
    * Create a persistent node.
    * @param path
@@ -531,6 +709,43 @@ public class ZkClient implements Watcher {
     create(path, data, acl, CreateMode.PERSISTENT);
   }
 
+  /**
+   * Create a persistent node with TTL.
+   * @param path the path where you want the node to be created
+   * @param data data of the node
+   * @param acl list of ACL for the node
+   * @param ttl TTL of the node in milliseconds
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createPersistentWithTTL(String path, Object data, List<ACL> acl, 
long ttl) {
+    create(path, data, acl, CreateMode.PERSISTENT_WITH_TTL, ttl);
+  }
+
+  /**
+   * Create a container node.
+   * @param path the path where you want the node to be created
+   * @param data data of the node
+   * @param acl list of ACL for the node
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public void createContainer(String path, Object data, List<ACL> acl) {
+    create(path, data, acl, CreateMode.CONTAINER);
+  }
+
   /**
    * Create a persistent, sequental node.
    * @param path
@@ -550,6 +765,26 @@ public class ZkClient implements Watcher {
     return create(path, data, CreateMode.PERSISTENT_SEQUENTIAL);
   }
 
+  /**
+   * Create a persistent, sequential node.
+   * @param path the path where you want the node to be created
+   * @param data data of the node
+   * @param ttl TTL of the node in milliseconds
+   * @return create node's path
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public String createPersistentSequentialWithTTL(String path, Object data, 
long ttl)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    return create(path, data, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, ttl);
+  }
+
   /**
    * Create a persistent, sequential node and set its ACL.
    * @param path
@@ -570,6 +805,27 @@ public class ZkClient implements Watcher {
     return create(path, data, acl, CreateMode.PERSISTENT_SEQUENTIAL);
   }
 
+  /**
+   * Create a persistent, sequential node and set its ACL.
+   * @param path the path where you want the node to be created
+   * @param acl list of ACL for the node
+   * @param data data of the node
+   * @param ttl TTL of the node in milliseconds
+   * @return create node's path
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public String createPersistentSequentialWithTTL(String path, Object data, 
List<ACL> acl, long ttl)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    return create(path, data, acl, CreateMode.PERSISTENT_SEQUENTIAL_WITH_TTL, 
ttl);
+  }
+
   /**
    * Create an ephemeral node.
    * @param path
@@ -648,7 +904,7 @@ public class ZkClient implements Watcher {
    */
   public void createEphemeral(final String path, final List<ACL> acl, final 
String sessionId)
       throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
-    create(path, null, acl, CreateMode.EPHEMERAL, sessionId);
+    create(path, null, acl, CreateMode.EPHEMERAL, TTL_NOT_SET, sessionId);
   }
 
   /**
@@ -671,6 +927,28 @@ public class ZkClient implements Watcher {
     return create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, mode);
   }
 
+  /**
+   * Create a node.
+   * @param path the path where you want the node to be created
+   * @param data data of the node
+   * @param mode {@link CreateMode} of the node
+   * @param ttl TTL of the node in milliseconds, if mode is {@link 
CreateMode#PERSISTENT_WITH_TTL}
+   *            or {@link CreateMode#PERSISTENT_SEQUENTIAL_WITH_TTL}
+   * @return create node's path
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public String create(final String path, Object data, final CreateMode mode, 
long ttl)
+      throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
+    return create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, mode, ttl);
+  }
+
   /**
    * Create a node with ACL.
    * @param path
@@ -689,7 +967,30 @@ public class ZkClient implements Watcher {
    */
   public String create(final String path, Object datat, final List<ACL> acl, 
final CreateMode mode)
       throws IllegalArgumentException, ZkException {
-    return create(path, datat, acl, mode, null);
+    return create(path, datat, acl, mode, TTL_NOT_SET, null);
+  }
+
+  /**
+   * Create a node with ACL.
+   * @param path the path where you want the node to be created
+   * @param datat data of the node
+   * @param acl list of ACL for the node
+   * @param mode {@link CreateMode} of the node
+   * @param ttl TTL of the node in milliseconds, if mode is {@link 
CreateMode#PERSISTENT_WITH_TTL}
+   *            or {@link CreateMode#PERSISTENT_SEQUENTIAL_WITH_TTL}
+   * @return create node's path
+   * @throws ZkInterruptedException
+   *           if operation was interrupted, or a required reconnection got 
interrupted
+   * @throws IllegalArgumentException
+   *           if called from anything except the ZooKeeper event thread
+   * @throws ZkException
+   *           if any ZooKeeper exception occurred
+   * @throws RuntimeException
+   *           if any other exception occurs
+   */
+  public String create(final String path, Object datat, final List<ACL> acl, 
final CreateMode mode,
+      long ttl) throws IllegalArgumentException, ZkException {
+    return create(path, datat, acl, mode, ttl, null);
   }
 
   /**
@@ -705,6 +1006,8 @@ public class ZkClient implements Watcher {
    * @param dataObject data of the node
    * @param acl list of ACL for the node
    * @param mode {@link CreateMode} of the node
+   * @param ttl TTL of the node in milliseconds, if mode is {@link 
CreateMode#PERSISTENT_WITH_TTL}
+   *            or {@link CreateMode#PERSISTENT_SEQUENTIAL_WITH_TTL}
    * @param expectedSessionId the expected session ID of the ZK connection. It 
is not necessarily the
    *                  session ID of current ZK Connection. If the expected 
session ID is NOT null,
    *                  the node is guaranteed to be created in the expected 
session, or creation is
@@ -715,7 +1018,7 @@ public class ZkClient implements Watcher {
    * @throws ZkException if any zookeeper exception occurs
    */
   private String create(final String path, final Object dataObject, final 
List<ACL> acl,
-      final CreateMode mode, final String expectedSessionId)
+      final CreateMode mode, long ttl, final String expectedSessionId)
       throws IllegalArgumentException, ZkException {
     if (path == null) {
       throw new NullPointerException("Path must not be null.");
@@ -728,8 +1031,14 @@ public class ZkClient implements Watcher {
       final byte[] dataBytes = dataObject == null ? null : 
serialize(dataObject, path);
       checkDataSizeLimit(path, dataBytes);
 
-      final String actualPath = retryUntilConnected(
-          () -> getExpectedZookeeper(expectedSessionId).create(path, 
dataBytes, acl, mode));
+      final String actualPath;
+      if (mode.isTTL()) {
+        actualPath = retryUntilConnected(() -> 
getExpectedZookeeper(expectedSessionId)
+            .create(path, dataBytes, acl, mode, null, ttl));
+      } else {
+        actualPath = retryUntilConnected(() -> 
getExpectedZookeeper(expectedSessionId)
+            .create(path, dataBytes, acl, mode));
+      }
 
       record(path, dataBytes, startT, ZkClientMonitor.AccessType.WRITE);
       return actualPath;
@@ -786,7 +1095,7 @@ public class ZkClient implements Watcher {
    */
   public void createEphemeral(final String path, final Object data, final 
String sessionId)
       throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
-    create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, 
sessionId);
+    create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL, 
TTL_NOT_SET, sessionId);
   }
 
   /**
@@ -836,7 +1145,7 @@ public class ZkClient implements Watcher {
   public void createEphemeral(final String path, final Object data, final 
List<ACL> acl,
       final String sessionId)
       throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
-    create(path, data, acl, CreateMode.EPHEMERAL, sessionId);
+    create(path, data, acl, CreateMode.EPHEMERAL, TTL_NOT_SET, sessionId);
   }
 
   /**
@@ -882,7 +1191,7 @@ public class ZkClient implements Watcher {
   public String createEphemeralSequential(final String path, final Object 
data, final List<ACL> acl,
       final String sessionId)
       throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
-    return create(path, data, acl, CreateMode.EPHEMERAL_SEQUENTIAL, sessionId);
+    return create(path, data, acl, CreateMode.EPHEMERAL_SEQUENTIAL, 
TTL_NOT_SET, sessionId);
   }
 
   /**
@@ -914,7 +1223,7 @@ public class ZkClient implements Watcher {
       final String sessionId)
       throws ZkInterruptedException, IllegalArgumentException, ZkException, 
RuntimeException {
     return create(path, data, ZooDefs.Ids.OPEN_ACL_UNSAFE, 
CreateMode.EPHEMERAL_SEQUENTIAL,
-        sessionId);
+        TTL_NOT_SET, sessionId);
   }
 
   /**
diff --git 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/ZkConnection.java
 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/ZkConnection.java
index 08a2fb9aa..01935919c 100644
--- 
a/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/ZkConnection.java
+++ 
b/zookeeper-api/src/main/java/org/apache/helix/zookeeper/zkclient/ZkConnection.java
@@ -133,6 +133,12 @@ public class ZkConnection implements IZkConnection {
     return _zk.create(path, data, acl, mode);
   }
 
+  @Override
+  public String create(String path, byte[] data, List<ACL> acl, CreateMode 
mode, long ttl)
+      throws KeeperException, InterruptedException {
+    return _zk.create(path, data, acl, mode, null, ttl);
+  }
+
   @Override
   public void delete(String path) throws InterruptedException, KeeperException 
{
     _zk.delete(path, -1);
diff --git 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestRawZkClient.java
 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestRawZkClient.java
index 20d070b52..9e8a75a73 100644
--- 
a/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestRawZkClient.java
+++ 
b/zookeeper-api/src/test/java/org/apache/helix/zookeeper/impl/client/TestRawZkClient.java
@@ -89,6 +89,135 @@ public class TestRawZkClient extends ZkTestBase {
     _zkClient.close();
   }
 
+  @Test
+  void testUnimplementedTypes() {
+    // Make sure extended types are disabled
+    System.clearProperty("zookeeper.extendedTypesEnabled");
+
+    // Make sure the test path is clear
+    String parentPath = "/tmp";
+    String path = "/tmp/unimplemented";
+    _zkClient.deleteRecursively(parentPath);
+
+    try {
+      long ttl = 1L;
+      _zkClient.createPersistentWithTTL(path, true, ttl);
+    } catch (ZkException e) {
+      AssertJUnit.assertTrue(e.getCause() instanceof 
KeeperException.UnimplementedException);
+      return;
+    }
+
+    // Clean up
+    _zkClient.deleteRecursively(parentPath);
+    AssertJUnit.fail();
+  }
+
+  @Test
+  void testCreatePersistentWithTTL() {
+    // Enable extended types and create a ZkClient
+    System.setProperty("zookeeper.extendedTypesEnabled", "true");
+    ZkClient zkClient = new ZkClient(ZkTestBase.ZK_ADDR);
+    zkClient.setZkSerializer(new ZNRecordSerializer());
+
+    // Make sure the test path is clear
+    String parentPath = "/tmp";
+    String path = "/tmp/createTTL";
+    zkClient.deleteRecursively(parentPath);
+    AssertJUnit.assertFalse(zkClient.exists(parentPath));
+    AssertJUnit.assertFalse(zkClient.exists(path));
+
+    long ttl = 1L;
+    ZNRecord record = new ZNRecord("record");
+    String key = "key";
+    String value = "value";
+    record.setSimpleField(key, value);
+
+    // Create a ZNode with the above ZNRecord and read back its data
+    zkClient.createPersistentWithTTL(parentPath, record, ttl);
+    AssertJUnit.assertTrue(zkClient.exists(parentPath));
+    ZNRecord retrievedRecord = zkClient.readData(parentPath);
+    AssertJUnit.assertEquals(value, retrievedRecord.getSimpleField(key));
+
+    // Clear the path and test with createParents = true
+    AssertJUnit.assertTrue(zkClient.delete(parentPath));
+    zkClient.createPersistentWithTTL(path, true, ttl);
+    AssertJUnit.assertTrue(zkClient.exists(path));
+
+    // Clean up
+    zkClient.deleteRecursively(parentPath);
+    zkClient.close();
+    System.clearProperty("zookeeper.extendedTypesEnabled");
+  }
+
+  @Test
+  void testCreatePersistentSequentialWithTTL() {
+    // Enable extended types and create a ZkClient
+    System.setProperty("zookeeper.extendedTypesEnabled", "true");
+    ZkClient zkClient = new ZkClient(ZkTestBase.ZK_ADDR);
+    zkClient.setZkSerializer(new ZNRecordSerializer());
+
+    // Make sure the test path is clear
+    String parentPath = "/tmp";
+    String path = "/tmp/createSequentialTTL";
+    zkClient.deleteRecursively(parentPath);
+    AssertJUnit.assertFalse(zkClient.exists(parentPath));
+    AssertJUnit.assertFalse(zkClient.exists(path + "0000000000"));
+
+    long ttl = 1L;
+    ZNRecord record = new ZNRecord("record");
+    String key = "key";
+    String value = "value";
+    record.setSimpleField(key, value);
+
+    // Create a ZNode with the above ZNRecord and read back its data
+    zkClient.createPersistent(parentPath);
+    zkClient.createPersistentSequentialWithTTL(path, record, ttl);
+    AssertJUnit.assertTrue(zkClient.exists(path + "0000000000"));
+    ZNRecord retrievedRecord = zkClient.readData(path + "0000000000");
+    AssertJUnit.assertEquals(value, retrievedRecord.getSimpleField(key));
+
+    // Clean up
+    zkClient.deleteRecursively(parentPath);
+    zkClient.close();
+    System.clearProperty("zookeeper.extendedTypesEnabled");
+  }
+
+  @Test
+  void testCreateContainer() {
+    // Enable extended types and create a ZkClient
+    System.setProperty("zookeeper.extendedTypesEnabled", "true");
+    ZkClient zkClient = new ZkClient(ZkTestBase.ZK_ADDR);
+    zkClient.setZkSerializer(new ZNRecordSerializer());
+
+    // Make sure the test path is clear
+    String parentPath = "/tmp";
+    String path = "/tmp/createContainer";
+    zkClient.deleteRecursively(parentPath);
+    AssertJUnit.assertFalse(zkClient.exists(parentPath));
+    AssertJUnit.assertFalse(zkClient.exists(path));
+
+    ZNRecord record = new ZNRecord("record");
+    String key = "key";
+    String value = "value";
+    record.setSimpleField(key, value);
+
+    // Create a ZNode with the above ZNRecord and read back its data
+    zkClient.createContainer(parentPath, record);
+    AssertJUnit.assertTrue(zkClient.exists(parentPath));
+    ZNRecord retrievedRecord = zkClient.readData(parentPath);
+    AssertJUnit.assertEquals(value, retrievedRecord.getSimpleField(key));
+
+    // Clear the path and test with createParents = true
+    AssertJUnit.assertTrue(zkClient.delete(parentPath));
+    zkClient.createContainer(path, true);
+    AssertJUnit.assertTrue(zkClient.exists(path));
+
+    // Clean up
+    zkClient.deleteRecursively(parentPath);
+    zkClient.close();
+    System.clearProperty("zookeeper.extendedTypesEnabled");
+  }
+
   @Test()
   void testGetStat() {
     String path = "/tmp/getStatTest";

Reply via email to