All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tangosol.internal.management.resources.CacheResource Maven / Gradle / Ivy

There is a newer version: 24.09
Show newest version
/*
 * 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.Converter;
import com.tangosol.internal.management.EntityMBeanResponse;

import com.tangosol.net.CacheFactory;

import com.tangosol.net.management.MBeanAccessor.QueryBuilder;

import com.tangosol.util.Filter;
import com.tangosol.util.filter.AlwaysFilter;

import java.net.URI;

import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import static java.lang.String.format;

/**
 * Handles management API requests for a cache in a service.
 *
 * @author sr  2017.08.29
 * @author Jonathan Knight  2022.01.25
 * @since 12.2.1.4.0
 */
public class CacheResource extends AbstractManagementResource
    {
    // ----- Routes methods -------------------------------------------------

    @Override
    public void addRoutes(RequestRouter router, String sPathRoot)
        {
        router.addGet(sPathRoot, this::get);

        router.addPost(sPathRoot, this::update);
        router.addPost(sPathRoot + "/" + RESET_STATS, this::resetStatistics);

        // child resources
        router.addRoutes(sPathRoot + "/" + MEMBERS, new CacheMembersResource());
        }

    // ----- GET API --------------------------------------------------------

    /**
     * Return the aggregated metrics of CacheMBean's for a single cache belonging to a Service.
     *
     * @param request  the {@link HttpRequest}
     *
     * @return the response object
     */
    public Response get(HttpRequest request)
        {
        String       sCacheName     = request.getFirstPathParameter(CACHE_NAME);
        String       sRoleName      = request.getFirstQueryParameter(ROLE_NAME);
        String       sCollector     = request.getFirstQueryParameter(COLLECTOR);
        String       sServiceName   = request.getPathParameters().getFirst(SERVICE_NAME);
        QueryBuilder queryBuilder   = getQuery(request, sCacheName, sServiceName);
        Set  setObjectNames = ensureBeanAccessor(request).queryKeys(queryBuilder.build());

        if (setObjectNames == null || setObjectNames.isEmpty())
            {
            return Response.status(Response.Status.NOT_FOUND).build();
            }

        EntityMBeanResponse responseEntity = createResponse(request, getParentUri(request), getCurrentUri(request), getLinksFilter(request));
        addObjectNamesToResponse(request, setObjectNames, responseEntity, getCurrentUri(request));

        Map mapResponse = responseEntity.toJson();

        QueryBuilder queryBuilderStorage = createQueryBuilder(request)
                .withBaseQuery(format(STORAGE_MANAGERS_QUERY, sCacheName))
                .withService(getService(request));

        // aggregate cache and storage metrics into the response, storage manage metrics is always sent along with cache
        addAggregatedMetricsToResponseMap(request, sRoleName, sCollector, queryBuilder, mapResponse);
        addAggregatedMetricsToResponseMap(request, sRoleName, sCollector, queryBuilderStorage, mapResponse);
        return response(mapResponse);
        }

    // ----- POST API(Operations) -------------------------------------------

    /**
     * Call "resetStatistics" operation on CacheMBean for all members.
     *
     * @param request  the {@link HttpRequest}
     *
     * @return the response object
     */
    public Response resetStatistics(HttpRequest request)
        {
        String       sCacheName   = request.getFirstPathParameter(CACHE_NAME);
        String       sServiceName = request.getPathParameters().getFirst(SERVICE_NAME);
        QueryBuilder queryBuilder = getQuery(request, sCacheName, sServiceName);

        return executeMBeanOperation(request, queryBuilder, RESET_STATS, null, null);
        }

    // ----- POST API(Update) -----------------------------------------------

    /**
     * Update a CacheMBean with the parameters present in the input entity map
     * for all the members.
     *
     * @param request  the {@link HttpRequest}
     *
     * @return the response object
     */
    public Response update(HttpRequest request)
        {
        String       sCacheName   = request.getFirstPathParameter(CACHE_NAME);
        String       sServiceName = request.getPathParameters().getFirst(SERVICE_NAME);
        QueryBuilder queryBuilder = getQuery(request, sCacheName, sServiceName);

        return update(request, getJsonBody(request), queryBuilder);
        }

    // ----- AbstractManagementResource methods -------------------------------------------

    @SuppressWarnings({"rawtypes", "unchecked"})
    @Override
    protected EntityMBeanResponse getQueryResult(HttpRequest         request,
                                                 URI                 uriParent,
                                                 URI                 uriCurrent,
                                                 Map mapQuery,
                                                 Map mapArguments)
        {
        String sCacheName = mapArguments.get(NAME);

        // collect attributes from the ObjectNames
        URI            uriSelf        = getSubUri(uriParent, sCacheName);
        Filter filterLinks    = getLinksFilter(request, mapQuery);
        String         sServiceName   = request.getPathParameters().getFirst(SERVICE_NAME);
        QueryBuilder   queryBuilder   = getQuery(request, sCacheName, sServiceName);
        Set    setObjectNames = ensureBeanAccessor(request).queryKeys(queryBuilder.build());

        if (setObjectNames == null || setObjectNames.isEmpty())
            {
            return null;
            }

        EntityMBeanResponse responseEntity = createResponse(request, uriParent, uriSelf, filterLinks);
        addObjectNamesToResponse(request, setObjectNames, responseEntity, uriCurrent);

        Map mapEntity = responseEntity.getEntity();

        QueryBuilder queryBuilderStorage = createQueryBuilder(request)
                .withBaseQuery(format(STORAGE_MANAGERS_QUERY, sCacheName))
                .withService(getService(request));

        addAggregatedMetricsToResponseMap(request, "*", null, queryBuilder, mapEntity);
        addAggregatedMetricsToResponseMap(request, "*", null, queryBuilderStorage, mapEntity);

        Object oChildren = mapQuery == null ? null : mapQuery.get(CHILDREN);
        if (oChildren instanceof Map)
            {
            Map mapChildrenQuery = (Map) oChildren;

            addChildResourceQueryResult(request, new CacheMembersResource(), MEMBERS,
                                        mapEntity, mapChildrenQuery, mapArguments);
            }

        return responseEntity;
        }

    // ----- CacheResource methods-------------------------------------------

    /**
     * MBean query to retrieve CacheMBeans for the provided cache.
     *
     *
     * @param request       the request
     * @param sCacheName    the cache name
     * @param sServiceName  the service name
     *
     * @return the MBean query
     */
    protected QueryBuilder getQuery(HttpRequest request, String sCacheName, String sServiceName)
        {
        return createQueryBuilder(request)
                .withBaseQuery(CACHE_QUERY + sCacheName)
                .withService(sServiceName);
        }

    /**
     * Add attributes from the ObjectNames to the given EntityMBeanResponse.
     *
     * @param request         the {@link HttpRequest}
     * @param setObjectNames  the set of ObjectNames from which to add to the response
     * @param responseEntity  the EntityMBeanResponse to add attributes to
     * @param uriCurrent      the current URI
     */
    @SuppressWarnings({"unchecked", "rawtypes"})
    protected void addObjectNamesToResponse(HttpRequest         request,
                                            Set         setObjectNames,
                                            EntityMBeanResponse responseEntity,
                                            URI                 uriCurrent)
        {
        Filter      filterAttributes = getAttributesFilter(request);
        Map mapAttributes    = new LinkedHashMap<>();

        // return name, service, and node_id if no field is specified
        if (filterAttributes instanceof AlwaysFilter)
            {
            filterAttributes = getAttributesFilter(String.join(",", NAME, SERVICE, NODE_ID), null);
            }

        for (String sName : setObjectNames)
            {
            try
                {
                ObjectName objectName = new ObjectName(sName);
                for (String sKey : objectName.getKeyPropertyList().keySet())
                    {
                    if (filterAttributes.evaluate(sKey))
                        {
                        Object oValue   = Converter.convert(objectName.getKeyProperty(sKey));
                        Object oCurrent = mapAttributes.get(sKey);

                        if (oCurrent == null)
                            {
                            mapAttributes.put(sKey, oValue);
                            }
                        else if (oCurrent instanceof Set)
                            {
                            ((Set) oCurrent).add(oValue);
                            }
                        else if (!Objects.equals(oCurrent, oValue))
                            {
                            Set values = new HashSet<>();
                            values.add(oCurrent);
                            values.add(oValue);
                            mapAttributes.put(sKey, values);
                            }
                        }
                    }
                }
            catch (MalformedObjectNameException e)
                {
                CacheFactory.log("Exception occurred while creating an ObjectName " +
                        sName + "\n" + CacheFactory.getStackTrace(e));
                }
            }

        responseEntity.setEntity(mapAttributes);
        responseEntity.addResourceLink(MEMBERS, getSubUri(uriCurrent, MEMBERS));
        }
    }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy