org.rhq.enterprise.communications.command.client
Class ClientCommandSender

java.lang.Object
  extended by org.rhq.enterprise.communications.command.client.ClientCommandSender

public class ClientCommandSender
extends Object

A client that sends commands to a server. This is different than CommandClient implementations because it maintains a queue of outgoing command requests which allows it to emit them asynchronously when appropriate Requests can be sent synchronously or asynchronously.

You have to tell this class when it is allowed to send commands (see startSending() and when it should no longer be sending commands (see stopSending(boolean). You are still allowed to queue commands via sendAsynch(Command, CommandResponseCallback) even if this object was told to stop sending. The queue will simply grow until its full or until this object is told to start sending again. This starting and stopping allows you to cleanly switch the server that this object sends commands to - see setRemoteCommunicator(RemoteCommunicator). See ServerPollingThread as a helper thread that can be used to automatically start and stop this sender when the server comes up or goes down.

This sender object supports two different kinds of throttling - queue throttling and send throttling. The configuration defines the parameters for both - you can enable one, both or none. They work independently.

Queue throttling affects all commands sent asynchronously and only asynchronously. The queue where the asynchronous commands are placed can be throttled in such a way that only X commands can be taken from the queue in any T time period (called the 'burst period', specified in milliseconds). This means that if X+n commands are queued, only X will be dequeued and sent in the first burst period of T milliseconds. After that T millisecond burst period passes, the rest of the commands are dequeued and sent. Note that if n > X, then only the first X will be dequeued until the second burst period passes. The cycle continues until queue throttling is disabled or this sender is told to stop sending messages altogether.

Send throttling affects commands sent both asynchronously and synchronously. Unlike queue throttling, an individual command can be configured to ignore send throttling. That is to say, some commands can be sent immediately even if send throttling is enabled. Send throttling works by allowing X commands to be sent - once that limit of X commands is reached, a forced 'quiet period' begins, with that quiet period defined in milliseconds. No commands can be sent until the quiet time period expires. Once the quiet period ends, another X commands can be sent before another quiet period must start. The cycle continues until sent throttling is disabled or this sender is told to stop sending messages altogether.

Queue throttling and send throttling can be enabled simultaneously. Queue throttling occurs first, and then send throttling second. That is to say, a command to be sent must pass through the queue throttle first and then must pass the send throttle in order for the command to actually be sent.

Author:
John Mazzitelli

Field Summary
static String CMDCONFIG_PROP_GUARANTEED_DELIVERY
          This is the name of the command configuration property whose value (if it exists) defines if the command should be sent with guaranteed delivery.
static String CMDCONFIG_PROP_SEND_THROTTLE
          This is the name of the command configuration property whose value (if it exists) defines if the command should be sent with send-throttling enabled.
static String CMDCONFIG_PROP_TIMEOUT
          This is the name of the command configuration property whose value (if it exists) defines what timeout (in milliseconds) should be used when issuing commands.
 
Constructor Summary
ClientCommandSender(RemoteCommunicator remote_communicator, ClientCommandSenderConfiguration config)
          Constructor for ClientCommandSender.
ClientCommandSender(RemoteCommunicator remote_communicator, ClientCommandSenderConfiguration config, LinkedList<Runnable> previously_queued_tasks)
          Constructor for ClientCommandSender.
 
Method Summary
 void addPollingListener(PollingListener listener)
           
 void addStateListener(ClientCommandSenderStateListener listener, boolean immediately_notify)
          Adds the given listener to this sender object.
 void disableQueueThrottling()
          Disables the queue throttling such that this sender will dequeue commands as fast as possible.
 void disableSendThrottling()
          Disables the send throttling such that this sender will send commands as fast as possible.
 LinkedList<Runnable> drainQueuedCommands()
          This drains all commands from this sender's queue and returns them in the list.
 void enableQueueThrottling(long max_commands, long period_millis)
          Turns on queue throttling and sets the queue throttling parameters such that commands are dequeued in bursts with pauses in between.
 void enableSendThrottling(long max_commands, long quiet_period_duration)
          Turns on send throttling and sets the send throttling parameters such that the given maximum number of commands are sent before a quiet period of the given time duration must pass without any commands being sent.
 CommandResponse executePostSendCallbacks(Command command, CommandResponse response)
          Execute the post-send callbacks for the given command if this sender was configured with one or more send callbacks.
 void executePreSendCallbacks(Command command)
          Execute the pre-send callbacks for the given command if this sender was configured with one or more send callbacks.
 ClientRemotePojoFactory getClientRemotePojoFactory()
          Returns the object that can be used to create remote POJO proxies which allows you to make remote calls to the POJOs that are remoted.
 CommandPreprocessor[] getCommandPreprocessors()
          Returns the list of command preprocessors that are currently assigned to this sender.
 ClientCommandSenderConfiguration getConfiguration()
          Provides a copy of this sender's configuration - because it is a copy, changes made to the returned object have no effect on this sender's behavior.
 ClientCommandSenderMetrics getMetrics()
          Returns the metrics that have currently been collected (e.g.
 RemoteCommunicator getRemoteCommunicator()
          Returns the communicator object that actually sends the commands to the remote endpoint.
 SendCallback[] getSendCallbacks()
          Returns the list of SendCallbacks that are currently assigned to this sender.
 boolean isSending()
          Returns the flag to indicate if this sender object has been enabled to send commands.
 boolean isServerPolling()
           
 void preprocessCommand(Command command)
          Preprocesses the given command if this sender was configured with one or more command preprocessors.
 void removePollingListener(PollingListener listener)
           
 void removeStateListener(ClientCommandSenderStateListener listener)
          Removes the given listener to this sender object.
 void sendAsynch(Command command, CommandResponseCallback callback)
          Sends the command asynchronously.
 void sendAsynchGuaranteed(Command command, CommandResponseCallback callback)
          Sends the command asynchronously with guaranteed delivery enabled.
 CommandResponse sendSynch(Command command)
          Sends the command synchronously.
 void setCommandPreprocessors(CommandPreprocessor[] preprocs)
          This method sets the list of preprocessor objects this sender will use - these are the preprocessors that will have an opportunity to manipulate a command prior to it being queued and sent.
 void setRemoteCommunicator(RemoteCommunicator remote_communicator)
          Sets the information about the server to which all commands are sent.
 void setSendCallbacks(SendCallback[] sendCallbacks)
          This method sets the list of SendCallback objects this sender will use - these are the objects that will have an opportunity to execute just prior and just after the command is sent.
 boolean startSending()
          This starts to send commands that are found in the queue and allows commands to be synchronously sent via send(Command).
 void startServerPolling()
          If configured to do so, this will start server polling by periodically sending requests to the server to ensure that it is online.
 boolean stopSending(boolean process_currently_queued_commands)
          This stops all sending, both synchronous and asynchronous.
 void stopServerPolling()
          Stops this object from polling the server.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

CMDCONFIG_PROP_TIMEOUT

public static final String CMDCONFIG_PROP_TIMEOUT
This is the name of the command configuration property whose value (if it exists) defines what timeout (in milliseconds) should be used when issuing commands. If this timeout is exceeded before the command response is received, the command is aborted.

See Also:
Constant Field Values

CMDCONFIG_PROP_GUARANTEED_DELIVERY

public static final String CMDCONFIG_PROP_GUARANTEED_DELIVERY
This is the name of the command configuration property whose value (if it exists) defines if the command should be sent with guaranteed delivery. If the property is true, the command will be guaranteed to be delivered. The default is false.

See Also:
Constant Field Values

CMDCONFIG_PROP_SEND_THROTTLE

public static final String CMDCONFIG_PROP_SEND_THROTTLE
This is the name of the command configuration property whose value (if it exists) defines if the command should be sent with send-throttling enabled. That is to say, if the command sender has send-throttling enabled, this command should be throttled when the sender deems it appropriate. If this configuration is not defined, it is assumed false (that is, this command will be sent as soon as possible and ignoring any send throttling that may be enabled). This setting should be used when a command is usually sent in large amounts and may, if not kept in check, overload the server or cause starvation of other agents from the server.

See Also:
Constant Field Values
Constructor Detail

ClientCommandSender

public ClientCommandSender(RemoteCommunicator remote_communicator,
                           ClientCommandSenderConfiguration config)
                    throws IllegalArgumentException
Constructor for ClientCommandSender. Note that if the configuration's queue size is less than or equal to 0, the queue will be unbounded - be careful since this means there will be no way to stop resources from being used up if commands keep getting queued but nothing is getting sent.

The object will not be sending commands yet - you must explicitly call startSending() to get this object to begin to start sending commands.

Parameters:
remote_communicator - defines what server all commands will be sent to
config - the initial configuration of this object
Throws:
IllegalArgumentException - if the given remote communicator or config is null

ClientCommandSender

public ClientCommandSender(RemoteCommunicator remote_communicator,
                           ClientCommandSenderConfiguration config,
                           LinkedList<Runnable> previously_queued_tasks)
                    throws IllegalArgumentException
Constructor for ClientCommandSender. Note that if the configuration's queue size is less than or equal to 0, the queue will be unbounded - be careful since this means there will be no way to stop resources from being used up if commands keep getting queued but nothing is getting sent.

The object will not be sending commands yet - you must explicitly call startSending() to get this object to begin to start sending commands.

This constructor allows you to reconstitute the queue with a set of previously queued tasks from an old sender - see drainQueuedCommands().

Parameters:
remote_communicator - defines what server all commands will be sent to
config - the initial configuration of this object
previously_queued_tasks - if not null, a list of previously queued tasks that we should bulk queue now in order to attempt to send them as soon as this sender starts
Throws:
IllegalArgumentException - if the given remote communicator or config is null
Method Detail

getConfiguration

public ClientCommandSenderConfiguration getConfiguration()
Provides a copy of this sender's configuration - because it is a copy, changes made to the returned object have no effect on this sender's behavior.

Returns:
a copy of this sender's configuration

getRemoteCommunicator

public RemoteCommunicator getRemoteCommunicator()
Returns the communicator object that actually sends the commands to the remote endpoint.

Returns:
remote communicator that defines the remote endpoint where the commands will be sent

getMetrics

public ClientCommandSenderMetrics getMetrics()
Returns the metrics that have currently been collected (e.g. the number of commands this sender has sent).

Returns:
this sender's metric data

setRemoteCommunicator

public void setRemoteCommunicator(RemoteCommunicator remote_communicator)
                           throws IllegalArgumentException
Sets the information about the server to which all commands are sent. You can set this to immediately switch which server will get sent the commands (that is, you don't have to be stopped in order to switch).

Parameters:
remote_communicator - information on the new server
Throws:
IllegalArgumentException - if the given remote communicator is null

getCommandPreprocessors

public CommandPreprocessor[] getCommandPreprocessors()
Returns the list of command preprocessors that are currently assigned to this sender. These are the objects that manipulate the command prior to being queued and sent.

Returns:
the list of command preprocessors (will never be null)

setCommandPreprocessors

public void setCommandPreprocessors(CommandPreprocessor[] preprocs)
This method sets the list of preprocessor objects this sender will use - these are the preprocessors that will have an opportunity to manipulate a command prior to it being queued and sent. If null is passed in, or the list has a size of 0, then this sender will not preprocess commands that it sends.

Parameters:
preprocs - the objects that will be handed all commands that are to be sent by this sender for preprocessing (may be null or empty)

getSendCallbacks

public SendCallback[] getSendCallbacks()
Returns the list of SendCallbacks that are currently assigned to this sender. These objects are called just before and just after the send.

Returns:
the list of SendCallbacks (will never be null)

setSendCallbacks

public void setSendCallbacks(SendCallback[] sendCallbacks)
This method sets the list of SendCallback objects this sender will use - these are the objects that will have an opportunity to execute just prior and just after the command is sent. If null is passed in, or the list has a size of 0, then this sender will not execute SendCcallbacks on the commands that it sends. The sendCallbacks are executed in the order supplied in the array.

Parameters:
callbacks - the objects that will be called pre/post all commands that are to sent by this sender (may be null or empty)

addStateListener

public void addStateListener(ClientCommandSenderStateListener listener,
                             boolean immediately_notify)
Adds the given listener to this sender object. When the sender starts sending or stops sending, this listener will be notified. If the listener already exists in the list of known listeners (i.e. it has been added before), a duplicate will not be added; however, if immediately_notify is true, it will be notified now.

Parameters:
listener -
immediately_notify - if true, the listener will be immediately notified of the current state of the sender; if false, the listener will next be notified when the state changes next

removeStateListener

public void removeStateListener(ClientCommandSenderStateListener listener)
Removes the given listener to this sender object. When the sender starts sending or stops sending, this listener will no longer be notified.

Parameters:
listener -

sendAsynchGuaranteed

public void sendAsynchGuaranteed(Command command,
                                 CommandResponseCallback callback)
                          throws Exception
Sends the command asynchronously with guaranteed delivery enabled.

The caller is not guaranteed when the command is sent or in what order from previously queue commands.

Parameters:
command - the command to queue and send asynchronously
callback - the callback object to be notified when the command has been sent and executed on the server
Throws:
Exception - if failed to queue the command

sendAsynch

public void sendAsynch(Command command,
                       CommandResponseCallback callback)
                throws Exception
Sends the command asynchronously. This will essentially queue the command and return. If callback is not null, that callback will be notified when the command has completed and will be told the results of the command execution.

The caller can configure the command for guaranteed delivery.

The caller is not guaranteed when the command is sent or in what order from previously queue commands.

Parameters:
command - the command to queue and send asynchronously
callback - the callback object to be notified when the command has been sent and executed on the server
Throws:
Exception - if failed to queue the command

sendSynch

public CommandResponse sendSynch(Command command)
                          throws Exception
Sends the command synchronously. The results of the command are returned. This method blocks until the command has been sent, executed on the server and the results sent back.

An exception might be thrown if the client could not send the command. Errors that occur on the server during execution of the command generally are returned in the response object. Exceptions thrown by this method are usually the result of rare low-level communications problems or a problem exists with the command such that it cannot be sent. Callers of this method should always check the returned CommandResponse.isSuccessful() flag to see if the command was actually successfully processed.

Parameters:
command - the command to send
Returns:
the response of the command as returned by the server
Throws:
Exception - if failed to send the command
IllegalStateException - if this sender object has not been told to start sending commands

getClientRemotePojoFactory

public ClientRemotePojoFactory getClientRemotePojoFactory()
Returns the object that can be used to create remote POJO proxies which allows you to make remote calls to the POJOs that are remoted. The caller is free to change the returned factory's asynchronous mode by calling ClientRemotePojoFactory.setAsynch(boolean, CommandResponseCallback).

Returns:
remote POJO factory

enableQueueThrottling

public void enableQueueThrottling(long max_commands,
                                  long period_millis)
Turns on queue throttling and sets the queue throttling parameters such that commands are dequeued in bursts with pauses in between.

Parameters:
max_commands - the maximum number of commands that are allowed to be sent in a single burst
period_millis - the time period in milliseconds that must pass before another burst of commands can be sent

disableQueueThrottling

public void disableQueueThrottling()
Disables the queue throttling such that this sender will dequeue commands as fast as possible.


enableSendThrottling

public void enableSendThrottling(long max_commands,
                                 long quiet_period_duration)
Turns on send throttling and sets the send throttling parameters such that the given maximum number of commands are sent before a quiet period of the given time duration must pass without any commands being sent. If send throttling was already enabled, this changes the send throttling parameters - those changes will take effect as soon as possible (for example, if send throttle is already in its quiet period, the old quiet period duration remains in effect; the new quiet period duration takes effect the next quiet period that occurs).

Parameters:
max_commands - the maximum number of commands that can be sent before a quiet period must start
quiet_period_duration - the length of time of the quiet period when no commands can be sent (unless the command is configured to allow itself to be sent regardless of the send throttling)

disableSendThrottling

public void disableSendThrottling()
Disables the send throttling such that this sender will send commands as fast as possible.


startServerPolling

public void startServerPolling()
If configured to do so, this will start server polling by periodically sending requests to the server to ensure that it is online. The interval between polls is defined by the configuration passed into this object's constructor. If the interval was 0 or less, this method does nothing and simply returns immediatly.

See Also:
stopServerPolling()

stopServerPolling

public void stopServerPolling()
Stops this object from polling the server. If server polling wasn't started, this method does nothing.


isServerPolling

public boolean isServerPolling()

addPollingListener

public void addPollingListener(PollingListener listener)

removePollingListener

public void removePollingListener(PollingListener listener)

startSending

public boolean startSending()
This starts to send commands that are found in the queue and allows commands to be synchronously sent via send(Command). Commands are placed in the queue by sendAsynch(Command, CommandResponseCallback) . This method also puts commands on the queue that it finds in the persistence command store (for those commands that failed but need to be delivered).

If this client was not already sending, this method returns true to indicate the client's mode has changed from stopped to started.

If this client is already sending, this method does nothing and returns false to indicate the mode hasn't changed - it is still in the sending mode.

Returns:
true if this client was not sending prior to this method being called (and hence this client changed modes); false if this client was already sending and thus this method ended up being a no-op

stopSending

public boolean stopSending(boolean process_currently_queued_commands)
This stops all sending, both synchronous and asynchronous. Asynchronous commands are still allowed to be queued up, they just won't be sent. If processCurrentlyQueuedCommands is false, then any current commands in the queue will be dequeued - guaranteed commands will be persisted; if and when startSending() is called, they will be re-queued (if the VM dies in the meantime, only the guaranteed commands will be preserved upon the restart). Any commands currently being executed will be interrupted and, if they do not require guaranteed delivery, will be lost. If processCurrentlyQueuedCommands is true, then all commands in the queue will be processed - once the queue is empty and all commands sent, this method will return.

If this client was not already stopped, this method returns true to indicate the client's mode has changed from started to stopped.

If this client is already stopped, this method does nothing and returns false to indicate the mode hasn't changed - it is still in the stopped mode.

This method will not return until the the executor thread pool has completely shutdown.

Parameters:
process_currently_queued_commands - if true, this will block and wait for all current commands in the queue to be sent before returning
Returns:
true if this client was sending prior to this method being called (and hence this client changed modes); false if this client was not already sending and thus this method ended up being a no-op

isSending

public boolean isSending()
Returns the flag to indicate if this sender object has been enabled to send commands. If false, this object can still queue up commands, it just won't send them.

Returns:
true if this sender is enabled to send commands; false if this sender will not send commands

drainQueuedCommands

public LinkedList<Runnable> drainQueuedCommands()
This drains all commands from this sender's queue and returns them in the list. The items in the list are opaque objects. The purpose of this method is to be able to reconstitute the queue in a new sender object by taking the returned list and passing to the appropriate constructor when building the new sender. Typically you only call this when the sender is stopped, but that isn't a hard requirement. If you do call this while this sender is not sending, only volatile commands (i.e. non-guaranteed) will be in the returned list. If this sender is not stopped, there may be guaranteed commands in the returned list.

Returns:
list of commands that are still queued waiting to be sent (null if we couldn't get them)

preprocessCommand

public void preprocessCommand(Command command)
Preprocesses the given command if this sender was configured with one or more command preprocessors.

Parameters:
command - the command to preprocess

executePreSendCallbacks

public void executePreSendCallbacks(Command command)
Execute the pre-send callbacks for the given command if this sender was configured with one or more send callbacks.

Parameters:
command - the command

executePostSendCallbacks

public CommandResponse executePostSendCallbacks(Command command,
                                                CommandResponse response)
Execute the post-send callbacks for the given command if this sender was configured with one or more send callbacks.

Parameters:
command - the command


Copyright © 2008-2012 Red Hat, Inc.. All Rights Reserved.