/*
* 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.protocol;
import java.util.ArrayList;
import java.util.HashMap;
import com.slamd.asn1.ASN1Boolean;
import com.slamd.asn1.ASN1Element;
import com.slamd.asn1.ASN1OctetString;
import com.slamd.asn1.ASN1Sequence;
import com.slamd.common.Constants;
import com.slamd.common.SLAMDException;
/**
* This class defines a SLAMD message that will be sent from the server to a
* client whenever the server is about to close that client connection. It can
* include a disconnect reason, an indication as to whether the disconnect is
* permanent or transient (e.g., if the server is being restarted and should be
* back up shortly), and can serve as an indication to the client that it needs
* to close its connection to the server in the very near future, optionally
* sending any job results first.
*
*
* @author Neil A. Wilson
*/
public class ServerDisconnect
extends SLAMDMessage
{
// Indicates whether the actual closure should be initiated by the client, so
// that it can potentially finish what it's doing and send any results to the
// server.
private boolean clientShouldClose;
// Indicates whether the disconnect is permanent or transient.
private boolean isTransient;
// The reason that the connection needs to be closed.
private String disconnectReason;
/**
* Creates a new instance of this server disconnect message which is intended
* for use in decoding a message transmitted between the server and the
* client. It is not intended for general use.
*/
public ServerDisconnect()
{
super();
disconnectReason = null;
isTransient = false;
clientShouldClose = false;
}
/**
* Creates a new instance of this server disconnect message with the provided
* information.
*
* @param messageID The message ID for this SLAMD message.
* @param extraProperties The "extra" properties for this SLAMD message.
* Both the names and values for the properties
* must be strings.
* @param disconnectReason The reason that the server has initiated the
* disconnect process.
* @param isTransient Indicates whether the disconnect is transient
* (meaning that the server connection should be
* available again shortly) or permanent.
* @param clientShouldClose Indicates whether the actual connection closure
* should be performed by the client, which may
* allow it time to send any results that it may
* have to the server.
*/
public ServerDisconnect(int messageID, HashMap<String,String> extraProperties,
String disconnectReason, boolean isTransient,
boolean clientShouldClose)
{
super(messageID, extraProperties);
this.disconnectReason = disconnectReason;
this.isTransient = isTransient;
this.clientShouldClose = clientShouldClose;
}
/**
* Retrieves the reason that the server has initiated the disconnect process.
*
* @return The reason that the server has initiated the disconnect process,
* or <CODE>null</CODE> if none was provided.
*/
public String getDisconnectReason()
{
return disconnectReason;
}
/**
* Specifies the reason that the server has initiated the disconnect process.
*
* @param disconnectReason The reason that the server has initiated the
* disconnect process.
*/
public void setDisconnectReason(String disconnectReason)
{
this.disconnectReason = disconnectReason;
}
/**
* Indicates whether the disconnect is transient (meaning that the server
* connection should be available again shortly, for example if the server is
* being restarted) or permanent. If the disconnect is transient, then the
* client may be able to re-establish the connection after a short delay.
*
* @return <CODE>true</CODE> if the disconnect is transient, or
* <CODE>false</CODE> if it is not.
*/
public boolean isTransient()
{
return isTransient;
}
/**
* Specifies whether the disconnect is transient.
*
* @param isTransient Specifies whether the disconnect is transient.
*/
public void setTransient(boolean isTransient)
{
this.isTransient = isTransient;
}
/**
* Indicates whether the actual disconnect should be initiated by the client.
* If this is the case, then the client may have a short period of time during
* which it may send any results that it may have to the server. If this
* returns <CODE>false</CODE>, then the client should assume that the server
* will immediately terminate the connection. If it returns
* <CODE>true</CODE>, then the server may still close the connection if the
* client does not do so in a sufficiently short period of time.
*
* @return <CODE>true</CODE> if the actual closure should be done by the
* client, or <CODE>false</CODE> if it will be done by the server.
*/
public boolean clientShouldClose()
{
return clientShouldClose;
}
/**
* Specifies whether the actual disconnect should be initiated by the client.
*
* @param clientShouldClose Specifies whether the actual disconnect should
* be initiated by the client.
*/
public void setClientShouldClose(boolean clientShouldClose)
{
this.clientShouldClose = clientShouldClose;
}
/**
* Encodes the payload component of this SLAMD message to an ASN.1 element for
* inclusion in the message envelope.
*
* @return The ASN.1 element containing the encoded message payload.
*/
@Override()
public ASN1Element encodeMessagePayload()
{
ArrayList<ASN1Element> elementList = new ArrayList<ASN1Element>();
if (disconnectReason != null)
{
elementList.add(encodeNameValuePair(
ProtocolConstants.PROPERTY_DISCONNECT_REASON,
new ASN1OctetString(disconnectReason)));
}
elementList.add(encodeNameValuePair(
ProtocolConstants.PROPERTY_DISCONNECT_IS_TRANSIENT,
new ASN1Boolean(isTransient)));
elementList.add(encodeNameValuePair(
ProtocolConstants.PROPERTY_CLIENT_SHOULD_CLOSE,
new ASN1Boolean(clientShouldClose)));
return new ASN1Sequence(elementList);
}
/**
* Decodes the provided ASN.1 element and uses it as the payload for this
* SLAMD message.
*
* @param payloadElement The ASN.1 element to decode as the payload for this
* SLAMD message.
*
* @throws SLAMDException If a problem occurs while attempting to decode the
* provided ASN.1 element as the payload for this
* SLAMD message.
*/
@Override()
public void decodeMessagePayload(ASN1Element payloadElement)
throws SLAMDException
{
HashMap<String,ASN1Element> propertyMap =
decodeNameValuePairSequence(payloadElement);
ASN1Element valueElement =
propertyMap.get(ProtocolConstants.PROPERTY_DISCONNECT_REASON);
if (valueElement != null)
{
try
{
disconnectReason = valueElement.decodeAsOctetString().getStringValue();
}
catch (Exception e)
{
throw new SLAMDException("Unable to decode the disconnect reason: " +
e, e);
}
}
valueElement =
propertyMap.get(ProtocolConstants.PROPERTY_DISCONNECT_IS_TRANSIENT);
if (valueElement != null)
{
try
{
isTransient = valueElement.decodeAsBoolean().getBooleanValue();
}
catch (Exception e)
{
throw new SLAMDException("Unable to decode the isTransient flag: " + e,
e);
}
}
valueElement =
propertyMap.get(ProtocolConstants.PROPERTY_CLIENT_SHOULD_CLOSE);
if (valueElement != null)
{
try
{
clientShouldClose = valueElement.decodeAsBoolean().getBooleanValue();
}
catch (Exception e)
{
throw new SLAMDException("Unable to decode the clientShouldClose " +
"flag: " + e, e);
}
}
}
/**
* Appends a string representation of the payload for this SLAMD message to
* the provided buffer. The string representation may contain multiple lines,
* but the last line should not end with an end-of-line marker.
*
* @param buffer The buffer to which the string representation is to be
* appended.
* @param indent The number of spaces to indent the payload content.
*/
@Override()
public void payloadToString(StringBuilder buffer, int indent)
{
StringBuilder indentBuf = new StringBuilder(indent);
for (int i=0; i < indent; i++)
{
indentBuf.append(' ');
}
if (disconnectReason != null)
{
buffer.append(indentBuf);
buffer.append("disconnectReason = ");
buffer.append(disconnectReason);
buffer.append(Constants.EOL);
}
buffer.append(indentBuf);
buffer.append("isTransient = ");
buffer.append(isTransient);
buffer.append(Constants.EOL);
buffer.append(indentBuf);
buffer.append("clientShouldClose = ");
buffer.append(clientShouldClose);
}
}