Cichlid Server API

Cichlid servers are made up of two major components: the 'user' server code, which produces data, and the Cichlid server library, which services client requests and provides for the server's data to be mirrored on the client side. The 'user' server code does not participate in the actual communication between the client and server; it simply creates and updates a data object, registers callback functions with the server API, and then hands control to the server library. Thus the server writer is absolved of having to write socket I/O code, writing OpenGL code, or worring about compatibility with Cichlid's client/server protocol.


Library Documentation


Client/Server Relationship

Cichlid servers provide the data which the client displays. Each server supplies one data set across a single TCP connection to a client; each data set corresponds to one graph. The server maintains the data set to be graphed, and it waits for clients to connect and query the server about the data set.

The data sets the client deals with are purely abstract and unitless; the client sees each data sets as either a rectangular array of arrays of unitless heights over a specific interval, in the case of a barchart graph, or as an array of "vertex" tuples and an array of "edge" tuples, in the case of a vertex/edge graph. Since the data is unitless, it is all handled uniformly by the client; the client has no notion of "RTT Variance", "Average Link Utilization", "Widgets per Second", or any such metric. It simply draws what you tell it to.

The servers, on the other hand, deal with some sort of real-world data. A data server's job is to analyze the real world data, perhaps a tcpdump capture of a network, perhaps temperature changes from a sensor array, perhaps BGP prefix info from your masterfully-written Perl script, and abstract them into a form the client uses: unitless heights on a given interval with optional color info for bar charts, or pairs of the unitless tuples (location, style, size, color) and (ends, direction, style, size, color) for vertex/edge graphs. Servers should also provide some sort of assistance in mapping the abstracted, unitless info back to the real-world values, in the form of labels and user feedback.


Server API Overview

To reduce the effort needed to create a data server, as well as to hide the details of what exactly is transmitted between the client and servers, a data server backend exists to manage server control. It takes care of all of the actual socket calls, as well as handshaking with the client. In the design of the server backend, flexibility and generality has in some places been traded for ease-of-use and extendibility.

The server backend is loosely based upon the GLUT model of using function callbacks for everything; you create C functions to do things such as "calculate the next matrix for transmission", pass pointers to the functions to the server backend, and then send it on it's merry way. The server backend code answers client requests, marshals data in and out, and all sorts of other things. When it feels the need, it calls the functions the user has registered (via the function pointers) in order to help it do useful things.

In the server binary, the C function main() lives in the user's code. The basic sequence of events in this function is:

  1. Call the server backend's initilization function, dsInit(), giving it the first crack at the command-line options. It will gobble up any it recognizes. There is a facility to hook into the usage message that the server prints if it finds a problem with the command line, if you wish your server to show one other than the default.
  2. Perform any per-startup initialization, perhaps allocating memory, parsing the remainder of the command line, and things of that sort.
  3. Create the DataSet object that the server is to operate on by calling the appropriate contstructor -- bchart_new() or veset_new() -- and pass a pointer to that object to the server.
  4. Register function callbacks for per-connection initialization, per-frame data calculation, server-idle loops, and other things.
  5. Set any desired server options and toggles.
  6. Call the server's "main loop" function, dsMainLoop(), which may never return.

Using The Server API

The actual server API code is bundled into "libserver.a", which gets built in the "lib" subdirectory of the Cichlid tree. To use the server back-end, you should #include the header file, "cichlid_server.h", which will in turn include the header files necessary to use the server library, and then link your code against "libserver.a". Included in this library are the functions that create and manipulate DataSet objects, which represent all of the data used to construct the graph displays.

If you #define the symbol INCLUDE_CICHLID_UTILS before including this header file, it will also include several other header files that provide access to the utility library routines Cichlid uses for routine tasks like string manipulation, number parsing, named color lookups, and system-dependent things such as getting time deltas and sleeping. These can come in handy, since each function you use in the utility libraries is already written and tested for you, and is portable to other OS's (such as win32 systems).

Documentation of both of these sets of functions is available; see the Library Documentation section.


Last modified: Mon Aug 30 10:14:32 PDT 1999