PMI interfaces

The PMI PerfServer exports the CpdCollection, CpdData, and CpdValue interfaces to provide performance data to interested clients. The PMI API provides the PmiClient interface to enable clients to receive performance data from servers. For details on these interfaces, see The CpdCollection interface, The CpdData and CpdValue objects, and The PmiClient class. In addition, PMI provides the CpdEventListener and CpdEvent interfaces to enable clients to register as listeners, and thus to be informed when new or changed data is available at the server; see The CpdEventListener and CpdEvent interfaces for details. Finally, PMI provides the CpdFamily class to assist with displaying data in table form; see The CpdFamily class for details.

The CpdCollection interface

The CpdCollection interface is the base interface to PMI. It organizes performance data in the hierarchy described in Data organization and hierarchy. Each member of the hierarchy is an instance of CpdCollection that contains a number of data members and a number of CpdCollection children.

The CpdCollection interface extends two other PMI interfaces, CpdXML and CpdEventSender. These interfaces are defined as follows:

Figure 3. Definitions of the CpdCollection, CpdXML, and CpdEventSender interfaces


public interface CpdCollection extends Serializable, CpdXML,
  CpdEventSender {
     public PerfDescriptor getPerfDescriptor();
     public String getDescription();
     public int numDataMembers();
     public CpdData[] dataMembers();
     public CpdData getData(int index);
     public int numSubcollection();
     public CpdCollection[] subcollections();
     public CpdCollection getSubcollection(int i);
     public CpdCollection findCollection(PerfDescriptor pd);
     public void addSubcollection(CpdCollection col);
     public CpdCollection getParent();
     public void update(CpdCollection other);
     public CpdCollection reset();
}
 
public interface CpdXML {
     public String toXML();
     public void fromXML(String xmlStr);
}
 
public interface CpdEventSender extends Cloneable {
     public void addCpdEventListener(CpdEventListener al);
     public void removeCpdEventListener(CpdEventListener al);
     public void notifyListeners(CpdEvent evt);
     public void notifyListeners(int evt_type);
}

The update method updates collections of data. To illustrate the functionality of this method, assume that the collection1.update(collection2) statement is used to update a data collection named collection1 with the data in a collection named collection2. In this case, the update method works as follows:

The PerfDescriptor interface is used to specify the data that the client is interested in. It includes methods that return node name, server name, module name, collection name, and full name. Its definition is as follows:

Figure 4. Definition of the PerfDescriptor interface


public interface PerfDescriptor extends Serializable {
     public int getType(); // Types include node, server, module, instance,
          // and data
     public String getNodeName();
     public String getServerName();
     public String getModuleName();
     public String getName(); // Returns node, server, module, instance,
          // or data name, depending on type
     public String getFullName(); // Returns a name in the following form:
          // node.server.module.instance.data
     public String[] getPath();
     public boolean equals(PerfDescriptor pd);
     public boolean isDescendingFrom(PerfDescriptor pd);
     public int[] getDataIds(); // Returns all data IDs (null, one, or multiple)
          // in the descriptor
}

The PerfDescriptorList class is used to gather data from multiple PerfDescriptor instances. It includes methods to add, remove, and get PerfDescriptor instances. Its definition is as follows:

Figure 5. Definition of the PerfDescriptorList interface


public class PerfDescriptorList {
     public boolean addDescriptor(PerfDescriptor pd); // If pd is not in the
          // list, add it and return true; otherwise, return false
     public boolean removeDescriptor(PerfDescriptor pd); // If pd is in the
          // list, remove it and return true; otherwise, return false
     public int numDescriptors(); // Return the number of PerfDescriptor
          // instances in the list
     public PerfDescriptor[] getDescriptors(); // Return all PerfDescriptors
          // in an array
}

The CpdData and CpdValue objects

The CpdData object is the lowest level in the CPD hierarchy. Each CpdData instance contains all the static information for the performance data as well as a getValue method to return the data's dynamic information in the form of an instance of the CpdValue object. The CpdData interface provides an update method to take a reference to a new version of a piece of data and update the current object with the new value. The value is updated only if the new data has the same name as the original object. The CpdData interface also includes an addListener interface to enable data objects to register as event listeners; see The CpdEventListener and CpdEvent interfaces for details. The CpdData interface extends the CpdXML and CpdEventSender interfaces, which are shown in Figure 3.

