/* * 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.stat; import java.util.ArrayList; import netscape.ldap.LDAPAttribute; import netscape.ldap.LDAPConnection; import netscape.ldap.LDAPEntry; import netscape.ldap.LDAPException; import netscape.ldap.LDAPSearchResults; import com.slamd.asn1.ASN1Element; import com.slamd.asn1.ASN1Exception; import com.slamd.asn1.ASN1Sequence; import com.slamd.common.Constants; import com.slamd.common.SLAMDException; /** * This class provides a means of dumping information about the statistics * collected by a SLAMD job. It is a command-line application, although it also * provides methods for accessing the information programmatically. * * * @author Neil A. Wilson */ public class StatDebugger { // The port number of the SLAMD configuration directory. private int ldapPort; // The DN under which the SLAMD config data exists in the directory. private String baseDN; // The DN to use when binding to the directory server. private String bindDN; // The password to use when binding to the directory server. private String bindPW; // The job ID for the job whose statistics should be dumped. private String jobID; // The address of the SLAMD configuration directory. private String ldapHost; /** * Parses the provided command-line parameters, creates a new instance of the * stat debugger, and dumps the statistics for the specified job. * * @param args The command-line arguments provided to this program. */ public static void main(String[] args) { // Specify default values for the configurable parameters. int ldapPort = 389; String baseDN = null; String bindDN = ""; String bindPW = ""; String jobID = null; String ldapHost = "127.0.0.1"; // Parse the command-line arguments. for (int i=0; i < args.length; i++) { if (args[i].equals("-h")) { ldapHost = args[++i]; } else if (args[i].equals("-p")) { ldapPort = Integer.parseInt(args[++i]); } else if (args[i].equals("-D")) { bindDN = args[++i]; } else if (args[i].equals("-w")) { bindPW = args[++i]; } else if (args[i].equals("-b")) { baseDN = args[++i]; } else if (args[i].equals("-j")) { jobID = args[++i]; } else { System.err.println("Unrecognized argument " + args[i]); displayUsage(); System.exit(1); } } // Make sure that at least the base DN and job ID were specified. if (baseDN == null) { System.err.println("ERROR: No configuration base DN provided"); displayUsage(); System.exit(1); } if (jobID == null) { System.err.println("ERROR: No job ID provided"); displayUsage(); System.exit(1); } // Create the StatDebugger and retrieve the data from it. StatDebugger debugger = new StatDebugger(ldapHost, ldapPort, bindDN, bindPW, baseDN); StatTracker[] trackers = null; try { trackers = debugger.getStatTrackers(jobID); } catch (SLAMDException se) { System.err.println(se.getMessage()); System.exit(1); } // Iterate through the trackers and dump the information contained in them. ArrayList<String> nameList = new ArrayList<String>(); for (int i=0; i < trackers.length; i++) { String name = trackers[i].getDisplayName(); if (! nameList.contains(name)) { nameList.add(name); } System.out.println("StatTracker " + i); System.out.println("Tracker Name: " + trackers[i].getDisplayName()); System.out.println("Client ID: " + trackers[i].getClientID()); System.out.println("Thread ID: " + trackers[i].getThreadID()); System.out.println("Collection Interval: " + trackers[i].getCollectionInterval()); System.out.println("Number of Intervals: " + trackers[i].getNumIntervals()); System.out.println("Duration: " + trackers[i].getDuration()); System.out.println(trackers[i].getDetailString()); System.out.println(); } // Aggregate the values contained in the trackers and display the aggregated // results. for (int i=0; i < nameList.size(); i++) { String name = nameList.get(i); ArrayList<StatTracker> trackerList = new ArrayList<StatTracker>(); for (int j=0; j < trackers.length; j++) { if (trackers[j].getDisplayName().equals(name)) { trackerList.add(trackers[j]); } } StatTracker[] trackersToAggregate = new StatTracker[trackerList.size()]; trackerList.toArray(trackersToAggregate); StatTracker tracker = trackersToAggregate[0].newInstance(); tracker.aggregate(trackersToAggregate); System.out.println("Aggregated Results for Stat Tracker " + name); System.out.println("Number of Intervals: " + tracker.getNumIntervals()); System.out.println("Duration: " + tracker.getDuration()); System.out.println(tracker.getDetailString()); System.out.println(); } } /** * Creates a new instance of this stat debugger using the provided * information. * * @param ldapHost The SLAMD configuration directory address. * @param ldapPort The SLAMD configuration directory port. * @param bindDN The SLAMD configuration directory bind DN. * @param bindPW The SLAMD configuration directory bind password. * @param baseDN The SLAMD configuration base DN. */ public StatDebugger(String ldapHost, int ldapPort, String bindDN, String bindPW, String baseDN) { this.ldapHost = ldapHost; this.ldapPort = ldapPort; this.bindDN = bindDN; this.bindPW = bindPW; this.baseDN = baseDN; } /** * Retrieves the stat trackers associated with the specified job. * * @param jobID The job ID of the job for which to retrieve the stat * trackers. * * @return The set of stat trackers associated with the specified job, or * <CODE>null</CODE> if it does not have any statistics. * * @throws SLAMDException If a problem occurs while trying to retrieve and * process the job information. */ public StatTracker[] getStatTrackers(String jobID) throws SLAMDException { // Establish a connection to the configuration directory. LDAPConnection conn = new LDAPConnection(); try { conn.connect(3, ldapHost, ldapPort, bindDN, bindPW); } catch (LDAPException le) { throw new SLAMDException("Unable to bind to the configuration " + "directory: " + le, le); } // Find the entry containing information about the specified job. String filter = "(&(objectClass=" + Constants.SCHEDULED_JOB_OC + ")(" + Constants.JOB_ID_AT + "=" + jobID + "))"; LDAPEntry jobEntry = null; try { LDAPSearchResults results = conn.search(baseDN, LDAPConnection.SCOPE_SUB, filter, null, false); while (results.hasMoreElements()) { Object element = results.nextElement(); if (element instanceof LDAPEntry) { if (jobEntry == null) { jobEntry = (LDAPEntry) element; } else { try { conn.disconnect(); } catch (Exception e) {} throw new SLAMDException("Multiple entries found for job ID " + jobID); } } else if (element instanceof LDAPException) { throw (LDAPException) element; } } } catch (LDAPException le) { try { conn.disconnect(); } catch (Exception e) {} throw new SLAMDException("Unable to search the configuration " + "directory: " + le, le); } // Make sure that an entry was returned. if (jobEntry == null) { try { conn.disconnect(); } catch (Exception e) {} throw new SLAMDException("Unable to find any information about job " + jobID + " in the configuration directory."); } // Get the statistics from the entry. LDAPAttribute attr = jobEntry.getAttribute(Constants.JOB_STAT_TRACKER_AT); if (attr == null) { try { conn.disconnect(); } catch (Exception e) {} return null; } byte[][] values = attr.getByteValueArray(); if ((values == null) || (values.length == 0)) { try { conn.disconnect(); } catch (Exception e) {} return null; } // Decode the value as an ASN.1 sequence and convert it to a stat tracker // array. StatTracker[] trackers; try { ASN1Sequence trackerSequence = ASN1Element.decode(values[0]).decodeAsSequence(); trackers = StatEncoder.sequenceToTrackers(trackerSequence); } catch (ASN1Exception ae) { try { conn.disconnect(); } catch (Exception e) {} throw new SLAMDException("Unable to decode job statistics for job " + jobID + ": " + ae, ae); } // Disconnect from the directory and return the stat trackers. try { conn.disconnect(); } catch (Exception e) {} return trackers; } /** * Displays usage information for this program. */ public static void displayUsage() { System.err.println("Configurable options include:"); System.err.println("-h {host} -- The SLAMD config directory address"); System.err.println("-p {port} -- The SLAMD config directory port"); System.err.println("-D {dn} -- The SLAMD config directory bind DN"); System.err.println("-w {pw} -- The SLAMD config directory bind password"); System.err.println("-b {dn} -- The SLAMD config directory base DN"); System.err.println("-j {job} -- The job ID for which to dump stats"); } }