ObjectController.h

Classes

ObjectController -- Link application objects to a server and the control bus (full description)

class ObjectController

Interface

Public Members
typedef Bool (*IdleFunction)(Int elapsedTimeInMilliSec)
void setIdleFunction(IdleFunction func = 0)
static Bool relinquishLockIdleFunction(Int elapsedTime)
ObjectController(int argc, char **argv, LogSinkInterface *globalSink=0)
ObjectController(int argc, char **argv, LogSinkInterface *globalSink, IdleFunction idleFunc)
~ObjectController()
void addMaker(const String &typeName, ApplicationObjectFactory *fromNew)
ObjectID addObject(ApplicationObject *&fromNew)
ObjectID createObject(const String &typeName, const String &whichCtor, GlishRecord *&inputRecord, String &errorMsg)
ApplicationObject *getObject(const ObjectID &id)
Vector<String> methods(const ObjectID &id)
MethodResult runMethod(uInt whichObj, const String &method, GlishRecord *&fromNew, CountedPtr<GlishRecord> &result)
Bool done(uInt &numleft, String &error, const ObjectID &id)
Bool hasGUI ()
void postError(const String &errorMessage)
void loop()
Bool trace() const
void trace(Bool doTrace)
Bool view(String &name)
Bool makePlotterIfNecessary(String &error, const String &name, uInt mincolors, uInt maxcolors, uInt sizex, uInt sizey)
Bool sendPlotCommands(String &error, GlishValue &out, const String &plotName, const GlishRecord &plot)
String choice(const String &descriptiveText, const Vector<String> &choices)
Bool stop()
Int makeProgressDisplay(Double min, Double max, const String &title, const String &subtitle, const String &minlabel, const String &maxlabel, Bool estimateTime = True)
void updateProgressDisplay(Int id, Double value)
void sendMemoryUse()
void handleEvent(GlishSysEvent &event)
void handleRun(GlishSysEvent &event, Bool async)
void handleCreate(GlishSysEvent &event)
void handleTrace(GlishSysEvent &event)
void handleMethods(GlishSysEvent &event)
void handleDone(GlishSysEvent &event)
void handleUnrecognized(GlishSysEvent &event)
void setGlobalLogSink(LogSinkInterface *globalSink=0)
Private Members
void init(int argc, char **argv, LogSinkInterface *globalSink, IdleFunction idleFunc)
ApplicationObjectFactory *maker(const String &which)
ApplicationObjectFactory *maker(uInt which)
Int n_makers() const
ObjectController(const ObjectController &)
ObjectController &operator=(const ObjectController &)

Description

Review Status

Date Reviewed:
yyyy/mm/dd

Prerequisite

Etymology

This class Controls Objects embedded within it.

Synopsis

The tasking system ("distribute object" system) is fundamentally described in AIPS++ note #197. However, a few words here might be useful.

The interaction with the application programmer will typically consist only of:

  1. Initializing the controller with argc,argv inside the main program; and
  2. calling addMaker() for each class that you want to allow the controller to be able to create.

The ObjectController has the following "internal" functions as well:

  1. It handles the creation of distributed objects upon request (i.e., over the Glish bus).
  2. Maintaining the list of created objects, and deleting them when the controller exits.
  3. Hand off the parameters to the distributed object when a method invocation is desired.
  4. Trap exceptions.
  5. Turn on and off tracing information for debugging.
  6. Attach the global logsink to GlishLogSink so that log messages will go to Glish, where they will typically appear in a GUI.

At present, these internal functions are ordered up solely through events received over the Glish bus. We intend to allow unix command line control in the future. The events which are presently understood are:

