org.hyperic.hq.control.agent.server.ActionThread.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hq.control.agent.server.ActionThread.java

Source

/*
 * NOTE: This copyright does *not* cover user programs that use HQ
 * 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, 2005, 2006], Hyperic, Inc.
 * This file is part of HQ.
 * 
 * HQ 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.control.agent.server;

import java.util.NoSuchElementException;

import org.hyperic.hq.bizapp.client.AgentCallbackClientException;
import org.hyperic.hq.bizapp.client.ControlCallbackClient;
import org.hyperic.hq.bizapp.shared.lather.ControlSendCommandResult_args;
import org.hyperic.hq.product.PluginNotFoundException;
import org.hyperic.hq.product.PluginException;
import org.hyperic.hq.product.ControlPluginManager;

import org.hyperic.util.config.ConfigResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * Class to run control actions.  Control actions should happen infrequently
 * enough that the simplicity of spawning a new thread each time should
 * outweigh the performance benefits of using a thread pool.  We can always
 * modify this behavior later.
 */
class ActionThread extends Thread {
    private ControlPluginManager manager;
    private ControlCallbackClient client;
    private String pluginName;
    private String pluginType;
    private String action;
    private String[] args;
    private String id;

    // Time to wait before requeuing a control job that failed because
    // the plugin was busy with a previous action
    protected static final int REQUEUE_INTERVAL = 2 * 1000;

    protected Log log = LogFactory.getLog(ActionThread.class.getName());

    ActionThread(String pluginName, String pluginType, String id, String action, String[] args,
            ControlCallbackClient client, ControlPluginManager manager) {
        this.pluginName = pluginName;
        this.pluginType = pluginType;
        this.id = id;
        this.action = action;
        this.args = args;
        this.client = client;
        this.manager = manager;
    }

    public void run() {
        int result = -1;
        String errMsg = null;

        // add ourselves to the job queue
        this.log.debug("Adding job " + id + " to " + pluginName + " queue");
        this.manager.addJob(pluginName, id);

        // wait for our turn
        while (true) {
            String nextJob;

            try {
                nextJob = this.manager.getNextJob(pluginName);
                if (nextJob.equals(id))
                    break;
            } catch (NoSuchElementException e) {
                // should never happen
                this.log.error("Job queue empty");
                return;
            }

            this.log.debug("Plugin busy with job " + nextJob + " requeueing in " + REQUEUE_INTERVAL + "ms");
            try {
                Thread.sleep(REQUEUE_INTERVAL);
            } catch (InterruptedException e) {
            }
        }

        this.log.debug("Running job " + id);
        long startTime = System.currentTimeMillis();

        final ControlSendCommandResult_args resultsMetadata = this.client.newResultsMetadata(this.pluginName,
                Integer.parseInt(id), startTime);

        try {
            this.manager.doAction(this.pluginName, this.action, this.args, resultsMetadata);
            result = this.manager.getResult(this.pluginName);
            errMsg = this.manager.getMessage(this.pluginName);
        } catch (PluginNotFoundException e) {

            // The plugin has not been configured locally, or the plugin
            // type is not found on this agent.  Try to get the config
            // from the server
            try {

                this.log.info("Fetching plugin configuration from server");
                byte[] configBytes = this.client.controlGetPluginConfiguration(this.pluginName);

                if (configBytes == null || configBytes.length == 0) {
                    // log something or send a message back to the server
                    errMsg = "Plugin configuration not found";
                    this.log.error(errMsg);
                    return;
                }

                ConfigResponse config = ConfigResponse.decode(configBytes);

                this.log.info("Config finished, running control action");
                this.manager.createControlPlugin(this.pluginName, this.pluginType, config);
                this.manager.doAction(this.pluginName, this.action, this.args, resultsMetadata);
                result = this.manager.getResult(this.pluginName);
                errMsg = this.manager.getMessage(this.pluginName);
            } catch (Exception exc) {
                errMsg = "Unable to fetch plugin configuration: " + exc.getMessage();
                this.log.error(errMsg, exc);
            }
        } catch (PluginException e) {
            errMsg = "Unable to run control action:  " + e.getMessage();
            this.log.error(errMsg, e);
        } finally {

            // Remove this job from the queue
            try {
                this.manager.removeNextJob(pluginName);
                this.log.debug("Removed job " + id + " from the queue");
            } catch (NoSuchElementException e) {
                // will never happen
            }

            // Lastly, send the status back to the server
            try {
                this.client.controlSendCommandResult(resultsMetadata, result, errMsg);
            } catch (AgentCallbackClientException e) {
                this.log.error("Unable to send command result: " + e.getMessage());
            }
        }
    }
}