SK.gnome.dwarf.thread
Class MultiThreadServer

java.lang.Object
  extended bySK.gnome.dwarf.GenericService
      extended bySK.gnome.dwarf.GenericServer
          extended bySK.gnome.dwarf.thread.ThreadServer
              extended bySK.gnome.dwarf.thread.MultiThreadServer
All Implemented Interfaces:
Reportable, java.lang.Runnable, Server, Service
Direct Known Subclasses:
TCPIPServer

public class MultiThreadServer
extends ThreadServer

Generic multi-threaded server.

This class implements an universal multi-threaded server. It works in cooperation with the Handler class. By developing a custom handlers and adding the handler instances to the MultiThreadServer you can easily create a powerful multi-threaded server with a very little effort.

Handler instances are added to the server automatically by setting the full class name of the handler via the setHandlerClass(Class) method. Furthemore, it is the only way how to add a handler to the server, because it cannot be added in any other way.

The general operational cycle of the server is as follows:

Each client request is represented by an instance of the basic java.lang.Object class. In order to process the request by the server, it must be added to the server's queue via the enqueue(Object) method. This method also causes the contained handlers to be notified that a request is waiting for the processing. The enqueued object is then picked up from the queue by one of the notified handlers via the server's dequeue(int) method. The handler processes the request and then returns it back to the server via its finish(Object) method. Thus server knows that the handling of the particular client request is finished.

The setMinHandlers(int) and setMaxHandlers(int) methods customize the dymanic behavior of the server. When the server is started, the minHandlers number of the handlers are started only, and only that number of threads will be up and running. If the server decides that there are more client requests than the available idle handlers, it tries to start a new handler, up to the maxHandlers number. If the handler is idle for a specified amount of time (see the setHandlerTimeout(int) method), and there is no request waiting in the server's queue at all, it may stop itself and wait to be started by the server again. This feature allows to dynamically adjust the total number of the active handler threads, thus saving the system resources.

The setSingleRequest(boolean) method may be used to prevent simultaneous handling of multiple request objects, which are equal according to the standard equals(Object) method. In that case the processing of such requests will be efficiently serialized by discarding the redundant ones.


Field Summary
protected  Counter counter
          The statistics of simultaneously processed client requests.
 
Fields inherited from class SK.gnome.dwarf.thread.ThreadServer
daemon, thread
 
Fields inherited from class SK.gnome.dwarf.GenericService
initParameters, parent
 
Fields inherited from interface SK.gnome.dwarf.Service
INITIALIZED, LOG_DEBUG, LOG_ERROR, LOG_FATAL, LOG_INFO, LOG_TRACE, LOG_WARN, LOG_XFER, SHUTDOWN, STARTED, STOPPED
 
Constructor Summary
MultiThreadServer(java.lang.String name)
          Creates a new MultiThreadServer.
 
Method Summary
 void addService(Service service)
          Adds the given service to the server.
 java.lang.Object dequeue(int timeout)
          Picks up a client request from the queue.
protected  boolean enableThread()
          Enables the service thread.
 boolean enqueue(java.lang.Object obj)
          Puts the client request to the queue.
 void finish(java.lang.Object obj)
          Returns the processed request to the server.
protected  int getHandlerTimeout()
          Returns the active handler timeout.
 void init(Server parent)
          Initializes the service.
protected  void loop()
          Main server thread loop.
 java.lang.String report()
          Returns the service report.
 void setHandlerClass(java.lang.Class cl)
          Sets the handler class.
 void setHandlerTimeout(int timeout)
          Sets the active handler timeout.
 void setMaxHandlers(int max)
          Sets the maximum number of active handlers.
 void setMinHandlers(int min)
          Sets the minimum number of active handlers.
 void setQueueSize(int size)
          Sets the size of the client request queue.
 void setSingleRequest(boolean enable)
          Enables or disables simultaneous processing of multiple equal request objects.
protected  void wakeUpHandlers()
          Starts spare handlers.
 
Methods inherited from class SK.gnome.dwarf.thread.ThreadServer
finish, run, setDaemon, shutdown, start, stop
 
Methods inherited from class SK.gnome.dwarf.GenericServer
addService, getAuthenticator, getLogger, getParameters, getService, getServices, getServices, removeService
 
