org.hyperic.hq.measurement.server.session.MeasurementProcessorImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.measurement.server.session.MeasurementProcessorImpl.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use Hyperic
 * program services by normal system calls through the application
 * program interfaces provided as part of the Hyperic Plug-in Development
 * Kit or the Hyperic Client Development Kit - this is merely considered
 * normal use of the program, and does *not* fall under the heading of
 * "derived work".
 *
 * Copyright (C) [2004-2010], VMware, Inc.
 * This file is part of Hyperic.
 *
 * Hyperic is free software; you can redistribute it and/or modify
 * it under the terms version 2 of the GNU General Public License as
 * published by the Free Software Foundation. This program is distributed
 * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
 * even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 * PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 * USA.
 */

package org.hyperic.hq.measurement.server.session;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.ObjectNotFoundException;
import org.hyperic.hq.agent.AgentConnectionException;
import org.hyperic.hq.agent.AgentRemoteException;
import org.hyperic.hq.appdef.Agent;
import org.hyperic.hq.appdef.shared.AgentManager;
import org.hyperic.hq.appdef.shared.AgentNotFoundException;
import org.hyperic.hq.appdef.shared.AppdefEntityID;
import org.hyperic.hq.appdef.shared.AppdefUtil;
import org.hyperic.hq.authz.server.session.Resource;
import org.hyperic.hq.authz.server.session.ResourceEdge;
import org.hyperic.hq.authz.shared.PermissionException;
import org.hyperic.hq.authz.shared.ResourceManager;
import org.hyperic.hq.measurement.MeasurementUnscheduleException;
import org.hyperic.hq.measurement.agent.client.AgentMonitor;
import org.hyperic.hq.measurement.agent.client.MeasurementCommandsClient;
import org.hyperic.hq.measurement.agent.client.MeasurementCommandsClientFactory;
import org.hyperic.hq.measurement.monitor.MonitorAgentException;
import org.hyperic.hq.measurement.shared.AvailabilityManager;
import org.hyperic.hq.measurement.shared.MeasurementManager;
import org.hyperic.hq.measurement.shared.MeasurementProcessor;
import org.hyperic.hq.measurement.shared.SRNManager;
import org.hyperic.hq.stats.ConcurrentStatsCollector;
import org.hyperic.hq.zevents.ZeventEnqueuer;
import org.hyperic.util.timer.StopWatch;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 */
@Service
@Transactional
public class MeasurementProcessorImpl implements MeasurementProcessor {
    private final Log log = LogFactory.getLog(MeasurementProcessorImpl.class);

    @Autowired
    private AgentManager agentManager;
    @Autowired
    private AvailabilityManager availManager;
    @Autowired
    private MeasurementManager measurementManager;
    @Autowired
    private SRNManager srnManager;
    @Autowired
    private AgentMonitor agentMonitor;
    @Autowired
    private MeasurementCommandsClientFactory measurementCommandsClientFactory;
    @Autowired
    private ResourceManager resourceManager;
    @Autowired
    private ZeventEnqueuer zEventManager;
    @Autowired
    private ConcurrentStatsCollector concurrentStatsCollector;

    public MeasurementProcessorImpl() {
    }

    @PostConstruct
    public void initStatsCollector() {
        concurrentStatsCollector.register(ConcurrentStatsCollector.MEASUREMENT_SCHEDULE_TIME);
    }

    /**
     * Ping the agent to make sure it's up
     */
    public boolean ping(Agent a) throws PermissionException {
        return agentMonitor.ping(a);
    }

    /**
     * Schedules enabled measurements for the entire ResourceEdge hierarchy
     * based on the "containment" relationship.  These metrics are scheduled
     * after the transaction is committed.
     * 
     */
    public void scheduleHierarchyAfterCommit(Collection<Resource> resources) {
        if (resources.isEmpty()) {
            return;
        }

        final Set<AppdefEntityID> aeids = new LinkedHashSet<AppdefEntityID>(resources.size() * 2);
        for (final Resource resource : resources) {
            if (resource == null || resource.isInAsyncDeleteState()) {
                continue;
            }
            final Collection<ResourceEdge> edges = resourceManager
                    .findResourceEdges(resourceManager.getContainmentRelation(), resource);
            aeids.add(AppdefUtil.newAppdefEntityId(resource));
            for (final ResourceEdge e : edges) {
                final Resource r = e.getTo();
                if (r == null || r.isInAsyncDeleteState()) {
                    continue;
                }
                aeids.add(AppdefUtil.newAppdefEntityId(e.getTo()));
            }
        }
        if (!aeids.isEmpty()) {
            final AgentScheduleSyncZevent event = new AgentScheduleSyncZevent(aeids);
            zEventManager.enqueueEventAfterCommit(event);
        }
    }