The definition of CpdData is as follows:

Figure 6. Definition of the CpdData interface


public interface CpdData extends Serializable, CpdXML, CpdEventSender {
     public PerfDescriptor getDescriptor();
     public String getDescription();
     public void setValue(CpdValue value);
     public void update(CpdData other);
     public CpdValue getValue();
     public Object getParent();
     public void setParent(Object parent);
     public boolean reset();
}

A variety of data types extend the CpdValue interface. The interface provides the getValue, getTime, delta, and rate methods to work with data values. The definition of CpdValue is as follows:

Figure 7. Definition of the CpdValue interface


public inteface CpdValue extends Serializable, Cloneable {
     public int getType();
     public long getTime();
     public double getValue();
     public CpdValue delta(CpdValue prev); // return the difference
     public CpdValue rate(CpdValue prev); // return the rate of the difference
     public void combine(CpdValue other); // add another value to this value
     public Object clone();
}

Each client value type extends the CpdValue interface. The specific types are listed in Table 1.

Table 1. CpdValue types and associated methods

Type Method Description
CpdInt int intValue() Value as an int
CpdLong long longValue() Value as a long
CpdDouble double doubleValue() Value as a double
CpdStatData double mean() Mean of the sample set
int count() Element count
double sumsquares() Sum of squares of the elements
double variance() Variance
double standardDeviation() Standard deviation
double confidence(int level) Confidence interval of the mean
CpdLoad double mean() Time-weighted average value
double getCurrentValue() Last data point
long getWeight() Measured time period

The getValue method retrieves the value and, if possible, converts it to a double value. If it cannot make the conversion, it returns Double.NaN. The values returned by getValue can be used for displaying and graphing data.

The getTime method returns the server time associated with the data.

The delta method takes the current value and a previous value of a piece of data, and returns an object that represents the change between the values. The delta method also returns a deltaTime value, which represents the time associated with the delta value and the current value of the data. The delta method is defined for all objects listed in Table 1. For CpdStatData, the delta between two values provides the statistics on all members of the current sample set, not on members of any previous set. The delta method is also defined for groups. For two groups, g1 and g2, the object returned by the statement g1.delta(g2) is a group whose members include all members common to both g1 and g2. For each member m1 of group g1 with a corresponding value of m2 in g2, the corresponding delta value is represented by m1.delta(m2).

The rate method returns the rate of change. This method is defined for the CpdInt, CpdLong, and CpdDouble types. If the rate cannot be calculated (for instance, if the method is used with the CpdStatData or CpdLoad types), the original value is returned.

For the CpdLoad object, the mean method returns the time-weighted average of the value being tracked. It is computed by dividing the integral value by the delta time. If the delta time is 0 (zero), the difference between the object's current time and its creation time is used.

The PmiClient class

The PmiClient class is used by clients to access performance data. It looks up session beans and invokes remote APIs, thus freeing the programmer from having to implement these tasks manually. A client can create an instance of PmiClient and call all subsequent methods on that object. The PmiClient object converts wire-level data to a client-side data collection hierarchy and exports methods for clients to create PerfDescriptor objects if the objects' names are known. If you know the static names for the node, server, module, instance, or data, you can call pmiClient.createPerfDescriptor to obtain the PerfDescriptor. Otherwise, you can get the names by issuing the listNodes, listServers, and listMembers methods on PmiClient.

The definition of PmiClient is as follows:

Figure 8. Definition of the PmiClient class


public class PmiClient {
     // Constructor: Look up a PerfRetrieve session bean home and
     //    create a bean object. Do all initialization (for example,
     //    get all configuration files).
     //    Default hostName is localhost; default port is 900
     //    Default JNDI name for perfRetrieveHome is "PerfRetrieveHome"
     PmiClient();
     PmiClient(String hostName);
     PmiClient(String hostName, String port);
     PmiClient(String hostName, String port, String perfRetrieveHome);
 
     // The top-level collection of the data hierarchy.
     CpdCollection createRootCollection();
 
     // The following methods serve as wrappers for the remote
     // methods in PerfRetrieve so that users do not need to
     // deal with remote APIs or wire-level data.
 