Methods inherited from class SK.gnome.dwarf.GenericService
getAuthFacility, getFullName, getInitParameter, getInitParameterNames, getLogFacility, getName, getPrincipal, getShutdownTimeout, getState, log, log, login, logout, setAuthFacility, setInitParameters, setLogFacility, toString
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 
Methods inherited from interface SK.gnome.dwarf.Service
getFullName, getName, getState, log, log, login, logout
 

Field Detail

counter

protected final Counter counter
The statistics of simultaneously processed client requests.

Contains the current/peak/total number of simultaneously processed client requests.

Constructor Detail

MultiThreadServer

public MultiThreadServer(java.lang.String name)
Creates a new MultiThreadServer.

Method Detail

setQueueSize

public void setQueueSize(int size)
Sets the size of the client request queue.

Parameters:
size - the size of the queue

setHandlerClass

public void setHandlerClass(java.lang.Class cl)
Sets the handler class.

The handlers are instantiated, configured and added to the server automatically by the init(Server) method according to value of this field.

Parameters:
cl - the handler class

setMinHandlers

public void setMinHandlers(int min)
Sets the minimum number of active handlers.

Parameters:
min - the minimum number of handlers

setMaxHandlers

public void setMaxHandlers(int max)
Sets the maximum number of active handlers.

Parameters:
max - the maximum number of handlers

setHandlerTimeout

public void setHandlerTimeout(int timeout)
Sets the active handler timeout.

Parameters:
timeout - the handler timout in seconds

setSingleRequest

public void setSingleRequest(boolean enable)
Enables or disables simultaneous processing of multiple equal request objects.

Default value: true

Parameters:
enable - false to disable processing of equal requests

addService

public void addService(Service service)
                throws ServiceException
Adds the given service to the server.

It overrides the default method behavior, so the instances of the Handler class cannot be added to the server (an exception is thrown in that case). Handlers must be added by setting the full class name of the handler via the setHandlerClass(Class) method instead.

Specified by:
addService in interface Server
Overrides:
addService in class GenericServer
Throws:
ServiceException

init

public void init(Server parent)
          throws ServiceException
Initializes the service.

The initialization procedure adds handlers specified via the setHandlerClass(Class) method. The handlers are inserted at the beginning of the service list, in a number specified via the setMaxHandlers(int) method.

Specified by:
init in interface Service
Overrides:
init in class GenericServer
Throws:
ServiceException

enqueue

public boolean enqueue(java.lang.Object obj)
Puts the client request to the queue.

The request is represented by an instance of the java.lang.Object, which is added to the server's internal queue. The idle handlers (which are blocked on the queue) are then notified that a client request is waiting for the processing. After that, if the current queue size is still greater than zero, the server also tries to start some of the temporarily stopped handlers - this process is actually preformed in the protected loop() method. The method returns true if the client request was accepted by the server, otherwise returns false - it probably means either that the overall server's processing capacity has been reached, or an object equal to obj is already processed by a handler.

Parameters:
obj - the client request
Returns:
true if object was accepted by the server, false otherwise

dequeue

public java.lang.Object dequeue(int timeout)
Picks up a client request from the queue.

This method is called by handlers in order to get a client request for processing. It tries to block the calling handler for the specified timeout if no request object is currently available in the queue.

Parameters:
timeout - the time to wait for the client request
Returns:
client request or null if there is no one available

finish

public void finish(java.lang.Object obj)
Returns the processed request to the server.

This method just adjusts the counter value.

Parameters:
obj - the request object

report

public java.lang.String report()
Returns the service report.

Returns report from the superclass plus the statistics of the handlers' activity and the internal client request queue.

Specified by:
report in interface Reportable
Overrides:
report in class GenericServer
Returns:
the report of all contained services

getHandlerTimeout

protected int getHandlerTimeout()
Returns the active handler timeout.

Returns:
the handler timeout in seconds

enableThread

protected boolean enableThread()
Enables the service thread.

It returns true so the new thread will be always initialized.

Overrides:
enableThread in class ThreadServer
Returns:
true if the thread is enabled

loop

protected void loop()
Main server thread loop.

This method calls the wakeUpHandlers() method and then waits blocked until notified.

Overrides:
loop in class ThreadServer

wakeUpHandlers

protected void wakeUpHandlers()
Starts spare handlers.

This method is invoked by the main server thread loop in the time of accepting a new client request, if there is no idle handler available to process it. The internal list of the contained services is searched for a spare handler which is not running currently, and if found, the handler is started. This process is repeated until either there are no more handlers available to be started, or the client request queue is empty.



Copyright (c) 1999-2005, Gnome Ltd. All rights reserved.