Although some servers connected to the Hub might be dedicated to a particular session (such as when they connect using -contact_hub and -session_id), most servers support multiple sessions through the same connection to the Hub. So, for instance, a single parser may be responsible for parsing all the user utterance strings for all the sessions currently connected to the Hub.
If new_session opened a new log every time it was called, any program which calls it would end up writing a very short log which covered the time from when the session was created (essentially, when the Hub first saw the session ID) to when new_session was called. Since this behavior would be unavoidable when new_session is used correctly, new_session has been implemented not to open a new log the first time it is called on a given session.
If you want to end a session explicitly, you can call the Builtin server function end_session.
If you want to control the memory state of a given session, you can do that from the server as well.
To support this functionality, the Galaxy Communicator library provides environment-aware broker callback and timed task setup, as well as a way of maintaining an environment through successive calls to dispatch functions. In this section, we describe some of these functions.
void GalSS_TaskSetEnvironment(Gal_TaskPkg
*p, GalSS_Environment *env)
Sets the environment associated with the
task p to env.
GalSS_Environment *GalSS_TaskGetEnvironment(Gal_TaskPkg
*p)
Returns the environment associated with
the task p.
Gal_TaskPkg *GalSS_EnvAddTask(GalSS_Environment
*env, void (*task)(Gal_TaskPkg *), void *caller_data,
long num_millisecs, int read_blocking_available, GAL_SOCKET
*read_socket, GAL_SOCKET *write_socket, GAL_SOCKET *err_socket,
FILE *read_file, FILE *write_file, FILE*err_file,
Gal_TaskConditionFn condition, void (*cleanup_fn)(void *))
This function provides all the functionality
of Gal_AddTaskExtended,
but also saves away the call environment env for access using the
function GalSS_TaskGetEnvironment. A task thus established can be refired
in any of the normal ways; see the timed task
documentation for details.
At times, connections may be associated with UI elements, which can issue new messages. So the UI itself is an element outside the scope of dispatch functions where it would be helpful to have a call environment to use to issue new messages. It's not enough to set up the environment when the connection is established; crucial properties of the UI interaction, such as the session ID, may be changed by other servers in the course of evaluation. The safest thing to do is to create an environment for the UI when the connection is established, update it every time a dispatch function is called, and free the environment when the connection is shut down. The function GalSS_EnvMaintainInLocation does this for you.
void GalSS_EnvMaintainInLocation(GalIO_CommStruct
*gcomm, char *initial_session_id, GalSS_Environment **env_loc)
The connection gcomm is the connection
to the Hub which is associated with a UI element for the current session,
and hosts the dispatch functions which are fired. This function seeds the
location env_loc with a new environment and updates its session
ID to initial_session_id. It sets a dispatch function callback via
GalIO_AddConnectionDispatchFnCallback
to
keep the location current, and sets up a shutdown callback to free the
environment.
GalSS_Environment *GalSS_EnvCreate(GalIO_CommStruct
*gcomm)
Creates an environment from the connection
gcomm.
void GalSS_EnvUpdateSessionID(GalSS_Environment
*env, char *session_id)
Sets the session_id as the session
for this environment. The session_id is copied. This function can
safely be called repeatedly on the same call environment to change the
session context.
char *GalSS_EnvGetSessionID(GalSS_Environment
*env)
Returns the session_id for
this environment. The session_id is not copied. It may be NULL.
void GalSS_EnvLock(GalSS_Environment
*env)
Increments the reference counter on the
environment env to indicate that it should not be freed.
void GalSS_EnvUnlock(GalSS_Environment
*env)
Decrements the reference counter on the
environment env. When the reference counter reaches 0, the environment
is freed.
int GalSS_EnvReturnRequired(GalSS_Environment
*env)
Returns 1 if the call environment represents
a dispatch function invocation for which a return is expected, or 0 if
it does not.
PROGRAM: FromAudioHowever, the programmer might prefer that the call to the recognizer appear to the Hub to be a synchronous call; that is, that the input string be the reply to the Recognize message:...
RULE: :audio_host & :audio_port & :call_id --> Recognizer.Recognize
IN: :audio_host :audio_port :call_id
OUT: none!PROGRAM: FromRecognizer
RULE: :input_string --> Parser.Parse
....
PROGRAM: FromAudioThis is easy to do, using the function GalSS_EnvPostponeReply....
RULE: :audio_host & :audio_port & :call_id --> Recognizer.Recognize
IN: :audio_host :audio_port :call_id
OUT: :input_stringRULE: :input_string --> Parser.Parse
....
int GalSS_EnvPostponeReply(GalSS_Environment
*env)
Informs the Hub that the response to its
message will be delayed, but that in the meantime it's available for other
incoming messages. It does this by sending a pacifier message of type GAL_POSTPONE_MSG_TYPE.
The programmer would then set up the broker as follows:
Gal_Frame Recognize(Gal_Frame f, void *server_data)Observe that the dispatch function postpones the response, and then the environment-aware finalizer explicitly sends the reply when recognition is done. This same strategy could be used with timed task callbacks as well, if the appropriate situation arose.
{
GalSS_Environment *env = (GalSS_Environment *) server_data;/* ... */
GalSS_EnvPostponeReply(env);
GalSS_EnvBrokerDataInInit(env, host, port, f, env_recognition_handler,
env_recognition_finalizer, (void *) NULL, 0);
return (Gal_Frame) NULL;
}static void env_recognition_handler(GalSS_Environment *env,
GalIO_BrokerStruct *broker_struct,
void *data, Gal_ObjectType data_type,
int n_samples)
{
if (data_type == GAL_INT_16) {
/* ... gather the audio ... */
}
}static void env_recognition_finalizer(GalSS_Environment *env,
GalIO_BrokerStruct *broker_struct)
{
/* Send the reply. The name doesn't matter because it will
be set by the environment as the original name of the
incoming message. */
Gal_Frame f = Gal_MakeFrame("foo", GAL_CLAUSE);/* ... */
Gal_SetProp(f, ":input_string", Gal_StringObject(recognized_string));
GalSS_EnvReply(env, f);
}
typedef Gal_Frame (*GalSS_ContinuationFn)(Gal_Frame,
GalIO_MsgType, GalSS_Environment *, void *);
This is the type of the continuation function.
int GalSS_EnvDispatchFrameWithContinuation(GalSS_Environment
*env, Gal_Frame frame, GalSS_ContinuationFn fn, void
*continuation_state, void (*continuation_state_free_fn)(void
*))
This function sends frame to the
Hub using the environment env, and indicates that it expects a reply.
It then notifies the Hub that the dispatch server response will be postponed
using GalSS_EnvPostponeReply, and
stores away the environment, along with the continuation function fn
and an arbitrary state continuation_state, which the programmer
can use to store arbitrary data for use in the continuation function. The
data will be freed using the continuation_state_free_fn. The continuation
function is invoked as the continuation of the dispatch function; in particular,
if the continuation function returns a frame, it will be treated as the
reply to the original dispatch function. It is called with the frame and
message type of the reply to the original request to the Hub, the environment
env,
and the continuation_state.
PROGRAM: FromAudioThe Hub will monitor the Recognizer server for a new message (in the current session) named FromRecognizer, and treat it as the reply to the call to Recognizer.Recognize. The processing proceeds normally from that point. The CONTINUE_ERROR: directive does the same for an error reply. Both directives can be repeated in a single rule....
RULE: :audio_host & :audio_port & :call_id --> Recognizer.Recognize
IN: :audio_host :audio_port :call_id
CONTINUE_REPLY: {c FromRecognizer }
OUT: :input_stringRULE: :input_string --> Parser.Parse
PROGRAM: FromAudioThe Hub will monitor any provider of the Recognizer service for a new message (in the current session) named FromRecognizer, and treat it as the reply to the call to Builtin.hub_continue. The processing proceeds normally at that point....
RULE: :audio_host & :audio_port & :call_id --> Recognizer.Recognize
IN: :audio_host :audio_port :call_id
OUT: none!RULE: --> Builtin.hub_continue
IN: (:reply_matches ( {c FromRecognizer } ) ) (:service_type "Recognizer")
OUT: :input_stringRULE: :input_string --> Parser.Parse
Please send comments and suggestions to:
bugs-darpacomm@linus.mitre.org
Last updated December 24, 2001.
Copyright
(c) 2000 - 2001
The MITRE
Corporation
ALL RIGHTS RESERVED