You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@zookeeper.apache.org by ph...@apache.org on 2014/07/18 02:19:03 UTC
svn commit: r1611516 [2/3] - in /zookeeper/trunk: ./ docs/
src/docs/src/documentation/content/xdocs/
src/java/main/org/apache/zookeeper/server/
src/java/main/org/apache/zookeeper/server/admin/
src/java/main/org/apache/zookeeper/server/quorum/ src/java/...
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/AdminServerFactory.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/AdminServerFactory.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/AdminServerFactory.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/AdminServerFactory.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,63 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.lang.reflect.InvocationTargetException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Factory class for creating an AdminServer.
+ */
+public class AdminServerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(AdminServerFactory.class);
+
+ /**
+ * This method encapsulates the logic for whether we should use a
+ * JettyAdminServer (i.e., the AdminServer is enabled) or a DummyAdminServer
+ * (i.e., the AdminServer is disabled). It uses reflection when attempting
+ * to create a JettyAdminServer, rather than referencing the class directly,
+ * so that it's ok to omit Jetty from the classpath if a user doesn't wish
+ * to pull in Jetty with ZooKeeper.
+ */
+ public static AdminServer createAdminServer() {
+ if (!"false".equals(System.getProperty("zookeeper.admin.enableServer"))) {
+ try {
+ Class<?> jettyAdminServerC = Class.forName("org.apache.zookeeper.server.admin.JettyAdminServer");
+ Object adminServer = jettyAdminServerC.getConstructor().newInstance();
+ return (AdminServer) adminServer;
+
+ } catch (ClassNotFoundException e) {
+ LOG.warn("Unable to start JettyAdminServer", e);
+ } catch (InstantiationException e) {
+ LOG.warn("Unable to start JettyAdminServer", e);
+ } catch (IllegalAccessException e) {
+ LOG.warn("Unable to start JettyAdminServer", e);
+ } catch (InvocationTargetException e) {
+ LOG.warn("Unable to start JettyAdminServer", e);
+ } catch (NoSuchMethodException e) {
+ LOG.warn("Unable to start JettyAdminServer", e);
+ } catch (NoClassDefFoundError e) {
+ LOG.warn("Unable to load jetty, not starting JettyAdminServer", e);
+ }
+ }
+ return new DummyAdminServer();
+ }
+}
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/Command.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/Command.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/Command.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/Command.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.zookeeper.server.ZooKeeperServer;
+
+/**
+ * Interface implemented by all commands runnable by JettyAdminServer.
+ *
+ * @see CommandBase
+ * @see Commands
+ * @see JettyAdminServer
+ */
+public interface Command {
+ /**
+ * The set of all names that can be used to refer to this command (e.g.,
+ * "configuration", "config", and "conf").
+ */
+ Set<String> getNames();
+
+ /**
+ * The name that is returned with the command response and that appears in
+ * the list of all commands. This should be a member of the set returned by
+ * getNames().
+ */
+ String getPrimaryName();
+
+ /**
+ * A string documentating this command (e.g., what it does, any arguments it
+ * takes).
+ */
+ String getDoc();
+
+ /**
+ * Run this command. Commands take a ZooKeeperServer and String-valued
+ * keyword arguments and return a map containing any information
+ * constituting the response to the command. Commands are responsible for
+ * parsing keyword arguments and performing any error handling if necessary.
+ * Errors should be reported by setting the "error" entry of the returned
+ * map with an appropriate message rather than throwing an exception.
+ *
+ * @param zkServer
+ * @param kwargs keyword -> argument value mapping
+ * @return Map representing response to command containing at minimum:
+ * - "command" key containing the command's primary name
+ * - "error" key containing a String error message or null if no error
+ */
+ CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs);
+}
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandBase.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandBase.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandBase.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandBase.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,66 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public abstract class CommandBase implements Command {
+ private final String primaryName;
+ private final Set<String> names;
+ private final String doc;
+
+ /**
+ * @param names The possible names of this command, with the primary name first.
+ */
+ protected CommandBase(List<String> names) {
+ this(names, null);
+ }
+
+ protected CommandBase(List<String> names, String doc) {
+ this.primaryName = names.get(0);
+ this.names = new HashSet<String>(names);
+ this.doc = doc;
+ }
+
+ @Override
+ public String getPrimaryName() {
+ return primaryName;
+ }
+
+ @Override
+ public Set<String> getNames() {
+ return names;
+ }
+
+ @Override
+ public String getDoc() {
+ return doc;
+ }
+
+ /**
+ * @return A response with the command set to the primary name and the
+ * error set to null (these are the two entries that all command
+ * responses are required to include).
+ */
+ protected CommandResponse initializeResponse() {
+ return new CommandResponse(primaryName);
+ }
+}
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandOutputter.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandOutputter.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandOutputter.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandOutputter.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,35 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.io.PrintWriter;
+import java.util.Map;
+
+/**
+ * CommandOutputters are used to format the responses from Commands.
+ *
+ * @see Command
+ * @see JettyAdminServer
+ */
+public interface CommandOutputter {
+ /** The MIME type of this output (e.g., "application/json") */
+ String getContentType();
+
+ void output(CommandResponse response, PrintWriter pw);
+}
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandResponse.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandResponse.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandResponse.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/CommandResponse.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,112 @@
+/*
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * A response from running a {@link Command}.
+ */
+public class CommandResponse {
+
+ /**
+ * The key in the map returned by {@link #toMap()} for the command name.
+ */
+ public static final String KEY_COMMAND = "command";
+ /**
+ * The key in the map returned by {@link #toMap()} for the error string.
+ */
+ public static final String KEY_ERROR = "error";
+
+ private final String command;
+ private final String error;
+ private final Map<String, Object> data;
+
+ /**
+ * Creates a new response with no error string.
+ *
+ * @param command command name
+ */
+ public CommandResponse(String command) {
+ this(command, null);
+ }
+ /**
+ * Creates a new response.
+ *
+ * @param command command name
+ * @param error error string (may be null)
+ */
+ public CommandResponse(String command, String error) {
+ this.command = command;
+ this.error = error;
+ data = new LinkedHashMap<String, Object>();
+ }
+
+ /**
+ * Gets the command name.
+ *
+ * @return command name
+ */
+ public String getCommand() {
+ return command;
+ }
+
+ /**
+ * Gets the error string (may be null).
+ *
+ * @return error string
+ */
+ public String getError() {
+ return error;
+ }
+
+ /**
+ * Adds a key/value pair to this response.
+ *
+ * @param key key
+ * @param value value
+ * @return prior value for key, or null if none
+ */
+ public Object put(String key, Object value) {
+ return data.put(key, value);
+ }
+
+ /**
+ * Adds all key/value pairs in the given map to this response.
+ *
+ * @param m map of key/value pairs
+ */
+ public void putAll(Map<? extends String,?> m) {
+ data.putAll(m);
+ }
+
+ /**
+ * Converts this response to a map. The returned map is mutable, and
+ * changes to it do not reflect back into this response.
+ *
+ * @return map representation of response
+ */
+ public Map<String, Object> toMap() {
+ Map<String, Object> m = new LinkedHashMap<String, Object>(data);
+ m.put(KEY_COMMAND, command);
+ m.put(KEY_ERROR, error);
+ m.putAll(data);
+ return m;
+ }
+}
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/Commands.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/Commands.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/Commands.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/Commands.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,501 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.OperatingSystemMXBean;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.zookeeper.Environment;
+import org.apache.zookeeper.Environment.Entry;
+import org.apache.zookeeper.Version;
+import org.apache.zookeeper.server.DataTree;
+import org.apache.zookeeper.server.ServerStats;
+import org.apache.zookeeper.server.ZKDatabase;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.apache.zookeeper.server.ZooTrace;
+import org.apache.zookeeper.server.quorum.Leader;
+import org.apache.zookeeper.server.quorum.LeaderZooKeeperServer;
+import org.apache.zookeeper.server.quorum.ReadOnlyZooKeeperServer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.sun.management.UnixOperatingSystemMXBean;
+
+/**
+ * Class containing static methods for registering and running Commands, as well
+ * as default Command definitions.
+ *
+ * @see Command
+ * @see JettyAdminServer
+ */
+public class Commands {
+ static final Logger LOG = LoggerFactory.getLogger(Commands.class);
+
+ /** Maps command names to Command instances */
+ private static Map<String, Command> commands = new HashMap<String, Command>();
+ private static Set<String> primaryNames = new HashSet<String>();
+
+ /**
+ * Registers the given command. Registered commands can be run by passing
+ * any of their names to runCommand.
+ */
+ public static void registerCommand(Command command) {
+ for (String name : command.getNames()) {
+ Command prev = commands.put(name, command);
+ if (prev != null) {
+ LOG.warn("Re-registering command %s (primary name = %s)", name, command.getPrimaryName());
+ }
+ }
+ primaryNames.add(command.getPrimaryName());
+ }
+
+ /**
+ * Run the registered command with name cmdName. Commands should not produce
+ * any exceptions; any (anticipated) errors should be reported in the
+ * "error" entry of the returned map. Likewise, if no command with the given
+ * name is registered, this will be noted in the "error" entry.
+ *
+ * @param cmdName
+ * @param zkServer
+ * @param kwargs String-valued keyword arguments to the command
+ * (may be null if command requires no additional arguments)
+ * @return Map representing response to command containing at minimum:
+ * - "command" key containing the command's primary name
+ * - "error" key containing a String error message or null if no error
+ */
+ public static CommandResponse runCommand(String cmdName, ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ if (!commands.containsKey(cmdName)) {
+ return new CommandResponse(cmdName, "Unknown command: " + cmdName);
+ }
+ if (zkServer == null) {
+ return new CommandResponse(cmdName, "This ZooKeeper instance is not currently serving requests");
+ }
+ return commands.get(cmdName).run(zkServer, kwargs);
+ }
+
+ /**
+ * Returns the primary names of all registered commands.
+ */
+ public static Set<String> getPrimaryNames() {
+ return primaryNames;
+ }
+
+ /**
+ * Returns the commands registered under cmdName with registerCommand, or
+ * null if no command is registered with that name.
+ */
+ public static Command getCommand(String cmdName) {
+ return commands.get(cmdName);
+ }
+
+ static {
+ registerCommand(new CnxnStatResetCommand());
+ registerCommand(new ConfCommand());
+ registerCommand(new ConsCommand());
+ registerCommand(new DumpCommand());
+ registerCommand(new EnvCommand());
+ registerCommand(new GetTraceMaskCommand());
+ registerCommand(new IsroCommand());
+ registerCommand(new MonitorCommand());
+ registerCommand(new RuokCommand());
+ registerCommand(new SetTraceMaskCommand());
+ registerCommand(new SrvrCommand());
+ registerCommand(new StatCommand());
+ registerCommand(new StatResetCommand());
+ registerCommand(new WatchCommand());
+ registerCommand(new WatchesByPathCommand());
+ registerCommand(new WatchSummaryCommand());
+ }
+
+ /**
+ * Reset all connection statistics.
+ */
+ public static class CnxnStatResetCommand extends CommandBase {
+ public CnxnStatResetCommand() {
+ super(Arrays.asList("connection_stat_reset", "crst"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ zkServer.getServerCnxnFactory().resetAllConnectionStats();
+ return response;
+
+ }
+ }
+
+ /**
+ * Server configuration parameters.
+ * @see ZooKeeperServer#getConf()
+ */
+ public static class ConfCommand extends CommandBase {
+ public ConfCommand() {
+ super(Arrays.asList("configuration", "conf", "config"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ response.putAll(zkServer.getConf().toMap());
+ return response;
+ }
+ }
+
+ /**
+ * Information on client connections to server. Returned Map contains:
+ * - "connections": list of connection info objects
+ * @see org.apache.zookeeper.server.ServerCnxn#getConnectionInfo(boolean)
+ */
+ public static class ConsCommand extends CommandBase {
+ public ConsCommand() {
+ super(Arrays.asList("connections", "cons"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ response.put("connections", zkServer.getServerCnxnFactory().getAllConnectionInfo(false));
+ return response;
+ }
+ }
+
+ /**
+ * Information on session expirations and ephemerals. Returned map contains:
+ * - "expiry_time_to_session_ids": Map<Long, Set<Long>>
+ * time -> sessions IDs of sessions that expire at time
+ * - "sesssion_id_to_ephemeral_paths": Map<Long, Set<String>>
+ * session ID -> ephemeral paths created by that session
+ * @see ZooKeeperServer#getSessionExpiryMap()
+ * @see ZooKeeperServer#getEphemerals()
+ */
+ public static class DumpCommand extends CommandBase {
+ public DumpCommand() {
+ super(Arrays.asList("dump"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ response.put("expiry_time_to_session_ids", zkServer.getSessionExpiryMap());
+ response.put("session_id_to_ephemeral_paths", zkServer.getEphemerals());
+ return response;
+ }
+ }
+
+ /**
+ * All defined environment variables.
+ */
+ public static class EnvCommand extends CommandBase {
+ public EnvCommand() {
+ super(Arrays.asList("environment", "env", "envi"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ for (Entry e : Environment.list()) {
+ response.put(e.getKey(), e.getValue());
+ }
+ return response;
+ }
+ }
+
+ /**
+ * The current trace mask. Returned map contains:
+ * - "tracemask": Long
+ */
+ public static class GetTraceMaskCommand extends CommandBase {
+ public GetTraceMaskCommand() {
+ super(Arrays.asList("get_trace_mask", "gtmk"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ response.put("tracemask", ZooTrace.getTextTraceLevel());
+ return response;
+ }
+ }
+
+ /**
+ * Is this server in read-only mode. Returned map contains:
+ * - "is_read_only": Boolean
+ */
+ public static class IsroCommand extends CommandBase {
+ public IsroCommand() {
+ super(Arrays.asList("is_read_only", "isro"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ response.put("read_only", zkServer instanceof ReadOnlyZooKeeperServer);
+ return response;
+ }
+ }
+
+ /**
+ * Some useful info for monitoring. Returned map contains:
+ * - "version": String
+ * server version
+ * - "avg_latency": Long
+ * - "max_latency": Long
+ * - "min_latency": Long
+ * - "packets_received": Long
+ * - "packets_sents": Long
+ * - "num_alive_connections": Integer
+ * - "outstanding_requests": Long
+ * number of unprocessed requests
+ * - "server_state": "leader", "follower", or "standalone"
+ * - "znode_count": Integer
+ * - "watch_count": Integer
+ * - "ephemerals_count": Integer
+ * - "approximate_data_size": Long
+ * - "open_file_descriptor_count": Long (unix only)
+ * - "max_file_descritpor_count": Long (unix only)
+ * - "followers": Integer (leader only)
+ * - "synced_followers": Integer (leader only)
+ * - "pending_syncs": Integer (leader only)
+ */
+ public static class MonitorCommand extends CommandBase {
+ public MonitorCommand() {
+ super(Arrays.asList("monitor", "mntr"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ ZKDatabase zkdb = zkServer.getZKDatabase();
+ ServerStats stats = zkServer.serverStats();
+
+ CommandResponse response = initializeResponse();
+
+ response.put("version", Version.getFullVersion());
+
+ response.put("avg_latency", stats.getAvgLatency());
+ response.put("max_latency", stats.getMaxLatency());
+ response.put("min_latency", stats.getMinLatency());
+
+ response.put("packets_received", stats.getPacketsReceived());
+ response.put("packets_sent", stats.getPacketsSent());
+ response.put("num_alive_connections", stats.getNumAliveClientConnections());
+
+ response.put("outstanding_requests", stats.getOutstandingRequests());
+
+ response.put("server_state", stats.getServerState());
+ response.put("znode_count", zkdb.getNodeCount());
+
+ response.put("watch_count", zkdb.getDataTree().getWatchCount());
+ response.put("ephemerals_count", zkdb.getDataTree().getEphemeralsCount());
+ response.put("approximate_data_size", zkdb.getDataTree().approximateDataSize());
+
+ OperatingSystemMXBean osMbean = ManagementFactory.getOperatingSystemMXBean();
+ if (osMbean != null && osMbean instanceof UnixOperatingSystemMXBean) {
+ UnixOperatingSystemMXBean unixos = (UnixOperatingSystemMXBean) osMbean;
+
+ response.put("open_file_descriptor_count", unixos.getOpenFileDescriptorCount());
+ response.put("max_file_descriptor_count", unixos.getMaxFileDescriptorCount());
+ }
+
+ if (zkServer instanceof LeaderZooKeeperServer) {
+ Leader leader = ((LeaderZooKeeperServer) zkServer).getLeader();
+
+ response.put("followers", leader.getLearners().size());
+ response.put("synced_followers", leader.getForwardingFollowers().size());
+ response.put("pending_syncs", leader.getNumPendingSyncs());
+ }
+
+ return response;
+
+ }}
+
+ /**
+ * No-op command, check if the server is running
+ */
+ public static class RuokCommand extends CommandBase {
+ public RuokCommand() {
+ super(Arrays.asList("ruok"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ return initializeResponse();
+ }
+ }
+
+ /**
+ * Sets the trace mask. Required arguments:
+ * - "traceMask": Long
+ * Returned Map contains:
+ * - "tracemask": Long
+ */
+ public static class SetTraceMaskCommand extends CommandBase {
+ public SetTraceMaskCommand() {
+ super(Arrays.asList("set_trace_mask", "stmk"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ long traceMask;
+ if (!kwargs.containsKey("traceMask")) {
+ response.put("error", "setTraceMask requires long traceMask argument");
+ return response;
+ }
+ try {
+ traceMask = Long.parseLong(kwargs.get("traceMask"));
+ } catch (NumberFormatException e) {
+ response.put("error", "setTraceMask requires long traceMask argument, got "
+ + kwargs.get("traceMask"));
+ return response;
+ }
+
+ ZooTrace.setTextTraceLevel(traceMask);
+ response.put("tracemask", traceMask);
+ return response;
+ }
+ }
+
+ /**
+ * Server information. Returned map contains:
+ * - "version": String
+ * version of server
+ * - "read_only": Boolean
+ * is server in read-only mode
+ * - "server_stats": ServerStats object
+ * - "node_count": Integer
+ */
+ public static class SrvrCommand extends CommandBase {
+ public SrvrCommand() {
+ super(Arrays.asList("server_stats", "srvr"));
+ }
+
+ // Allow subclasses (e.g. StatCommand) to specify their own names
+ protected SrvrCommand(List<String> names) {
+ super(names);
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ LOG.info("running stat");
+ response.put("version", Version.getFullVersion());
+ response.put("read_only", zkServer instanceof ReadOnlyZooKeeperServer);
+ response.put("server_stats", zkServer.serverStats());
+ response.put("node_count", zkServer.getZKDatabase().getNodeCount());
+ return response;
+
+ }
+ }
+
+ /**
+ * Same as SrvrCommand but has extra "connections" entry.
+ */
+ public static class StatCommand extends SrvrCommand {
+ public StatCommand() {
+ super(Arrays.asList("stats", "stat"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = super.run(zkServer, kwargs);
+ response.put("connections", zkServer.getServerCnxnFactory().getAllConnectionInfo(true));
+ return response;
+ }
+ }
+
+ /**
+ * Resets server statistics.
+ */
+ public static class StatResetCommand extends CommandBase {
+ public StatResetCommand() {
+ super(Arrays.asList("stat_reset", "srst"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ CommandResponse response = initializeResponse();
+ zkServer.serverStats().reset();
+ return response;
+ }
+ }
+
+ /**
+ * Watch information aggregated by session. Returned Map contains:
+ * - "session_id_to_watched_paths": Map<Long, Set<String>> session ID -> watched paths
+ * @see DataTree#getWatches()
+ */
+ public static class WatchCommand extends CommandBase {
+ public WatchCommand() {
+ super(Arrays.asList("watches", "wchc"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ DataTree dt = zkServer.getZKDatabase().getDataTree();
+ CommandResponse response = initializeResponse();
+ response.put("session_id_to_watched_paths", dt.getWatches().toMap());
+ return response;
+ }
+ }
+
+ /**
+ * Watch information aggregated by path. Returned Map contains:
+ * - "path_to_session_ids": Map<String, Set<Long>> path -> session IDs of sessions watching path
+ * @see DataTree#getWatchesByPath()
+ */
+ public static class WatchesByPathCommand extends CommandBase {
+ public WatchesByPathCommand() {
+ super(Arrays.asList("watches_by_path", "wchp"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ DataTree dt = zkServer.getZKDatabase().getDataTree();
+ CommandResponse response = initializeResponse();
+ response.put("path_to_session_ids", dt.getWatchesByPath().toMap());
+ return response;
+ }
+ }
+
+ /**
+ * Summarized watch information.
+ * @see DataTree#getWatchesSummary()
+ */
+ public static class WatchSummaryCommand extends CommandBase {
+ public WatchSummaryCommand() {
+ super(Arrays.asList("watch_summary", "wchs"));
+ }
+
+ @Override
+ public CommandResponse run(ZooKeeperServer zkServer, Map<String, String> kwargs) {
+ DataTree dt = zkServer.getZKDatabase().getDataTree();
+ CommandResponse response = initializeResponse();
+ response.putAll(dt.getWatchesSummary().toMap());
+ return response;
+ }
+ }
+
+ private Commands() {}
+}
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/DummyAdminServer.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/DummyAdminServer.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/DummyAdminServer.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/DummyAdminServer.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,39 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import org.apache.zookeeper.server.ZooKeeperServer;
+
+/**
+ * An AdminServer that does nothing.
+ *
+ * We use this class when we wish to disable the AdminServer. (This way we only
+ * have to consider whether the server is enabled when we create the
+ * AdminServer, which is handled by AdminServerFactory.)
+ */
+public class DummyAdminServer implements AdminServer {
+ @Override
+ public void start() throws AdminServerException {}
+
+ @Override
+ public void shutdown() throws AdminServerException {}
+
+ @Override
+ public void setZooKeeperServer(ZooKeeperServer zkServer) {}
+}
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/JettyAdminServer.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/JettyAdminServer.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/JettyAdminServer.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/JettyAdminServer.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,176 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.servlet.Context;
+import org.mortbay.jetty.servlet.ServletHolder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class encapsulates a Jetty server for running Commands.
+ *
+ * Given the default settings, start a ZooKeeper server and visit
+ * http://<hostname>:8080/commands for links to all registered commands. Visiting
+ * http://<hostname>:8080/commands/<commandname> will execute the associated
+ * Command and return the result in the body of the response. Any keyword
+ * arguments to the command are specified with URL parameters (e.g.,
+ * http://localhost:8080/commands/set_trace_mask?traceMask=306).
+ *
+ * @see Commands
+ * @see CommandOutputter
+ */
+public class JettyAdminServer implements AdminServer {
+ static final Logger LOG = LoggerFactory.getLogger(JettyAdminServer.class);
+
+ public static final int DEFAULT_PORT = 8080;
+ public static final String DEFAULT_COMMAND_URL = "/commands";
+
+ private final Server server;
+ private ZooKeeperServer zkServer;
+ private final int port;
+ private final String commandUrl;
+
+ public JettyAdminServer() throws AdminServerException {
+ this(Integer.getInteger("zookeeper.admin.serverPort", DEFAULT_PORT),
+ System.getProperty("zookeeper.admin.commandURL", DEFAULT_COMMAND_URL));
+ }
+
+ public JettyAdminServer(int port, String commandUrl) {
+ this.port = port;
+ this.commandUrl = commandUrl;
+
+ server = new Server(port);
+ Context context = new Context(server, "/");
+ server.setHandler(context);
+ context.addServlet(new ServletHolder(new CommandServlet()), commandUrl + "/*");
+ }
+
+ /**
+ * Start the embedded Jetty server.
+ */
+ @Override
+ public void start() throws AdminServerException {
+ try {
+ server.start();
+ } catch (Exception e) {
+ // Server.start() only throws Exception, so let's at least wrap it
+ // in an identifiable subclass
+ throw new AdminServerException(
+ String.format("Problem starting AdminServer on port %d, command URL %s",
+ port, commandUrl), e);
+ }
+ LOG.info(String.format("Started AdminServer on port %d, command URL %s",
+ port, commandUrl));
+ }
+
+ /**
+ * Stop the embedded Jetty server.
+ *
+ * This is not very important except for tests where multiple
+ * JettyAdminServers are started and may try to bind to the same ports if
+ * previous servers aren't shut down.
+ */
+ @Override
+ public void shutdown() throws AdminServerException {
+ try {
+ server.stop();
+ } catch (Exception e) {
+ throw new AdminServerException(
+ String.format("Problem stopping AdminServer on port %d, command URL %s",
+ port, commandUrl), e);
+ }
+ }
+
+ /**
+ * Set the ZooKeeperServer that will be used to run Commands.
+ *
+ * It is not necessary to set the ZK server before calling
+ * AdminServer.start(), and the ZK server can be set to null when, e.g.,
+ * that server is being shut down. If the ZK server is not set or set to
+ * null, the AdminServer will still be able to issue Commands, but they will
+ * return an error until a ZK server is set.
+ */
+ @Override
+ public void setZooKeeperServer(ZooKeeperServer zkServer) {
+ this.zkServer = zkServer;
+ }
+
+ private class CommandServlet extends HttpServlet {
+ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
+ // Capture the command name from the URL
+ String cmd = request.getPathInfo();
+ if (cmd == null || cmd.equals("/")) {
+ // No command specified, print links to all commands instead
+ for (String link : commandLinks()) {
+ response.getWriter().println(link);
+ response.getWriter().println("<br />");
+ }
+ return;
+ }
+ // Strip leading "/"
+ cmd = cmd.substring(1);
+
+ // Extract keyword arguments to command from request parameters
+ @SuppressWarnings("unchecked")
+ Map<String, String[]> parameterMap = request.getParameterMap();
+ Map<String, String> kwargs = new HashMap<String, String>();
+ for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
+ kwargs.put(entry.getKey(), entry.getValue()[0]);
+ }
+
+ // Run the command
+ CommandResponse cmdResponse = Commands.runCommand(cmd, zkServer, kwargs);
+
+ // Format and print the output of the command
+ CommandOutputter outputter = new JsonOutputter();
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType(outputter.getContentType());
+ outputter.output(cmdResponse, response.getWriter());
+ }
+ }
+
+ /**
+ * Returns a list of URLs to each registered Command.
+ */
+ private List<String> commandLinks() {
+ List<String> links = new ArrayList<String>();
+ List<String> commands = new ArrayList<String>(Commands.getPrimaryNames());
+ Collections.sort(commands);
+ for (String command : commands) {
+ String url = commandUrl + "/" + command;
+ links.add(String.format("<a href=\"%s\">%s</a>", url, command));
+ }
+ return links;
+ }
+}
Added: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/JsonOutputter.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/JsonOutputter.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/JsonOutputter.java (added)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/admin/JsonOutputter.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,68 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Map;
+
+import org.codehaus.jackson.JsonGenerationException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.PropertyNamingStrategy;
+import org.codehaus.jackson.map.SerializationConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JsonOutputter implements CommandOutputter {
+ static final Logger LOG = LoggerFactory.getLogger(JsonOutputter.class);
+
+ public static final String ERROR_RESPONSE = "{\"error\": \"Exception writing command response to JSON\"}";
+
+ private ObjectMapper mapper;
+
+ public JsonOutputter() {
+ mapper = new ObjectMapper();
+ mapper.configure(SerializationConfig.Feature.WRITE_ENUMS_USING_TO_STRING, true);
+ mapper.configure(SerializationConfig.Feature.INDENT_OUTPUT, true);
+ mapper.setPropertyNamingStrategy(PropertyNamingStrategy.CAMEL_CASE_TO_LOWER_CASE_WITH_UNDERSCORES);
+ }
+
+ @Override
+ public String getContentType() {
+ return "application/json";
+ }
+
+ @Override
+ public void output(CommandResponse response, PrintWriter pw) {
+ try {
+ mapper.writeValue(pw, response.toMap());
+ } catch (JsonGenerationException e) {
+ LOG.warn("Exception writing command response to JSON:", e);
+ pw.write(ERROR_RESPONSE);
+ } catch (JsonMappingException e) {
+ LOG.warn("Exception writing command response to JSON:", e);
+ pw.write(ERROR_RESPONSE);
+ } catch (IOException e) {
+ LOG.warn("Exception writing command response to JSON:", e);
+ pw.write(ERROR_RESPONSE);
+ }
+ }
+
+}
Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Leader.java Fri Jul 18 00:19:01 2014
@@ -533,6 +533,9 @@ public class Leader {
if (!System.getProperty("zookeeper.leaderServes", "yes").equals("no")) {
self.cnxnFactory.setZooKeeperServer(zk);
}
+
+ self.adminServer.setZooKeeperServer(zk);
+
// Everything is a go, simply start counting the ticks
// WARNING: I couldn't find any wait statement on a synchronized
// block that would be notified by this notifyAll() call, so
@@ -619,6 +622,7 @@ public class Leader {
// NIO should not accept conenctions
self.cnxnFactory.setZooKeeperServer(null);
+ self.adminServer.setZooKeeperServer(null);
try {
ss.close();
} catch (IOException e) {
Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderSessionTracker.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderSessionTracker.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderSessionTracker.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LeaderSessionTracker.java Fri Jul 18 00:19:01 2014
@@ -18,6 +18,9 @@
package org.apache.zookeeper.server.quorum;
import java.io.PrintWriter;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.zookeeper.KeeperException.SessionExpiredException;
@@ -200,4 +203,17 @@ public class LeaderSessionTracker extend
}
globalSessionTracker.setSessionClosing(sessionId);
}
+
+ public Map<Long, Set<Long>> getSessionExpiryMap() {
+ Map<Long, Set<Long>> sessionExpiryMap;
+ // combine local and global sessions, getting local first so upgrades
+ // to global are caught
+ if (localSessionTracker != null) {
+ sessionExpiryMap = localSessionTracker.getSessionExpiryMap();
+ } else {
+ sessionExpiryMap = new TreeMap<Long, Set<Long>>();
+ }
+ sessionExpiryMap.putAll(globalSessionTracker.getSessionExpiryMap());
+ return sessionExpiryMap;
+ }
}
Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Learner.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Learner.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Learner.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/Learner.java Fri Jul 18 00:19:01 2014
@@ -469,6 +469,7 @@ public class Learner {
self.setCurrentEpoch(newEpoch);
}
self.cnxnFactory.setZooKeeperServer(zk);
+ self.adminServer.setZooKeeperServer(zk);
break outerLoop;
case Leader.NEWLEADER: // it will be NEWLEADER in v1.0
LOG.info("Learner received NEWLEADER message");
@@ -583,6 +584,7 @@ public class Learner {
self.cnxnFactory.setZooKeeperServer(null);
// clear all the connections
self.cnxnFactory.closeAll();
+ self.adminServer.setZooKeeperServer(null);
// shutdown previous zookeeper
if (zk != null) {
zk.shutdown();
Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerSessionTracker.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerSessionTracker.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerSessionTracker.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/LearnerSessionTracker.java Fri Jul 18 00:19:01 2014
@@ -18,7 +18,9 @@
package org.apache.zookeeper.server.quorum;
import java.io.PrintWriter;
+import java.util.HashMap;
import java.util.Map;
+import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
@@ -213,4 +215,9 @@ public class LearnerSessionTracker exten
localSessionTracker.setSessionClosing(sessionId);
}
}
+
+ @Override
+ public Map<Long, Set<Long>> getSessionExpiryMap() {
+ return new HashMap<Long, Set<Long>>();
+ }
}
Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeer.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeer.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeer.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeer.java Fri Jul 18 00:19:01 2014
@@ -57,6 +57,9 @@ import org.apache.zookeeper.server.Serve
import org.apache.zookeeper.server.ZKDatabase;
import org.apache.zookeeper.server.ZooKeeperServer;
import org.apache.zookeeper.server.ZooKeeperThread;
+import org.apache.zookeeper.server.admin.AdminServer;
+import org.apache.zookeeper.server.admin.AdminServer.AdminServerException;
+import org.apache.zookeeper.server.admin.AdminServerFactory;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
import org.apache.zookeeper.server.quorum.flexible.QuorumMaj;
@@ -584,10 +587,13 @@ public class QuorumPeer extends ZooKeepe
private final QuorumStats quorumStats;
+ AdminServer adminServer;
+
public QuorumPeer() {
super("QuorumPeer");
quorumStats = new QuorumStats(this);
jmxRemotePeerBean = new HashMap<Long, RemotePeerBean>();
+ adminServer = AdminServerFactory.createAdminServer();
}
@@ -623,6 +629,7 @@ public class QuorumPeer extends ZooKeepe
this.dynamicConfigFilename = (memFilename != null) ? memFilename : "zoo_replicated" + myid + ".dynamic";
if(quorumConfig == null) quorumConfig = new QuorumMaj(quorumPeers);
setQuorumVerifier(quorumConfig, false);
+ adminServer = AdminServerFactory.createAdminServer();
}
QuorumStats quorumStats() {
@@ -636,6 +643,12 @@ public class QuorumPeer extends ZooKeepe
}
loadDataBase();
cnxnFactory.start();
+ try {
+ adminServer.start();
+ } catch (AdminServerException e) {
+ LOG.warn("Problem starting AdminServer", e);
+ System.out.println(e);
+ }
startLeaderElection();
super.start();
}
@@ -1054,6 +1067,12 @@ public class QuorumPeer extends ZooKeepe
udpSocket.close();
}
+ try {
+ adminServer.shutdown();
+ } catch (AdminServerException e) {
+ LOG.warn("Problem stopping AdminServer", e);
+ }
+
if(getElectionAlg() != null){
this.interrupt();
getElectionAlg().shutdown();
Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerMain.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerMain.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerMain.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/QuorumPeerMain.java Fri Jul 18 00:19:01 2014
@@ -28,6 +28,7 @@ import org.apache.zookeeper.server.Serve
import org.apache.zookeeper.server.ZKDatabase;
import org.apache.zookeeper.server.DatadirCleanupManager;
import org.apache.zookeeper.server.ZooKeeperServerMain;
+import org.apache.zookeeper.server.admin.AdminServer.AdminServerException;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog;
import org.apache.zookeeper.server.persistence.FileTxnSnapLog.DatadirException;
import org.apache.zookeeper.server.quorum.QuorumPeerConfig.ConfigException;
@@ -89,6 +90,10 @@ public class QuorumPeerMain {
LOG.error("Unable to access datadir, exiting abnormally", e);
System.err.println("Unable to access datadir, exiting abnormally");
System.exit(3);
+ } catch (AdminServerException e) {
+ LOG.error("Unable to start AdminServer, exiting abnormally", e);
+ System.err.println("Unable to start AdminServer, exiting abnormally");
+ System.exit(4);
} catch (Exception e) {
LOG.error("Unexpected exception, exiting abnormally", e);
System.exit(1);
@@ -98,7 +103,7 @@ public class QuorumPeerMain {
}
protected void initializeAndRun(String[] args)
- throws ConfigException, IOException
+ throws ConfigException, IOException, AdminServerException
{
QuorumPeerConfig config = new QuorumPeerConfig();
if (args.length == 1) {
@@ -121,7 +126,7 @@ public class QuorumPeerMain {
}
}
- public void runFromConfig(QuorumPeerConfig config) throws IOException {
+ public void runFromConfig(QuorumPeerConfig config) throws IOException, AdminServerException {
try {
ManagedUtil.registerLog4jMBeans();
} catch (JMException e) {
Modified: zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyZooKeeperServer.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyZooKeeperServer.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyZooKeeperServer.java (original)
+++ zookeeper/trunk/src/java/main/org/apache/zookeeper/server/quorum/ReadOnlyZooKeeperServer.java Fri Jul 18 00:19:01 2014
@@ -69,6 +69,7 @@ public class ReadOnlyZooKeeperServer ext
registerJMX(new ReadOnlyBean(this), self.jmxLocalPeerBean);
super.startup();
self.cnxnFactory.setZooKeeperServer(this);
+ self.adminServer.setZooKeeperServer(this);
LOG.info("Read-only server started");
}
@@ -144,6 +145,8 @@ public class ReadOnlyZooKeeperServer ext
// clear all the connections
self.cnxnFactory.closeAll();
+ self.adminServer.setZooKeeperServer(null);
+
// shutdown the server itself
super.shutdown();
}
Modified: zookeeper/trunk/src/java/test/org/apache/zookeeper/ZKTestCase.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/ZKTestCase.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/ZKTestCase.java (original)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/ZKTestCase.java Fri Jul 18 00:19:01 2014
@@ -47,6 +47,10 @@ public class ZKTestCase {
public MethodRule watchman = new TestWatchman() {
@Override
public void starting(FrameworkMethod method) {
+ // By default, disable starting a JettyAdminServer in tests to avoid
+ // accidentally attempting to start multiple admin servers on the
+ // same port.
+ System.setProperty("zookeeper.admin.enableServer", "false");
testName = method.getName();
LOG.info("STARTING " + testName);
}
Modified: zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PrepRequestProcessorTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PrepRequestProcessorTest.java?rev=1611516&r1=1611515&r2=1611516&view=diff
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PrepRequestProcessorTest.java (original)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/server/PrepRequestProcessorTest.java Fri Jul 18 00:19:01 2014
@@ -23,6 +23,9 @@ import static org.junit.Assert.*;
import java.io.File;
import java.io.PrintWriter;
import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
import java.util.concurrent.CountDownLatch;
import org.apache.zookeeper.PortAssignment;
@@ -145,5 +148,9 @@ public class PrepRequestProcessorTest ex
throws SessionExpiredException, SessionMovedException {
// TODO Auto-generated method stub
}
+ @Override
+ public Map<Long, Set<Long>> getSessionExpiryMap() {
+ return new HashMap<Long, Set<Long>>();
+ }
}
}
Added: zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesPathReportTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesPathReportTest.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesPathReportTest.java (added)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesPathReportTest.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.zookeeper.server;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class WatchesPathReportTest {
+ private Map<String, Set<Long>> m;
+ private WatchesPathReport r;
+ @Before public void setUp() {
+ m = new HashMap<String, Set<Long>>();
+ Set<Long> s = new HashSet<Long>();
+ s.add(101L);
+ s.add(102L);
+ m.put("path1", s);
+ s = new HashSet<Long>();
+ s.add(201L);
+ m.put("path2", s);
+ r = new WatchesPathReport(m);
+ }
+ @Test public void testHasSessions() {
+ assertTrue(r.hasSessions("path1"));
+ assertTrue(r.hasSessions("path2"));
+ assertFalse(r.hasSessions("path3"));
+ }
+ @Test public void testGetSessions() {
+ Set<Long> s = r.getSessions("path1");
+ assertEquals(2, s.size());
+ assertTrue(s.contains(101L));
+ assertTrue(s.contains(102L));
+ s = r.getSessions("path2");
+ assertEquals(1, s.size());
+ assertTrue(s.contains(201L));
+ assertNull(r.getSessions("path3"));
+ }
+ @Test public void testToMap() {
+ assertEquals(m, r.toMap());
+ }
+}
Added: zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesReportTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesReportTest.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesReportTest.java (added)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesReportTest.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package org.apache.zookeeper.server;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class WatchesReportTest {
+ private Map<Long, Set<String>> m;
+ private WatchesReport r;
+ @Before public void setUp() {
+ m = new HashMap<Long, Set<String>>();
+ Set<String> s = new HashSet<String>();
+ s.add("path1a");
+ s.add("path1b");
+ m.put(1L, s);
+ s = new HashSet<String>();
+ s.add("path2a");
+ m.put(2L, s);
+ r = new WatchesReport(m);
+ }
+ @Test public void testHasPaths() {
+ assertTrue(r.hasPaths(1L));
+ assertTrue(r.hasPaths(2L));
+ assertFalse(r.hasPaths(3L));
+ }
+ @Test public void testGetPaths() {
+ Set<String> s = r.getPaths(1L);
+ assertEquals(2, s.size());
+ assertTrue(s.contains("path1a"));
+ assertTrue(s.contains("path1b"));
+ s = r.getPaths(2L);
+ assertEquals(1, s.size());
+ assertTrue(s.contains("path2a"));
+ assertNull(r.getPaths(3L));
+ }
+ @Test public void testToMap() {
+ assertEquals(m, r.toMap());
+ }
+}
Added: zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesSummaryTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesSummaryTest.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesSummaryTest.java (added)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/server/WatchesSummaryTest.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+package org.apache.zookeeper.server;
+
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class WatchesSummaryTest {
+ private WatchesSummary s;
+ @Before public void setUp() {
+ s = new WatchesSummary(1, 2, 3);
+ }
+ @Test public void testGetters() {
+ assertEquals(1, s.getNumConnections());
+ assertEquals(2, s.getNumPaths());
+ assertEquals(3, s.getTotalWatches());
+ }
+ @Test public void testToMap() {
+ Map<String, Object> m = s.toMap();
+ assertEquals(3, m.size());
+ assertEquals(Integer.valueOf(1), m.get(WatchesSummary.KEY_NUM_CONNECTIONS));
+ assertEquals(Integer.valueOf(2), m.get(WatchesSummary.KEY_NUM_PATHS));
+ assertEquals(Integer.valueOf(3), m.get(WatchesSummary.KEY_NUM_TOTAL_WATCHES));
+ }
+}
Added: zookeeper/trunk/src/java/test/org/apache/zookeeper/server/ZooKeeperServerConfTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/ZooKeeperServerConfTest.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/server/ZooKeeperServerConfTest.java (added)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/server/ZooKeeperServerConfTest.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,51 @@
+/*
+ * 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.
+ */
+package org.apache.zookeeper.server;
+
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class ZooKeeperServerConfTest {
+ private ZooKeeperServerConf c;
+ @Before public void setUp() {
+ c = new ZooKeeperServerConf(1, "a", "b", 2, 3, 4, 5, 6L);
+ }
+ @Test public void testGetters() {
+ assertEquals(1, c.getClientPort());
+ assertEquals("a", c.getDataDir());
+ assertEquals("b", c.getDataLogDir());
+ assertEquals(2, c.getTickTime());
+ assertEquals(3, c.getMaxClientCnxnsPerHost());
+ assertEquals(4, c.getMinSessionTimeout());
+ assertEquals(5, c.getMaxSessionTimeout());
+ assertEquals(6L, c.getServerId());
+ }
+ @Test public void testToMap() {
+ Map<String, Object> m = c.toMap();
+ assertEquals(8, m.size());
+ assertEquals(Integer.valueOf(1), m.get(ZooKeeperServerConf.KEY_CLIENT_PORT));
+ assertEquals("a", m.get(ZooKeeperServerConf.KEY_DATA_DIR));
+ assertEquals("b", m.get(ZooKeeperServerConf.KEY_DATA_LOG_DIR));
+ assertEquals(Integer.valueOf(2), m.get(ZooKeeperServerConf.KEY_TICK_TIME));
+ assertEquals(Integer.valueOf(3), m.get(ZooKeeperServerConf.KEY_MAX_CLIENT_CNXNS));
+ assertEquals(Integer.valueOf(4), m.get(ZooKeeperServerConf.KEY_MIN_SESSION_TIMEOUT));
+ assertEquals(Integer.valueOf(5), m.get(ZooKeeperServerConf.KEY_MAX_SESSION_TIMEOUT));
+ assertEquals(Long.valueOf(6L), m.get(ZooKeeperServerConf.KEY_SERVER_ID));
+ }
+}
Added: zookeeper/trunk/src/java/test/org/apache/zookeeper/server/admin/CommandResponseTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/admin/CommandResponseTest.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/server/admin/CommandResponseTest.java (added)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/server/admin/CommandResponseTest.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,53 @@
+/*
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+
+public class CommandResponseTest {
+ private CommandResponse r;
+
+ @Before public void setUp() throws Exception {
+ r = new CommandResponse("makemeasandwich", "makeityourself");
+ }
+
+ @Test public void testGetters() {
+ assertEquals("makemeasandwich", r.getCommand());
+ assertEquals("makeityourself", r.getError());
+ }
+
+ @Test public void testMap() {
+ r.put("missing", "sudo");
+ Map<String, Object> m = new HashMap<String, Object>();
+ m.put("origin", "xkcd");
+ m.put("url", "http://xkcd.com/149/");
+ r.putAll(m);
+
+ Map<String, Object> rmap = r.toMap();
+ assertEquals(5, rmap.size());
+ assertEquals("makemeasandwich", rmap.get(CommandResponse.KEY_COMMAND));
+ assertEquals("makeityourself", rmap.get(CommandResponse.KEY_ERROR));
+ assertEquals("sudo", rmap.get("missing"));
+ assertEquals("xkcd", rmap.get("origin"));
+ assertEquals("http://xkcd.com/149/", rmap.get("url"));
+ }
+}
Added: zookeeper/trunk/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java
URL: http://svn.apache.org/viewvc/zookeeper/trunk/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java?rev=1611516&view=auto
==============================================================================
--- zookeeper/trunk/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java (added)
+++ zookeeper/trunk/src/java/test/org/apache/zookeeper/server/admin/CommandsTest.java Fri Jul 18 00:19:01 2014
@@ -0,0 +1,236 @@
+/**
+ * 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.
+ */
+
+package org.apache.zookeeper.server.admin;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.zookeeper.server.ServerStats;
+import org.apache.zookeeper.server.ZooKeeperServer;
+import org.apache.zookeeper.test.ClientBase;
+import org.junit.Test;
+
+public class CommandsTest extends ClientBase {
+ /**
+ * Checks that running a given Command returns the expected Map. Asserts
+ * that all specified keys are present with values of the specified types
+ * and that there are no extra entries.
+ *
+ * @param cmdName
+ * - the primary name of the command
+ * @param kwargs
+ * - keyword arguments to the command
+ * @param keys
+ * - the keys that are expected in the returned Map
+ * @param types
+ * - the classes of the values in the returned Map. types[i] is
+ * the type of the value for keys[i].
+ * @throws IOException
+ * @throws InterruptedException
+ */
+ public void testCommand(String cmdName, Map<String, String> kwargs, Field... fields)
+ throws IOException, InterruptedException {
+ ZooKeeperServer zks = serverFactory.getZooKeeperServer();
+ Map<String, Object> result = Commands.runCommand(cmdName, zks, kwargs).toMap();
+
+ assertTrue(result.containsKey("command"));
+ // This is only true because we're setting cmdName to the primary name
+ assertEquals(cmdName, result.remove("command"));
+ assertTrue(result.containsKey("error"));
+ assertNull("error: " + result.get("error"), result.remove("error"));
+
+ for (Field field : fields) {
+ String k = field.key;
+ assertTrue("Result from command " + cmdName + " missing field \"" + k + "\""
+ + "\n" + result,
+ result.containsKey(k));
+ Class<?> t = field.type;
+ Object v = result.remove(k);
+ assertTrue("\"" + k + "\" field from command " + cmdName + " should be of type " + t
+ + ", is actually of type " + v.getClass(),
+ t.isAssignableFrom(v.getClass()));
+ }
+
+ assertTrue("Result from command " + cmdName + " contains extra fields: " + result,
+ result.isEmpty());
+ }
+
+ public void testCommand(String cmdName, Field... fields)
+ throws IOException, InterruptedException {
+ testCommand(cmdName, new HashMap<String, String>(), fields);
+ }
+
+ private static class Field {
+ String key;
+ Class<?> type;
+ Field(String key, Class<?> type) {
+ this.key = key;
+ this.type = type;
+ }
+ }
+
+ @Test
+ public void testConfiguration() throws IOException, InterruptedException {
+ testCommand("configuration",
+ new Field("client_port", Integer.class),
+ new Field("data_dir", String.class),
+ new Field("data_log_dir", String.class),
+ new Field("tick_time", Integer.class),
+ new Field("max_client_cnxns", Integer.class),
+ new Field("min_session_timeout", Integer.class),
+ new Field("max_session_timeout", Integer.class),
+ new Field("server_id", Long.class));
+ }
+
+ @Test
+ public void testConnections() throws IOException, InterruptedException {
+ testCommand("connections",
+ new Field("connections", Iterable.class));
+ }
+
+ @Test
+ public void testConnectionStatReset() throws IOException, InterruptedException {
+ testCommand("connection_stat_reset");
+ }
+
+ @Test
+ public void testDump() throws IOException, InterruptedException {
+ testCommand("dump",
+ new Field("expiry_time_to_session_ids", Map.class),
+ new Field("session_id_to_ephemeral_paths", Map.class));
+ }
+
+ @Test
+ public void testEnvironment() throws IOException, InterruptedException {
+ testCommand("environment",
+ new Field("zookeeper.version", String.class),
+ new Field("host.name", String.class),
+ new Field("java.version", String.class),
+ new Field("java.vendor", String.class),
+ new Field("java.home", String.class),
+ new Field("java.class.path", String.class),
+ new Field("java.library.path", String.class),
+ new Field("java.io.tmpdir", String.class),
+ new Field("java.compiler", String.class),
+ new Field("os.name", String.class),
+ new Field("os.arch", String.class),
+ new Field("os.version", String.class),
+ new Field("user.name", String.class),
+ new Field("user.home", String.class),
+ new Field("user.dir", String.class),
+ new Field("os.memory.free", String.class),
+ new Field("os.memory.max", String.class),
+ new Field("os.memory.total", String.class));
+ }
+
+ @Test
+ public void testGetTraceMask() throws IOException, InterruptedException {
+ testCommand("get_trace_mask",
+ new Field("tracemask", Long.class));
+ }
+
+ @Test
+ public void testIsReadOnly() throws IOException, InterruptedException {
+ testCommand("is_read_only",
+ new Field("read_only", Boolean.class));
+ }
+
+ @Test
+ public void testMonitor() throws IOException, InterruptedException {
+ testCommand("monitor",
+ new Field("version", String.class),
+ new Field("avg_latency", Long.class),
+ new Field("max_latency", Long.class),
+ new Field("min_latency", Long.class),
+ new Field("packets_received", Long.class),
+ new Field("packets_sent", Long.class),
+ new Field("num_alive_connections", Integer.class),
+ new Field("outstanding_requests", Long.class),
+ new Field("server_state", String.class),
+ new Field("znode_count", Integer.class),
+ new Field("watch_count", Integer.class),
+ new Field("ephemerals_count", Integer.class),
+ new Field("approximate_data_size", Long.class),
+ new Field("open_file_descriptor_count", Long.class),
+ new Field("max_file_descriptor_count", Long.class));
+ }
+
+ @Test
+ public void testRuok() throws IOException, InterruptedException {
+ testCommand("ruok");
+ }
+
+ @Test
+ public void testServerStats() throws IOException, InterruptedException {
+ testCommand("server_stats",
+ new Field("version", String.class),
+ new Field("read_only", Boolean.class),
+ new Field("server_stats", ServerStats.class),
+ new Field("node_count", Integer.class));
+ }
+
+ @Test
+ public void testSetTraceMask() throws IOException, InterruptedException {
+ Map<String, String> kwargs = new HashMap<String, String>();
+ kwargs.put("traceMask", "1");
+ testCommand("set_trace_mask", kwargs,
+ new Field("tracemask", Long.class));
+ }
+
+ @Test
+ public void testStat() throws IOException, InterruptedException {
+ testCommand("stats",
+ new Field("version", String.class),
+ new Field("read_only", Boolean.class),
+ new Field("server_stats", ServerStats.class),
+ new Field("node_count", Integer.class),
+ new Field("connections", Iterable.class));
+ }
+
+ @Test
+ public void testStatReset() throws IOException, InterruptedException {
+ testCommand("stat_reset");
+ }
+
+ @Test
+ public void testWatches() throws IOException, InterruptedException {
+ testCommand("watches",
+ new Field("session_id_to_watched_paths", Map.class));
+ }
+
+ @Test
+ public void testWatchesByPath() throws IOException, InterruptedException {
+ testCommand("watches_by_path",
+ new Field("path_to_session_ids", Map.class));
+ }
+
+ @Test
+ public void testWatchSummary() throws IOException, InterruptedException {
+ testCommand("watch_summary",
+ new Field("num_connections", Integer.class),
+ new Field("num_paths", Integer.class),
+ new Field("num_total_watches", Integer.class));
+ }
+
+}