This is an automated email from the ASF dual-hosted git repository. xyuanlu pushed a commit to branch metaclient in repository https://gitbox.apache.org/repos/asf/helix.git
commit a6252856b14c8e7164cd4d70da2ebfd72218472b Author: Marcos Rico Peng <[email protected]> AuthorDate: Tue Sep 12 22:24:22 2023 +0200 MetaClientCache Part 1 - API's, configs, and builders (#2612) MetaClientCache Part 1 - API's, configs, and builders --------- Co-authored-by: mapeng <[email protected]> --- .../metaclient/api/MetaClientCacheInterface.java | 61 ++++++++++++++ .../MetaClientCacheConfig.java} | 43 ++++++---- .../metaclient/factories/MetaClientFactory.java | 17 ++++ .../metaclient/impl/zk/ZkMetaClientCache.java | 94 ++++++++++++++++++++++ .../impl/zk/factory/ZkMetaClientFactory.java | 15 ++++ .../metaclient/impl/zk/TestZkMetaClientCache.java | 57 +++++++++++++ 6 files changed, 272 insertions(+), 15 deletions(-) diff --git a/meta-client/src/main/java/org/apache/helix/metaclient/api/MetaClientCacheInterface.java b/meta-client/src/main/java/org/apache/helix/metaclient/api/MetaClientCacheInterface.java new file mode 100644 index 000000000..348bd0929 --- /dev/null +++ b/meta-client/src/main/java/org/apache/helix/metaclient/api/MetaClientCacheInterface.java @@ -0,0 +1,61 @@ +package org.apache.helix.metaclient.api; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.HashMap; +import java.util.Map; + +public interface MetaClientCacheInterface<T> extends MetaClientInterface<T> { + + /** + * TrieNode class to store the children of the entries to be cached. + */ + class TrieNode { + // A mapping between trie key and children nodes. + private Map<String, TrieNode> _children; + + // the complete path/prefix leading to the current node. + private final String _path; + + private final String _nodeKey; + + TrieNode(String path, String nodeKey) { + _path = path; + _nodeKey = nodeKey; + _children = new HashMap<>(); + } + + public Map<String, TrieNode> getChildren() { + return _children; + } + + public String getPath() { + return _path; + } + + public String getNodeKey() { + return _nodeKey; + } + + public void addChild(String key, TrieNode node) { + _children.put(key, node); + } + } +} diff --git a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/factory/ZkMetaClientFactory.java b/meta-client/src/main/java/org/apache/helix/metaclient/factories/MetaClientCacheConfig.java similarity index 50% copy from meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/factory/ZkMetaClientFactory.java copy to meta-client/src/main/java/org/apache/helix/metaclient/factories/MetaClientCacheConfig.java index 9eba28b91..9e0323601 100644 --- a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/factory/ZkMetaClientFactory.java +++ b/meta-client/src/main/java/org/apache/helix/metaclient/factories/MetaClientCacheConfig.java @@ -1,4 +1,4 @@ -package org.apache.helix.metaclient.impl.zk.factory; +package org.apache.helix.metaclient.factories; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,21 +19,34 @@ package org.apache.helix.metaclient.impl.zk.factory; * under the License. */ -import org.apache.helix.metaclient.api.MetaClientInterface; -import org.apache.helix.metaclient.factories.MetaClientConfig; -import org.apache.helix.metaclient.factories.MetaClientFactory; -import org.apache.helix.metaclient.impl.zk.ZkMetaClient; -public class ZkMetaClientFactory extends MetaClientFactory { - @Override - public MetaClientInterface getMetaClient(MetaClientConfig config) { - if (config == null) { - throw new IllegalArgumentException("MetaClientConfig cannot be null."); + +public class MetaClientCacheConfig { + private final String _rootEntry; + private boolean _cacheData = false; + private boolean _cacheChildren = false; + private boolean _lazyCaching = true; + + public MetaClientCacheConfig(String rootEntry, boolean cacheData, boolean cacheChildren, boolean lazyCaching) { + _rootEntry = rootEntry; + _cacheData = cacheData; + _cacheChildren = cacheChildren; + _lazyCaching = lazyCaching; } - if (MetaClientConfig.StoreType.ZOOKEEPER.equals(config.getStoreType()) - && config instanceof ZkMetaClientConfig) { - return new ZkMetaClient((ZkMetaClientConfig) config); + + public String getRootEntry() { + return _rootEntry; + } + + public boolean getCacheData() { + return _cacheData; + } + + public boolean getCacheChildren() { + return _cacheChildren; + } + + public boolean getLazyCaching() { + return _lazyCaching; } - throw new IllegalArgumentException("Invalid MetaClientConfig type."); - } } diff --git a/meta-client/src/main/java/org/apache/helix/metaclient/factories/MetaClientFactory.java b/meta-client/src/main/java/org/apache/helix/metaclient/factories/MetaClientFactory.java index 045374332..ebb4549da 100644 --- a/meta-client/src/main/java/org/apache/helix/metaclient/factories/MetaClientFactory.java +++ b/meta-client/src/main/java/org/apache/helix/metaclient/factories/MetaClientFactory.java @@ -20,6 +20,7 @@ package org.apache.helix.metaclient.factories; */ +import org.apache.helix.metaclient.api.MetaClientCacheInterface; import org.apache.helix.metaclient.api.MetaClientInterface; import org.apache.helix.metaclient.impl.zk.factory.ZkMetaClientConfig; import org.apache.helix.metaclient.impl.zk.factory.ZkMetaClientFactory; @@ -49,4 +50,20 @@ public class MetaClientFactory { } return null; } + + public MetaClientCacheInterface getMetaClientCache(MetaClientConfig config, MetaClientCacheConfig cacheConfig) { + if (config == null) { + throw new IllegalArgumentException("MetaClientConfig cannot be null."); + } + if (MetaClientConfig.StoreType.ZOOKEEPER.equals(config.getStoreType())) { + ZkMetaClientConfig zkMetaClientConfig = new ZkMetaClientConfig.ZkMetaClientConfigBuilder(). + setConnectionAddress(config.getConnectionAddress()) + .setMetaClientReconnectPolicy(config.getMetaClientReconnectPolicy()) + .setConnectionInitTimeoutInMillis(config.getConnectionInitTimeoutInMillis()) + .setSessionTimeoutInMillis(config.getSessionTimeoutInMillis()) + .build(); + return new ZkMetaClientFactory().getMetaClientCache(zkMetaClientConfig, cacheConfig); + } + return null; + } } diff --git a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/ZkMetaClientCache.java b/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/ZkMetaClientCache.java new file mode 100644 index 000000000..af1c9d791 --- /dev/null +++ b/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/ZkMetaClientCache.java @@ -0,0 +1,94 @@ +package org.apache.helix.metaclient.impl.zk; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import org.apache.helix.metaclient.api.ChildChangeListener; +import org.apache.helix.metaclient.api.MetaClientCacheInterface; +import org.apache.helix.metaclient.datamodel.DataRecord; +import org.apache.helix.metaclient.exception.MetaClientException; +import org.apache.helix.metaclient.factories.MetaClientCacheConfig; +import org.apache.helix.metaclient.factories.MetaClientConfig; +import org.apache.helix.metaclient.impl.zk.factory.ZkMetaClientConfig; +import org.apache.helix.metaclient.impl.zk.factory.ZkMetaClientFactory; +import org.apache.helix.metaclient.recipes.lock.LockInfoSerializer; +import org.apache.helix.zookeeper.zkclient.ZkClient; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; +import java.util.Map; + +public class ZkMetaClientCache<T> extends ZkMetaClient<T> implements MetaClientCacheInterface<T> { + + private Map<String, DataRecord> _dataCacheMap; + private final String _rootEntry; + private TrieNode _childrenCacheTree; + private ChildChangeListener _eventListener; + private boolean _cacheData; + private boolean _cacheChildren; + private boolean _lazyCaching; + private static final Logger LOG = LoggerFactory.getLogger(ZkMetaClientCache.class); + private ZkClient _cacheClient; + + /** + * Constructor for ZkMetaClientCache. + * @param config ZkMetaClientConfig + * @param cacheConfig MetaClientCacheConfig + */ + public ZkMetaClientCache(ZkMetaClientConfig config, MetaClientCacheConfig cacheConfig) { + super(config); + _cacheClient = getZkClient(); + _rootEntry = cacheConfig.getRootEntry(); + _lazyCaching = cacheConfig.getLazyCaching(); + _cacheData = cacheConfig.getCacheData(); + _cacheChildren = cacheConfig.getCacheChildren(); + } + + @Override + public Stat exists(String key) { + throw new MetaClientException("Not implemented yet."); + } + + @Override + public T get(final String key) { + throw new MetaClientException("Not implemented yet."); + } + + @Override + public List<String> getDirectChildrenKeys(final String key) { + throw new MetaClientException("Not implemented yet."); + } + + @Override + public int countDirectChildren(final String key) { + throw new MetaClientException("Not implemented yet."); + } + + @Override + public List<T> get(List<String> keys) { + throw new MetaClientException("Not implemented yet."); + } + + @Override + public List<Stat> exists(List<String> keys) { + throw new MetaClientException("Not implemented yet."); + } + +} diff --git a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/factory/ZkMetaClientFactory.java b/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/factory/ZkMetaClientFactory.java index 9eba28b91..c4018eb2f 100644 --- a/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/factory/ZkMetaClientFactory.java +++ b/meta-client/src/main/java/org/apache/helix/metaclient/impl/zk/factory/ZkMetaClientFactory.java @@ -19,10 +19,13 @@ package org.apache.helix.metaclient.impl.zk.factory; * under the License. */ +import org.apache.helix.metaclient.api.MetaClientCacheInterface; import org.apache.helix.metaclient.api.MetaClientInterface; +import org.apache.helix.metaclient.factories.MetaClientCacheConfig; import org.apache.helix.metaclient.factories.MetaClientConfig; import org.apache.helix.metaclient.factories.MetaClientFactory; import org.apache.helix.metaclient.impl.zk.ZkMetaClient; +import org.apache.helix.metaclient.impl.zk.ZkMetaClientCache; public class ZkMetaClientFactory extends MetaClientFactory { @Override @@ -36,4 +39,16 @@ public class ZkMetaClientFactory extends MetaClientFactory { } throw new IllegalArgumentException("Invalid MetaClientConfig type."); } + + @Override + public MetaClientCacheInterface getMetaClientCache(MetaClientConfig config, MetaClientCacheConfig cacheConfig) { + if (config == null) { + throw new IllegalArgumentException("MetaClientConfig cannot be null."); + } + if (MetaClientConfig.StoreType.ZOOKEEPER.equals(config.getStoreType()) + && config instanceof ZkMetaClientConfig) { + return new ZkMetaClientCache((ZkMetaClientConfig) config, cacheConfig); + } + throw new IllegalArgumentException("Invalid MetaClientConfig type."); + } } diff --git a/meta-client/src/test/java/org/apache/helix/metaclient/impl/zk/TestZkMetaClientCache.java b/meta-client/src/test/java/org/apache/helix/metaclient/impl/zk/TestZkMetaClientCache.java new file mode 100644 index 000000000..a3a5b4eee --- /dev/null +++ b/meta-client/src/test/java/org/apache/helix/metaclient/impl/zk/TestZkMetaClientCache.java @@ -0,0 +1,57 @@ +package org.apache.helix.metaclient.impl.zk; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +import org.apache.helix.metaclient.factories.MetaClientCacheConfig; +import org.apache.helix.metaclient.impl.zk.factory.ZkMetaClientConfig; +import org.testng.Assert; +import org.testng.annotations.Test; + +public class TestZkMetaClientCache extends ZkMetaClientTestBase { + private static final String PATH = "/Cache"; + + @Test + public void testCreateClient() { + final String key = "/TestZkMetaClientCache_testCreate"; + try (ZkMetaClient<String> zkMetaClientCache = createZkMetaClientCache()) { + zkMetaClientCache.connect(); + // Perform some random non-read operation + zkMetaClientCache.create(key, ENTRY_STRING_VALUE); + + try { + //Perform some read operation - should fail. + // TODO: Remove this once implemented. + zkMetaClientCache.get(key); + Assert.fail("Should have failed with non implemented yet."); + } catch (Exception ignored) { + } + } + } + + protected static ZkMetaClientCache<String> createZkMetaClientCache() { + ZkMetaClientConfig config = + new ZkMetaClientConfig.ZkMetaClientConfigBuilder().setConnectionAddress(ZK_ADDR) + //.setZkSerializer(new TestStringSerializer()) + .build(); + MetaClientCacheConfig cacheConfig = new MetaClientCacheConfig(PATH, true, true, true); + return new ZkMetaClientCache<>(config, cacheConfig); + } +}
