This is an automated email from the ASF dual-hosted git repository. jxue pushed a commit to branch metaclient in repository https://gitbox.apache.org/repos/asf/helix.git
commit 8af1b60abf3078a4256c06762decd8b75c328ad9 Author: xyuanlu <[email protected]> AuthorDate: Wed Jun 21 09:05:02 2023 -0700 Add API for getDataAndStat (#2535) Add API for getDataAndStat --- .../helix/metaclient/api/MetaClientInterface.java | 13 ++++++++-- .../helix/metaclient/impl/zk/ZkMetaClient.java | 16 +++++++++++-- .../metaclient/impl/zk/util/ZkMetaClientUtil.java | 8 +++++++ .../helix/metaclient/impl/zk/TestZkMetaClient.java | 28 ++++++++++++++++++++++ 4 files changed, 61 insertions(+), 4 deletions(-) diff --git a/meta-client/src/main/java/org/apache/helix/metaclient/api/MetaClientInterface.java b/meta-client/src/main/java/org/apache/helix/metaclient/api/MetaClientInterface.java index 375c0814c..b4bfaac2e 100644 --- a/meta-client/src/main/java/org/apache/helix/metaclient/api/MetaClientInterface.java +++ b/meta-client/src/main/java/org/apache/helix/metaclient/api/MetaClientInterface.java @@ -23,7 +23,9 @@ import java.util.List; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.NotImplementedException; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.helix.metaclient.exception.MetaClientInterruptException; +import org.apache.helix.metaclient.exception.MetaClientNoNodeException; import org.apache.helix.metaclient.exception.MetaClientTimeoutException; @@ -195,12 +197,19 @@ public interface MetaClientInterface<T> { /** * Fetch the data for a given key. - * TODO: define exception type when key does not exist * @param key key to identify the entry - * @return Return data of the entry + * @return Return data of the entry. Return null if data does not exists. */ T get(final String key); + /** + * Fetch the data and stat for a given key. + * @param key key to identify the entry + * @return Return an ImmutablePair of data and stat for the entry. + * @throws MetaClientNoNodeException if no such entry + */ + ImmutablePair<T, Stat> getDataAndStat(final String key); + /** * API for transaction. The list of operation will be executed as an atomic operation. * @param ops a list of operations. These operations will all be executed or none of them. diff --git a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/ZkMetaClient.java b/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/ZkMetaClient.java index 4398e8e3a..fc8998e95 100644 --- a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/ZkMetaClient.java +++ b/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/ZkMetaClient.java @@ -28,6 +28,7 @@ import java.util.concurrent.locks.ReentrantLock; import com.google.common.annotations.VisibleForTesting; import org.apache.commons.lang3.NotImplementedException; +import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.helix.metaclient.api.AsyncCallback; import org.apache.helix.metaclient.api.ChildChangeListener; import org.apache.helix.metaclient.api.ConnectStateChangeListener; @@ -166,8 +167,7 @@ public class ZkMetaClient<T> implements MetaClientInterface<T>, AutoCloseable { if (zkStats == null) { return null; } - return new Stat(convertZkEntryModeToMetaClientEntryMode(zkStats.getEphemeralOwner()), - zkStats.getVersion(), zkStats.getCtime(), zkStats.getMtime(), -1); + return ZkMetaClientUtil.convertZkStatToStat(zkStats); } catch (ZkException e) { throw translateZkExceptionToMetaclientException(e); } @@ -178,6 +178,18 @@ public class ZkMetaClient<T> implements MetaClientInterface<T>, AutoCloseable { return _zkClient.readData(key, true); } + + @Override + public ImmutablePair<T, Stat> getDataAndStat(final String key) { + try { + org.apache.zookeeper.data.Stat zkStat = new org.apache.zookeeper.data.Stat(); + T data = _zkClient.readData(key, zkStat); + return ImmutablePair.of(data, ZkMetaClientUtil.convertZkStatToStat(zkStat)); + } catch (ZkException e) { + throw translateZkExceptionToMetaclientException(e); + } + } + @Override public List<String> getDirectChildrenKeys(String key) { try { diff --git a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/util/ZkMetaClientUtil.java b/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/util/ZkMetaClientUtil.java index f21a883f3..6bf0ce74b 100644 --- a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/util/ZkMetaClientUtil.java +++ b/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/util/ZkMetaClientUtil.java @@ -262,6 +262,14 @@ public class ZkMetaClientUtil { } } + public static MetaClientInterface.Stat convertZkStatToStat( + org.apache.zookeeper.data.Stat zkStat) { + return new MetaClientInterface.Stat( + convertZkEntryModeToMetaClientEntryMode(zkStat.getEphemeralOwner()), zkStat.getVersion(), + zkStat.getCtime(), zkStat.getMtime(), + EphemeralType.TTL.getValue(zkStat.getEphemeralOwner())); + } + /** * This function translate and group Zk exception code to metaclient code. * It currently includes all ZK code on 3.6.3. diff --git a/meta-client/src/test/java/org/apache/helix/metaclient/impl/zk/TestZkMetaClient.java b/meta-client/src/test/java/org/apache/helix/metaclient/impl/zk/TestZkMetaClient.java index 69724c9fe..8aca150b0 100644 --- a/meta-client/src/test/java/org/apache/helix/metaclient/impl/zk/TestZkMetaClient.java +++ b/meta-client/src/test/java/org/apache/helix/metaclient/impl/zk/TestZkMetaClient.java @@ -19,6 +19,7 @@ package org.apache.helix.metaclient.impl.zk; * under the License. */ +import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.helix.metaclient.api.ChildChangeListener; import org.apache.helix.metaclient.api.DataUpdater; import org.apache.helix.metaclient.api.MetaClientInterface; @@ -208,6 +209,33 @@ public class TestZkMetaClient extends ZkMetaClientTestBase{ } } + @Test + public void testGetDataAndStat() { + final String key = "/TestZkMetaClient_testGetDataAndStat"; + ZkMetaClientConfig config = + new ZkMetaClientConfig.ZkMetaClientConfigBuilder().setConnectionAddress(ZK_ADDR).build(); + try (ZkMetaClient<Integer> zkMetaClient = new ZkMetaClient<>(config)) { + zkMetaClient.connect(); + int initValue = 3; + zkMetaClient.create(key, initValue); + MetaClientInterface.Stat entryStat = zkMetaClient.exists(key); + Assert.assertEquals(entryStat.getVersion(), 0); + zkMetaClient.set(key, initValue+1, -1); + ImmutablePair<Integer, MetaClientInterface.Stat> touple = zkMetaClient.getDataAndStat(key); + Assert.assertEquals(touple.right.getVersion(), 1); + zkMetaClient.delete(key); + + // test non exist key + try{ + zkMetaClient.getDataAndStat(key); + } catch (MetaClientException ex){ + Assert.assertEquals(ex.getClass().getName(), + "org.apache.helix.metaclient.exception.MetaClientNoNodeException"); + } + + } + } + @Test public void testGetAndCountChildrenAndRecursiveDelete() { final String key = "/TestZkMetaClient_testGetAndCountChildren";
