com.cosylab.jcosyne.server
Class RemoteTask

java.lang.Object
  extended byjavax.management.NotificationBroadcasterSupport
      extended bycom.cosylab.jcosyne.server.RemoteTask
All Implemented Interfaces:
javax.management.MBeanRegistration, javax.management.NotificationBroadcaster, javax.management.NotificationEmitter, RemoteTaskMBean, java.lang.Runnable
Direct Known Subclasses:
Executor, Factorization, LogCollector, ResultRepository, Sentinel

public abstract class RemoteTask
extends javax.management.NotificationBroadcasterSupport
implements RemoteTaskMBean, javax.management.MBeanRegistration

Remote Task is the base convenience class from which all remote tasks inherit. It canonically implements the RemoteTaskMBean. See documentation in that interface for design contract behavior. In addition, this implementation contains many convenience methods that allow quick development of new remote tasks. Features include:

  1. Logging is accessible through protected member called log. This is Java 1.4 logging. If you submit a log, it will be displayed on the console, but will, as a side effect, also cause the log notification to be emitted (and caught by log collector, which will record and forward it).
  2. Automatic issuing of sequence numbers for JMX notifications, use getSequence().
  3. Useful references are initialized and accessible: getName() returns the name of this remote task in ObjectName format, where "MBeans:type=" + getClass().getName() is the design prescription to form the name; serverRef contains the reference to the JMX server running this task.
  4. Call checkState() from the run() method periodically to check and respond to changes in running and suspended states. The method will block until resumed, or in case of forceful stop, will throw an exception that will break loops in run().
  5. Out-of-thread dispatching of attribute change notifications, so that they do not block the execution of the main algorithm. This is more optimal if the notifications are sent to notify about the progress while calculation is being run. Use notifyAttributeChange to schedule such a notification.
  6. Server callback is implemented here: pre- and post- registration / deregistration methods are implemented that release resources and keep track of important references. Override these methods to provide custom processing when the remote task is installed and deinstalled in the server, but be sure to call these parent implementations.
  7. Support for dispatching execution notifications through notifyExecutionStarts() and notifyExecutionStops(). The latter also invokes post-execution script and finally moves remote task into the Finished state.
  8. State capture. getState() will scan introspectively throgh all attributes of this and assemble attribute lists. Note that the framework will take snapshots at execution start and execution stop checkpoints automatically, when corresponding execution notifications are created by notifyExecution...() methods. Note that by default getState(true) will throw UnsupportedOperationException, signifying that this class does not know how to capture arbitrary internal data. Subclasses should override and provide for this functionality. getState(false), however, works by capturing all RW attributes.
  9. Convenience methods for getting input and output resources. See getInputResource() and getOutputResource(). This methods, on your behalf, contact the result repository, obtain appropriate filenames and return initialized streams that can be used immediately. By using these methods, the result repository automatically assmebles the list of all opened input and output files and will store it in remote task invocation entry.
  10. Support for canonical initialization procedure is coded in final void initialize(). This method starts the notification dispatcher, calls abstract internalInitialize() which you implement in your subclass, invokes post-initialization script and affects the state change.
  11. Support for attribute change notifications in notifyAttributeChange(). The method creates and dispatches events.
  12. State checking in checkState() should be called periodically by subclasses from their run() loops. This method will check if the computation needs to be interrupted (and will throw InterruptedException if so, which you catch and handle by gracefully ending the computation); or suspended, in which case the method will block on your behalf until the process is resumed again through the executor. Call checkState() from the point in your run() loop where intermediate results make best sense and will not be affected by accessing them through accessors.
  13. Progress attribute is a predefined attribute for tracking the progress of the calculation, and it expresses the completion in the range from 0 to 100. Use setProgress() to change the value and dispatch notifications. These can be used by GUI to track progress of the calculation.
  14. Support for BeanScripts, through the use of post-initialization, post-execution and custom scripts. Instances of this class invoke BeanScript interpreter at the correct phases in the lifecycle to evaluate the scripts. Remember that all scripts must implement RemoteTaskScript interface and must be written in BeanScript syntax. Custom script suspends execution immediately prior to the execution and resumes afterwards. It stores the result in LastScriptResult as per design contract.
  15. Convenience methods for saving and loading matrices, see saveMatrix() and loadMatrix().

Author:
Gasper Tkacik (gasper.tkacik@cosylab.com)
See Also:
RemoteTaskMBean

Field Summary
protected  java.util.logging.Logger log
          Logger that remote task can use to submit logs.
protected  javax.management.ObjectName name
          Contains the name of this remote task, calculated accoring to the prescription of RemoteTaskMBean.
protected  boolean running
          Running flag.
protected  long sequence
          Automatic sequence counting for notifications.
static javax.management.ObjectName SERVER_DELEGATE
          The name prescribed by JMX specification that denotes the JMX server.
protected  javax.management.MBeanServer serverRef
          Contains a reference to the collocated JMX server that is hosting this remote task.
protected  boolean suspended
          Suspended flag.
 
Constructor Summary
RemoteTask()
          Construct a new instance of remote task.
 
Method Summary
protected  void checkState()
          Checks the running and suspended flags.
 boolean copyStateFrom(javax.management.AttributeList state, javax.management.AttributeList internal)
          Throws exception.
 boolean copyStateFrom(RemoteTaskInvocation rti)
          Throws exception.
 java.lang.Object executeScript(java.lang.String script)
          Executes a script immediatelly.
 java.io.InputStream getInputResource(java.lang.String resourceName)
          Get input stream for a named input resource.
 java.lang.Object getLastScriptResult()
          Return the last script result executed with executeScript().
 javax.management.ObjectName getName()
          Returns the name under which this remote task is registered in the server.
 java.io.OutputStream getOutputResource(java.lang.String subspec)
          Get output stream for an output resource.
 java.lang.String getPostExecutionScript()
          Returns the post execution script.
 java.lang.String getPostInitializactionScript()
          Returns the post-initialization script.
 double getProgress()
          Returns the progress variable.
protected  long getSequence()
          Returns a new sequence number for the notification, internally increases sequence count.
 javax.management.AttributeList getState(boolean internal)
          Captures the state of this remote task.
 void initialize()
          A cannonical implementation of initialize.
protected abstract  void internalInitialize()
          Override this method to provide specific initialization for your remote algorithm.
 boolean isAborting()
          Returns true iff the task is currently aborting, that is, is being forcefully terminated.
 boolean isFinished()
          Returns the value of the Finished attribute.
 boolean isInitialized()
          Returns the value of the Initialized attribute.
 boolean isRunning()
          Returns the value of the Running attribute.
 boolean isSuspended()
          Returns the value of the Suspended attribute.
protected  double[][] loadMatrix(java.io.InputStream is)
          A convenience method for loading the matrix from an input stream.
protected  double[][] loadMatrix(java.lang.String input)
          A convenience method for loading matrix from a input resource.
protected  void notifyAttributeChange(java.lang.String name, java.lang.Object oldValue, java.lang.Object newValue)
          Call this method to inform listeners about the change in the attribute value.
protected  void notifyExecutionStarts()
          Sends execution start notification to all listeners.
protected  void notifyExecutionStops(java.lang.String message, int success)
          Sends stop execution notification to all listeners.
 void postDeregister()
          Releases resources.
 void postRegister(java.lang.Boolean arg0)
          NOP.
 void preDeregister()
          Releases resources and stops the notification dispatcher thread.
 javax.management.ObjectName preRegister(javax.management.MBeanServer arg0, javax.management.ObjectName arg1)
          Initializes the server reference and this object name.
protected  void saveMatrix(java.lang.String sub, double[][] data)
          A convenience method for saving matrix into the output file.
protected  void setFinished(boolean value)
          Call this method at the end of computation to switch to finished state.
 void setPostExecutionScript(java.lang.String postExecutionScript)
          Sets the post execution script.
 void setPostInitializationScript(java.lang.String postInitializationScript)
          Sets a script that implements RemoteTaskScript interface.
protected  void setProgress(double progress)
          Call this method from run() to update the variable and send notifications.
 void setRunning(boolean running)
          Invoked by the Executor.
 void setSuspended(boolean suspended)
          This method can only be called by the Executor.
 
Methods inherited from class javax.management.NotificationBroadcasterSupport
addNotificationListener, getNotificationInfo, handleNotification, removeNotificationListener, removeNotificationListener, sendNotification
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 
Methods inherited from interface com.cosylab.jcosyne.server.RemoteTaskMBean
equals, hashCode, isReadyToRun
 
