gv_util - EPOCH Global Variable UtilitiesThe GV utilities provide a C language, client interface to EPOCH global variables.
The EPOCH C++ implementation of a client interface accesses global variables directly out of shared memory, thus requiring that an EPOCH global server be running on the client's host. When a client needs to access global variables residing on another machine, the local global server communicates with the remote global server in order to provide a mirror image of the remote machine's shared memory segment.
The GV_UTIL package takes a different approach: rather than requiring a local global server and shared memory, the GV utilities communicate directly with the home global server of the target global segment in order to get information about the variables and to retrieve or store the values of variables.
Before accessing individual variables, an application must first initialize access to the global segment(s) containing the variables:
#include <stdio.h> -- Standard I/O definitions.
#include "gv_util.h" -- EPOCH global variables.
GlobSeg segment ;
...
gvsCreate (NULL, "stream[@host]", &segment) ;
A network connection is established with the home global server for the stream's segment and a list of the variables in the segment is downloaded and saved by the GV_UTIL package.
After the global segment is created, gvsPoll() must be called
periodically or as necessary in order to receive and process messages from
the segment's global server. gvsPoll() waits for and reads a
single batch of incoming messages; a timeout may be specified to limit how
long gvsPoll() waits for input:
for ( ; ; ) {
gvsPoll (segment, 5.0) ; -- Wait 5 seconds.
... do something else ...
}
In event-driven applications (e.g., those based on the X Toolkit or the
IOX dispatcher), the socket connection
to the global server, returned by gvsFd(), can be monitored for
input by your event dispatcher. The input callback, when invoked, should
call gvsPoll() with a 0.0-second timeout to read and process
the waiting messages.
A specific variable can be looked up by name:
GlobVar global ;
...
global = gvsFind (segment, "name") ;
or the entire list of variables can be scanned by index:
for (i = 0 ; i < gvsCount (segment) ; i++) {
global = gvsGet (segment, i) ;
if (global == NULL) continue ;
...
}
(Because there may be gaps in indices caused by temporary variables,
gvsGet() may return NULL for a seemingly valid index.)
Before retrieving the value of a global variable, you must initiate updates to the variable's value. Binding an update callback to the global variable:
extern GvUpdateCB updateCB ; -- Callback function.
...
gvBind (global, updateCB) ;
results in a request for updates being sent to the segment's global
server, which immediately sends the current value of the variable.
When this and subsequent update messages for the variable are received
from the global server, the application's update callback function is
automatically invoked by gvsPoll() after the variable's
value has been updated.
Finally, to terminate access to a global segment, call
gvsDestroy():
gvsDestroy (segment) ;
There is no need (and no way) to explicitly terminate access to a specific
global variable, although a callback on a global variable can be cancelled
by calling gvCancel():
GvCallback callback = gvBind (global, updateCB) ;
...
gvCancel (callback) ;
The following simple client requests updates for all the variables in a segment; as each update is received, it is written to standard output as:
timestamp flags (segment) variable = value
Here is some actual output:
...
1997-336-19:48:45.099 00000000 (e3_nml@claudius) ETRG_PITCMD = 0
1997-336-19:48:45.099 00000000 (e3_nml@claudius) ETRG_ROLCMD = 0
1997-336-19:48:45.099 00000000 (e3_nml@claudius) ETRG_YAWCMD = 0
...
and here is the actual code (the first argument on the command should be the segment name, "stream[@host]"):
#include <stdio.h> -- Standard I/O definitions.
#include "gv_util.h" -- EPOCH global variables.
#include "tv_util.h" -- "timeval" utilities.
int updateCB (GlobSeg segment, GlobVar global, GvCallback callback,
GvCondition condition, void *clientData)
{
long flags ;
struct timeval timestamp ;
NamedVariable variable ;
if (condition != GvUpdated) return (0) ;
variable = gvValue (global, &flags, ×tamp) ;
printf ("%s %08lX (%s) %s = %s\n",
tvShow (timestamp, 0, NULL), flags, gvsName (segment),
gvName (global), nvrString (variable)) ;
return (0) ;
}
main (int argc, char *argv[])
{
GlobSeg segment ;
GlobVar global ;
int i ;
-- Create the segment.
gvsCreate (NULL, argv[1], &segment) ;
-- Request updates on all.
for (i = 0 ; i < gvsCount (segment) ; i++) {
global = gvsGet (segment, i) ;
if (global != NULL) gvBind (global, updateCB, NULL) ;
}
-- Listen for updates.
for ( ; ; ) {
if (gvsPoll (segment, -1.0)) break ;
}
-- Delete the segment.
gvsDestroy (segment) ;
}
gvsBind() - binds a callback to a global segment.
gvsCount() - returns the maximum number of variables in a global segment.
gvsCreate() - creates a global segment.
gvsDestroy() - deletes a global segment.
gvsFd() - returns a global segment's socket number.
gvsFind() - looks up a variable by name in a global segment.
gvsGet() - looks up a variable by index in a global segment.
gvsIsUp() - checks if a global segment is active.
gvsName() - returns a global segment's name.
gvsPoll() - process pending updates to a global segment.
gvBind() - binds a callback to a global variable.
gvCancel() - cancels a callback.
gvName() - returns a global variable's name.
gvSegment() - returns a global variable's segment.
gvValue() - returns a global variable's current value.
gv_util.c
gv_util.h