ObjectController Glish Protocol
Event (In) Value Event (Out)> Value
run The run event is used to invoke ("run") a member function in a distributed object. The object must already exist. A record, which must contain the sequence part of the ObjectID in field _sequence, and the method name in _method. The other fields of the record are the input arguments for the method. run_result The same record with the output arguments filled in.
done/b> The done event is used to destruct an object which exists in the current server. An ObjectID record. done_result, an integer giving the number of remaining live objects, or error if something has gone awry. The same record with the output arguments filled in.
run_async Like run, except from the users point of view the method is running asynchronously. Like run, with an additional _jobid field. run_result_async The same as for run_result, except _jobid is reflected back as well.
create Create an object of some class. A record. _type is the classname, _creator is the constructor "name" (it can be ommitted if the default constructor is the only one) create_result A record containing the ObjectID mapped to _sequence, _pid, _time and _host.
trace Turn on (off) tracing information for debugging purposes. Also sets the global logging filter to DEBUGGING (NORMAL). A Bool. None None
any After the controller discovers any error (e.g. exception), it will return an error event. The value is a string with the error message. any error String (error message)
choice This event is in response to a get_choice event. The users choice (String) get_choice [description=String, choices=StringVector]
progress_result This is in response to a get_progress event. A progress ID (integer). get_progress [min=double,max=double,title=string,subtitle=string, minlabel=string, maxlabel=string, estimate=bool]

Example

Typically the use of this class will be when setting up an executable to serve one or more classes of distributed object.
    #include <aips/Tasking.h>
    #include <your includes go here>
    
    int main(int argc, char **argv)
    {
        ObjectController controller(argc, argv);
        controller.addMaker("squarer", new StandardObjectFactory<class1>);
        controller.addMaker("squarer", new StandardObjectFactory<class2>);
        controller.loop();
        return 0;
    }
    
In the above example, this executable serves two classes, class1 and class2. For more details read note #197.

Motivation

This class contains the fundamental connection between distributed objects and the communications system.

To Do

Member Description

static Bool relinquishLockIdleFunction(Int elapsedTime)

Implements an idle function protocol. If an idleFunction is set then it is called every BasicTimeout when the server is otherwise idle. The idleFunction return value indicates whether the idle function needs to be called again (True). It is reset every time there is some activity. The idle function can choose to do something more drastic if LongIdleTime is exceeded.

Times are in millisec.

This function is called by the standard function. It relinquished locks requested on Tables by other processes.

typedef Bool (*IdleFunction)(Int elapsedTimeInMilliSec)
void setIdleFunction(IdleFunction func = 0)

Implements an idle function protocol. If an idleFunction is set then it is called every BasicTimeout when the server is otherwise idle. The idleFunction return value indicates whether the idle function needs to be called again (True). It is reset every time there is some activity. The idle function can choose to do something more drastic if LongIdleTime is exceeded.

Times are in millisec.

ObjectController(int argc, char **argv, LogSinkInterface *globalSink=0)
ObjectController(int argc, char **argv, LogSinkInterface *globalSink, IdleFunction idleFunc)

Initialize from the command line arguments. Also sets the global LogSink to post messages to Glish, where they will typically end up in a GUI.

If globalSink is set, use if for the global sink, otherwise use a GlishLogSink. The sink must come from the heap if it is set.

The default constructor will automatically clear Table locks when idle, however you can avoid this behaviour for servers with no tables (i.e. avoid lining against tables) or other idle needs. If no idle loop is needed, just set idleFunc to zero.

~ObjectController()

Besides freeing up local resources, if Glish is no longer connected to the process, sets the global LogSink to only pass SEVERE messages, since the messages are just being dumped to stdout.

void addMaker(const String &typeName, ApplicationObjectFactory *fromNew)

Add a maker (factory). Note that after calling addMaker, the controller is responsible for deleting the pointer. You must not delete it yourself. Besides the constructor, this is probably the only function you will call.

ObjectID addObject(ApplicationObject *&fromNew)

If you want to, you can add a new object directory. This is typically done by an object that wants to add another object to the controller. The controller takes over responsibility for deleting the pointer, which must have been allocated with new. The pointer is set to zero to reduce the chances of it being accidentally deleted.

