/*
* 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 com.slamd.asn1.ASN1Element;
import com.slamd.asn1.ASN1Exception;
import com.slamd.asn1.ASN1Integer;
import com.slamd.asn1.ASN1OctetString;
import com.slamd.asn1.ASN1Sequence;
import com.slamd.common.Constants;
import com.slamd.common.SLAMDException;
/**
* This class provides a mechanism to encode and decode stat trackers in a
* manner that can be transferred over the network or written to persistent
* storage. The encoding will be as an ASN.1 element with the following BNF:
*
* <CODE>StatTracker ::= SEQUENCE {</CODE><BR>
* <CODE> className OCTET STRING,</CODE><BR>
* <CODE> clientID OCTET STRING,</CODE><BR>
* <CODE> threadID OCTET STRING,</CODE><BR>
* <CODE> displayName OCTET STRING,</CODE><BR>
* <CODE> collectionInterval INTEGER,</CODE><BR>
* <CODE> duration INTEGER,</CODE><BR>
* <CODE> data OCTET STRING }</CODE><BR>
*
*
* @author Neil A. Wilson
*/
public class StatEncoder
{
/**
* Encodes the provided stat tracker into an ASN.1 sequence.
*
* @param tracker The stat tracker to be encoded.
*
* @return The ASN.1 sequence encoded from the information in the provided
* stat tracker.
*/
public static ASN1Sequence trackerToSequence(StatTracker tracker)
{
ASN1Element[] trackerElements = new ASN1Element[]
{
new ASN1OctetString(tracker.getClass().getName()),
new ASN1OctetString(tracker.getClientID()),
new ASN1OctetString(tracker.getThreadID()),
new ASN1OctetString(tracker.getDisplayName()),
new ASN1Integer(tracker.getCollectionInterval()),
new ASN1Integer(tracker.getDuration()),
new ASN1OctetString(tracker.encode())
};
return new ASN1Sequence(trackerElements);
}
/**
* Decodes the provided ASN.1 sequence as a stat tracker.
*
* @param sequence The ASN.1 sequence to be decoded as a stat tracker.
*
* @return The decoded stat tracker.
*
* @throws SLAMDException If the provided sequence cannot be decoded as a
* stat tracker.
*/
public static StatTracker sequenceToTracker(ASN1Sequence sequence)
throws SLAMDException
{
try
{
ASN1Element[] elements = sequence.getElements();
if (elements.length != 7)
{
throw new SLAMDException("There must be 7 elements in a stat tracker " +
"sequence");
}
String className = elements[0].decodeAsOctetString().getStringValue();
String clientID = elements[1].decodeAsOctetString().getStringValue();
String threadID = elements[2].decodeAsOctetString().getStringValue();
String displayName = elements[3].decodeAsOctetString().getStringValue();
int interval = elements[4].decodeAsInteger().getIntValue();
int duration = elements[5].decodeAsInteger().getIntValue();
byte[] data = elements[6].decodeAsOctetString().getValue();
Class<?> trackerClass = Constants.classForName(className);
StatTracker tracker = (StatTracker) trackerClass.newInstance();
tracker.setClientID(clientID);
tracker.setThreadID(threadID);
tracker.setDisplayName(displayName);
tracker.setCollectionInterval(interval);
tracker.setDuration(duration);
tracker.decode(data);
// If the stat tracker was not stopped properly, or if it was a persistent
// statistic taken while the job was still running, then the duration
// might be zero which could cause some problems. If that is the case,
// then at least provide an estimate of the duration.
if ((duration <= 0) && (interval > 0) && (tracker.getNumIntervals() > 0))
{
tracker.setDuration(interval * tracker.getNumIntervals());
}
return tracker;
}
catch (Exception e)
{
e.printStackTrace();
if (e instanceof SLAMDException)
{
throw (SLAMDException) e;
}
else
{
throw new SLAMDException("Unable to decode sequence as a stat " +
"tracker: " + e, e);
}
}
}
/**
* Encodes the provided set of stat trackers into an ASN.1 sequence. Each
* element of the sequence will itself be a sequence with information about a
* single stat tracker.
*
* @param trackers The set of stat trackers to be encoded.
*
* @return The ASN.1 sequence encoded from the information in the provided
* stat trackers.
*/
public static ASN1Sequence trackersToSequence(StatTracker[] trackers)
{
ASN1Element[] elements = new ASN1Element[trackers.length];
for (int i=0; i < elements.length; i++)
{
elements[i] = trackerToSequence(trackers[i]);
}
return new ASN1Sequence(elements);
}
/**
* Decodes the provided ASN.1 sequence as a set of stat trackers.
*
* @param sequence The ASN.1 sequence to be decoded as a set of stat
* trackers.
*
* @return The decoded stat trackers.
*
* @throws SLAMDException If the provided sequence cannot be decoded as a
* set of stat trackers.
*/
public static StatTracker[] sequenceToTrackers(ASN1Sequence sequence)
throws SLAMDException
{
ASN1Element[] elements = sequence.getElements();
StatTracker[] trackers = new StatTracker[elements.length];
for (int i=0; i < elements.length; i++)
{
try
{
trackers[i] = sequenceToTracker(elements[i].decodeAsSequence());
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode sequence element " + i +
"as a sequence", ae);
}
}
return trackers;
}
}