This section contains additional information relevant to coding 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:
The function must use the C link-object naming convention. C++ programmers must declare EAServer callbacks in an extern C block. You will get link errors otherwise.
Callback prototypes must include the CS_PUBLIC macro as shown by the examples in this chapter. On platforms such as Windows, the C compiler supports a broad collection of calling conventions for C functions. On these platforms, the CS_PUBLIC macro encapsulates the appropriate compiler keywords to ensure that the same calling convention is used by both EAServer and your callbacks. If the calling convention used by your callback and the calling convention used by EAServer do not match, the server will probably crash when the callback is called or soon after it returns.
WARNING! Declare your callback functions with the CS_PUBLIC macro to avoid server crashes.
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:
Server initialization – Initialization handler (if installed) is called.
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.
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.
Server shutdown – The server terminates all threads, then calls the exit handler.
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.
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 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
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.
srv_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); }
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; }
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.
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.
Never 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. |
|
|