Porting to ECho Version 2

Greg Eisenhauer  --  eisen at cc.gatech.edu

ECho Version 2.0

Introduction

ECho version 2 is the first version of ECho in which the new Connection Manager (CM) infrastructure replaces the earlier DataExchange-based message passing. Porting code from older versions of ECho to the new version involves a variety of (relatively) minor changes in your source code and in how you build and run your application.

Compiling

Include files

Instead of including ``DE.h'', you should now include ``cm.h'' to get the connection manager definitions and ``echo.h'' to get the ECho definitions.

API Changes

The most widespread change in the API is the replacement of the ubiquitous DExchange de parameter in ECho calls with an EControlContext ec parameter. The old DE parameter served a dual purpose. In specialized calls, like ECsink_subscribe_context(), it (indirectly) identified a thread that would run the handler when it was invoked. In other calls like EChannel_create(), it identified a message handler (the dataexchange) that would be responsible for handling the control messages associated with the newly created channel. ECho also borrowed the thread servicing the DataExchange message handler in order to execute event handler functions.

ECho V2 makes this duality a bit more explicit. Conceptually, the EControlContext somehow identifies a thread which can run handlers and otherwise service the channel. At this point, one can only acquire an EControlContext by using ECho_CM_init() to initialize ECho message handling in a Connection Manager. Future releases will support other forms of EControlContext variables. In the case of CM-derived EControl contexts, the CM initialization allows ECho to piggyback on the Connection Manager and use the thread of control which is used by CM for servicing the network. In particular, there are a couple of common ways to structure the control flow in ECho/CM programs. In the simplest, non-threaded program the control flow looks like this:

int main()
{
    CManager cm;
    EControlContext ec;

    /*  ...  */
    cm = CManager_create();
    ec = ECho_CM_init(cm);

    /*  ...  */
    CMrun_network(cm);
}
In this program, the CMrun_network() call runs the CM network handler using the thread of the main program. Non-threaded programs are often more efficient than threaded programs, but some CM transports cannot run without additional threads to support specialized blocking network features.

For threaded programs, CM relies on the gen_threads package to provide a generic wrapper around threads libraries. After gen_threads has been initialized, the subroutine CMform_comm_thread() causes CM to fork a kernel-level thread to handle network traffic. ECho will also use this thread for various asynchronous tasks. A sample control structure for a threaded program using Pthreads is given below:

int main()
{
    CManager cm;
    EControlContext ec;
    int forked;

    gen_pthread_init();

    cm = CManager_create();
    forked = CMfork_comm_thread(cm);
    if (!forked) {
        printf("Fork of communications thread failed, exitting\n");
        exit(1);
    }
    ec = ECho_CM_init(cm);

    /* 
     * communications thread is forked - main() should not return
     * until time for program exit.
    */
}
There is no need to call the equivalent of DExchange_listen() as there was in ECho V1. The ECho_CM_init() call will ensure that a listen point is created if necessary.

ECho routines which did not have a DExchange parameter should have the same API under ECho V2 as they did before. (Proto Channels are not yet functional, so the ECproto_* functions will not work.)

Linking

ECho V2 is built with `libtool', a tool which hides the complexity of building and using shared libraries behind a consistent, portable interface. On platforms where it is possible, the ECho library will be built as both a traditional static library (.a file) and a shared library (.so file). In addition, CM is built with libtool and uses extensively libtool's support for dynamically loading code modules at runtime.

ECho applications can also be built with libtool. How this is done is best explained by the libtool documentation, available from http://www.gnu.org/software/libtool/libtool.html. If libtool is utilized, using ECho involves adding ``-lecho'' to the link line, preceeded if necessary by an appropriate ``-Llibdirectory'' flag. Libtool will locate any other libraries required by libtool.

It is also possible to link ECho applications without libtool. If this is done, the libraries that ECho depends upon must be specified explicitly. A typical library spec might be ``-lecho -lecl -licode -lvcode -lcm -latl'', again preceeded by an appropriate ``-Llibdirectory'' flag. However there are some subtleties that may cause difficulties. In particular, on many platforms, the linker will preferentially use the shared library if it is available. So, if both a .a and .so file are available in ``libdirectory'', the .so form will be used with implications describe in the next subsection.

Using the shared library version

On some platforms (such as Solaris), the -L flag is not the only flag that controls where shared libraries might be found. In particular, -L only controls the link time search path for shared libraries. Other flags, typically -R, control the search path that will be used at run time. libtool would automatically do this for you, but you must do it manually if you don't use libtool. If you don't specify the appropriate run-time link path, the dynamic linker won't be able to locate the appropriate shared libraries and you'll get a run-time error. On most platforms, 'ldd' is a tool that lists the dynamic dependencies of an executable, including what the library search paths are and which libraries would be loaded if the program were run.

Using the traditional library version

Creating statically linked versions of programs can be useful for debugging. You can (generally) use the traditional library version (.a files) of ECho and CM if you specify the .a file directly. Additionally, some versions of ld accept flags that cause only the static versions of libraries to be used (such as -Bstatic on Solaris).

The principal caveat to using static libraries is that CM uses program-controlled dynamic linking (dlopen-style) to load its network transport layer. On some platforms, statically linked programs cannot use dlopen(). If CM is unable to load its transport layer, your program will exit with the error ``Failed to initialize default transport. Exiting.''. You may be able to avoid this by linking only some libraries statically and letting others, particularly libc, be dynamic. libtool users can produce a completely statically linked executable because CM uses libtool's ltdl library. That library is capable of simulating dynamic linking in a statically linked environment (if all the dlls are known at link time.) See the libtool docs for how this works.

Running

Depending upon how it was linked, ECho applications may require the environment variable LD_LIBRARY_PATH to be set at run-time. Using LD_LIBRARY_PATH can fix-up executables which do not have the correct run-time link paths built in with ld's -R flag.

This page is maintained by  Greg Eisenhauer