Methods inherited from interface java.lang.Runnable
run
 

Field Detail

log

protected java.util.logging.Logger log
Logger that remote task can use to submit logs. The logs automatically become remote notifications collected by log collector remote task.


sequence

protected long sequence
Automatic sequence counting for notifications. Use getSequence() to get a unique sequence number, do not access this field directly.


name

protected javax.management.ObjectName name
Contains the name of this remote task, calculated accoring to the prescription of RemoteTaskMBean.


serverRef

protected javax.management.MBeanServer serverRef
Contains a reference to the collocated JMX server that is hosting this remote task.


running

protected boolean running
Running flag. Do not modify this by hand, since it is modified through the mutator method by the executor remote task. Call checkState() periodically from run() to detect running state change.


suspended

protected boolean suspended
Suspended flag. Do not modify this by hand, since it is modified through the mutator method by the executor remote task. Call checkState() periodically from run() to detect suspended state change.


SERVER_DELEGATE

public static javax.management.ObjectName SERVER_DELEGATE
The name prescribed by JMX specification that denotes the JMX server.

Constructor Detail

RemoteTask

public RemoteTask()
Construct a new instance of remote task. Initializes the logger. Because loggers are static, takes care to remove existing handlers and add a fresh one, so that multiple logs are not produced.

Method Detail

getSequence