    /**
     * Schedules enabled measurements for the entire ResourceEdge hierarchy
     * based on the "containment" relationship.  These metrics are scheduled
     * after the transaction is committed.
     * 
     */
    public void scheduleHierarchyAfterCommit(Resource resource) {
        scheduleHierarchyAfterCommit(Collections.singletonList(resource));
    }

    /**
     * @param aeids {@link List} of {@link AppdefEntityID}
     */
    public void scheduleSynchronous(Collection<AppdefEntityID> aeids) {
        try {
            Map<Integer, Collection<AppdefEntityID>> agents = getAgentMap(aeids);
            for (Map.Entry<Integer, Collection<AppdefEntityID>> entry : agents.entrySet()) {
                Agent agent = agentManager.findAgent(entry.getKey());
                Collection<AppdefEntityID> entityIds = entry.getValue();
                scheduleEnabled(agent, entityIds);
            }
        } catch (Exception e) {
            log.error("Exception scheduling [" + aeids + "]: " + e.getMessage(), e);
        }
    }

    /**
     * @return Map of {@link Agent} to {@link List<AppdefEntityID>}
     */
    private Map<Integer, Collection<AppdefEntityID>> getAgentMap(Collection<AppdefEntityID> aeids) {
        return agentManager.getAgentMap(aeids);
    }

    /**
     * @param eids List<AppdefEntityID>
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public void scheduleEnabled(Agent agent, Collection<AppdefEntityID> eids) throws MonitorAgentException {
        final StopWatch watch = new StopWatch();
        final boolean debug = log.isDebugEnabled();
        if (debug)
            watch.markTimeBegin("findEnabledMeasurements");
        Map<Integer, List<Measurement>> measMap = measurementManager.findEnabledMeasurements(eids);
        if (debug)
            watch.markTimeEnd("findEnabledMeasurements");

        // availability measurements in scheduled downtime are disabled, but not unscheduled.
        // need to schedule these measurements for "new" agents.
        if (debug)
            watch.markTimeBegin("getAvailMeasurementsInDowntime");
        Map<Integer, Measurement> downtimeMeasMap = availManager.getAvailMeasurementsInDowntime(eids);
        if (debug)
            watch.markTimeEnd("getAvailMeasurementsInDowntime");

        for (Map.Entry<Integer, Measurement> entry : downtimeMeasMap.entrySet()) {
            Integer resourceId = entry.getKey();
            List<Measurement> measurements = measMap.get(resourceId);
            if (measurements == null) {
                measurements = new ArrayList<Measurement>();
                measMap.put(resourceId, measurements);
            }
            measurements.add(entry.getValue());
        }

        final int batchSize = 10000;
        final List<AppdefEntityID> aeids = new ArrayList<AppdefEntityID>(eids);
        for (int i = 0; i < aeids.size(); i += batchSize) {
            final int end = Math.min(i + batchSize, aeids.size());
            if (debug)
                watch.markTimeBegin("scheduleMeasurements[" + end + "]");
            scheduleMeasurements(agent, measMap, aeids.subList(i, end));
            if (debug)
                watch.markTimeEnd("scheduleMeasurements[" + end + "]");
        }
        if (debug) {
            log.debug("scheduleEnabled: " + watch + ", { Size: [appdefEntity=" + eids.size()
                    + "] [availMeasurementsInDowntime=" + downtimeMeasMap.size() + "] }");
        }
    }

    private void scheduleMeasurements(Agent agent, Map<Integer, List<Measurement>> measMap,
            Collection<AppdefEntityID> eids) throws MonitorAgentException {
        final boolean debug = log.isDebugEnabled();
        final Map<SRN, List<Measurement>> schedMap = new HashMap<SRN, List<Measurement>>();

        MeasurementCommandsClient client = null;

        final StringBuilder debugBuf = new StringBuilder();
        try {
            client = measurementCommandsClientFactory.getClient(agent);

            for (AppdefEntityID eid : eids) {
                final long begin = now();
                ScheduleRevNum srnObj = srnManager.get(eid);
                SRN srn = new SRN(eid, srnObj == null ? -1 : srnObj.getSrn());
                Resource r = resourceManager.findResource(eid);
                if (r == null || r.isInAsyncDeleteState()) {
                    continue;
                }
                List<Measurement> measurements = measMap.get(r.getId());
                if (measurements == null) {
                    continue;
                }
                schedMap.put(srn, measurements);
                try {
                    if (debug) {
                        debugBuf.append("scheduling mids=").append(measurements).append(" for aeid=").append(eid)
                                .append("\n");
                    }
                    Measurement[] array = measurements.toArray(new Measurement[0]);
                    agentMonitor.schedule(client, srn, array);
                    concurrentStatsCollector.addStat((now() - begin),
                            ConcurrentStatsCollector.MEASUREMENT_SCHEDULE_TIME);
                } catch (AgentConnectionException e) {
                    final String emsg = "Error reported by agent @ " + agent.connectionString() + ": "
                            + e.getMessage();
                    log.warn(emsg);
                    throw new MonitorAgentException(e.getMessage(), e);
                } catch (AgentRemoteException e) {
                    final String emsg = "Error reported by agent @ " + agent.connectionString() + ": "
                            + e.getMessage();
                    log.warn(emsg);
                    throw new MonitorAgentException(emsg, e);
                }
            }
        } finally {
            if (debug)
                log.debug(debugBuf);
        }
    }

    private final long now() {
        return System.currentTimeMillis();
    }

    private void unschedule(Agent a, Collection<AppdefEntityID> entIds)
            throws MeasurementUnscheduleException, MonitorAgentException {
        if (log.isDebugEnabled()) {
            log.debug("unschedule agentId=" + a.getId() + ", numOfResources=" + entIds.size());
        }
        for (AppdefEntityID entId : entIds) {
            try {
                srnManager.removeSrn(entId);
            } catch (ObjectNotFoundException e) {
                // Ok to ignore, this is the first time scheduling metrics
                // for this resource.
            }
        }
        List<AppdefEntityID> tmp = new ArrayList<AppdefEntityID>(entIds);
        agentMonitor.unschedule(a, tmp.toArray(new AppdefEntityID[0]));
    }

    /**
     * Unschedule metrics of multiple appdef entities
     * @param agentToken the entity whose agent will be contacted for the
     *        unschedule
     * @param entIds the entity IDs whose metrics should be unscheduled
     * @throws MeasurementUnscheduleException if an error occurs
     */
    @Transactional(readOnly = true)
    public void unschedule(String agentToken, Collection<AppdefEntityID> entIds) {
        try {
            // Get the agent from agent token
            Agent a = agentManager.getAgent(agentToken);
            unschedule(a, entIds);
        } catch (MonitorAgentException e) {
            log.error("Error unscheduling metrics: " + e);
            log.debug(e, e);
        } catch (AgentNotFoundException e) {
            log.warn("Error unscheduling metrics: " + e);
            log.debug(e, e);
        } catch (MeasurementUnscheduleException e) {
            log.error("Error unscheduling metrics: " + e, e);
        }
    }

    /**
     * Unschedule metrics of multiple appdef entities
     * @param agentEnt the entity whose agent will be contacted for the
     *        unschedule
     * @param entIds the entity IDs whose metrics should be unscheduled
     * @throws MeasurementUnscheduleException if an error occurs
     */
    @Transactional(readOnly = true)
    public void unschedule(AppdefEntityID agentEnt, AppdefEntityID[] entIds) {
        try {
            // Get the agent IP and Port from server ID
            Agent a = agentManager.getAgent(agentEnt);
            unschedule(a, Arrays.asList(entIds));
        } catch (MonitorAgentException e) {
            log.warn("Error unscheduling metrics: " + e);
            log.debug(e, e);
        } catch (AgentNotFoundException e) {
            log.warn("Error unscheduling metrics: " + e);
            log.debug(e, e);
        } catch (MeasurementUnscheduleException e) {
            log.warn("Error unscheduling metrics: " + e);
            log.debug(e, e);
        }
    }

    /**
     * Unschedule measurements
     * @param aeids List of {@link AppdefEntityID}
     * @throws MeasurementUnscheduleException if an error occurs
     */
    @Transactional(readOnly = true)
    public void unschedule(Collection<AppdefEntityID> aeids) {
        Map<Integer, Collection<AppdefEntityID>> agents = getAgentMap(aeids);
        for (Map.Entry<Integer, Collection<AppdefEntityID>> entry : agents.entrySet()) {
            Agent agent = agentManager.findAgent(entry.getKey());
            Collection<AppdefEntityID> eids = entry.getValue();
            unschedule(agent.getAgentToken(), eids);
        }
    }

}