001: /*
002: * <copyright>
003: *
004: * Copyright 2001-2004 BBNT Solutions, LLC
005: * under sponsorship of the Defense Advanced Research Projects
006: * Agency (DARPA).
007: *
008: * You can redistribute this software and/or modify it under the
009: * terms of the Cougaar Open Source License as published on the
010: * Cougaar Open Source Website (www.cougaar.org).
011: *
012: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
013: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
014: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
015: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
016: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
017: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
018: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
019: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
020: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
021: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
022: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
023: *
024: * </copyright>
025: */
026: package org.cougaar.tools.csmart.recipe;
027:
028: import org.cougaar.tools.csmart.core.cdata.AgentAssetData;
029: import org.cougaar.tools.csmart.core.cdata.AgentComponentData;
030: import org.cougaar.tools.csmart.core.cdata.ComponentData;
031: import org.cougaar.tools.csmart.core.cdata.GenericComponentData;
032: import org.cougaar.tools.csmart.core.cdata.RelationshipData;
033: import org.cougaar.tools.csmart.core.property.Property;
034: import org.cougaar.tools.csmart.experiment.DBExperiment;
035: import org.cougaar.tools.csmart.experiment.ExperimentBase;
036: import org.cougaar.tools.csmart.experiment.Experiment;
037: import org.cougaar.tools.csmart.util.ResultsFileFilter;
038:
039: import java.io.FileFilter;
040: import java.io.Serializable;
041: import java.net.URL;
042: import java.util.List;
043:
044: /**
045: * A Metric that adds the CSMART Metric collection Plugin to any society. <br>
046: * These add no agents, but do add 1 plugin to every agent in the society,
047: * plus one controlling plugin to one of the agents, picked at random.<br>
048: * The user can specify the sample interval, the start delay, and the maximum
049: * number of samples to take.<br>
050: */
051: public class BasicMetric extends RecipeBase implements MetricComponent,
052: Serializable {
053: private static final String DESCRIPTION_RESOURCE_NAME = "basic-metric-description.html";
054: private static final String BACKUP_DESCRIPTION = "BasicMetric provides basic runtime performance metrics";
055:
056: /** Sample Interval Property Definitions **/
057: public static final String PROP_SAMPLEINTERVAL = "Metrics: Sample Interval";
058: public static final Integer PROP_SAMPLEINTERVAL_DFLT = new Integer(
059: 10);
060: public static final String PROP_SAMPLEINTERVAL_DESC = "Sample Interval to collect metrics";
061:
062: /** Start Delay Property Definitions **/
063: public static final String PROP_STARTDELAY = "Metrics: Start Delay";
064: public static final Integer PROP_STARTDELAY_DFLT = new Integer(0);
065: public static final String PROP_STARTDELAY_DESC = "Delay to wait before metric collection";
066:
067: /** Maximum Number of Samples Property Definitions **/
068: public static final String PROP_MAXNUMBSAMPLES = "Metrics: Maximum Number of Samples";
069: public static final Integer PROP_MAXNUMBSAMPLES_DFLT = new Integer(
070: 20);
071: public static final String PROP_MAXNUMBSAMPLES_DESC = "Number of metric samples to collect";
072:
073: // Props for metrics
074: private Property propSampleInterval;
075: private Property propStartDelay;
076: private Property propMaxSamples;
077:
078: // Properties to define parameters to MetricsPlugin
079: // Directory to saveresults files in - default "."
080: // public static final String PROP_RESULTSDIR = "Metrics results directory";
081: public static final String PROP_RESULTSDIR_DFLT = ".";
082: // FIXME: Should use org.cougaar.workspace -- see bug 1668
083: // public static final String PROP_RESULTSDIR_DESC = "Relative path in which to save results files";
084: // private Property propResultsDir;
085:
086: // Verb to search for - default null
087: public static final String PROP_TVERB = "Task Verb";
088: public static final String PROP_TVERB_DFLT = org.cougaar.glm.ldm.Constants.Verb.GETLOGSUPPORT;
089: public static final String PROP_TVERB_DESC = "Task Verb to search for and count";
090: private Property propTVerb;
091:
092: public static final String PROP_BBSERV = "Blackboard Statistics Service On";
093: public static final boolean PROP_BBSERV_DFLT = false;
094: public static final String PROP_BBSERV_DESC = "Turn Blackboard metrics collection on or off";
095: private Property propBBServ;
096:
097: public static final String PROP_PRSERV = "Prototype Registry Service On";
098: public static final boolean PROP_PRSERV_DFLT = false;
099: public static final String PROP_PRSERV_DESC = "Turn Prototype Registry metrics on or off";
100: private Property propPRServ;
101:
102: public static final String PROP_NODESERV = "Node Metrics Service On";
103: public static final boolean PROP_NODESERV_DFLT = false;
104: public static final String PROP_NODESERV_DESC = "Turn Node metrics on or off";
105: private Property propNodeServ;
106:
107: public static final String PROP_MSTATSSERV = "Message Stats Service On";
108: public static final boolean PROP_MSTATSSERV_DFLT = false;
109: public static final String PROP_MSTATSSERV_DESC = "Turn Message Transport metrics on or off";
110: private Property propMStatsServ;
111:
112: public static final String PROP_MWATCHSERV = "Message Watcher Service On";
113: public static final boolean PROP_MWATCHSERV_DFLT = false;
114: public static final String PROP_MWATCHSERV_DESC = "Turn Message Watcher on or off";
115: private Property propMWatchServ;
116:
117: private static final String MetricsPlugin_name = "org.cougaar.tools.csmart.runtime.plugin.MetricsPlugin";
118: private static final String MetricsInitializerPlugin_name = "org.cougaar.tools.csmart.runtime.plugin.MetricsInitializerPlugin";
119: private static final String MetricControl_Role = "MetricsControlProvider";
120:
121: private transient int numAgs2 = 0;
122:
123: // FileFilter for metrics:
124: private static FileFilter metricsFileFilter = new ResultsFileFilter();
125:
126: public BasicMetric() {
127: this ("Basic Metric");
128: }
129:
130: public BasicMetric(String name) {
131: super (name);
132: }
133:
134: public void initProperties() {
135:
136: propSampleInterval = addProperty(PROP_SAMPLEINTERVAL,
137: PROP_SAMPLEINTERVAL_DFLT);
138: propSampleInterval.setToolTip(PROP_SAMPLEINTERVAL_DESC);
139:
140: propMaxSamples = addProperty(PROP_MAXNUMBSAMPLES,
141: PROP_MAXNUMBSAMPLES_DFLT);
142: propMaxSamples.setToolTip(PROP_MAXNUMBSAMPLES_DESC);
143:
144: propStartDelay = addProperty(PROP_STARTDELAY,
145: PROP_STARTDELAY_DFLT);
146: propStartDelay.setToolTip(PROP_STARTDELAY_DESC);
147:
148: // propResultsDir = addProperty(PROP_RESULTSDIR, PROP_RESULTSDIR_DFLT);
149: // propResultsDir.setToolTip(PROP_RESULTSDIR_DESC);
150:
151: // For now, don't show this property - we need the results filter to change
152: // appropriately before we can let the user change this
153: // FIXME!
154:
155: // Task Verb to search for
156: propTVerb = addProperty(PROP_TVERB, PROP_TVERB_DFLT);
157: propTVerb.setToolTip(PROP_TVERB_DESC);
158:
159: propBBServ = addBooleanProperty(PROP_BBSERV, PROP_BBSERV_DFLT);
160: propBBServ.setToolTip(PROP_BBSERV_DESC);
161:
162: propPRServ = addBooleanProperty(PROP_PRSERV, PROP_PRSERV_DFLT);
163: propPRServ.setToolTip(PROP_PRSERV_DESC);
164:
165: propNodeServ = addBooleanProperty(PROP_NODESERV,
166: PROP_NODESERV_DFLT);
167: propNodeServ.setToolTip(PROP_NODESERV_DESC);
168:
169: propMStatsServ = addBooleanProperty(PROP_MSTATSSERV,
170: PROP_MSTATSSERV_DFLT);
171: propMStatsServ.setToolTip(PROP_MSTATSSERV_DESC);
172:
173: propMWatchServ = addBooleanProperty(PROP_MWATCHSERV,
174: PROP_MWATCHSERV_DFLT);
175: propMWatchServ.setToolTip(PROP_MWATCHSERV_DESC);
176:
177: }
178:
179: /**
180: * Gets the name of the html help file for this component.
181: *
182: * @return an <code>URL</code> value
183: */
184: public URL getDescription() {
185: return getClass().getResource(DESCRIPTION_RESOURCE_NAME);
186: }
187:
188: public String getMetricName() {
189: return getShortName();
190: }
191:
192: /**
193: * Return a file filter which can be used to fetch
194: * the metrics files for this experiment.
195: * @return file filter to get metrics files for this experiment
196: */
197: public FileFilter getResultFileFilter() {
198: // FIXME: Make this more specific?
199: return metricsFileFilter;
200: }
201:
202: /**
203: * Return a file filter which can be used to delete
204: * the files generated by this experiment.
205: * @return file filter for cleanup
206: */
207: public FileFilter getCleanupFileFilter() {
208: // Fixme: make this more specific
209: // Also, should this delete additional ini files (of which there are none)?
210: return metricsFileFilter;
211: }
212:
213: private transient int numAgents = 0; // numAgents collecting stats
214: private transient RelationshipData metricRelate = null; // name of agent doing controling
215:
216: private ComponentData addInitPICD(ComponentData data) {
217: GenericComponentData plugin = new GenericComponentData();
218: plugin.setType(ComponentData.PLUGIN);
219: plugin.setName(MetricsInitializerPlugin_name);
220: plugin.setClassName(MetricsInitializerPlugin_name);
221: plugin.addParameter(new Integer(numAgents)); // numProviders
222: plugin
223: .addParameter(getProperty(PROP_SAMPLEINTERVAL)
224: .getValue()); // sampleInterval
225: plugin.addParameter(getProperty(PROP_STARTDELAY).getValue()); // startDelay
226: plugin
227: .addParameter(getProperty(PROP_MAXNUMBSAMPLES)
228: .getValue()); // maxSamples
229: plugin.setParent(data);
230: plugin.setOwner(this );
231: // Add the plugin such that it replaces any previous version
232: data.addChildDefaultLoc(plugin);
233: return plugin;
234: }
235:
236: private void addCollectorCD(ComponentData data) {
237: //Only add this if its not there already
238: ComponentData[] children = data.getChildren();
239: for (int i = 0; i < data.childCount(); i++) {
240: if (children[i].getName().equals(MetricsPlugin_name))
241: return;
242: }
243: GenericComponentData plugin = new GenericComponentData();
244: plugin.setType(ComponentData.PLUGIN);
245: //plugin.setName("MetricPlugin");
246: plugin.setName(MetricsPlugin_name);
247: plugin.setClassName(MetricsPlugin_name);
248: plugin.setParent(data);
249: plugin.setOwner(this );
250:
251: // Add parameters here:
252: // Switch to using the actual resultsDir prop
253: // when we allow the user to edit it. See above in initProperties.
254: plugin.addParameter(PROP_RESULTSDIR_DFLT); // dir for Results files
255: // FIXME: See bug 1668
256: plugin.addParameter(getProperty(PROP_TVERB).getValue()); // Task Verb to search for
257: addParameter(plugin, PROP_BBSERV);
258: addParameter(plugin, PROP_PRSERV);
259: addParameter(plugin, PROP_NODESERV);
260: addParameter(plugin, PROP_MSTATSSERV);
261: addParameter(plugin, PROP_MWATCHSERV);
262:
263: // Add the plugin such that it replaces any previous version
264: data.addChildDefaultLoc(plugin);
265: }
266:
267: private void addParameter(GenericComponentData plugin, String name) {
268: if (((Boolean) (getProperty(name).getValue())).booleanValue())
269: plugin.addParameter(new Integer(1));
270: else
271: plugin.addParameter(new Integer(0));
272: }
273:
274: private void addRelationship(AgentComponentData data) {
275: if (metricRelate == null)
276: return;
277: // Only add the relationship if its not already there
278: AgentAssetData aad = data.getAgentAssetData();
279: if (aad == null)
280: return; // No agent asset data available
281: RelationshipData[] relats = aad.getRelationshipData();
282: for (int i = 0; i < relats.length; i++) {
283: // FIXME: This should be equals based on the Role not the agent
284: // Or rather, we must be careful....
285: if (relats[i].equals(metricRelate))
286: return;
287: }
288: aad.addRelationship(metricRelate);
289: }
290:
291: public ComponentData modifyComponentData(ComponentData data) {
292: numAgs2 = 0; // Gets counted as metrics plugins are inserted
293: ComponentData picd = addMetricsComponentData(data);
294:
295: // OK, now set numAgs2 val in the numProviders slot
296: // First, find the MetricsInitializer Plugin
297: if (picd == null) {
298: // couldn't find the initializer plugin. Big problem
299: if (log.isErrorEnabled()) {
300: log.error("BasicMetric: Could not insert initializer?");
301: }
302: return data;
303: }
304:
305: // Then, reset the value of the first parameter
306: picd.setParameter(0, new Integer(numAgs2));
307:
308: return data;
309: }
310:
311: private ComponentData addMetricsComponentData(ComponentData data) {
312:
313: ComponentData picd = null;
314:
315: // Find the Experiment.
316: // From it, get a count of the Agents in the Society & set the numAgents
317: if (numAgents == 0 && data.getOwner() instanceof ExperimentBase) {
318: Experiment exp = (Experiment) data.getOwner();
319: List ags = exp.getAgentsList();
320: if (ags != null)
321: numAgents = ags.size();
322: else
323: numAgents = 0;
324: }
325: // recurse down from the top, finding all of the AgentComponents
326: // save the name of the first I find
327: if (data.getType().equals(ComponentData.AGENT)) {
328: numAgs2++;
329: if (metricRelate == null) {
330: metricRelate = new RelationshipData();
331: metricRelate.setRole(MetricControl_Role);
332: metricRelate.setItemId(data.getName()); // name
333: metricRelate.setType(data.getName().substring(
334: data.getName().lastIndexOf(".") + 1));
335: metricRelate.setSupported(data.getName()); // name
336: // and to the first, add the MetricsInitializerPlugin
337: picd = addInitPICD(data);
338: }
339: // for each Agent, add the MetricsPlugin & the relationship
340: addCollectorCD(data);
341: addRelationship((AgentComponentData) data);
342: } else if (data.childCount() > 0) {
343: // for each child, call this same method.
344: ComponentData[] children = data.getChildren();
345: for (int i = 0; i < children.length; i++) {
346: ComponentData xpicd = addMetricsComponentData(children[i]);
347: if (xpicd != null)
348: picd = xpicd;
349: }
350: }
351: return picd;
352: }
353: } // end of BasicMetric.java
|