/* * Sun Public License * * The contents of this file are subject to the Sun Public License Version * 1.0 (the "License"). You may not use this file except in compliance with * the License. A copy of the License is available at http://www.sun.com/ * * The Original Code is the SLAMD Distributed Load Generation Engine. * The Initial Developer of the Original Code is Neil A. Wilson. * Portions created by Neil A. Wilson are Copyright (C) 2004-2010. * Some preexisting portions Copyright (C) 2002-2006 Sun Microsystems, Inc. * All Rights Reserved. * * Contributor(s): Neil A. Wilson */ package com.slamd.resourcemonitor; import java.util.ArrayList; import com.slamd.job.JobClass; import com.slamd.stat.RealTimeStatReporter; import com.slamd.stat.ResourceMonitorStatTracker; import com.slamd.stat.StatTracker; /** * This class defines a "job" that will be used to tell resource monitor clients * how they should collect statistics. * * * @author Neil A. Wilson */ public class ResourceMonitorJob { // The list of resource monitors associated with this monitor job. private ArrayList<ResourceMonitor> activeMonitors; // The list of log messages associated with this monitor job. private ArrayList<String> logMessages; // The list of stat trackers maintained by each of the monitor threads. private ArrayList<ResourceMonitorStatTracker> statList; // Indicates whether this client should enable real-time statistics reporting. private boolean enableRealTimeStats; // A flag used to determine whether the monitor threads have already been // requested to stop. private boolean stopRequested; // The statistics collection interval that should be used by monitors. private int collectionInterval; // The maximum length of time that the monitor threads should run. private int duration; // The time that the job should start and stop running. private long startTime; private long stopTime; // The actual start and stop times for the job. private long actualStartTime; private long actualStopTime; // A mutex used to provide threadsafe access to the list of active monitors. private final Object monitorMutex; // The stat reporter to use for reporting real-time statistics to the SLAMD // server. private RealTimeStatReporter statReporter; // The resource monitor client with which this job is associated. private ResourceMonitorClient monitorClient; // The job ID of the SLAMD job with which this monitor job is associated. private String jobID; /** * Creates a new resource monitor job with the provided information. * * @param monitorClient The resource monitor client that created this * monitor job. * @param jobID The job ID of the SLAMD job with which this * monitor job is associated. * @param startTime The time that the monitor threads should start * collecting statistics. * @param stopTime The time that the monitor threads should stop * collecting statistics. * @param duration The maximum length of time in seconds that the * monitor threads should run. * @param collectionInterval The statistics collection interval that should * be used by monitor threads. * @param enableRealTimeStats Indicates whether real-time statistics * collection should be enabled for this job. * @param statReporter The real-time stat reporter to use for this * job. */ public ResourceMonitorJob(ResourceMonitorClient monitorClient, String jobID, long startTime, long stopTime, int duration, int collectionInterval, boolean enableRealTimeStats, RealTimeStatReporter statReporter) { this.monitorClient = monitorClient; this.jobID = jobID; this.startTime = startTime; this.stopTime = stopTime; this.duration = duration; this.collectionInterval = collectionInterval; this.enableRealTimeStats = enableRealTimeStats; this.statReporter = statReporter; logMessages = new ArrayList<String>(); statList = new ArrayList<ResourceMonitorStatTracker>(); stopRequested = false; monitorMutex = new Object(); synchronized (monitorMutex) { activeMonitors = new ArrayList<ResourceMonitor>(); ResourceMonitor[] definedMonitors = monitorClient.getDefinedMonitors(); for (int i=0; i < definedMonitors.length; i++) { try { ResourceMonitor monitor = definedMonitors[i].newInstance(); monitor.setName(monitor.getMonitorName() + " -- " + jobID); activeMonitors.add(monitor); } catch (Exception e) { monitorClient.logVerbose("Unable to create resource monitor " + definedMonitors[i].getMonitorName() + " -- " + JobClass.stackTraceToString(e)); } } } } /** * Retrieves the job ID of the SLAMD job with which this resource monitor job * is associated. * * @return The job ID of the SLAMD job with which this resource monitor job * is associated. */ public String getJobID() { return jobID; } /** * Retrieves the time that this monitor job should start. * * @return The time that this monitor job should start. */ public long getStartTime() { return startTime; } /** * Retrieves the time that this monitor job should stop. * * @return The time that this monitor job should stop. */ public long getStopTime() { return stopTime; } /** * Retrieves the maximum length of time in seconds that this monitor job * should run. * * @return The maximum length of time in seconds that this monitor job should * run. */ public int getDuration() { return duration; } /** * Retrieves the actual start time for this monitor job. * * @return The actual start time for this monitor job. */ public long getActualStartTime() { return actualStartTime; } /** * Retrieves the actual stop time for this monitor job. * * @return The actual stop time for this monitor job. */ public long getActualStopTime() { return actualStopTime; } /** * Retrieves the time at which this job should stop running. * * @return The time at which this job should stop running. */ public long getShouldStopTime() { long durationStopTime = -1; if (duration > 0) { durationStopTime = actualStartTime + (duration * 1000); } if (stopTime > 0) { return Math.min(stopTime, durationStopTime); } else { return durationStopTime; } } /** * Retrieves the collection interval that monitor threads should use. * * @return The collection interval that monitor threads should use. */ public int getCollectionInterval() { return collectionInterval; } /** * Indicates whether this job should collect statistical data in real time. * * @return <CODE>true</CODE> if the client should collect statistical data in * real time, or <CODE>false</CODE> if not. */ public boolean enableRealTimeStats() { return enableRealTimeStats; } /** * Retrieves the stat reporter that should be used to report real-time * statistical data. * * @return The stat reporter that should be used to report real-time * statistical data, or <CODE>null</CODE> if no reporting should be * done. */ public RealTimeStatReporter getStatReporter() { return statReporter; } /** * Notifies all the resource monitors that they should start collecting * statistics. */ public void startCollecting() { actualStartTime = System.currentTimeMillis(); synchronized (monitorMutex) { for (int i=0; i < activeMonitors.size(); i++) { activeMonitors.get(i).startCollecting(this); } } } /** * Notifies all the resource monitors that they should stop collecting * statistics. */ public void stopCollecting() { ResourceMonitor[] runningMonitors; synchronized (monitorMutex) { runningMonitors = new ResourceMonitor[activeMonitors.size()]; activeMonitors.toArray(runningMonitors); } if (stopRequested) { for (int i=0; i < runningMonitors.length; i++) { runningMonitors[i].stopAndWait(); } } else { stopRequested = true; for (int i=0; i < runningMonitors.length; i++) { runningMonitors[i].stopCollecting(); } } } /** * Indicates that the provided monitor thread has completed its processing for * this job. * * @param monitor The monitor thread that has completed its processing. */ public void monitorDone(ResourceMonitor monitor) { boolean jobDone = false; synchronized (monitorMutex) { StatTracker[] monitorStats = monitor.getResourceStatistics(); for (int i=0; ((monitorStats != null) && (i < monitorStats.length)); i++) { statList.add(new ResourceMonitorStatTracker(monitor, monitorStats[i])); } String[] monitorMessages = monitor.getLogMessages(); for (int i=0; i < monitorMessages.length; i++) { logMessages.add(monitorMessages[i]); } activeMonitors.remove(monitor); if (activeMonitors.isEmpty()) { // All the monitors are done. Notify the monitor client. actualStopTime = System.currentTimeMillis(); jobDone = true; } } if (jobDone) { monitorClient.jobDone(this); } } /** * Retrieves the set stat trackers associated with this resource monitor job. * * @return The set of stat trackers associated with this resource monitor * job. */ public StatTracker[] getStatTrackers() { // FIXME -- Get rid of this method when we move to the new protocol since // it won't be valid anymore. StatTracker[] trackers = new StatTracker[statList.size()]; for (int i=0; i < trackers.length; i++) { trackers[i] = statList.get(i).getStatTracker(); } return trackers; } /** * Retrieves the set of resource monitor stat trackers associated with this * resource monitor job. * * @return The set of resource monitor stat trackers associated with this * resource monitor job. */ public ResourceMonitorStatTracker[] getResourceMonitorStatTrackers() { ResourceMonitorStatTracker[] trackers = new ResourceMonitorStatTracker[statList.size()]; statList.toArray(trackers); return trackers; } /** * Retrieves the set of log messages associated with this resource monitor * job. * * @return The set of log messages associated with this resource monitor job. */ public String[] getLogMessages() { String[] messages = new String[logMessages.size()]; logMessages.toArray(messages); return messages; } }