![]() |
License / Documentation home / Help and feedback | ![]() |
Upgrading to Galaxy Communicator 4.0 is simple. Most of the obligatory upgrades are restricted to very recent or obscure functionality.
This document describes only the steps required or recommended to upgrade
existing features of Galaxy Communicator. You can find a list of new
features here. You can find the complete
release notes here.
Step | Who's affected | Status |
Step 1: Updating logging support | All users of the TIMESTAMP: Hub directive and LOG_IN: and LOG_OUT: directives in the scope of the PROGRAM: or MESSAGE: directives who may be relying on a sloppy 3.3 implementation | Obligatory |
Step 2: Update use of -gui | All users of the -gui Hub command line argument | Obligatory |
Step 3: Update use of variable substitution |
All users of Gal_VAReadVarFrameFromString
and Gal_ReadVarFrameFromString |
Obligatory |
Step 4: Update expectations for
missing Hub programs and operations |
All users of GalSS_EnvDispatchFrame
and its relatives |
Obligatory |
Step
5: Upgrade to broker proxies |
All users of brokering |
Optional |
Step 6: Upgrade references to
verbosity constants |
All C programmers who refer to the undocumented
constants GAL_FATAL_LEVEL, etc. |
Obligatory |
Step
7: Upgrade use of hub_continue |
All Hub program writers who use the :service_provider
key of the Builtin server function hub_continue |
Obligatory |
Step 8: Update
broker startup |
All C programmers who use brokers in threaded
Communicator servers |
Recommended |
Step 9:
Update broker callback setup |
All C programmers who refer to the events GAL_CONNECTION_BROKER_OUT_STARTUP_EVENT
and GAL_CONNECTION_BROKER_IN_STARTUP_EVENT |
Obligatory |
Step 10: Upgrade
Java servers |
All users of Java bindings. |
Obligatory |
Step 11: Upgrade
use of EXPAND: in process monitor configuration files |
All users of the EXPAND: process monitor
configuration file directive who used it to generate unique temporary file
names |
Obligatory |
Step 12: Upgrade argument
lists of Server class in Python |
All users of the Server class in Python who rely
on order-based arguments to the constructor |
Obligatory |
Step 13:
Upgrade use of host and port override rules for -locations and -server_locations_file |
All users of the -locations and -server_locations_file
Hub command line arguments |
Obligatory |
In version 3.3, we introduced, but did not document, the ability of the Hub to contact remote servers for visualization and profiling. The location of this remote server is provided to the Hub via the -gui command line argument. In version 3.3, the format of this argument was direction@host:port, where direction was either server (i.e., the server has the listener) or hub (i.e., the Hub should set up the listener). When the Hub had the listener, the host argument was ignored.
In the context of cleaning up references to provider names and documenting the Hub GUI functionality, we decided that this format was not particularly informative. So in 4.0, the format is host:port, where host can be the distinguished string <listener>, indicating the Hub should set up the listener.
Gal_VAReadVarFrameFromString("{c foo :string $a :int $b }", 2,This invocation would have led to memory leaks if there were no references to some of the variables in the frame string. In version 4.0, these functions now assume that the programmer will manage the memory for the variable values, and copy the variable values before substitution. This both enables the programmer to ensure that newly-created elements are freed, and also eliminates the possibility of multiple references to the same Gal_Object in a single frame, which is currently not supported. In 4.0, the equivalent invocation should look like this:
"$a", Gal_StringObject("bar"),
"$b", Gal_IntObject(5));
Gal_Object o1 = Gal_StringObject("bar");
Gal_Object o2 = Gal_IntObject(5);
Gal_VAReadVarFrameFromString("{c foo :string $a :int $b }", 2,
"$a", o1, "$b", o2);
Gal_FreeObject(o1);
Gal_FreeObject(o2);
In version 3.3, a call to GalSS_EnvDispatchFrame
would do something somewhat unintuitive when the Hub could neither find
a matching Hub program nor identify a matching service type which supported
the specified operation. The Hub would create a new message named system-error
and process it as an incoming message. However, it would not return any
error to the caller. This behavior differs from the behavior of service
providers which are sent messages by the Hub which they don't support:
they raise an error directly back to the Hub.
In version 4.0, we have augmented this behavior to be more consistent. The Hub still generates its new message, in case Hub script programmers rely on this feature; however, instead of a normaly reply, the caller of GalSS_EnvDispatchFrame or its relatives receives an error. We highlight this change in case programmers have been inadvertantly careless about checking the message type of the reply, which should be done as follows:
GalIO_MsgType t;
Gal_Frame msg, reply;
/* ... */
reply = GalSS_EnvWriteFrame(env, msg, &t);
switch (t) {
case GAL_REPLY_MSG_TYPE:
/* normal reply */
break;
case GAL_ERROR_MSG_TYPE;
/* error */
break;
default:
break;
}
Here's a comparison of the use of brokers for streaming data, using proxies
and raw brokers:
Writing through a raw broker
static Gal_Frame prepare_audio_frame(GalSS_Environment *env,
char *filename)
{
Gal_Frame f = Gal_MakeFrame("main", GAL_CLAUSE);
int total = 0;
char *buf = (char *) NULL;
GalIO_BrokerStruct *b;
/* In the code omitted here, the data from the named file is
read into buf, and total is the number of bytes in buf */
/* .... */
/* Now that we have the audio, we write the binary data
through the broker. */
b = GalIO_BrokerDataOutInit(GalSS_EnvComm(env), 0, 10);
if (b && (GalIO_GetBrokerListenPort(b) > 0)) {
GalIO_BrokerPopulateFrame(b, f, ":binary_host", ":binary_port");
GalIO_BrokerWriteBinary(b, buf, total);
GalIO_BrokerDataOutDone(b);
}
free(buf);
return f;
}
Writing through a proxy
static Gal_Frame prepare_audio_frame(GalSS_Environment *env,
char *filename)
{
Gal_Frame f = Gal_MakeFrame("main", GAL_CLAUSE);
int total = 0;
char *buf = (char *) NULL;
Gal_Object proxy;
/* In the code omitted here, the data from the named file is
read into buf, and total is the number of bytes in buf */
/* .... */
proxy = GalSS_ObjProxifyObjectType(env, GAL_BINARY, 0, 10);
if (proxy) {
GalSS_ObjProxyArrayAdd(proxy, buf, total);
/* Because the data object is a streaming object, it must
be marked as done. */
GalSS_ObjProxyDone(proxy);
Gal_SetProp(f, ":binary_proxy", proxy);
}
return f;
}
Reading from a raw broker
Gal_Frame receive_audio(Gal_Frame f, void *server_data)
{
DataHandler *d = (DataHandler *) malloc(sizeof(DataHandler));
GalIO_BrokerStruct *b;
char *host = Gal_GetString(f, ":binary_host");
int port = Gal_GetInt(f, ":binary_port");
d->data_buf = (char *) NULL;
d->size = 0;
if (host && port) {
b = GalSS_EnvBrokerDataInInit((GalSS_Environment *) server_data,
host, port, f,
env_audio_handler, 0, d, __FreeDataHandler);
if (b) {
GalIO_AddBrokerCallback(b, GAL_BROKER_ABORT_EVENT,
__report_abort, (void *) NULL);
GalIO_AddBrokerCallback(b, GAL_BROKER_DATA_DONE_EVENT,
__report_done, (void *) NULL);
GalIO_SetBrokerActive(b);
}
} else {
free(d);
}
return (Gal_Frame) NULL;
}
Reading from a proxy
Gal_Frame receive_audio(Gal_Frame f, void *server_data)Note that especially on the receiving end, there's much less to do, and the callback infrastructure is handled for you, as is the assembly of streaming data into a single object. In addition to these benefits, and the fact that the contact information is encapsulated and typed, it's also possible to read objects from proxies without using callbacks, if you so choose. In general, the new API is much more flexible and powerful. For more information, see the broker documentation.
{
GalSS_Environment *env = (GalSS_Environment *) server_data;
GalSS_BrokerProxy *proxy;
/* We get the proxy object, and proceed asynchronously. The
object passed into the callback is owned by the callback.
We use a non-immediate callback, which will cache all the
data for us and call the data handler when it's done. */
proxy = Gal_GetObject(f, ":binary_proxy");
if (Gal_Proxyp(proxy)) {
GalSS_ObjUnproxify(env, proxy, proxy_audio_handler,
__proxy_report_done, __proxy_report_abort,
0, 0, NULL, NULL);
}
}
return (Gal_Frame) NULL;
}
So let's say you want to print something out if GAL_VERBOSE corresponds to the default level of printing, which is the level for GalUtil_PInfo1. Here's the difference:
Version 3.3
if (GAL_VERBOSE > GAL_PINFO1_LEVEL) {
/* ... */
}
Version 4.0
if (GAL_VERBOSE >= GAL_PINFO1_LEVEL) {
/* ... */
}
Here's a minimal pair for those of you who need to upgrade:
Version 3.3
SERVER: Parser
LOCATION: localhost:5003
OPERATIONS: Parse
...
RULE: --> Parser.Parse
IN: :string
OUT: none!
RULE: --> Builtin.hub_continue
IN: (:reply_matches ( {c ParseResult } )) (:service_provider "localhost:5003")
OUT: :frame
Version 4.0
SERVER: Parser
LOCATION: localhost:5003
OPERATIONS: Parse
PROVIDER_ID: [myparser]
...
RULE: -->Parser.Parse
IN: :string
OUT: none!
RULE: --> Builtin.hub_continue
IN: (:reply_matches ( {c ParseResult } )) (:service_provider "[myparser]")
OUT: :frame
EXPAND: $TEMPThe interpretation of this entry is that $TEMP would be bound, in each process block, to a unique temporary file name which could be passed around in that process block. However, as a result, it was impossible to define an empty expansion. This latter functionality became desirable in the context of defining configuration files which could run on either Unix or Windows. Therefore, in 4.0, the entry shown here does expand to the empty string, and we've introduced the TEMPFILE: directive to provide explicit temporary file substitutions.
SERVICE_TYPE: foocould have its CLIENT_PORT: value overridden by this command line argument:
CLIENT_PORT: 2700
... -locations "foo@ignore:2900" ...However, in 4.0, the assumption is that any host name which is present indicates that the Hub should expect the listener to be on that host; so in 4.0, this declaration would remove the listener and add a service provider for foo which is expected to be found on the host ignore at port 2900. In order to achieve the intended effect in 4.0, you should use the special <listener> token:
... -locations "foo@<listener>:2900" ...This syntax is also consistent with the upgraded format for the -gui Hub argument.
![]() |
License / Documentation home / Help and feedback | ![]() |