BASE has a simple system for sending signals between different parts of a system. This signalling system was initially developed to be able to kill plug-ins that a user for some reason wanted to abort. The signalling system as such is not limited to this and it can be used for other purposes as well. Signals can of course be handled internally in a single JVM but also sent externally to other JVM:s running on the same or a different computer. The transport mechanism for signals is decoupled from the actual handling of them. If you want to, you could implement a signal transporter that sends signal as emails and the target plug-in would never know.
The remainder of this section will focus mainly on the sending and transportation of signals. For more information about handling signals on the receiving end, see Section 26.7, “Enable support for aborting a running a plug-in”.
The signalling system is rather simple. An object that wish
to receieve signals must implement the
SignalTarget
getSignalHandler()
. A
SignalHandler
SignalHandler
itself
or use one of the existing handlers.
The difficult part here is to be aware that a signal is usually
delivered by a separate thread. The target object must be aware
of this and know how to handle multiple threads. As an example we
can use the ThreadSignalHandler
Thread.interrupt()
to deliver a signal. The target
object that uses this signal handler it must know that it should check
Thread.interrupted()
at regular intervals from the main
thread. If that method returns true, it means that the ABORT
signal has been delivered and the main thread should clean up and exit as
soon as possible.
Even if a signal handler could be given directly to the party
that may be interested in sending a signal to the target this
is not recommended. This would only work when sending signals
within the same virtual machine. The signalling system includes
SignalTransporter
SignalReceiver
SocketSignalTransporters
SocketSignalReceiver
Setting up the transport mechanism is usually a system responsibility.
Only the system know what kind of transport that is appropriate for it's current
setup. Ie. should signals be delievered by TCP/IP sockets, only internally, or
should a delivery mechanism based on web services be implemented?
If a system wants to receive signals it must create an appropriate
SignalReceiver
object. Within BASE the
internal job queue set up it's own signalling system that can be used to
send signals (eg. kill) running jobs. The job agents do the same but uses
a different implementation. See the section called “Internal job queue section”
for more information about how to configure the internal job queue's
signal receiver. In both cases, there is only one signal receiver instance
active in the system.
Let's take the internal job queue as an example. Here is how it works:
When the internal job queue is started, it will also create a signal
receiver instance according to the settings in base.config
.
The default is to create LocalSignalReceiver
SocketSignalReceiver
When the job queue has found a plug-in to execute it will check if
it also implements the SignalTarget
PluginExecutionRequest.registerSignalReceiver()
which also makes sure that the the ID returned from the registration is
stored in the database together with the job item representing the
plug-in to execute.
Now, when the web client see's a running job which has a non-empty
signal transporter property, the Abort
button is activated. If the user clicks this button the BASE core
uses the information in the database to create
SignalTransporter
Job.getSignalTransporter()
.
The created signal transporter knows how to send a signal
to the signal receiver it was first registered with. When the
signal arrives at the receiver it will find the handler for it
and call SignalHandler.handleSignal()
. This will in it's turn
trigger some action in the signal target which soon will abort what
it is doing and exit.