protected long getSequence()
Returns a new sequence number for the notification, internally increases sequence count. This is NOT static (nor does it need to be, we only need sequence numbers to be unique within the scope of the source instance, as per JMX specs. You have to use this method manually only if you do not use the predefined methods starting with notify... to send notifications.

Returns:
a new sequence number to use in notifications

postDeregister

public void postDeregister()
Releases resources. If you override, be sure to call this parent.

Specified by:
postDeregister in interface javax.management.MBeanRegistration

postRegister

public void postRegister(java.lang.Boolean arg0)
NOP. You can override.

Specified by:
postRegister in interface javax.management.MBeanRegistration
Parameters:
arg0 - ignored

preDeregister

public void preDeregister()
                   throws java.lang.Exception
Releases resources and stops the notification dispatcher thread. If you override, be sure to call this parent.

Specified by:
preDeregister in interface javax.management.MBeanRegistration
Throws:
java.lang.Exception

preRegister

public javax.management.ObjectName preRegister(javax.management.MBeanServer arg0,
                                               javax.management.ObjectName arg1)
                                        throws java.lang.Exception
Initializes the server reference and this object name.

Specified by:
preRegister in interface javax.management.MBeanRegistration
Parameters:
arg0 - collocated server hosting this remote task
arg1 - the name under which this remote task is registered in the server
Returns:
the name supplied in arg1
Throws:
java.lang.Exception - not thrown

setRunning

public void setRunning(boolean running)
Invoked by the Executor. This method sets the new value of the running attribute and does state change notification. Wakes up all threads blocking on this object, if any, so that they can check the state again. Do not call this method by hand, rather call notifyExecutionStarts() or notifyExecutionStops().

Specified by:
setRunning in interface RemoteTaskMBean
Parameters:
running - the new value of Running attribute.

isRunning

public boolean isRunning()
Returns the value of the Running attribute.

Specified by:
isRunning in interface RemoteTaskMBean
Returns:
true if execution is in progress.
See Also:
RemoteTaskMBean.setRunning(boolean)

notifyExecutionStarts

protected void notifyExecutionStarts()
Sends execution start notification to all listeners. When this is received by the executor, it will add this task to the list of active tasks and will respond by setting Running attribute to true on this instance. Call this method when you start executing run()


notifyExecutionStops

protected void notifyExecutionStops(java.lang.String message,
                                    int success)
Sends stop execution notification to all listeners. When received by the executor, it will capture the final state, remove this task from the active task list. This method, before the notification is actually sent, invokes the post-execution script, if there is one (that means that you can, in the script, execute commands while formally still in the Running state). Goes into Finished state as a side-effect.

Parameters:
message - custom message string to put into the execution notification.
success - success flag that carried by stop execution notification

getName

public javax.management.ObjectName getName()
Returns the name under which this remote task is registered in the server. Returns a valid value as soon as the registration procedure has begun.

Specified by:
getName in interface RemoteTaskMBean
Returns:
the object name of this
See Also:
preRegister(javax.management.MBeanServer, javax.management.ObjectName)

getState

public javax.management.AttributeList getState(boolean internal)
Captures the state of this remote task. As per the design agreement with RemoteTaskMBean the state of a remote task is composed of the values of all RW attributes of the remote task. These (name, value) pairs are encapsulated into serializable instance of AttributeList and returned.

Specified by:
getState in interface RemoteTaskMBean
Parameters:
internal - if true throws UnsupportedOperationException; to support internal state transfer you must override this method and pack specific, algorithm dependent-data into the attribute list; if false this method does classic RW attribute capture
Returns:
a list of all RW attributes and their values
Throws:
java.lang.UnsupportedOperationException - if the internal data transfer is requested
See Also:
RemoteTaskMBean.copyStateFrom(AttributeList, AttributeList)

getInputResource

public java.io.InputStream getInputResource(java.lang.String resourceName)
Get input stream for a named input resource. This method uses the result repository to calculate the absolute input name from the relative name supplied as an argument, opens the input file and returns the input stream.

Parameters:
resourceName - the name of the input resource to open
Returns:
the input stream

getOutputResource

public java.io.OutputStream getOutputResource(java.lang.String subspec)
Get output stream for an output resource. This method uses the result repository to calculate the absolute output name from the name of this remote task and the (optional) subspecification, opens the new output file and returns the output stream.

Parameters:
subspec - identifier appended to the file name in case this task requests multiple output resources; if a single resource is needed, this can be null
Returns:
output stream; do not forget to close it when you finish writing

initialize

public final void initialize()
A cannonical implementation of initialize. If already initialized, this method simply returns; otherwise it creates a new notification dispatcher, which is automatically started, then calls abstract internalInitialize(), after which it invokes post-initialization script and performs state change (and notifications) into Initialized state.

Specified by:
initialize in interface RemoteTaskMBean

internalInitialize

protected abstract void internalInitialize()
Override this method to provide specific initialization for your remote algorithm. This is called automatically by canonical implementation of initialize()

See Also:
initialize()

notifyAttributeChange

protected void notifyAttributeChange(java.lang.String name,
                                     java.lang.Object oldValue,
                                     java.lang.Object newValue)
Call this method to inform listeners about the change in the attribute value. This method creates and dispatches appropriate AttributeChangeNotification out-of-thread.

Parameters:
name - the name of the attribute that has changed, watch out for proper capitalization (different than JavaBeans)
oldValue - old value, can be null
newValue - new value of the attribute

isInitialized

public boolean isInitialized()
Returns the value of the Initialized attribute.

Specified by:
isInitialized in interface RemoteTaskMBean
Returns:
true iff initialize() has completed successfully

isSuspended

public boolean isSuspended()
Returns the value of the Suspended attribute.

Specified by:
isSuspended in interface RemoteTaskMBean
Returns:
true iff the execution of this remote task has been suspended, because suspendRemoteTask() on Executor has been invoked for this task
See Also:
Executor

setSuspended

public void setSuspended(boolean suspended)
This method can only be called by the Executor. If you wish to suspend a task, obtain a reference to the executor and invoke suspendRemoteTask() on it. Notifies listeners about the state transition. Notifies all threads that they should check their state. Call checkState() periodically in your run() method to react to suspended state change and block execution if necessary.

Specified by:
setSuspended in interface RemoteTaskMBean
Parameters:
suspended - the new value of the suspended flag, determined by the Executor
See Also:
Executor.suspendRemoteTask(javax.management.ObjectName, boolean), checkState()

checkState

protected void checkState()
                   throws java.lang.InterruptedException
Checks the running and suspended flags. If it finds that the execution has been stopped, throws an exception to break from the run() loop. Subclasses should, in their run() methods catch this exception and hande it appropriately by gracefully terminating the calculation. If suspended flag is true, this method will block, until the suspended returns to false. Also sends resumed and suspended execution notifications as appropriate.

Throws:
java.lang.InterruptedException - if the computation has been stopped; catch and handle

copyStateFrom

public boolean copyStateFrom(javax.management.AttributeList state,
                             javax.management.AttributeList internal)
Throws exception. Override to implement.

Specified by:
copyStateFrom in interface RemoteTaskMBean
Parameters:
state - the collection of RW attributes
internal - arbitrary collection of data that is needed to replicate internal state in another instance of the same type of remote task
Returns:
true iff state transfer has been successful
Throws:
java.lang.UnsupportedOperationException - always thrown by this default implementation

copyStateFrom

public boolean copyStateFrom(RemoteTaskInvocation rti)
Throws exception. Override to implement.

Specified by:
copyStateFrom in interface RemoteTaskMBean
Parameters:
rti - task invocation data from the result repository, use to reconstruct the state
Returns:
true iff state transfer has been successful
Throws:
java.lang.UnsupportedOperationException - always thrown by this implementation

isFinished

public boolean isFinished()
Returns the value of the Finished attribute.

Specified by:
isFinished in interface RemoteTaskMBean
Returns:
true iff this task is in finished state, after the execution has stopped

setFinished

protected void setFinished(boolean value)
Call this method at the end of computation to switch to finished state. This method will dispatch notifications.

Parameters:
value - new value for the finished attribute

getProgress

public double getProgress()
Returns the progress variable.

Specified by:
getProgress in interface RemoteTaskMBean
Returns:
the value of the progress, from 0 to 100

setProgress

protected void setProgress(double progress)
Call this method from run() to update the variable and send notifications. This is used by GUI clients to track the progress of the computation.

Parameters:
progress - a value from 0 to 100 indicating progress

getPostExecutionScript

public java.lang.String getPostExecutionScript()
Returns the post execution script.

Specified by:
getPostExecutionScript in interface RemoteTaskMBean
Returns:
the actual script or null iff no script is used

setPostExecutionScript

public void setPostExecutionScript(java.lang.String postExecutionScript)
Sets the post execution script. The script must implement RemoteTaskScript interface.

Specified by:
setPostExecutionScript in interface RemoteTaskMBean
Parameters:
postExecutionScript - new BeanShell script or null
See Also:
RemoteTaskScript

getPostInitializactionScript

public java.lang.String getPostInitializactionScript()
Returns the post-initialization script.

Specified by:
getPostInitializactionScript in interface RemoteTaskMBean
Returns:
post initialization script or null iff no script is used
See Also:
initialize()

setPostInitializationScript

public void setPostInitializationScript(java.lang.String postInitializationScript)
Sets a script that implements RemoteTaskScript interface.

Specified by:
setPostInitializationScript in interface RemoteTaskMBean
Parameters:
postInitializationScript - script to invoke after initialization or null
See Also:
RemoteTaskScript

saveMatrix

protected void saveMatrix(java.lang.String sub,
                          double[][] data)
A convenience method for saving matrix into the output file.

Parameters:
sub - subspecification used when requesting the output resource, see getOutputResource()
data - the matrix to store
See Also:
getOutputResource(java.lang.String)

loadMatrix

protected double[][] loadMatrix(java.io.InputStream is)
A convenience method for loading the matrix from an input stream. The method figures the dimensions of the matrix dynamically. The items are separated by spaces or tabs, and the rows are separated by newline.

Parameters:
is - inputstream from which to read the matrix in text form
Returns:
the matrix

loadMatrix

protected double[][] loadMatrix(java.lang.String input)
A convenience method for loading matrix from a input resource.

Parameters:
input - the name of the input resource relative to the result repository input path
Returns:
loaded matrix

executeScript

public java.lang.Object executeScript(java.lang.String script)
Executes a script immediatelly. If, when this method is called, the computation is in progress, the computation is first suspended, then the script is executed, and then the computation resumes. This guarantees that the internal state of the task does not change during script execution. The result of the script is stored into LastScriptResult and attribute notifications are dispatched.

Specified by:
executeScript in interface RemoteTaskMBean
Parameters:
script - the script to execute, must implement RemoteTaskScript
Returns:
the result of the script
See Also:
RemoteTaskScript

getLastScriptResult

public java.lang.Object getLastScriptResult()
Return the last script result executed with executeScript().

Specified by:
getLastScriptResult in interface RemoteTaskMBean
Returns:
last script result or null iff no script has been executed

isAborting

public boolean isAborting()
Returns true iff the task is currently aborting, that is, is being forcefully terminated. If true, stop executing as quickly as possible, without saving the results and so on.

Returns:
aborting flag