EAServer configuration  Appendix C: Creating C Components

Appendix B: Migrating Open Server Applications to EAServer

Additional event handler information

This section contains additional information relevant to coding event handlers.


Calling convention for event handlers

All event handlers, error handlers, and any other function that is installed as a callback in the EAServer runtime must be coded according to the following rules:


Initialization, run, start and exit events

An application’s initialization handler and start handler are invoked when the server starts up. The exit handler is invoked when the server shuts down. Initialization and exit handlers are typically used to manage global resources used by the application. The sequence is as follows:

  1. Server initialization – Initialization handler (if installed) is called.

  2. Server start-up – Initialization handler has returned. The Start handler is called. The server is now ready to spawn new threads, but will not accept client connections until after the Start handler returns. The Start handler can spawn service (non-client) threads if necessary.

  3. Normal operation – The server accepts client connections and associates each with a thread, spawning new threads when necessary. Each time a client connects, the server calls the application’s connect handler. Each time a client disconnects, the server calls the application’s disconnect handler.

  4. Server shutdown – The server terminates all threads, then calls the exit handler.


Start handler template

The template for a start handler is:

#include <ospublic.h>

CS_RETCODE CS_PUBLIC start_handler (
                          CS_CONTEXT *ctx
                          )

where

context – is pointer to the CS_CONTEXT structure.

Start handlers must return CS_SUCCEED unless an error occurs that prevents the application from running successfully. Returning a value other than CS_SUCCEED aborts the server start-up sequence.

Your application does not require a start handler unless you want to use service threads or create global mutexes. In this case, the service threads must be created in the start handler.


Exit handler template

The template for an exit handler is:

#include <ospublic.h>

CS_RETCODE CS_PUBLIC exit_handler(
             CS_CONTEXT      *context
            )
{
    ... your code goes here ...
    return CS_SUCCEED;
}

where

context – is pointer to the CS_CONTEXT structure.

Exit handlers must return CS_SUCCEED.


Connect and disconnect handlers

Connect and disconnect handlers are invoked when client applications open and close connections to EAServer.

The connect and disconnect handler examples in this chapter call Server-Library routines. You can use these routines to perform user authentication.

You can find documentation for these routines in the Open Server Server-Library/C Reference Manual. You can view it on the web from the Technical Library page:

http://sybooks.sybase.com

Connect handler

The connect handler can be used to authenticate the connection’s user name. Users must be validated based on user name/password, and you must supply code for password maintenance and checking.

Notesrv_thread_props(SRV_T_USERDATA) is off-limits to EAServer programmers.

The following is an example of a connect handler that logs the user name, password, and locale name when a connection is opened:

CS_RETCODE CS_PUBLIC
debug_connect(srvproc)
SRV_PROC    *srvproc;
{
    CS_INT      spid;
    CS_INT      ulen;
    CS_INT      plen;
    CS_INT      llen;
    CS_CHAR     msg[CS_MAX_MSG];
    CS_CHAR     user[CS_MAX_NAME+1];
    CS_CHAR     password[CS_MAX_NAME+1];
    /* Initialization                           */
    spid = 0;
    /* Get the spid    */
    if (srv_thread_props(srvproc, CS_GET, SRV_T_SPID, 
        (CS_VOID *)&spid,
        CS_SIZEOF(spid), NIL(CS_INT *)) != CS_SUCCEED)
    {
        return (CS_FAIL);
    }
    /*
    ** Get the username and password
    */
    if (srv_thread_props(srvproc, CS_GET, SRV_T_USER, 
        (CS_VOID *)user,
        CS_MAX_NAME, &ulen) != CS_SUCCEED)
    {
        return (CS_FAIL);
    }
    if (srv_thread_props(srvproc, CS_GET, SRV_T_PWD, 
           (CS_VOID *)password,
           CS_MAX_NAME, &plen) != CS_SUCCEED)
    {
        return (CS_FAIL);
    }
    /* Null terminate the username and password      */
    user[ulen] = (CS_CHAR)’\0’;
    password[plen] = (CS_CHAR)’\0’;
    /* Log the username and password values.    */
    sprintf(msg,"SPID %d) user ’%s’, password ’%s’\n",
            spid, user, password);
    SRV_LOG(CS_TRUE, msg, CS_NULLTERM);
    return (CS_SUCCEED);
}

Disconnect handler

The following is an example of a disconnect handler:

CS_RETCODE CS_PUBLIC
fullpass_disconnect(srvproc)
SRV_PROC        *srvproc;
{
    CS_INT      spid;
    CS_CHAR     msg[CS_MAX_MSG];
    /* Initialization                           */
    spid = 0;
    /* Get the spid    */
    if (srv_thread_props(srvproc, CS_GET, SRV_T_SPID, 
        (CS_VOID *)&spid,
        CS_SIZEOF(spid), NIL(CS_INT *)) != CS_SUCCEED)
    {
        return (CS_FAIL);
    }
    sprintf(msg,"SPID %d disconnected.\n", spid);
    SRV_LOG(CS_TRUE, msg, CS_NULLTERM);
    return CS_SUCCEED;
}

Build with the Visual C++ IDE

On Windows Platoforms, if you use the Visual C++ IDE or another command line compiler to build your DLL, make sure that you specify the correct options so that the compiler generates C functions using the standard C calling convention. After you build the DLL, copy it to the EAServer dll subdirectory.


A sample module definition (.def) file

EAServer Manager generates a .def file for your component. Visual C++ requires a module definition file that specifies which functions are exported from a DLL and some options that control how the DLL is loaded into memory. Module definition files end with the extension .def.

For most projects, you can use the generated file as-is. In some cases, you may want to edit settings other than those in the EXPORTS section. For example, your component may perform better with a smaller or larger HEAPSIZE setting.

NoteNever edit the generated function names in the EXPORTS section of the .def file for a C component, otherwise, the EAServer dispatcher will not be able to call your methods.

Below is the example module definition file for the sample Enrollment component:

LIBRARY libEnrollment     INITINSTANCE
Description  ’EnrollmentComponent - EAServer’
HEAPSIZE      22000
PROTMODE
CODE LOADONCALL EXECUTEREAD NONCONFORMING
DATA PRELOAD READWRITE MULTIPLE NONSHARED
EXPORTS
__skl_Enrollment_v_1_0_getMajorList
__skl_Enrollment_v_1_0_getCourses
__skl_Enrollment_v_1_0_getStudentRecord
__skl_Enrollment_v_1_0_putCourseRecord
__skl_Enrollment_v_1_0_destroy
__skl_Enrollment_v_1_0_createStudentRecord
__skl_Enrollment_v_1_0_create
__skl_Enrollment_v_1_0_getMajorEnrollmentRecord
__skl_Enrollment_v_1_0_removeCourseRecord
__skl_Enrollment_v_1_0_getCourseList
__skl_Enrollment_v_1_0_getAllEnrollmentRecord

For components, the .def file must use the mangled function names as shown in the example. For each method in your component, the mangled name is:

__skl_Comp_v_1_0_method

where

Comp is the component name.

method is the method name.





Copyright © 2005. Sybase Inc. All rights reserved. Appendix C: Creating C Components