/*
* 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.message;
import com.slamd.asn1.ASN1Element;
import com.slamd.asn1.ASN1Enumerated;
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;
import com.slamd.stat.StatEncoder;
import com.slamd.stat.StatTracker;
/**
* This class defines a message type that the client can use to provide status
* information back to the server. The information in the status response may
* vary based on the request received from the server.
*
*
* @author Neil A. Wilson
*/
public class StatusResponseMessage
extends Message
{
// A numeric code that indicates the current state of the client.
private final int clientStatusCode;
// The state of the requested job.
private final int jobState;
// The response code from the request operation
private final int responseCode;
// Status counter information that the client has about the specified job.
private final StatTracker[] statTrackers;
// A text message about the status of the client.
private final String clientStatusMessage;
// The ID of the job for which this status information is being provided.
private final String jobID;
/**
* Creates a new status response message using the specified client status
* code. It will not contain a client status message or job-specific
* information.
*
* @param messageID The message ID for this message.
* @param responseCode The response code for the status request
* operation.
* @param clientStatusCode The client status code to include in this status
* response message.
*/
public StatusResponseMessage(int messageID, int responseCode,
int clientStatusCode)
{
this(messageID, responseCode, clientStatusCode, "", "",
Constants.JOB_STATE_UNKNOWN, new StatTracker[0]);
}
/**
* Creates a new status response message using the specified client status
* code and message. It will not contain any job-specific information.
*
* @param messageID The message ID for this message.
* @param responseCode The response code for the status request
* operation.
* @param clientStatusCode The client status code to include in this
* status response message.
* @param clientStatusMessage The client status message to include in this
* status response message.
*/
public StatusResponseMessage(int messageID, int responseCode,
int clientStatusCode, String clientStatusMessage)
{
this(messageID, responseCode, clientStatusCode, clientStatusMessage, "",
Constants.JOB_STATE_UNKNOWN, new StatTracker[0]);
}
/**
* Creates a new status response message based on the provided client and
* job-specific information. There will be no client status message.
*
* @param messageID The message ID for this message.
* @param responseCode The response code for the status request
* operation.
* @param clientStatusCode The client status code to include in this status
* response message.
* @param jobID The ID of the job for which job-specific
* information is being provided.
* @param jobState The current processing state for the specified
* job.
* @param statTrackers The set of stat trackers associated with the job
* the client is currently processing.
*/
public StatusResponseMessage(int messageID, int responseCode,
int clientStatusCode, String jobID, int jobState,
StatTracker[] statTrackers)
{
this(messageID, responseCode, clientStatusCode, "", jobID, jobState,
statTrackers);
}
/**
* Creates a new status response message based on the provided client and
* job-specific information.
*
* @param messageID The message ID for this message.
* @param responseCode The response code for the status request
* operation.
* @param clientStatusCode The client status code to include in this
* status response message.
* @param clientStatusMessage The client status message to include in this
* status response message.
* @param jobID The ID of the job for which job-specific
* information is being provided.
* @param jobState The current processing state for the specified
* job.
* @param statTrackers The set of stat trackers associated with the
* job the client is currently processing.
*/
public StatusResponseMessage(int messageID, int responseCode,
int clientStatusCode, String clientStatusMessage,
String jobID, int jobState,
StatTracker[] statTrackers)
{
super(messageID, Constants.MESSAGE_TYPE_STATUS_RESPONSE);
this.responseCode = responseCode;
this.clientStatusCode = clientStatusCode;
this.clientStatusMessage = clientStatusMessage;
this.jobID = jobID;
this.jobState = jobState;
this.statTrackers = statTrackers;
}
/**
* Retrieves the response code associated with the status request.
*
* @return The response code associated with the status request.
*/
public int getResponseCode()
{
return responseCode;
}
/**
* Retrieves the client status code associated with this status response
* message.
*
* @return The client status code associated with this status response
* message.
*/
public int getClientStatusCode()
{
return clientStatusCode;
}
/**
* Retrieves the client status message associated with this status response
* message.
*
* @return The client status message associated with this status response
* message.
*/
public String getClientStatusMessage()
{
return clientStatusMessage;
}
/**
* Retrieves the ID of the job associated with this status response message.
*
* @return The ID of the job associated with this status response message.
*/
public String getJobID()
{
return jobID;
}
/**
* Retrieves the state of the job associated with this status response
* message.
*
* @return The state of the job associated with this status response message.
*/
public int getJobState()
{
return jobState;
}
/**
* Retrieves the stat tracker information associated with this status response
* message.
*
* @return The stat tracker information associated with this status response
* message.
*/
public StatTracker[] getStatTrackers()
{
return statTrackers;
}
/**
* Retrieves a string representation of this message.
*
* @return A string representation of this message.
*/
@Override()
public String toString()
{
String eol = System.getProperty("line.separator");
String statStr = "";
for (int i=0; ((statTrackers != null) && (i < statTrackers.length));
i++)
{
statStr += " " + statTrackers[i].getSummaryString() + eol;
}
return "Status Response Message" + eol +
" Message ID: " + messageID + eol +
" Client Status Code: " + clientStatusCode + eol +
" Client Status Message: " + clientStatusMessage + eol +
" Job ID: " + jobID + eol +
" Job State: " + jobState + eol +
" Stat Trackers:" + eol +
statStr;
}
/**
* Decodes the provided ASN.1 element as a status response message.
*
* @param messageID The message ID to use for this message.
* @param element The ASN.1 element containing the StatusResponse
* sequence.
*
* @return The status response message decoded from the ASN.1 element.
*
* @throws SLAMDException If the provided ASN.1 element cannot be decoded
* as a status response message.
*/
public static StatusResponseMessage decodeStatusResponse(int messageID,
ASN1Element element)
throws SLAMDException
{
ASN1Sequence responseSequence = null;
try
{
responseSequence = element.decodeAsSequence();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the provided ASN.1 element " +
"as a sequence", ae);
}
ASN1Element[] elements = responseSequence.getElements();
if ((elements.length != 3) && (elements.length != 4))
{
throw new SLAMDException("There must be either 3 or 4 elements in a " +
"status response");
}
int responseCode = 0;
try
{
responseCode = elements[0].decodeAsEnumerated().getIntValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the first element as an " +
"enumerated", ae);
}
int clientState = 0;
try
{
clientState = elements[0].decodeAsEnumerated().getIntValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the second element as an " +
"enumerated", ae);
}
String clientMessage = null;
try
{
clientMessage = elements[2].decodeAsOctetString().getStringValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the third element as an " +
"octet string", ae);
}
if (elements.length == 3)
{
return new StatusResponseMessage(messageID, responseCode,
clientState, clientMessage);
}
ASN1Sequence jobStatusSequence = null;
try
{
jobStatusSequence = elements[3].decodeAsSequence();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the fourth element as a " +
"sequence", ae);
}
elements = jobStatusSequence.getElements();
if (elements.length != 3)
{
throw new SLAMDException("There must be 3 elements in a job status " +
"sequence");
}
String jobID = null;
try
{
jobID = elements[0].decodeAsOctetString().getStringValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode first job status element " +
"as an octet string", ae);
}
int jobState =0;
try
{
jobState = elements[1].decodeAsEnumerated().getIntValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode second job status element " +
"as an enumerated", ae);
}
StatTracker[] statTrackers = null;
try
{
ASN1Sequence trackerSequence = elements[2].decodeAsSequence();
statTrackers = StatEncoder.sequenceToTrackers(trackerSequence);
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode third job status element " +
"as a sequence of stat trackers", ae);
}
return new StatusResponseMessage(messageID, responseCode, clientState,
clientMessage, jobID, jobState,
statTrackers);
}
/**
* Encodes this message into an ASN.1 element. A status response message has
* the following syntax:
* <BR><BR>
* <CODE>StatusResponse ::= [APPLICATION 9] SEQUENCE {</CODE>
* <CODE> responseCode ResponseCode,</CODE>
* <CODE> clientStatusCode ClientState,</CODE>
* <CODE> clientStatusMessage OCTET STRING,</CODE>
* <CODE> jobStatus JobStatus OPTIONAL }</CODE>
* <BR>
*
* @return An ASN.1 encoded representation of this message.
*/
@Override()
public ASN1Element encode()
{
ASN1Integer messageIDElement = new ASN1Integer(messageID);
ASN1Enumerated responseCodeElement = new ASN1Enumerated(responseCode);
ASN1Enumerated clientStateElement = new ASN1Enumerated(clientStatusCode);
ASN1OctetString clientMessageElement =
new ASN1OctetString(clientStatusMessage);
ASN1Element[] statusResponseElements;
if ((jobID == null) || (jobID.length() == 0))
{
statusResponseElements = new ASN1Element[]
{
responseCodeElement,
clientStateElement,
clientMessageElement
};
}
else
{
ASN1OctetString jobIDElement = new ASN1OctetString(jobID);
ASN1Enumerated jobStateElement = new ASN1Enumerated(jobState);
ASN1Sequence trackerSequence =
StatEncoder.trackersToSequence(statTrackers);
ASN1Element[] jobStatusElements = new ASN1Element[]
{
jobIDElement,
jobStateElement,
trackerSequence
};
ASN1Sequence jobStatusSequence = new ASN1Sequence(jobStatusElements);
statusResponseElements = new ASN1Element[]
{
responseCodeElement,
clientStateElement,
clientMessageElement,
jobStatusSequence
};
}
ASN1Sequence statusSequence =
new ASN1Sequence(ASN1_TYPE_STATUS_RESPONSE, statusResponseElements);
ASN1Element[] messageElements = new ASN1Element[]
{
messageIDElement,
statusSequence
};
return new ASN1Sequence(messageElements);
}
}