/*
* 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 java.text.SimpleDateFormat;
import java.util.Date;
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;
import com.slamd.parameter.Parameter;
import com.slamd.parameter.ParameterList;
/**
* This class defines a message that is used by the server to submit a job
* request to a client.
*
*
* @author Neil A. Wilson
*/
public class JobRequestMessage
extends Message
{
// The length of time in seconds to use as the statistics collection interval.
private final int collectionInterval;
// The maximum length of time in seconds that this job should be allowed to
// run.
private final int duration;
// The client number associated with this job request message.
private final int clientNumber;
// The number of threads that each client should create to execute this job.
private final int threadsPerClient;
// The length of time in milliseconds that each client should wait between
// starting each thread.
private final int threadStartupDelay;
// The time at which the job processing should begin (in number of seconds
// since January 1, 1970).
private final long startTime;
// The time at which the job processing should end (in number of seconds
// since January 1, 1970).
private final long stopTime;
// The list of parameters that can be used to customize the way that the job
// works.
private final ParameterList parameters;
// The Java class name that should be invoked to actually run the job.
private final String jobClass;
// The job ID for the job to be run.
private final String jobID;
/**
* Creates a new job request message with the specified information.
*
* @param messageID The message ID for this message.
* @param jobID The job ID of the job to be executed.
* @param jobClass The name of the Java class that is a subclass
* of com.slamd.job.JobClass that can be
* executed to perform the work of this job.
* @param startTime The time (as a Java Date) at which the job
* should be started.
* @param stopTime The time (as a Java Date) at which the job
* should be stopped if it is still running.
* @param clientNumber The client number assigned to the client for
* this job request.
* @param duration The maximum length of time in seconds that the
* job should be allowed to run.
* @param threadsPerClient The number of threads that each client should
* start to run the job.
* @param threadStartupDelay The delay in milliseconds that should be used
* between starting each thread on the client.
* @param collectionInterval The length of time in seconds to use as the
* statistics collection interval.
* @param parameters The list of parameters that can customize the
* way that the job works.
*/
public JobRequestMessage(int messageID, String jobID, String jobClass,
Date startTime, Date stopTime, int clientNumber,
int duration, int threadsPerClient,
int threadStartupDelay, int collectionInterval,
ParameterList parameters)
{
this(messageID, jobID, jobClass, startTime.getTime(),
((stopTime == null) ? 0 : stopTime.getTime()), clientNumber, duration,
threadsPerClient, threadStartupDelay, collectionInterval, parameters);
}
/**
* Creates a new job request message with the specified information.
*
* @param messageID The message ID for this message.
* @param jobID The job ID of the job to be executed.
* @param jobClass The name of the Java class that is a subclass
* of com.slamd.job.JobClass that can be
* executed to perform the work of this job.
* @param startTime The time (as a Java Date) at which the job
* should be started.
* @param stopTime The time (as a Java Date) at which the job
* should be stopped if it is still running.
* @param clientNumber The client number associated with this job
* request message.
* @param duration The maximum length of time in seconds that the
* job should be allowed to run.
* @param threadsPerClient The number of threads that each client should
* start to run the job.
* @param threadStartupDelay The delay in milliseconds that should be used
* between starting each thread on the client.
* @param collectionInterval The length of time in seconds to use as the
* statistics collection interval.
* @param parameters The list of parameters that can customize the
* way that the job works.
*/
public JobRequestMessage(int messageID, String jobID, String jobClass,
long startTime, long stopTime, int clientNumber,
int duration, int threadsPerClient,
int threadStartupDelay, int collectionInterval,
ParameterList parameters)
{
super(messageID, Constants.MESSAGE_TYPE_JOB_REQUEST);
this.jobID = jobID;
this.jobClass = jobClass;
this.startTime = startTime;
this.stopTime = stopTime;
this.clientNumber = clientNumber;
this.duration = duration;
this.threadsPerClient = threadsPerClient;
this.threadStartupDelay = threadStartupDelay;
this.collectionInterval = collectionInterval;
this.parameters = parameters;
}
/**
* Retrieves the job ID associated with this job request.
*
* @return The job ID associated with this job request.
*/
public String getJobID()
{
return jobID;
}
/**
* Retrieves the name of the Java class that should be executed for this job.
*
* @return The name of the Java class that should be executed for this job.
*/
public String getJobClass()
{
return jobClass;
}
/**
* Retrieves the time at which the job should start running.
*
* @return The time at which the job should stop running.
*/
public Date getStartTime()
{
if (startTime > 0)
{
return new Date(startTime);
}
else
{
return null;
}
}
/**
* Retrieves the time at which the job should stop running if it has not
* already completed.
*
* @return The time at which the job should stop running if it has not
* already completed.
*/
public Date getStopTime()
{
if (stopTime > 0)
{
return new Date(stopTime);
}
else
{
return null;
}
}
/**
* Retrieves the client number associated with this job request message.
*
* @return The client number associated with this job request message.
*/
public int getClientNumber()
{
return clientNumber;
}
/**
* Retrieves the maximum length of time in seconds that the job should be
* allowed to run.
*
* @return The maximum length of time in seconds that the job should be
* allowed to run.
*/
public int getDuration()
{
return duration;
}
/**
* Retrieves the number of threads that the client should create to execute
* this job.
*
* @return The number of threads that the client should create to execute
* this job.
*/
public int getThreadsPerClient()
{
return threadsPerClient;
}
/**
* Retrieves the number of milliseconds that a client should wait between
* starting each thread.
*
* @return The number of milliseconds that a client should wait between
* starting each thread.
*/
public int getThreadStartupDelay()
{
return threadStartupDelay;
}
/**
* Retrieves the length of time in seconds that should be used as the
* statistics collection interval.
*
* @return The length of time in seconds that should be used as the
* statistics collection interval.
*/
public int getCollectionInterval()
{
return collectionInterval;
}
/**
* Retrieves the list of parameters that should be used to customize the way
* the job operates.
*
* @return The list of parameters that should be used to customize the way
* the job operates.
*/
public ParameterList getParameters()
{
return parameters;
}
/**
* Retrieves a string representation of this message.
*
* @return A string representation of this message.
*/
@Override()
public String toString()
{
String eol = System.getProperty("line.separator");
SimpleDateFormat dateFormat =
new SimpleDateFormat(Constants.DISPLAY_DATE_FORMAT);
String startTimeStr = dateFormat.format(new Date(startTime));
String stopTimeStr = "<not defined>";
if (stopTime > 0)
{
stopTimeStr = dateFormat.format(new Date(stopTime));
}
String paramStr = "";
Parameter[] params = parameters.getParameters();
for (int i=0; i < params.length; i++)
{
paramStr += " " + params[i].toString() + eol;
}
return "Job Request Message" + eol +
" Message ID: " + messageID + eol +
" Job ID: " + jobID + eol +
" Job Class: " + jobClass + eol +
" Threads per Client: " + threadsPerClient + eol +
" Thread Startup Delay: " + threadStartupDelay + eol +
" Start Time: " + startTimeStr + eol +
" Stop Time: " + stopTimeStr + eol +
" Client Number: " + clientNumber + eol +
" Duration: " + duration + eol +
" Collection Interval: " + collectionInterval + eol +
" Job-Specific Parameters:" + eol +
paramStr;
}
/**
* Decodes the provided ASN.1 element as a job request message.
*
* @param messageID The message ID to use for this message.
* @param element The ASN.1 element containing the JobRequest sequence.
*
* @return The job request decoded from the ASN.1 element.
*
* @throws SLAMDException If the provided ASN.1 element cannot be decoded
* as a job request message.
*/
public static JobRequestMessage decodeJobRequest(int messageID,
ASN1Element element)
throws SLAMDException
{
ASN1Sequence requestSequence = null;
try
{
requestSequence = element.decodeAsSequence();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("The ASN.1 element cannot be decoded as a " +
"sequence", ae);
}
ASN1Element[] elements = requestSequence.getElements();
if (elements.length != 10)
{
throw new SLAMDException("There must be ten elements in a job " +
"request sequence -- I counted " +
elements.length);
}
String jobID = null;
try
{
jobID = elements[0].decodeAsOctetString().getStringValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the first element as an " +
"octet string", ae);
}
String jobClass = null;
try
{
jobClass = elements[1].decodeAsOctetString().getStringValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the second element as an " +
"octet string", ae);
}
long startTime = 0;
try
{
String startTimeStr = elements[2].decodeAsOctetString().getStringValue();
try
{
startTime = Long.parseLong(startTimeStr);
}
catch (NumberFormatException nfe)
{
throw new SLAMDException("Could not decode " + startTimeStr +
" as a long", nfe);
}
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the third element as an " +
"octet string", ae);
}
long stopTime = 0;
try
{
String stopTimeStr = elements[3].decodeAsOctetString().getStringValue();
try
{
stopTime = Long.parseLong(stopTimeStr);
}
catch (NumberFormatException nfe)
{
throw new SLAMDException("Could not decode " + stopTimeStr +
" as a long", nfe);
}
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the fourth element as an " +
"octet string", ae);
}
int clientNumber = -1;
try
{
clientNumber = elements[4].decodeAsInteger().getIntValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the fifth element as an " +
"integer", ae);
}
int duration = 0;
try
{
duration = elements[5].decodeAsInteger().getIntValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the sixth element as an " +
"integer", ae);
}
int threadsPerClient = 0;
try
{
threadsPerClient = elements[6].decodeAsInteger().getIntValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the seventh element as an " +
"integer", ae);
}
int threadStartupDelay = 0;
try
{
threadStartupDelay = elements[7].decodeAsInteger().getIntValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the eighth element as an " +
"integer", ae);
}
int collectionInterval = 0;
try
{
collectionInterval = elements[8].decodeAsInteger().getIntValue();
}
catch (ASN1Exception ae)
{
throw new SLAMDException("Could not decode the ninth element as an " +
"integer", ae);
}
ParameterList parameters = ParameterList.decode(elements[9]);
return new JobRequestMessage(messageID, jobID, jobClass, startTime,
stopTime, clientNumber, duration,
threadsPerClient, threadStartupDelay,
collectionInterval, parameters);
}
/**
* Encodes this message into an ASN.1 element. A job request message has
* the following syntax:
* <BR><BR>
* <CODE>JobRequest ::= [APPLICATION 3] SEQUENCE {</CODE>
* <CODE> jobID OCTET STRING,</CODE>
* <CODE> jobClass OCTET STRING,</CODE>
* <CODE> startTime OCTET STRING,</CODE>
* <CODE> stopTime OCTET STRING,</CODE>
* <CODE> clientNumber INTEGER,</CODE>
* <CODE> duration INTEGER,</CODE>
* <CODE> threadsPerClient INTEGER,</CODE>
* <CODE> threadStartupDelay INTEGER,</CODE>
* <CODE> collectionInterval INTEGER,</CODE>
* <CODE> parameters Parameters }</CODE>
* <BR>
*
* @return An ASN.1 encoded representation of this message.
*/
@Override()
public ASN1Element encode()
{
ASN1Integer messageIDElement = new ASN1Integer(messageID);
ASN1OctetString jobIDElement = new ASN1OctetString(jobID);
ASN1OctetString jobClassElement = new ASN1OctetString(jobClass);
ASN1OctetString startTimeElement =
new ASN1OctetString(String.valueOf(startTime));
ASN1OctetString stopTimeElement =
new ASN1OctetString(String.valueOf(stopTime));
ASN1Integer clientNumberElement = new ASN1Integer(clientNumber);
ASN1Integer durationElement = new ASN1Integer(duration);
ASN1Integer threadsElement = new ASN1Integer(threadsPerClient);
ASN1Integer delayElement = new ASN1Integer(threadStartupDelay);
ASN1Integer collectionIntervalElement = new ASN1Integer(collectionInterval);
ASN1Element parametersElement = parameters.encode();
ASN1Element[] jobRequestElements = new ASN1Element[]
{
jobIDElement,
jobClassElement,
startTimeElement,
stopTimeElement,
clientNumberElement,
durationElement,
threadsElement,
delayElement,
collectionIntervalElement,
parametersElement
};
ASN1Sequence jobRequestSequence =
new ASN1Sequence(ASN1_TYPE_JOB_REQUEST, jobRequestElements);
ASN1Element[] messageElements = new ASN1Element[]
{
messageIDElement,
jobRequestSequence
};
return new ASN1Sequence(messageElements);
}
}