ObjectID createObject(const String &typeName, const String &whichCtor, GlishRecord *&inputRecord, String &errorMsg)

Create an object of the given type and constructor. inputRecord must have come from new, and will be deleted by this function. If creation fails the returned ObjectID will be null and errorMsg will be set. Normally, application programmers will not call this function.

ApplicationObject *getObject(const ObjectID &id)

Get the specified object. Returns a null pointer if it does not exist. Do not delete the returned pointer! The object controller will do it for you. Note that the entire object id must match, not just the sequence number, which is all that is used by runMethod.

Normally, application programmers will not call this function.

Vector<String> methods(const ObjectID &id)

Return list of methods in this object

MethodResult runMethod(uInt whichObj, const String &method, GlishRecord *&fromNew, CountedPtr<GlishRecord> &result)

Normally, application programmers will not call this function.

Bool done(uInt &numleft, String &error, const ObjectID &id)

Destroy the given object if possible (i.e. if it exists). Returns the number of remaining active objects.

Bool hasGUI ()

Do we have a GUI available ? Usually False if environment variable DISPLAY is not set.

void postError(const String &errorMessage)

Posts an "error" event containing errorMessage. Normally, application programmers will not call this function.

void loop()

Run object methods until we're done Normally, application programmers will not call this function.

Bool trace() const
void trace(Bool doTrace)

Check or change the tracing status. Besides the controllers own messages, Trace==True also puts the global log sink at DEBUG level. False turns it back to NORMAL Normally, application programmers will not call this function.

Bool view(String &name)

Use the catalog viewer to view a file

Bool makePlotterIfNecessary(String &error, const String &name, uInt mincolors, uInt maxcolors, uInt sizex, uInt sizey)

Attempt to make a plotter. If a plotter with the given name already exists we return True (so that a plotter can be shared).

Bool sendPlotCommands(String &error, GlishValue &out, const String &plotName, const GlishRecord &plot)

Send plot commands in the form created by PGPlotterGlish

String choice(const String &descriptiveText, const Vector<String> &choices)

If isInteractive() and connected to Glish, get a choice from the user. IF !isInteractive(), always return the first choice, so it should be the default. For example, if you are asking whether or not the user wants to overwrite a file, the default should be "no". If choices is zero length, always return the empty string.

Bool stop()

If isInteractive() and connected to Glish, get a choice from the user. If !isInteractive(), always return False, else check to see if the user has told this object to stop.

Int makeProgressDisplay(Double min, Double max, const String &title, const String &subtitle, const String &minlabel, const String &maxlabel, Bool estimateTime = True)
void updateProgressDisplay(Int id, Double value)

void sendMemoryUse()

Send our controlling process an event named memory with the value of our memory use in MB.

void handleEvent(GlishSysEvent &event)
void handleRun(GlishSysEvent &event, Bool async)
void handleCreate(GlishSysEvent &event)
void handleTrace(GlishSysEvent &event)
void handleMethods(GlishSysEvent &event)
void handleDone(GlishSysEvent &event)
void handleUnrecognized(GlishSysEvent &event)

Carry out the nitty-gritty details of handling the particular events. Normally these methods will only be called from loop(), but they can be called explicitly if desired for testing or other purposes. Normally, application programmers will not call this function.

void setGlobalLogSink(LogSinkInterface *globalSink=0)

Under very rare conditions you might want to change the global logsink after creation. You can do so with this function. The default (=0) is to attach the global logsink to Glish (i.e. the normal logging function).

void init(int argc, char **argv, LogSinkInterface *globalSink, IdleFunction idleFunc)

Common constructor code

ApplicationObjectFactory *maker(const String &which)

Get a factory by name.

ApplicationObjectFactory *maker(uInt which)

Get a factory by (0-relative) index.

Int n_makers() const

How many makers do we have anyway?

ObjectController(const ObjectController &)
ObjectController &operator=(const ObjectController &)

in millisec

Disallow copying and assignment