
com.tangosol.internal.management.resources.ClusterMemberResource Maven / Gradle / Ivy
/*
* Copyright (c) 2000, 2022, Oracle and/or its affiliates.
*
* Licensed under the Universal Permissive License v 1.0 as shown at
* https://oss.oracle.com/licenses/upl.
*/
package com.tangosol.internal.management.resources;
import com.tangosol.internal.http.HttpRequest;
import com.tangosol.internal.http.RequestRouter;
import com.tangosol.internal.http.Response;
import com.tangosol.internal.management.EntityMBeanResponse;
import com.tangosol.net.management.MBeanAccessor.QueryBuilder;
import com.tangosol.util.Filter;
import java.net.URI;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import static java.lang.String.format;
/**
* Handles management API requests for Coherence cluster member.
*
* @author sr 2017.08.21
* @author Jonathan Knight 2022.01.25
* @author Gunnar Hillert 2022.05.13
*
* @since 12.2.1.4.0
*/
public class ClusterMemberResource
extends AbstractManagementResource
{
// ----- Routes methods -------------------------------------------------
@Override
public void addRoutes(RequestRouter router, String sPathRoot)
{
router.addGet(sPathRoot, this::get);
router.addGet(sPathRoot + "/" + PLATFORM + "/{" + PLATFORM_MBEAN + "}", this::getPlatformMBeanResponse);
router.addGet(sPathRoot + "/{" + NETWORK_STATS + "}", this::getPointToPointResponse);
router.addGet(sPathRoot + "/" + ENVIRONMENT, this::getEnvironmentResponse);
router.addGet(sPathRoot + "/" + STATE, this::getStateResponse);
router.addGet(sPathRoot + "/" + FEDERATION, this::getFederationResponse);
router.addGet(sPathRoot + "/" + FEDERATION+ "/" + TOPOLOGIES, this::getTopologiesResponse);
router.addGet(sPathRoot + "/" + FEDERATION + "/" + TOPOLOGIES + "/{" + TOPOLOGY_NAME + "}", this::getTopologyResponse);
router.addPost(sPathRoot, this::update);
router.addPost(sPathRoot + "/{" + OPERATION_NAME + "}", this::executeOperation);
router.addPost(sPathRoot + "/" + MEMBER_STATE, new LogMemberStateHandler());
router.addPost(sPathRoot + "/" + MEMBER_DUMP_HEAP, new DumpHeapHandler());
router.addPost(sPathRoot + "/" + NETWORK_STATS + "/trackWeakest", this::trackWeakestMember);
router.addPost(sPathRoot + "/" + DIAGNOSTIC_CMD + "/{" + JFR_CMD + "}", this::diagnosticCmd);
}
// ----- GET API --------------------------------------------------------
/**
* Return NodeMBean attributes for a cluster member.
*
* @return the response object
*/
public Response get(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
return response(getResponseEntityForMbean(request, getQuery(request, sMemberKey), CHILD_LINKS));
}
/**
* Return a platform(JVM) MBean attributes for a particular MBean of a cluster member.
*
* @return the response object
*/
public Response getPlatformMBeanResponse(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
String sPlatformMBeanType = request.getFirstPathParameter(PLATFORM_MBEAN);
String sBaseQuery = MAP_PLATFORM_URL_TO_MBEAN_QUERY.get(sPlatformMBeanType);
if (sBaseQuery == null)
{
sBaseQuery = MAP_PLATFORM_PS_URL_TO_MBEAN_QUERY.get(sPlatformMBeanType);
if (sBaseQuery == null)
{
sBaseQuery = MAP_PLATFORM_G1_URL_TO_MBEAN_QUERY.get(sPlatformMBeanType);
if (sBaseQuery == null)
{
return Response.status(Response.Status.NOT_FOUND).build();
}
}
}
QueryBuilder queryBuilder = createQueryBuilder(request).withBaseQuery(sBaseQuery).withMember(sMemberKey);
return response(getResponseEntityForMbean(request, queryBuilder));
}
/**
* Return PointToPointMBean attributes for a cluster member.
*
* @return the response object
*/
public Response getPointToPointResponse(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
return response(getResponseEntityForMbean(request, getPointToPointMBeanQuery(request, sMemberKey)));
}
/**
* Return the response of "reportNodeState" operation of {@code ClusterNodeMBean}.
*
* @return the response object
*/
public Response getStateResponse(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
return response(getResponseFromMBeanOperation(request, getQuery(request, sMemberKey), STATE, "reportNodeState"));
}
/**
* Return the response of the {@code reportEnvironment} operation of {@code ClusterNodeMBean}.
*
* @return the response object
*/
public Response getEnvironmentResponse(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
return response(getResponseFromMBeanOperation(request, getQuery(request, sMemberKey), ENVIRONMENT, "reportEnvironment"));
}
/**
* Return the response of "federation" link of a cluster member.
*
* @return the response object
*/
public Response getFederationResponse(HttpRequest request)
{
return response(getLinksOnlyResponseBody(request, getParentUri(request), getCurrentUri(request), TOPOLOGIES).toJson());
}
/**
* Return the attributes of TopologyMBean(s) of this cluster member.
*
* @return the response object
*/
public Response getTopologiesResponse(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
QueryBuilder queryBuilder = createQueryBuilder(request)
.withBaseQuery(FEDERATION_TOPOLOGIES_QUERY)
.withMember(sMemberKey);
return response(getResponseBodyForMBeanCollection(request, queryBuilder, NAME,
null, getParentUri(request), getCurrentUri(request)));
}
/**
* Return the attributes of a TopologyMBean of this cluster member.
*
* @return the response object
*/
public Response getTopologyResponse(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
String sTopologyName = request.getFirstPathParameter(TOPOLOGY_NAME);
QueryBuilder queryBuilder = createQueryBuilder(request)
.withBaseQuery(format(FEDERATION_TOPOLOGY_MEMBER_QUERY, sTopologyName))
.withMember(sMemberKey);
return response(getResponseEntityForMbean(request, queryBuilder));
}
// ----- POST API(Update) -----------------------------------------------
/**
* Update a ClusterNodeMBean with the parameters present in the input entity map.
*
* @return the response object
*/
public Response update(HttpRequest request)
{
Map entity = getJsonBody(request);
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
QueryBuilder queryBuilder = getQuery(request, sMemberKey);
return update(request, entity, queryBuilder);
}
// ----- POST API -------------------------------------------------------
/**
* Call "shutdown/resetStatistics" operation on NodeMBean.
*
* @return the response object
*/
public Response executeOperation(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
String sOperationName = request.getFirstPathParameter(OPERATION_NAME);
if ("shutdown".equals(sOperationName) || "resetStatistics".equals(sOperationName))
{
return executeMBeanOperation(request, getQuery(request, sMemberKey), sOperationName,
null, null);
}
return Response.notFound().build();
}
/**
* Call "logNodeState" operation on NodeMBean.
*
* @return the response object
*/
public Response logMemberState(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
return executeMBeanOperation(request, getQuery(request, sMemberKey),
"logNodeState", null, null);
}
/**
* {@link RequestRouter.RequestHandler} to call "logNodeState" operation on NodeMBean.
*/
public class LogMemberStateHandler
implements RequestRouter.RequestHandler
{
@Override
public Response handle(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
return executeMBeanOperation(request, getQuery(request, sMemberKey),
"logNodeState", null, null);
}
}
/**
* {@link RequestRouter.RequestHandler} to call "dumpHeap" operation on NodeMBean.
*/
public class DumpHeapHandler
implements RequestRouter.RequestHandler
{
@Override
public Response handle(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
String[] asSignature = {String.class.getName()};
Object[] aoArguments = {null};
// dynamically named hprof file, "heapdump-*.hprof" saved in a specified tmp directory
return executeMBeanOperation(request, getQuery(request, sMemberKey), "dumpHeap", aoArguments, asSignature);
}
}
/**
* Call "trackWeakest" operation on PointToPointMBean.
*
* @return the response object
*/
public Response trackWeakestMember(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
return executeMBeanOperation(request, getPointToPointMBeanQuery(request, sMemberKey),
"trackWeakest", null, null);
}
/**
* Call "diagnostic-cmd/jfrCmd" on {@link com.sun.management.DiagnosticCommandMBean}.
*
* Valid commands are jfrStart, jfrStop, jfrDump, and jfrCheck. See jcmd JFR
* command for more information.
*
* @return the response object, includes a message returned by the JFR command.
*/
public Response diagnosticCmd(HttpRequest request)
{
String sMemberKey = request.getFirstPathParameter(MEMBER_KEY);
String sCmd = request.getFirstPathParameter(JFR_CMD);
String sOptions = request.getFirstQueryParameter(OPTIONS);
String sBaseQuery = ":type=DiagnosticCommand,Domain=com.sun.management,subType=DiagnosticCommand";
QueryBuilder queryBuilder = createQueryBuilder(request).withBaseQuery(sBaseQuery).withMember(sMemberKey);
Object[] aoArguments = sOptions == null ? new Object[0] : new Object[]{sOptions.split(",")};
String[] signature = sOptions == null ? new String[0] : new String[]{String[].class.getName()};
// execute the JFR operation and return the result message from the operation
return response(getResponseFromMBeanOperation(request, queryBuilder,
"status", sCmd, aoArguments, signature));
}
// -------------------------- AbstractManagementResource methods------------------------------------------
@Override
@SuppressWarnings("rawtypes")
protected EntityMBeanResponse getQueryResult(HttpRequest request,
URI uriParent,
URI uriCurrent,
Map mapQuery,
Map mapArguments)
{
String sMemberKey = mapArguments.get(MEMBER_KEY);
Object oChildren = getChildrenQuery(mapQuery);
URI uriSelf = getSubUri(uriParent, sMemberKey);
EntityMBeanResponse response = getLinksOnlyResponseBody(request, uriParent, uriSelf, getLinksFilter(request, mapQuery),
CHILD_LINKS);
Map mapResponse = response.getEntity();
if (oChildren instanceof Map)
{
Map mapChildrenQuery = (Map) oChildren;
addChildMbeanQueryResult(request, uriParent, uriCurrent, NETWORK_STATS, getPointToPointMBeanQuery(request, sMemberKey), mapResponse, mapChildrenQuery);
addPlatformMBeansQueryResult(request, uriParent, uriCurrent, sMemberKey, mapResponse, mapChildrenQuery);
addFederationTopologiesQueryResult(request, sMemberKey, mapResponse, mapChildrenQuery, uriSelf);
}
return response;
}
// ----- ClusterMemberResource methods-----------------------------------
/**
* Return the NodeMBean query for the provided member.
*
*
* @param request the http request
* @param sMemberKey the member key
*
* @return the MBean query
*/
protected QueryBuilder getQuery(HttpRequest request, String sMemberKey)
{
return createQueryBuilder(request)
.withBaseQuery(CLUSTER_MEMBERS_QUERY)
.withMember(sMemberKey);
}
/**
* Return the PointToPoint MBean query for the member.
*
*
* @param request the http request
* @param sMemberKey the member key
*
* @return the MBean query
*/
protected QueryBuilder getPointToPointMBeanQuery(HttpRequest request, String sMemberKey)
{
return createQueryBuilder(request)
.withBaseQuery(POINT_TO_POINT_QUERY)
.withMember(sMemberKey);
}
/**
* Return the child query for platform. Platform queries are like this
* {"platform":{
* "children":{
* "memory":{
* "fields":[]
* }
* }
* }}
*
* @param mapQuery the query to execute
*
* @return the query for a platform MBean.
*/
@SuppressWarnings("rawtypes")
protected Object getPlatformChildrenQueryMap(Map mapQuery)
{
Object oPlatformQuery = mapQuery.get(PLATFORM);
// the platform MBeans are queried under children->platform
Object oChildrenQueryObject = null;
if (oPlatformQuery instanceof Map)
{
oChildrenQueryObject = ((Map) oPlatformQuery).get(CHILDREN);
}
return oChildrenQueryObject;
}
/**
* Add platform MBeans to query response.
*
* @param request the {@link HttpRequest}
* @param uriParent the parent URI
* @param uriCurrent the current URI
* @param sMemberId the member ID
* @param mapResponse the response map
* @param mapQuery the query map
*/
@SuppressWarnings("rawtypes")
protected void addPlatformMBeansQueryResult(HttpRequest request,
URI uriParent,
URI uriCurrent,
String sMemberId,
Map mapResponse,
Map mapQuery)
{
Object oChildrenQueryObject = getPlatformChildrenQueryMap(mapQuery);
if (oChildrenQueryObject instanceof Map)
{
Map mapPlatform = new LinkedHashMap<>();
Map mapPlatformChildrenQueryMap = (Map) oChildrenQueryObject;
// add the child JVM Mbean results
for (Map.Entry entry : MAP_PLATFORM_URL_TO_MBEAN_QUERY.entrySet())
{
String sPlatformMBeanKey = entry.getKey();
QueryBuilder queryBuilder = createQueryBuilder(request)
.withBaseQuery(entry.getValue())
.withMember(sMemberId);
addChildMbeanQueryResult(request, uriParent, uriCurrent, sPlatformMBeanKey, queryBuilder,
mapPlatform, mapPlatformChildrenQueryMap);
}
// add the child JVM GC Mbean results
for (Map.Entry entry : MAP_PLATFORM_G1_URL_TO_MBEAN_QUERY.entrySet())
{
String sPlatformMBeanKey = entry.getKey();
QueryBuilder queryBuilder = createQueryBuilder(request)
.withBaseQuery(entry.getValue())
.withMember(sMemberId);
addChildMbeanQueryResult(request, uriParent, uriCurrent, sPlatformMBeanKey, queryBuilder,
mapPlatform, mapPlatformChildrenQueryMap);
}
// add the child JVM Mbean results
for (Map.Entry entry : MAP_PLATFORM_PS_URL_TO_MBEAN_QUERY.entrySet())
{
String sPlatformMBeanKey = entry.getKey();
QueryBuilder queryBuilder = createQueryBuilder(request)
.withBaseQuery(entry.getValue())
.withMember(sMemberId);
addChildMbeanQueryResult(request, uriParent, uriCurrent, sPlatformMBeanKey, queryBuilder,
mapPlatform, mapPlatformChildrenQueryMap);
}
mapResponse.put(PLATFORM, mapPlatform);
}
}
/**
* Add federation topologies in the search response.
*
* @param request the {@link HttpRequest}
* @param sMemberId the current member Id
* @param mapResponse the response map, to which the results must be appended
* @param mapQuery the query map
* @param uriParent the parent uri
*/
@SuppressWarnings({"rawtypes", "unchecked"})
protected void addFederationTopologiesQueryResult(HttpRequest request,
String sMemberId,
Map mapResponse,
Map mapQuery,
URI uriParent)
{
Object oFederationQueryObject = mapQuery.get(FEDERATION);
if (oFederationQueryObject instanceof Map)
{
Map mapFederationQuery = (Map) oFederationQueryObject;
URI uriSelf = getSubUri(uriParent, FEDERATION);
Filter filterLinks = getLinksFilter(request, mapFederationQuery);
Object oFederationChildren = getChildrenQuery(mapFederationQuery);
Map mapTopologiesResponse =
getLinksOnlyResponseBody(request, uriParent, uriSelf, filterLinks, TOPOLOGIES).toJson();
if (oFederationChildren instanceof Map)
{
Object oTopologiesQuery = ((Map) oFederationChildren).get(TOPOLOGIES);
if (oTopologiesQuery != null)
{
Map mapTopologiesQuery = (Map) oTopologiesQuery;
QueryBuilder queryBuilder = createQueryBuilder(request)
.withBaseQuery(FEDERATION_TOPOLOGIES_QUERY)
.withMember(sMemberId);
EntityMBeanResponse responseEntity
= getResponseBodyForMBeanCollection(request, queryBuilder,
NAME, mapTopologiesQuery, uriParent, uriSelf);
mapTopologiesResponse.put(TOPOLOGIES, responseEntity.toJson());
}
}
mapResponse.put(FEDERATION, mapTopologiesResponse);
}
}
// ----- constants ------------------------------------------------------
/**
* The constant for dump heap POST API (Operation)
*/
public static final String MEMBER_DUMP_HEAP = "dumpHeap";
/**
* The constant for JFR POST API (Operations)
*/
public static final String DIAGNOSTIC_CMD = "diagnostic-cmd";
/**
* The constant for the child links. The child links are all the platform MBeans and
* the networkStats.
*/
public static String[] CHILD_LINKS;
static
{
List listChildLinks = new ArrayList<>();
listChildLinks.addAll(MAP_PLATFORM_URL_TO_MBEAN_QUERY.keySet().stream()
.map(s -> PLATFORM + "/" + s).collect(Collectors.toSet()));
listChildLinks.addAll(MAP_PLATFORM_G1_URL_TO_MBEAN_QUERY.keySet().stream()
.map(s -> PLATFORM + "/" + s).collect(Collectors.toSet()));
listChildLinks.addAll(MAP_PLATFORM_PS_URL_TO_MBEAN_QUERY.keySet().stream()
.map(s -> PLATFORM + "/" + s).collect(Collectors.toSet()));
listChildLinks.add(NETWORK_STATS);
listChildLinks.add(FEDERATION);
CHILD_LINKS = listChildLinks.toArray(new String[]{});
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy