org.hyperic.hq.measurement.agent.server.MeasurementCommandsServer.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.measurement.agent.server.MeasurementCommandsServer.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.agent.server;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hyperic.hq.agent.AgentAPIInfo;
import org.hyperic.hq.agent.AgentAssertionException;
import org.hyperic.hq.agent.AgentConfig;
import org.hyperic.hq.agent.AgentRemoteException;
import org.hyperic.hq.agent.AgentRemoteValue;
import org.hyperic.hq.agent.server.AgentDaemon;
import org.hyperic.hq.agent.server.AgentNotificationHandler;
import org.hyperic.hq.agent.server.AgentRunningException;
import org.hyperic.hq.agent.server.AgentServerHandler;
import org.hyperic.hq.agent.server.AgentStartException;
import org.hyperic.hq.agent.server.AgentStorageProvider;
import org.hyperic.hq.agent.server.AgentTransportLifecycle;
import org.hyperic.hq.agent.server.CollectorThread;
import org.hyperic.hq.bizapp.agent.CommandsAPIInfo;
import org.hyperic.hq.bizapp.client.MeasurementCallbackClient;
import org.hyperic.hq.bizapp.client.StorageProviderFetcher;
import org.hyperic.hq.measurement.agent.MeasurementCommandsAPI;
import org.hyperic.hq.measurement.agent.ScheduledMeasurement;
import org.hyperic.hq.measurement.agent.client.MeasurementCommandsClient;
import org.hyperic.hq.measurement.agent.commands.DeleteProperties_args;
import org.hyperic.hq.measurement.agent.commands.DeleteProperties_result;
import org.hyperic.hq.measurement.agent.commands.GetMeasurements_args;
import org.hyperic.hq.measurement.agent.commands.ScheduleMeasurements_args;
import org.hyperic.hq.measurement.agent.commands.ScheduleMeasurements_result;
import org.hyperic.hq.measurement.agent.commands.ScheduleTopn_args;
import org.hyperic.hq.measurement.agent.commands.SetProperties_args;
import org.hyperic.hq.measurement.agent.commands.SetProperties_result;
import org.hyperic.hq.measurement.agent.commands.TrackPluginAdd_args;
import org.hyperic.hq.measurement.agent.commands.TrackPluginAdd_result;
import org.hyperic.hq.measurement.agent.commands.TrackPluginRemove_args;
import org.hyperic.hq.measurement.agent.commands.TrackPluginRemove_result;
import org.hyperic.hq.measurement.agent.commands.UnscheduleMeasurements_args;
import org.hyperic.hq.measurement.agent.commands.UnscheduleMeasurements_result;
import org.hyperic.hq.measurement.agent.commands.UnscheduleTopn_result;
import org.hyperic.hq.measurement.agent.server.ScheduleThread.ParsedTemplate;
import org.hyperic.hq.product.ConfigTrackPluginManager;
import org.hyperic.hq.product.LogTrackPluginManager;
import org.hyperic.hq.product.MeasurementPluginManager;
import org.hyperic.hq.product.ProductPlugin;

public class MeasurementCommandsServer implements AgentServerHandler, AgentNotificationHandler {
    private static final long THREAD_JOIN_WAIT = 10 * 1000;

    private final MeasurementCommandsAPI verAPI; // Common API specifics
    private Thread scheduleThread; // Thread of scheduler
    private ScheduleThread scheduleObject; // Our scheduler
    private Thread senderThread; // Thread of sender
    private SenderThread senderObject; // Our sender
    private AgentStorageProvider storage; // Agent storage
    private final Map validProps; // Map of valid props
    private AgentConfig bootConfig; // Agent boot config
    private MeasurementSchedule schedStorage; // Schedule storage
    private MeasurementPluginManager pluginManager; // Plugin manager
    private final Log log; // Our log

    // Config and Log track
    private ConfigTrackPluginManager ctPluginManager;
    private LogTrackPluginManager ltPluginManager;
    private Thread trackerThread; // Config and Log tracker thread
    private TrackerThread trackerObject; // Config and Log tracker object

    private TopNScheduler topnScheduler;

    private MeasurementCommandsService measurementCommandsService;

    private CollectorThread collectorThread;

    public MeasurementCommandsServer() {
        this.verAPI = new MeasurementCommandsAPI();
        this.scheduleThread = null;
        this.scheduleObject = null;
        this.senderThread = null;
        this.senderObject = null;
        this.storage = null;
        this.validProps = Collections.synchronizedMap(new HashMap());
        this.bootConfig = null;
        this.schedStorage = null;
        this.pluginManager = null;
        this.log = LogFactory.getLog(MeasurementCommandsServer.class);

        this.ctPluginManager = null;
        this.ltPluginManager = null;
        this.trackerThread = null;
        this.trackerObject = null;

        this.topnScheduler = null;

        for (String element : this.verAPI.propSet) {
            // Simply setup true object values for properties we know about
            this.validProps.put(element, this);
        }
    }

    private void spawnThreads(SenderThread senderObject, ScheduleThread scheduleObject, TrackerThread trackerObject)
            throws AgentStartException {
        this.senderThread = new Thread(senderObject, "SenderThread");
        senderThread.setDaemon(true);
        this.scheduleThread = new Thread(scheduleObject, "ScheduleThread");
        scheduleThread.setDaemon(true);
        this.trackerThread = new Thread(trackerObject, "TrackerThread");
        this.trackerThread.setDaemon(true);
        this.collectorThread = CollectorThread.getInstance(pluginManager);

        this.senderThread.start();
        this.scheduleThread.start();
        this.trackerThread.start();
        this.collectorThread.doStart();
    }

    public AgentAPIInfo getAPIInfo() {
        return this.verAPI;
    }

    public String[] getCommandSet() {
        return MeasurementCommandsAPI.commandSet;
    }

    public AgentRemoteValue dispatchCommand(String cmd, AgentRemoteValue args, InputStream in, OutputStream out)
            throws AgentRemoteException {
        if (cmd.equals(MeasurementCommandsAPI.command_scheduleMeasurements)) {
            ScheduleMeasurements_args sa = new ScheduleMeasurements_args(args);
            measurementCommandsService.scheduleMeasurements(sa);
            return new ScheduleMeasurements_result();
        }

        else if (cmd.equals(MeasurementCommandsAPI.command_unscheduleMeasurements)) {
            UnscheduleMeasurements_args sa = new UnscheduleMeasurements_args(args);
            measurementCommandsService.unscheduleMeasurements(sa);
            return new UnscheduleMeasurements_result();
        }

        else if (cmd.equals(MeasurementCommandsAPI.command_getMeasurements)) {
            GetMeasurements_args sa = new GetMeasurements_args(args);
            return measurementCommandsService.getMeasurements(sa);
        }

        else if (cmd.equals(MeasurementCommandsAPI.command_setProperties)) {
            SetProperties_args sa = new SetProperties_args(args);
            measurementCommandsService.setProperties(sa);
            return new SetProperties_result();
        }

        else if (cmd.equals(MeasurementCommandsAPI.command_deleteProperties)) {
            DeleteProperties_args sa = new DeleteProperties_args(args);
            measurementCommandsService.deleteProperties(sa);
            return new DeleteProperties_result();
        }

        else if (cmd.equals(MeasurementCommandsAPI.command_trackAdd)) {
            TrackPluginAdd_args ta = new TrackPluginAdd_args(args);
            measurementCommandsService.addTrackPlugin(ta);
            return new TrackPluginAdd_result();
        }

        else if (cmd.equals(MeasurementCommandsAPI.command_trackRemove)) {
            TrackPluginRemove_args ta = new TrackPluginRemove_args(args);
            measurementCommandsService.removeTrackPlugin(ta);
            return new TrackPluginRemove_result();
        }

        else if (cmd.equals(MeasurementCommandsAPI.command_scheduleTopn)) {
            ScheduleTopn_args topnArgs = new ScheduleTopn_args(args);
            measurementCommandsService.scheduleTopn(topnArgs);
            return new TrackPluginRemove_result();
        }

        else if (cmd.equals(MeasurementCommandsAPI.command_unscheduleTopn)) {
            measurementCommandsService.unscheduleTopn();
            return new UnscheduleTopn_result();
        }

        else {
            throw new AgentRemoteException("Unknown command: " + cmd);
        }
    }

    public void startup(AgentDaemon agent) throws AgentStartException {
        Iterator<ScheduledMeasurement> i = null;

        try {
            this.storage = agent.getStorageProvider();
            this.bootConfig = agent.getBootConfig();
            this.schedStorage = new MeasurementSchedule(this.storage, bootConfig.getBootProperties());
            logMeasurementSchedule(this.schedStorage);
        } catch (AgentRunningException exc) {
            throw new AgentAssertionException("Agent should be running here", exc);
        }

        try {
            this.pluginManager = (MeasurementPluginManager) agent.getPluginManager(ProductPlugin.TYPE_MEASUREMENT);
            this.ctPluginManager = (ConfigTrackPluginManager) agent
                    .getPluginManager(ProductPlugin.TYPE_CONFIG_TRACK);
            this.ltPluginManager = (LogTrackPluginManager) agent.getPluginManager(ProductPlugin.TYPE_LOG_TRACK);

        } catch (Exception e) {
            throw new AgentStartException("Unable to get measurement " + "plugin manager: " + e.getMessage());
        }

        this.senderObject = new SenderThread(this.bootConfig.getBootProperties(), this.storage, this.schedStorage);

        this.scheduleObject = new ScheduleThread(this.senderObject, this.pluginManager,
                this.bootConfig.getBootProperties());

        this.trackerObject = new TrackerThread(this.ctPluginManager, this.ltPluginManager, this.storage,
                this.bootConfig.getBootProperties());

        this.topnScheduler = new TopNScheduler(this.storage, this.bootConfig.getBootProperties());

        this.measurementCommandsService = new MeasurementCommandsService(this.storage, this.validProps,
                this.schedStorage, this.pluginManager, this.ltPluginManager, this.ctPluginManager,
                this.scheduleObject, this.topnScheduler);

        AgentTransportLifecycle agentTransportLifecycle;

        try {
            agentTransportLifecycle = agent.getAgentTransportLifecycle();
        } catch (Exception e) {
            throw new AgentStartException("Unable to get agent transport lifecycle: " + e.getMessage());
        }

        log.info("Registering Measurement Commands Service with Agent Transport");

        try {
            agentTransportLifecycle.registerService(MeasurementCommandsClient.class, measurementCommandsService);
        } catch (Exception e) {
            throw new AgentStartException("Failed to register Measurement Commands Service.", e);
        }

        spawnThreads(this.senderObject, this.scheduleObject, this.trackerObject);

        try {
            i = this.schedStorage.getMeasurementList();
        } catch (Exception e) {
            throw new AgentStartException("Failed reading the measurement list from the storage.", e);
        }
        while (i.hasNext()) {
            ScheduledMeasurement meas = i.next();
            this.measurementCommandsService.scheduleMeasurement(meas);
        }

        agent.registerMonitor("camMetric.schedule", this.scheduleObject);
        agent.registerMonitor("camMetric.sender", this.senderObject);

        // If we have don't have a provider, register a handler until
        // we get one
        if (CommandsAPIInfo.getProvider(this.storage) == null) {
            agent.registerNotifyHandler(this, CommandsAPIInfo.NOTIFY_SERVER_SET);
        } else {
            this.startConfigPopulator();
        }

        this.log.info("Measurement Commands Server started up");
    }

    public void handleNotification(String msgClass, String msg) {
        this.startConfigPopulator();
    }

    private void startConfigPopulator() {
        StorageProviderFetcher fetcher = new StorageProviderFetcher(this.storage);
        MeasurementCallbackClient client = new MeasurementCallbackClient(fetcher);
        ConfigPopulateThread populator = new ConfigPopulateThread(client, this.ltPluginManager,
                this.ctPluginManager);
        populator.setDaemon(true);
        populator.start();
    }

    private void interruptThread(Thread t) throws InterruptedException {
        if (t.isAlive()) {
            t.interrupt();
            t.join(THREAD_JOIN_WAIT);

            if (t.isAlive()) {
                this.log.warn(t.getName() + " did not die within the " + "timeout period.  Killing it");
                t.stop();
            }
        }
    }

    private void logMeasurementSchedule(MeasurementSchedule sched) {
        if (this.log.isDebugEnabled()) {
            try {
                Iterator scheduleIter = sched.getMeasurementList();
                int scheduleSize = 0;

                while (scheduleIter.hasNext()) {
                    ScheduledMeasurement metric = (ScheduledMeasurement) scheduleIter.next();
                    if (metric != null) {
                        ParsedTemplate templ = ScheduleThread.getParsedTemplate(metric);
                        scheduleSize++;
                        StringBuffer s = new StringBuffer("Measurement Schedule[").append(scheduleSize)
                                .append("]: entityId=").append(metric.getEntity()).append(", category=")
                                .append(metric.getCategory()).append(", interval=").append(metric.getInterval())
                                .append(", derivedId=").append(metric.getDerivedID()).append(", dsnId=")
                                .append(metric.getDsnID()).append(", dsn=").append(templ.metric.toDebugString());

                        this.log.debug(s.toString());
                    }
                }
                this.log.debug("Measurement schedule list size=" + scheduleSize);
            } catch (Exception e) {
                // since logging the measurement schedule is in debug mode,
                // also log any exceptions in debug mode
                this.log.debug("Could not display measurement schedule: " + e.getMessage(), e);
            }
        }
    }

    public final void postInitActions() throws AgentStartException {
        /*do nothing*/ }//EOM

    public void shutdown() {
        this.log.info("Measurement Commands Server shutting down");
        logMeasurementSchedule(this.schedStorage);

        this.scheduleObject.die();
        this.collectorThread.doStop();
        this.senderObject.die();
        this.topnScheduler.die();

        try {
            this.interruptThread(this.senderThread);
            this.interruptThread(this.scheduleThread);
        } catch (InterruptedException exc) {
            // Someone wants us to die badly .... ok 
            this.log.warn("shutdown interrupted");
        }

        this.log.info("Measurement Commands Server shut down");
    }
}