     // List all nodes in the domain, then call
     // PerfDescriptorInstance.getName() to get the node names.
     PerfDescriptor[] listNodes();
 
     // List all servers in a node; pd is the one returned from
     // listNodes. Call PerfDescriptorInstance.getName() to get
     // the server names.
     PerfDescriptor[] listServers(String nodeName);
     PerfDescriptor[] listServers(PerfDescriptor pd);
 
     // List the members in a server. The returned PerfDescriptor
     // can be passed to the next listMembers call until it
     // returns null (that is, when the leaf node is reached).
     PerfDescriptor[] listMembers(PerfDescriptor pd);
 
     // Get module configuration, which contains all the static
     // information for the data.
     PmiModuleConfig[] getConfigs();
     PmiModuleConfig[] getConfigs(String nodeName);
     PmiModuleConfig getConfig(String moduleID);
 
     // Retrieve performance data. The following modes are available:
     // - Single pd versus an array of pds
     // - With or without time interval
     // - Recursive versus nonrecursive (recursive retrieves data
     //   for each subgroup instead of aggregate data)
     CpdCollection get(PerfDescriptor pd, boolean recursive);
     CpdCollection get(PerfDescriptor pd, boolean recursive, int time);
     CpdCollection[] gets(PerfDescriptorList pds, boolean recursive);
     CpdCollection[] gets(PerfDescriptorList pds, boolean recursive,
          int time);
 
 
     // Retrieve performance data in XML format
     String getXML(PerfDescriptor pd, boolean recursive);
     String getXML(PerfDescriptor pd, boolean recursive, int time);
     String getXML(PerfDescriptorList pds, boolean recursive);
     String getXML(PerfDescriptorList pds, boolean recursive,
          int time);
 
     // Convert data ID and name
     public static String getDataName(String moduleID, int dataId);
     public static int getDataId(String moduleID, String name);
 
     // Methods to create a PerfDescriptor, used when you know
     // static names
     public PerfDescriptor createPerfDescriptor(){
     public PerfDescriptor createPerfDescriptor(String[] dataPath);
     public PerfDescriptor createPerfDescriptor(String[] dataPath,
          int dataId);
     public PerfDescriptor createPerfDescriptor(String[] dataPath,
          int[] dataIds);
     public PerfDescriptor createPerfDescriptor(PerfDescriptor parent,
          String name);
     public PerfDescriptor createPerfDescriptor(PerfDescriptor parent,
          int dataId);
     public PerfDescriptor createPerfDescriptor(PerfDescriptor parent,
          int[] dataIds);
     }
}

The CpdEventListener and CpdEvent interfaces

The PMI client package provides event and listener interfaces to inform clients (for instance, a GUI display) when new or changed data is available. The CpdEventObject interface, which extends java.util.EventObject, is the parent to the PMI event and listener interfaces. The CpdEventListener interface, which extends CpdEventObject, is the interface that objects need to implement to receive performance data events. Objects can use the addListener method to register as event listeners. The definition of the method is as follows:

void addListener(CpdEventListener listener);

The definitions of the CpdEventListener and CpdEvent interfaces are as follows:

Figure 9. Definitions of the CpdEventListener and CpdEvent interfaces


public interface CpdEventListener {
     public void CpdEventPerformed(CpdEvent evt);
}
 
public class CpdEvent {
     final static int EVENT_NEW_MEMBER = 0;
     final static int EVENT_NEW_SUBCOLLECTION = 1;
     final static int EVENT_NEW_DATA = 2;
 
     private int type;
     private Object source = null;
 
     public CpdEvent(Object source, int type);
     public CpdEvent(int type);
     public Object getSource();
     public int getType();
}

The CpdFamily class

The PMI client provides the CpdFamily class to simplify displaying data in a table. When two data objects have the same module identifier, they are in the same family and can be displayed in the same table by using this class. The definition of CpdFamily is as follows:

Figure 10. Definition of the CpdFamily class


public class CpdFamily {
     static public boolean isSameFamily(CpdData d1, CpdData d2);
     static public boolean isSameRow(CpdData d1, CpdData d2);
     static public boolean isSameColumn(CpdData d1, CpdData d2);
     static public boolean getRow(CpdData d1);
     static public boolean getColumn(CpdData d1);
     static public boolean getFamilyName(CpdData d1);
}