This is an automated email from the ASF dual-hosted git repository. hulee pushed a commit to branch rest0 in repository https://gitbox.apache.org/repos/asf/helix.git
commit e1f13b81089637f92b7beb5c6bf9b521ec857a4a Author: Hunter Lee <[email protected]> AuthorDate: Sat Jan 11 18:25:55 2020 -0800 Implement ZkAccessor --- .../org/apache/helix/rest/common/ServletType.java | 12 +++- .../resources/zookeeper/ZooKeeperAccessor.java | 82 +++++++++++++++------- .../helix/rest/server/TestZooKeeperAccessor.java | 2 +- 3 files changed, 68 insertions(+), 28 deletions(-) diff --git a/helix-rest/src/main/java/org/apache/helix/rest/common/ServletType.java b/helix-rest/src/main/java/org/apache/helix/rest/common/ServletType.java index bbff2d6..f068f95 100644 --- a/helix-rest/src/main/java/org/apache/helix/rest/common/ServletType.java +++ b/helix-rest/src/main/java/org/apache/helix/rest/common/ServletType.java @@ -21,21 +21,27 @@ package org.apache.helix.rest.common; import org.apache.helix.rest.server.resources.helix.AbstractHelixResource; import org.apache.helix.rest.server.resources.metadata.NamespacesAccessor; +import org.apache.helix.rest.server.resources.zookeeper.ZooKeeperAccessor; + public enum ServletType { /** * Servlet serving default API endpoints (/admin/v2/clusters/...) */ DEFAULT_SERVLET(HelixRestNamespace.DEFAULT_NAMESPACE_PATH_SPEC, - new String[] { AbstractHelixResource.class.getPackage().getName(), - NamespacesAccessor.class.getPackage().getName() + new String[] { + AbstractHelixResource.class.getPackage().getName(), + NamespacesAccessor.class.getPackage().getName(), + ZooKeeperAccessor.class.getPackage().getName() }), /** * Servlet serving namespaced API endpoints (/admin/v2/namespaces/{namespaceName}) */ COMMON_SERVLET("/namespaces/%s/*", - new String[] { AbstractHelixResource.class.getPackage().getName(), + new String[] { + AbstractHelixResource.class.getPackage().getName(), + ZooKeeperAccessor.class.getPackage().getName() }); private final String _servletPathSpecTemplate; diff --git a/helix-rest/src/main/java/org/apache/helix/rest/server/resources/zookeeper/ZooKeeperAccessor.java b/helix-rest/src/main/java/org/apache/helix/rest/server/resources/zookeeper/ZooKeeperAccessor.java index 4752168..fc2abe0 100644 --- a/helix-rest/src/main/java/org/apache/helix/rest/server/resources/zookeeper/ZooKeeperAccessor.java +++ b/helix-rest/src/main/java/org/apache/helix/rest/server/resources/zookeeper/ZooKeeperAccessor.java @@ -19,24 +19,21 @@ package org.apache.helix.rest.server.resources.zookeeper; * under the License. */ -import java.util.HashMap; import java.util.List; import java.util.Map; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Response; +import com.google.common.collect.ImmutableMap; import org.apache.helix.AccessOption; -import org.apache.helix.HelixAdmin; -import org.apache.helix.ZNRecord; import org.apache.helix.manager.zk.ZkBaseDataAccessor; import org.apache.helix.rest.common.ContextPropertyKeys; import org.apache.helix.rest.server.ServerContext; import org.apache.helix.rest.server.resources.AbstractResource; -import org.apache.helix.rest.server.resources.helix.ClusterAccessor; -import org.codehaus.jackson.node.ObjectNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -48,42 +45,68 @@ import org.slf4j.LoggerFactory; @Path("/zookeeper") public class ZooKeeperAccessor extends AbstractResource { private static final Logger LOG = LoggerFactory.getLogger(ZooKeeperAccessor.class.getName()); + private ZkBaseDataAccessor<byte[]> _zkBaseDataAccessor; - private ServerContext _serverContext = - (ServerContext) _application.getProperties().get(ContextPropertyKeys.SERVER_CONTEXT.name()); - private ZkBaseDataAccessor<byte[]> _zkBaseDataAccessor = - _serverContext.getByteArrayZkBaseDataAccessor(); + public enum ZooKeeperCommand { + exists, getBinaryData, getStringData, getChildren + } @GET @Path("{path: .+}") - public Response get(@PathParam("path") String path) + public Response get(@PathParam("path") String path, @QueryParam("command") String commandStr) { + ZooKeeperCommand cmd; + try { + cmd = ZooKeeperCommand.valueOf(commandStr); + } catch (Exception e) { + return badRequest("Invalid ZooKeeper command: " + commandStr); + } + + // Lazily initialize ZkBaseDataAccessor + ServerContext _serverContext = + (ServerContext) _application.getProperties().get(ContextPropertyKeys.SERVER_CONTEXT.name()); + _zkBaseDataAccessor = _serverContext.getByteArrayZkBaseDataAccessor(); + + // Need to prepend a "/" since JAX-RS regex removes it + path = "/" + path; + switch (cmd) { + case exists: + return exists(path); + case getBinaryData: + return getData(path, cmd); + case getStringData: + return getData(path, cmd); + case getChildren: + return getChildren(path); + default: + LOG.error("Unsupported command :" + commandStr); + return badRequest("Unsupported command :" + commandStr); + } + } /** * Checks if a ZNode exists in the given path. * @param path * @return true if a ZNode exists, false otherwise */ - @GET - @Path("exists/{path: .+}") - public Response exists(@PathParam("path") String path) { + private Response exists(String path) { if (!isPathValid(path)) { String errMsg = "exists(): The given path {} is not a valid ZooKeeper path!" + path; LOG.error(errMsg); return badRequest(errMsg); } - boolean exists = _zkBaseDataAccessor.exists(path, AccessOption.PERSISTENT); - return JSONRepresentation(exists); + Map<String, Boolean> result = ImmutableMap.of(ZooKeeperCommand.exists.name(), + _zkBaseDataAccessor.exists(path, AccessOption.PERSISTENT)); + return JSONRepresentation(result); } /** * Reads the given path from ZooKeeper and returns the binary data for the ZNode. * @param path + * @param command denotes whether return type should be binary or String * @return binary data in the ZNode */ - @GET - @Path("getData/{path: .+}") - public Response getData(@PathParam("path") String path) { + private Response getData(String path, ZooKeeperCommand command) { if (!isPathValid(path)) { String errMsg = "getData(): The given path {} is not a valid ZooKeeper path!" + path; LOG.error(errMsg); @@ -92,7 +115,19 @@ public class ZooKeeperAccessor extends AbstractResource { if (_zkBaseDataAccessor.exists(path, AccessOption.PERSISTENT)) { byte[] bytes = _zkBaseDataAccessor.get(path, null, AccessOption.PERSISTENT); - return JSONRepresentation(bytes); + switch (command) { + case getBinaryData: + Map<String, byte[]> binaryResult = + ImmutableMap.of(ZooKeeperCommand.getBinaryData.name(), bytes); + return JSONRepresentation(binaryResult); + case getStringData: + Map<String, String> stringResult = + ImmutableMap.of(ZooKeeperCommand.getStringData.name(), new String(bytes)); + return JSONRepresentation(stringResult); + default: + LOG.error("Unsupported command :" + command); + return badRequest("Unsupported command :" + command); + } } else { throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND) .entity(String.format("The ZNode at path %s does not exist", path)).build()); @@ -104,9 +139,7 @@ public class ZooKeeperAccessor extends AbstractResource { * @param path * @return list of child ZNodes */ - @GET - @Path("getChildren/{path: .+}") - public Response getChildren(@PathParam("path") String path) { + private Response getChildren(String path) { if (!isPathValid(path)) { String errMsg = "getChildren(): The given path {} is not a valid ZooKeeper path!" + path; LOG.error(errMsg); @@ -114,8 +147,9 @@ public class ZooKeeperAccessor extends AbstractResource { } if (_zkBaseDataAccessor.exists(path, AccessOption.PERSISTENT)) { - List<String> children = _zkBaseDataAccessor.getChildNames(path, AccessOption.PERSISTENT); - return JSONRepresentation(children); + Map<String, List<String>> result = ImmutableMap.of(ZooKeeperCommand.getChildren.name(), + _zkBaseDataAccessor.getChildNames(path, AccessOption.PERSISTENT)); + return JSONRepresentation(result); } else { throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND) .entity(String.format("The ZNode at path %s does not exist", path)).build()); diff --git a/helix-rest/src/test/java/org/apache/helix/rest/server/TestZooKeeperAccessor.java b/helix-rest/src/test/java/org/apache/helix/rest/server/TestZooKeeperAccessor.java index a46f0fd..175f0b2 100644 --- a/helix-rest/src/test/java/org/apache/helix/rest/server/TestZooKeeperAccessor.java +++ b/helix-rest/src/test/java/org/apache/helix/rest/server/TestZooKeeperAccessor.java @@ -67,7 +67,7 @@ public class TestZooKeeperAccessor extends AbstractTestClass { Assert.assertTrue(_testBaseDataAccessor.create(path, content.getBytes(), AccessOption.PERSISTENT)); Assert.assertTrue(_testBaseDataAccessor.exists(path, AccessOption.PERSISTENT)); - String data = new JerseyUriRequestBuilder("zookeeper/exists{}").format(path) + String data = new JerseyUriRequestBuilder("zookeeper{}?command=exists").format(path) .isBodyReturnExpected(true).get(this); // Clean up
