Extend Cluster API Servlet, += Config / Stats
- New APIs to return NC stats & configs, discoverable URIs returned as
part of /admin/cluster.
- Tests for constant info (still need non-exact match tests for config /
stats endpoints)
Change-Id: Ia7549f2bb0b6621886356d50df800d447928aa2c
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1147
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Till Westmann <tillw@apache.org>
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterAPIServlet.java
index 8a16cd7..8cedabc 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterAPIServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterAPIServlet.java
@@ -31,6 +31,7 @@
import org.apache.asterix.app.result.ResultUtil;
import org.apache.asterix.common.config.AbstractAsterixProperties;
import org.apache.asterix.runtime.util.AsterixClusterProperties;
+import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
@@ -42,13 +43,16 @@
response.setContentType("application/json");
response.setCharacterEncoding("utf-8");
PrintWriter responseWriter = response.getWriter();
+ JSONObject json;
+
try {
- JSONObject responseObject = AsterixClusterProperties.INSTANCE.getClusterStateDescription();
- Map<String, Object> allProperties = getAllClusterProperties();
- responseObject.put("config", allProperties);
- responseWriter.write(responseObject.toString(4));
+ json = getClusterStateJSON(request, "node/");
response.setStatus(HttpServletResponse.SC_OK);
- } catch (JSONException e) {
+ responseWriter.write(json.toString(4));
+ } catch (IllegalArgumentException e) {
+ ResultUtil.apiErrorHandler(responseWriter, e);
+ response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
+ } catch (Exception e) {
ResultUtil.apiErrorHandler(responseWriter, e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
@@ -66,4 +70,26 @@
protected List<AbstractAsterixProperties> getPropertiesInstances() {
return AbstractAsterixProperties.getImplementations();
}
+
+ protected JSONObject getClusterStateJSON(HttpServletRequest request, String pathToNode)
+ throws JSONException {
+ JSONObject json;
+ json = AsterixClusterProperties.INSTANCE.getClusterStateDescription();
+ Map<String, Object> allProperties = getAllClusterProperties();
+ json.put("config", allProperties);
+
+ JSONArray ncs = json.getJSONArray("ncs");
+ final StringBuffer requestURL = request.getRequestURL();
+ if (requestURL.charAt(requestURL.length() - 1) != '/') {
+ requestURL.append('/');
+ }
+ requestURL.append(pathToNode);
+ String nodeURL = requestURL.toString().replaceAll("/[^./]+/\\.\\./", "/");
+ for (int i = 0; i < ncs.length(); i++) {
+ JSONObject nc = ncs.getJSONObject(i);
+ nc.put("configUri", nodeURL + nc.getString("node_id") + "/config");
+ nc.put("statsUri", nodeURL + nc.getString("node_id") + "/stats");
+ }
+ return json;
+ }
}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterNodeDetailsAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterNodeDetailsAPIServlet.java
new file mode 100644
index 0000000..9cccdad
--- /dev/null
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterNodeDetailsAPIServlet.java
@@ -0,0 +1,163 @@
+/*
+ * 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.asterix.api.http.servlet;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.asterix.app.result.ResultUtil;
+import org.apache.hyracks.api.client.IHyracksClientConnection;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
+
+public class ClusterNodeDetailsAPIServlet extends ClusterAPIServlet {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
+ PrintWriter responseWriter = response.getWriter();
+ ServletContext context = getServletContext();
+ IHyracksClientConnection hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
+ JSONObject json;
+
+ try {
+ if (request.getPathInfo() == null) {
+ json = new JSONObject();
+ json.put("ncs", getClusterStateJSON(request, "").getJSONArray("ncs"));
+ } else {
+ json = processNode(request, hcc);
+ }
+ response.setStatus(HttpServletResponse.SC_OK);
+ response.setContentType("application/json");
+ response.setCharacterEncoding("utf-8");
+ responseWriter.write(json.toString(4));
+ } catch (IllegalArgumentException e) { //NOSONAR - exception not logged or rethrown
+ response.sendError(HttpServletResponse.SC_NOT_FOUND);
+ } catch (Exception e) {
+ ResultUtil.apiErrorHandler(responseWriter, e);
+ response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+ }
+ responseWriter.flush();
+ }
+
+ private JSONObject processNode(HttpServletRequest request, IHyracksClientConnection hcc)
+ throws Exception {
+ String[] parts = request.getPathInfo().substring(1).replaceAll("/+", "/").split("/");
+ final String node = parts[0];
+
+ if (parts.length == 1) {
+ JSONArray ncs = getClusterStateJSON(request, "../").getJSONArray("ncs");
+ for (int i = 0; i < ncs.length(); i++) {
+ JSONObject json = ncs.getJSONObject(i);
+ if (node.equals(json.getString("node_id"))) {
+ return json;
+ }
+ }
+ if ("cc".equals(node)) {
+ return new JSONObject();
+ }
+ throw new IllegalArgumentException();
+ } else if (parts.length == 2) {
+ JSONObject json;
+
+ switch (parts[1]) {
+ case "config":
+ json = processNodeConfig(hcc, node);
+ break;
+ case "stats":
+ json = processNodeStats(hcc, node);
+ break;
+ default:
+ throw new IllegalArgumentException();
+ }
+ fixupKeys(json);
+
+ return json;
+ } else {
+ throw new IllegalArgumentException();
+ }
+ }
+
+ private void fixupKeys(JSONObject json) throws JSONException {
+ // TODO (mblow): generate the keys with _ to begin with
+ List<String> keys = new ArrayList<>();
+ for (Iterator iter = json.keys(); iter.hasNext(); ) {
+ keys.add((String) iter.next());
+ }
+ for (String key : keys) {
+ String newKey = key.replace('-', '_');
+ if (!newKey.equals(key)) {
+ json.put(newKey, json.remove(key));
+ }
+ }
+ }
+
+ private JSONObject processNodeStats(IHyracksClientConnection hcc, String node) throws Exception {
+ if ("cc".equals(node)) {
+ return new JSONObject();
+ }
+
+ final String details = hcc.getNodeDetailsJSON(node, true, false);
+ if (details == null) {
+ throw new IllegalArgumentException();
+ }
+ JSONObject json = new JSONObject(details);
+ int index = json.getInt("rrd-ptr") - 1;
+ json.remove("rrd-ptr");
+
+ List<String> keys = new ArrayList<>();
+ for (Iterator iter = json.keys(); iter.hasNext(); ) {
+ keys.add((String) iter.next());
+ }
+
+ int gcNames = json.getJSONArray("gc-names").length();
+ for (String key : keys) {
+ if (key.startsWith("gc-collection-")) {
+ final JSONArray gcArray = json.getJSONArray(key);
+ for (int i = 0; i < gcNames; i++) {
+ gcArray.put(i, gcArray.getJSONArray(i).get(index));
+ }
+ } else if (!"node-id".equals(key) && !"gc-names".equals(key)) {
+ json.put(key, json.getJSONArray(key).get(index));
+ }
+ }
+ return json;
+ }
+
+ private JSONObject processNodeConfig(IHyracksClientConnection hcc, String node) throws Exception {
+ if ("cc".equals(node)) {
+ return new JSONObject();
+ }
+ String config = hcc.getNodeDetailsJSON(node, false, true);
+ if (config == null) {
+ throw new IllegalArgumentException();
+ }
+ return new JSONObject(config);
+ }
+}
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
index 5b36782..9883960 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/CCApplicationEntryPoint.java
@@ -18,9 +18,6 @@
*/
package org.apache.asterix.hyracks.bootstrap;
-import static org.apache.asterix.api.http.servlet.ServletConstants.ASTERIX_BUILD_PROP_ATTR;
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
@@ -32,6 +29,7 @@
import org.apache.asterix.api.http.servlet.APIServlet;
import org.apache.asterix.api.http.servlet.AQLAPIServlet;
import org.apache.asterix.api.http.servlet.ClusterAPIServlet;
+import org.apache.asterix.api.http.servlet.ClusterNodeDetailsAPIServlet;
import org.apache.asterix.api.http.servlet.ConnectorAPIServlet;
import org.apache.asterix.api.http.servlet.DDLAPIServlet;
import org.apache.asterix.api.http.servlet.FeedServlet;
@@ -72,6 +70,10 @@
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlet.ServletMapping;
+
+import static org.apache.asterix.api.http.servlet.ServletConstants.ASTERIX_BUILD_PROP_ATTR;
+import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
public class CCApplicationEntryPoint implements ICCApplicationEntryPoint {
@@ -216,6 +218,7 @@
addServlet(context, Servlets.SHUTDOWN);
addServlet(context, Servlets.VERSION);
addServlet(context, Servlets.CLUSTER_STATE);
+ addServlet(context, Servlets.CLUSTER_STATE_NODE_DETAIL);
return jsonAPIServer;
}
@@ -235,8 +238,13 @@
return queryWebServer;
}
- protected void addServlet(ServletContextHandler context, Servlet servlet, String path) {
- context.addServlet(new ServletHolder(servlet), path);
+ protected void addServlet(ServletContextHandler context, Servlet servlet, String... paths) {
+ final ServletHolder holder = new ServletHolder(servlet);
+ context.getServletHandler().addServlet(holder);
+ ServletMapping mapping = new ServletMapping();
+ mapping.setServletName(holder.getName());
+ mapping.setPathSpecs(paths);
+ context.getServletHandler().addServletMapping(mapping);
}
protected void addServlet(ServletContextHandler context, Servlets key) {
@@ -284,6 +292,8 @@
return new VersionAPIServlet();
case CLUSTER_STATE:
return new ClusterAPIServlet();
+ case CLUSTER_STATE_NODE_DETAIL:
+ return new ClusterNodeDetailsAPIServlet();
default:
throw new IllegalStateException(String.valueOf(key));
}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/api/cluster_state_3/cluster_state_3.1.cstate.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/api/cluster_state_3/cluster_state_3.1.cstate.aql
new file mode 100644
index 0000000..22b4a19
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/api/cluster_state_3/cluster_state_3.1.cstate.aql
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+/*
+ * Test case Name : cluster_state_3
+ * Description : cluster state api all nodes
+ * Expected Result : Positive
+ * Date : 8th September 2016
+ */
+/node
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/queries/api/cluster_state_4/cluster_state_4.1.cstate.aql b/asterixdb/asterix-app/src/test/resources/runtimets/queries/api/cluster_state_4/cluster_state_4.1.cstate.aql
new file mode 100644
index 0000000..0faba10
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/queries/api/cluster_state_4/cluster_state_4.1.cstate.aql
@@ -0,0 +1,25 @@
+/*
+ * 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.
+ */
+/*
+ * Test case Name : cluster_state_4
+ * Description : cluster state api valid node
+ * Expected Result : Positive
+ * Date : 8th September 2016
+ */
+/node/asterix_nc1
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_1/cluster_state_1.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_1/cluster_state_1.1.adm
index 0bc8f17..1dfa743 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_1/cluster_state_1.1.adm
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_1/cluster_state_1.1.adm
@@ -1,6 +1,4 @@
{
- "Metadata_Node": "asterix_nc1",
- "State": "ACTIVE",
"config": {
"api.port": 19002,
"cc.java.opts": "-Xmx1024m",
@@ -51,8 +49,26 @@
"web.queryinterface.port": 19006,
"web.secondary.port": 19005
},
- "partition_0": "asterix_nc1",
- "partition_1": "asterix_nc1",
- "partition_2": "asterix_nc2",
- "partition_3": "asterix_nc2"
+ "metadata_node": "asterix_nc1",
+ "ncs": [
+ {
+ "configUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc1/config",
+ "node_id": "asterix_nc1",
+ "partitions": [
+ "partition_0",
+ "partition_1"
+ ],
+ "statsUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc1/stats"
+ },
+ {
+ "configUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc2/config",
+ "node_id": "asterix_nc2",
+ "partitions": [
+ "partition_2",
+ "partition_3"
+ ],
+ "statsUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc2/stats"
+ }
+ ],
+ "state": "ACTIVE"
}
\ No newline at end of file
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_3/cluster_state_3.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_3/cluster_state_3.1.adm
new file mode 100644
index 0000000..2bbfa10
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_3/cluster_state_3.1.adm
@@ -0,0 +1,20 @@
+{"ncs": [
+ {
+ "configUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc1/config",
+ "node_id": "asterix_nc1",
+ "partitions": [
+ "partition_0",
+ "partition_1"
+ ],
+ "statsUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc1/stats"
+ },
+ {
+ "configUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc2/config",
+ "node_id": "asterix_nc2",
+ "partitions": [
+ "partition_2",
+ "partition_3"
+ ],
+ "statsUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc2/stats"
+ }
+]}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_4/cluster_state_4.1.adm b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_4/cluster_state_4.1.adm
new file mode 100644
index 0000000..819c1e7
--- /dev/null
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/results/api/cluster_state_4/cluster_state_4.1.adm
@@ -0,0 +1,9 @@
+{
+ "configUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc1/config",
+ "node_id": "asterix_nc1",
+ "partitions": [
+ "partition_0",
+ "partition_1"
+ ],
+ "statsUri": "http://127.0.0.1:19002/admin/cluster/node/asterix_nc1/stats"
+}
diff --git a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
index 34a0805..b00d995 100644
--- a/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
+++ b/asterixdb/asterix-app/src/test/resources/runtimets/testsuite.xml
@@ -7315,5 +7315,15 @@
<expected-error>HTTP/1.1 404 Not Found</expected-error>
</compilation-unit>
</test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="cluster_state_3">
+ <output-dir compare="Text">cluster_state_3</output-dir>
+ </compilation-unit>
+ </test-case>
+ <test-case FilePath="api">
+ <compilation-unit name="cluster_state_4">
+ <output-dir compare="Text">cluster_state_4</output-dir>
+ </compilation-unit>
+ </test-case>
</test-group>
</test-suite>
diff --git a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/ServletUtil.java b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/ServletUtil.java
index 9e9bbc5..047f010 100644
--- a/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/ServletUtil.java
+++ b/asterixdb/asterix-common/src/main/java/org/apache/asterix/common/utils/ServletUtil.java
@@ -35,7 +35,8 @@
CONNECTOR("/connector"),
SHUTDOWN("/admin/shutdown"),
VERSION("/admin/version"),
- CLUSTER_STATE("/admin/cluster");
+ CLUSTER_STATE("/admin/cluster"),
+ CLUSTER_STATE_NODE_DETAIL("/admin/cluster/node/*");
private final String path;
diff --git a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/util/AsterixClusterProperties.java b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/util/AsterixClusterProperties.java
index 2457ddc..d201d60 100644
--- a/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/util/AsterixClusterProperties.java
+++ b/asterixdb/asterix-runtime/src/main/java/org/apache/asterix/runtime/util/AsterixClusterProperties.java
@@ -668,10 +668,17 @@
public synchronized JSONObject getClusterStateDescription() throws JSONException {
JSONObject stateDescription = new JSONObject();
- stateDescription.put("State", state.name());
- stateDescription.put("Metadata_Node", currentMetadataNode);
- for (ClusterPartition partition : clusterPartitions.values()) {
- stateDescription.put("partition_" + partition.getPartitionId(), partition.getActiveNodeId());
+ stateDescription.put("state", state.name());
+ stateDescription.put("metadata_node", currentMetadataNode);
+ for (Map.Entry<String, ClusterPartition[]> entry : node2PartitionsMap.entrySet()) {
+ JSONObject nodeJSON = new JSONObject();
+ nodeJSON.put("node_id", entry.getKey());
+ List<String> partitions = new ArrayList<>();
+ for (ClusterPartition part : entry.getValue()) {
+ partitions.add("partition_" + part.getPartitionId());
+ }
+ nodeJSON.put("partitions", partitions);
+ stateDescription.accumulate("ncs", nodeJSON);
}
return stateDescription;
}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksClientInterfaceFunctions.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksClientInterfaceFunctions.java
index bf36183..ca0783b 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksClientInterfaceFunctions.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksClientInterfaceFunctions.java
@@ -45,7 +45,8 @@
GET_NODE_CONTROLLERS_INFO,
CLI_DEPLOY_BINARY,
CLI_UNDEPLOY_BINARY,
- CLUSTER_SHUTDOWN
+ CLUSTER_SHUTDOWN,
+ GET_NODE_DETAILS_JSON
}
public abstract static class Function implements Serializable {
@@ -294,4 +295,34 @@
}
}
+ public static class GetNodeDetailsJSONFunction extends Function {
+ private static final long serialVersionUID = 1L;
+ private final String nodeId;
+ private final boolean includeStats;
+ private final boolean includeConfig;
+
+ public GetNodeDetailsJSONFunction(String nodeId, boolean includeStats, boolean includeConfig) {
+ this.nodeId = nodeId;
+ this.includeStats = includeStats;
+ this.includeConfig = includeConfig;
+ }
+
+ public String getNodeId() {
+ return nodeId;
+ }
+
+ public boolean isIncludeStats() {
+ return includeStats;
+ }
+
+ public boolean isIncludeConfig() {
+ return includeConfig;
+ }
+
+ @Override
+ public FunctionId getFunctionId() {
+ return FunctionId.GET_NODE_DETAILS_JSON;
+ }
+ }
+
}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksClientInterfaceRemoteProxy.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksClientInterfaceRemoteProxy.java
index 25b5a0f..3f453e5 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksClientInterfaceRemoteProxy.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksClientInterfaceRemoteProxy.java
@@ -131,4 +131,11 @@
throw new IPCException("CC refused to release connection after 9 seconds");
}
}
+
+ @Override
+ public String getNodeDetailsJSON(String nodeId, boolean includeStats, boolean includeConfig) throws Exception {
+ HyracksClientInterfaceFunctions.GetNodeDetailsJSONFunction gjsf =
+ new HyracksClientInterfaceFunctions.GetNodeDetailsJSONFunction(nodeId, includeStats, includeConfig);
+ return (String) rpci.call(ipcHandle, gjsf);
+ }
}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksConnection.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksConnection.java
index 3f1ced6..73813f3 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksConnection.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/HyracksConnection.java
@@ -187,8 +187,14 @@
public JobInfo getJobInfo(JobId jobId) throws Exception {
return hci.getJobInfo(jobId);
}
+
@Override
public void stopCluster() throws Exception{
hci.stopCluster();
}
+
+ @Override
+ public String getNodeDetailsJSON(String nodeId, boolean includeStats, boolean includeConfig) throws Exception {
+ return hci.getNodeDetailsJSON(nodeId, includeStats, includeConfig);
+ }
}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/IHyracksClientConnection.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/IHyracksClientConnection.java
index 824c914..0690c9f 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/IHyracksClientConnection.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/IHyracksClientConnection.java
@@ -188,4 +188,13 @@
*/
public void stopCluster() throws Exception;
+ /**
+ * Get details of specified node as JSON object
+ * @param nodeId
+ * id the subject node
+ * @param includeStats
+ * @param includeConfig @return serialized JSON containing the node details
+ * @throws Exception
+ */
+ public String getNodeDetailsJSON(String nodeId, boolean includeStats, boolean includeConfig) throws Exception;
}
diff --git a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/IHyracksClientInterface.java b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/IHyracksClientInterface.java
index b70ef41..4ddb81f 100644
--- a/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/IHyracksClientInterface.java
+++ b/hyracks-fullstack/hyracks/hyracks-api/src/main/java/org/apache/hyracks/api/client/IHyracksClientInterface.java
@@ -56,4 +56,5 @@
public void stopCluster() throws Exception;
+ public String getNodeDetailsJSON(String nodeId, boolean includeStats, boolean includeConfig) throws Exception;
}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
index ae097a6..8dada48 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
@@ -41,7 +41,6 @@
import org.apache.hyracks.api.client.NodeControllerInfo;
import org.apache.hyracks.api.comm.NetworkAddress;
import org.apache.hyracks.api.context.ICCContext;
-import org.apache.hyracks.api.dataset.DatasetDirectoryRecord;
import org.apache.hyracks.api.dataset.DatasetJobRecord.Status;
import org.apache.hyracks.api.deployment.DeploymentId;
import org.apache.hyracks.api.exceptions.HyracksDataException;
@@ -67,6 +66,7 @@
import org.apache.hyracks.control.cc.work.GetJobInfoWork;
import org.apache.hyracks.control.cc.work.GetJobStatusWork;
import org.apache.hyracks.control.cc.work.GetNodeControllersInfoWork;
+import org.apache.hyracks.control.cc.work.GetNodeDetailsJSONWork;
import org.apache.hyracks.control.cc.work.GetResultPartitionLocationsWork;
import org.apache.hyracks.control.cc.work.GetResultStatusWork;
import org.apache.hyracks.control.cc.work.JobStartWork;
@@ -418,6 +418,8 @@
return;
}
+ case CREATE_JOB:
+ break;
case GET_JOB_STATUS: {
HyracksClientInterfaceFunctions.GetJobStatusFunction gjsf =
(HyracksClientInterfaceFunctions.GetJobStatusFunction) fn;
@@ -457,12 +459,14 @@
return;
}
+ case GET_DATASET_RECORD_DESCRIPTOR:
+ break;
case GET_DATASET_RESULT_LOCATIONS: {
HyracksClientInterfaceFunctions.GetDatasetResultLocationsFunction gdrlf =
(HyracksClientInterfaceFunctions.GetDatasetResultLocationsFunction) fn;
workQueue.schedule(new GetResultPartitionLocationsWork(ClusterControllerService.this,
gdrlf.getJobId(), gdrlf.getResultSetId(), gdrlf.getKnownRecords(),
- new IPCResponder<DatasetDirectoryRecord[]>(handle, mid)));
+ new IPCResponder<>(handle, mid)));
return;
}
@@ -476,7 +480,7 @@
case GET_NODE_CONTROLLERS_INFO: {
workQueue.schedule(new GetNodeControllersInfoWork(ClusterControllerService.this,
- new IPCResponder<Map<String, NodeControllerInfo>>(handle, mid)));
+ new IPCResponder<>(handle, mid)));
return;
}
@@ -493,7 +497,7 @@
HyracksClientInterfaceFunctions.CliDeployBinaryFunction dbf =
(HyracksClientInterfaceFunctions.CliDeployBinaryFunction) fn;
workQueue.schedule(new CliDeployBinaryWork(ClusterControllerService.this, dbf.getBinaryURLs(),
- dbf.getDeploymentId(), new IPCResponder<DeploymentId>(handle, mid)));
+ dbf.getDeploymentId(), new IPCResponder<>(handle, mid)));
return;
}
@@ -501,14 +505,21 @@
HyracksClientInterfaceFunctions.CliUnDeployBinaryFunction udbf =
(HyracksClientInterfaceFunctions.CliUnDeployBinaryFunction) fn;
workQueue.schedule(new CliUnDeployBinaryWork(ClusterControllerService.this, udbf.getDeploymentId(),
- new IPCResponder<DeploymentId>(handle, mid)));
+ new IPCResponder<>(handle, mid)));
return;
}
case CLUSTER_SHUTDOWN: {
workQueue.schedule(new ClusterShutdownWork(ClusterControllerService.this,
- new IPCResponder<Boolean>(handle, mid)));
+ new IPCResponder<>(handle, mid)));
return;
}
+
+ case GET_NODE_DETAILS_JSON:
+ HyracksClientInterfaceFunctions.GetNodeDetailsJSONFunction gndjf =
+ (HyracksClientInterfaceFunctions.GetNodeDetailsJSONFunction) fn;
+ workQueue.schedule(new GetNodeDetailsJSONWork(ClusterControllerService.this, gndjf.getNodeId(),
+ gndjf.isIncludeStats(), gndjf.isIncludeConfig(), new IPCResponder<>(handle, mid)));
+ return;
}
try {
handle.send(mid, null, new IllegalArgumentException("Unknown function " + fn.getFunctionId()));
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java
index 7fd027b..a848c6e 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/NodeControllerState.java
@@ -20,7 +20,6 @@
import java.io.File;
import java.util.Arrays;
-import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -77,6 +76,8 @@
private final Map<String, String> systemProperties;
+ private final int pid;
+
private final HeartbeatSchema hbSchema;
private final long[] hbTime;
@@ -147,7 +148,7 @@
dataPort = reg.getDataPort();
datasetPort = reg.getDatasetPort();
messagingPort = reg.getMessagingPort();
- activeJobIds = new HashSet<JobId>();
+ activeJobIds = new HashSet<>();
osName = reg.getOSName();
arch = reg.getArch();
@@ -161,6 +162,7 @@
bootClasspath = reg.getBootClasspath();
inputArguments = reg.getInputArguments();
systemProperties = reg.getSystemProperties();
+ pid = reg.getPid();
hbSchema = reg.getHeartbeatSchema();
@@ -203,7 +205,7 @@
rrdPtr = 0;
}
- public void notifyHeartbeat(HeartbeatData hbData) {
+ public synchronized void notifyHeartbeat(HeartbeatData hbData) {
lastHeartbeatDuration = 0;
hbTime[rrdPtr] = System.currentTimeMillis();
if (hbData != null) {
@@ -282,51 +284,57 @@
return o;
}
- public JSONObject toDetailedJSON() throws JSONException {
+ public synchronized JSONObject toDetailedJSON(boolean includeStats, boolean includeConfig) throws JSONException {
JSONObject o = new JSONObject();
o.put("node-id", ncConfig.nodeId);
- o.put("os-name", osName);
- o.put("arch", arch);
- o.put("os-version", osVersion);
- o.put("num-processors", nProcessors);
- o.put("vm-name", vmName);
- o.put("vm-version", vmVersion);
- o.put("vm-vendor", vmVendor);
- o.put("classpath", new JSONArray(Arrays.asList(classpath.split(File.pathSeparator))));
- o.put("library-path", new JSONArray(Arrays.asList(libraryPath.split(File.pathSeparator))));
- o.put("boot-classpath", new JSONArray(Arrays.asList(bootClasspath.split(File.pathSeparator))));
- o.put("input-arguments", new JSONArray(inputArguments));
- o.put("rrd-ptr", rrdPtr);
- o.put("heartbeat-times", hbTime);
- o.put("heap-init-sizes", heapInitSize);
- o.put("heap-used-sizes", heapUsedSize);
- o.put("heap-committed-sizes", heapCommittedSize);
- o.put("heap-max-sizes", heapMaxSize);
- o.put("nonheap-init-sizes", nonheapInitSize);
- o.put("nonheap-used-sizes", nonheapUsedSize);
- o.put("nonheap-committed-sizes", nonheapCommittedSize);
- o.put("nonheap-max-sizes", nonheapMaxSize);
- o.put("thread-counts", threadCount);
- o.put("peak-thread-counts", peakThreadCount);
- o.put("system-load-averages", systemLoadAverage);
- o.put("gc-names", gcNames);
- o.put("gc-collection-counts", gcCollectionCounts);
- o.put("gc-collection-times", gcCollectionTimes);
- o.put("net-payload-bytes-read", netPayloadBytesRead);
- o.put("net-payload-bytes-written", netPayloadBytesWritten);
- o.put("net-signaling-bytes-read", netSignalingBytesRead);
- o.put("net-signaling-bytes-written", netSignalingBytesWritten);
- o.put("dataset-net-payload-bytes-read", datasetNetPayloadBytesRead);
- o.put("dataset-net-payload-bytes-written", datasetNetPayloadBytesWritten);
- o.put("dataset-net-signaling-bytes-read", datasetNetSignalingBytesRead);
- o.put("dataset-net-signaling-bytes-written", datasetNetSignalingBytesWritten);
- o.put("ipc-messages-sent", ipcMessagesSent);
- o.put("ipc-message-bytes-sent", ipcMessageBytesSent);
- o.put("ipc-messages-received", ipcMessagesReceived);
- o.put("ipc-message-bytes-received", ipcMessageBytesReceived);
- o.put("disk-reads", diskReads);
- o.put("disk-writes", diskWrites);
+ if (includeConfig) {
+ o.put("os-name", osName);
+ o.put("arch", arch);
+ o.put("os-version", osVersion);
+ o.put("num-processors", nProcessors);
+ o.put("vm-name", vmName);
+ o.put("vm-version", vmVersion);
+ o.put("vm-vendor", vmVendor);
+ o.put("classpath", new JSONArray(Arrays.asList(classpath.split(File.pathSeparator))));
+ o.put("library-path", new JSONArray(Arrays.asList(libraryPath.split(File.pathSeparator))));
+ o.put("boot-classpath", new JSONArray(Arrays.asList(bootClasspath.split(File.pathSeparator))));
+ o.put("input-arguments", new JSONArray(inputArguments));
+ o.put("system-properties", new JSONObject(systemProperties));
+ o.put("pid", pid);
+ }
+ if (includeStats) {
+ o.put("rrd-ptr", rrdPtr);
+ o.put("heartbeat-times", hbTime);
+ o.put("heap-init-sizes", heapInitSize);
+ o.put("heap-used-sizes", heapUsedSize);
+ o.put("heap-committed-sizes", heapCommittedSize);
+ o.put("heap-max-sizes", heapMaxSize);
+ o.put("nonheap-init-sizes", nonheapInitSize);
+ o.put("nonheap-used-sizes", nonheapUsedSize);
+ o.put("nonheap-committed-sizes", nonheapCommittedSize);
+ o.put("nonheap-max-sizes", nonheapMaxSize);
+ o.put("thread-counts", threadCount);
+ o.put("peak-thread-counts", peakThreadCount);
+ o.put("system-load-averages", systemLoadAverage);
+ o.put("gc-names", gcNames);
+ o.put("gc-collection-counts", gcCollectionCounts);
+ o.put("gc-collection-times", gcCollectionTimes);
+ o.put("net-payload-bytes-read", netPayloadBytesRead);
+ o.put("net-payload-bytes-written", netPayloadBytesWritten);
+ o.put("net-signaling-bytes-read", netSignalingBytesRead);
+ o.put("net-signaling-bytes-written", netSignalingBytesWritten);
+ o.put("dataset-net-payload-bytes-read", datasetNetPayloadBytesRead);
+ o.put("dataset-net-payload-bytes-written", datasetNetPayloadBytesWritten);
+ o.put("dataset-net-signaling-bytes-read", datasetNetSignalingBytesRead);
+ o.put("dataset-net-signaling-bytes-written", datasetNetSignalingBytesWritten);
+ o.put("ipc-messages-sent", ipcMessagesSent);
+ o.put("ipc-message-bytes-sent", ipcMessageBytesSent);
+ o.put("ipc-messages-received", ipcMessagesReceived);
+ o.put("ipc-message-bytes-received", ipcMessageBytesReceived);
+ o.put("disk-reads", diskReads);
+ o.put("disk-writes", diskWrites);
+ }
return o;
}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/NodesRESTAPIFunction.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/NodesRESTAPIFunction.java
index 8423ea6..58deb55 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/NodesRESTAPIFunction.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/NodesRESTAPIFunction.java
@@ -43,7 +43,7 @@
result.put("result", gnse.getSummaries());
} else {
String nodeId = arguments[0];
- GetNodeDetailsJSONWork gnde = new GetNodeDetailsJSONWork(ccs, nodeId);
+ GetNodeDetailsJSONWork gnde = new GetNodeDetailsJSONWork(ccs, nodeId, true, true);
ccs.getWorkQueue().scheduleAndSync(gnde);
result.put("result", gnde.getDetail());
}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/GetNodeDetailsJSONWork.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/GetNodeDetailsJSONWork.java
index ca3f1e5..6d20874 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/GetNodeDetailsJSONWork.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/work/GetNodeDetailsJSONWork.java
@@ -18,6 +18,7 @@
*/
package org.apache.hyracks.control.cc.work;
+import org.apache.hyracks.control.common.work.IPCResponder;
import org.json.JSONObject;
import org.apache.hyracks.control.cc.ClusterControllerService;
@@ -27,21 +28,35 @@
public class GetNodeDetailsJSONWork extends SynchronizableWork {
private final ClusterControllerService ccs;
private final String nodeId;
+ private final boolean includeStats;
+ private final boolean includeConfig;
+ private final IPCResponder<String> callback;
private JSONObject detail;
- public GetNodeDetailsJSONWork(ClusterControllerService ccs, String nodeId) {
+ public GetNodeDetailsJSONWork(ClusterControllerService ccs, String nodeId, boolean includeStats,
+ boolean includeConfig, IPCResponder<String> callback) {
this.ccs = ccs;
this.nodeId = nodeId;
+ this.includeStats = includeStats;
+ this.includeConfig = includeConfig;
+ this.callback = callback;
+ }
+
+ public GetNodeDetailsJSONWork(ClusterControllerService ccs, String nodeId, boolean includeStats,
+ boolean includeConfig) {
+ this(ccs, nodeId, includeStats, includeConfig, null);
}
@Override
protected void doRun() throws Exception {
NodeControllerState ncs = ccs.getNodeMap().get(nodeId);
- if (ncs == null) {
- detail = new JSONObject();
- return;
+ if (ncs != null) {
+ detail = ncs.toDetailedJSON(includeStats, includeConfig);
}
- detail = ncs.toDetailedJSON();
+
+ if (callback != null) {
+ callback.setValue(detail == null ? null : detail.toString());
+ }
}
public JSONObject getDetail() {
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeRegistration.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeRegistration.java
index bb8022e..e95a004 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeRegistration.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/controllers/NodeRegistration.java
@@ -67,11 +67,13 @@
private final NetworkAddress messagingPort;
+ private final int pid;
+
public NodeRegistration(InetSocketAddress ncAddress, String nodeId, NCConfig ncConfig, NetworkAddress dataPort,
- NetworkAddress datasetPort, String osName, String arch, String osVersion, int nProcessors, String vmName,
- String vmVersion, String vmVendor, String classpath, String libraryPath, String bootClasspath,
- List<String> inputArguments, Map<String, String> systemProperties, HeartbeatSchema hbSchema,
- NetworkAddress messagingPort) {
+ NetworkAddress datasetPort, String osName, String arch, String osVersion, int nProcessors,
+ String vmName, String vmVersion, String vmVendor, String classpath, String libraryPath,
+ String bootClasspath, List<String> inputArguments, Map<String, String> systemProperties,
+ HeartbeatSchema hbSchema, NetworkAddress messagingPort, int pid) {
this.ncAddress = ncAddress;
this.nodeId = nodeId;
this.ncConfig = ncConfig;
@@ -91,6 +93,7 @@
this.systemProperties = systemProperties;
this.hbSchema = hbSchema;
this.messagingPort = messagingPort;
+ this.pid = pid;
}
public InetSocketAddress getNodeControllerAddress() {
@@ -168,4 +171,6 @@
public NetworkAddress getMessagingPort() {
return messagingPort;
}
+
+ public int getPid() { return pid; }
}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/utils/PidHelper.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/utils/PidHelper.java
new file mode 100644
index 0000000..79642c0
--- /dev/null
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-common/src/main/java/org/apache/hyracks/control/common/utils/PidHelper.java
@@ -0,0 +1,52 @@
+/*
+ * 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.hyracks.control.common.utils;
+
+import java.lang.management.ManagementFactory;
+import java.lang.management.RuntimeMXBean;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+public class PidHelper {
+
+ private static final Logger LOGGER = Logger.getLogger(PidHelper.class.getName());
+
+ private PidHelper() {
+ }
+
+ public static int getPid() {
+ return getPid(ManagementFactory.getRuntimeMXBean());
+ }
+
+ public static int getPid(RuntimeMXBean runtimeMXBean) {
+ try {
+ Field jvmField = runtimeMXBean.getClass().getDeclaredField("jvm");
+ jvmField.setAccessible(true);
+ Object vmManagement = jvmField.get(runtimeMXBean);
+ Method getProcessIdMethod = vmManagement.getClass().getDeclaredMethod("getProcessId");
+ getProcessIdMethod.setAccessible(true);
+ return (Integer) getProcessIdMethod.invoke(vmManagement);
+ } catch (Exception e) {
+ LOGGER.log(Level.INFO, "Unable to determine PID due to exception", e);
+ return -1;
+ }
+ }
+}
diff --git a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
index 8373ebe..edadf57 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-nc/src/main/java/org/apache/hyracks/control/nc/NodeControllerService.java
@@ -65,6 +65,7 @@
import org.apache.hyracks.control.common.ipc.CCNCFunctions.StateDumpRequestFunction;
import org.apache.hyracks.control.common.ipc.ClusterControllerRemoteProxy;
import org.apache.hyracks.control.common.job.profiling.om.JobProfile;
+import org.apache.hyracks.control.common.utils.PidHelper;
import org.apache.hyracks.control.common.work.FutureValue;
import org.apache.hyracks.control.common.work.WorkQueue;
import org.apache.hyracks.control.nc.application.NCApplicationContext;
@@ -290,7 +291,8 @@
osMXBean.getName(), osMXBean.getArch(), osMXBean.getVersion(), osMXBean.getAvailableProcessors(),
runtimeMXBean.getVmName(), runtimeMXBean.getVmVersion(), runtimeMXBean.getVmVendor(),
runtimeMXBean.getClassPath(), runtimeMXBean.getLibraryPath(), runtimeMXBean.getBootClassPath(),
- runtimeMXBean.getInputArguments(), runtimeMXBean.getSystemProperties(), hbSchema, meesagingPort));
+ runtimeMXBean.getInputArguments(), runtimeMXBean.getSystemProperties(), hbSchema, meesagingPort,
+ PidHelper.getPid()));
synchronized (this) {
while (registrationPending) {