Example: Client-Library initialization and cleanup

The following code fragment, taken from the ctfirst.c migration sample program, illustrates Client-Library initialization and cleanup.

The fragment installs error handlers for CS-Library and Client-Library, as well as a Client-Library server message callback. For examples of a Client-Library error handler and a server message handler, see the “Callbacks” topics page in the Open Client Client-Library/C Reference Manual. For an example CS-Library error handler, see the Open Client and Open Server Common Libraries Reference Manual.

CS_CONTEXT    *context = (CS_CONTEXT *) NULL;
CS_CONNECTION *conn;
CS_RETCODE    ret;/*
** Setup screen output.
*/EX_SCREEN_INIT();/*
** Step 1.
** Allocate a CS_CONTEXT structure and initialize Client-Libary. The 
** EXIT_ON_FAIL() macro used for return code error checking is defined in 
** dbtoctex.h. If the return code passed to EXIT_ON_FAIL() is not CS_SUCCEED,
** it:
- Cleans up the context structure if the pointer is not NULL.
- Exits to the operating system. 
**
-- if (dbinit() == FAIL 
--   exit(ERREXIT);
*/ret = cs_ctx_alloc(CS_VERSION_150, &context);
EXIT_ON_FAIL(context, ret, "Could not allocate context.");ret = ct_init(context, CS_VERSION_150);
EXIT_ON_FAIL(context, ret, "Client-Library initialization failed.");/* 
** Step 2.
** Install callback handlers for CS-Library errors, Client-Library errors, and
** Server-Library errors. The handlers are defined at the bottom of 
** this source file.
**
-- dberrhandle(err_handler);
-- dbmsghandle(msg_handler);
*//*
** cs_config() installs a handler for CS-Library errors.
*/ret = cs_config(context, CS_SET, CS_MESSAGE_CB, (CS_VOID *) cserror_cb,
      CS_UNUSED, NULL);
EXIT_ON_FAIL(context, ret, "Could not install CS-Library error handler.");/*
** ct_callback() installs handlers for Client-Library errors and server messages. 
**
** ct_callback() lets you install handlers in the context or the connection. 
** Here, we install them in the context so that they are inherited by the 
** connections that are allocated using this context.
*/ret = ct_callback(context, NULL, CS_SET, CS_CLIENTMSG_CB, (CS_VOID       clientmsg_cb);
EXIT_ON_FAIL(context,ret,"Could not install Client-Library error handler.");
ret = ct_callback(context, NULL, CS_SET, CS_SERVERMSG_CB, (CS_VOID *)       servermsg_cb);
EXIT_ON_FAIL(context,ret,"Could not install server message handler.");
... deleted code that connects and interacts with the server ...
/*
** Clean up Client-Library.
** ct_exit(context, CS_UNUSED) requests an "orderly" exit -- this
** call fails if we have open connections. If it fails, EXIT_ON_FAIL() calls 
** ct_exit(context, CS_FORCE_EXIT) to force cleanup of Client-Library.
*/
ret = ct_exit(context, CS_UNUSED);
EXIT_ON_FAIL(context, ret, "ct_exit(CS_UNUSED) failed.");/*
** Clean up CS-Library. cs_ctx_drop() always fails if ct_init()
** succeeded on the context but ct_exit() did not (or if ct_exit() 
** was not called at all).
*/
(CS_VOID) cs_ctx_drop(context);
context = (CS_CONTEXT *) NULL;
exit(NORMAL_EXIT);
/*
** clientmsg_cb() -- Callback handler for Client-Library messages.
** Client-Library messages inform the application of errors or 
** significant conditions.
** Parameters:
** context -- Pointer to the context structure where the error occurred.
** The handler can retrieve context properties and set the CS_USERDATA
** property.
** connection -- Pointer to the connection on which the error occurred.
** This parameter can be NULL if no connection was involved in the
** error. If connection is non-NULL, the handler can retrieve connection
** properties, set the CS_USERDATA property, and call 
** ct_cancel(CS_CANCEL_ATTN) on the connection.
** errmsg -- Pointer to a CS_CLIENTMSG structure that describes the 
** error. See the "CS_CLIENTMSG" topics page in the Client-Library
** reference manual for a description of the fields.
** Returns: CS_SUCCEED
** Side Effects: None.
*/
CS_RETCODE CS_PUBLIC
clientmsg_cb(context, connection, errmsg)
CS_CONTEXT     *context;
CS_CONNECTION  *connection; 
CS_CLIENTMSG   *errmsg;

CS_RETCODE ret;
CS_INT     timeout_val; 
/*
** Composition of error messages.
** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** Client-Library message numbers encode values for severity,
** layer, origin, and number. The layer, origin, and number
** correspond to national language strings from the ctlib.loc
** locales file. Client-Library composes the text of the message
** (received in errmsg->msgstring) as follows:
** <routine name>: <layer string>: <origin string>: <description>
** where:
** <routine name> is the name of the Client-Library routine
** that was active when the exception occurred.
** <layer string> describes the layer where the exception occurred
** or was found.
** <origin string> indicates whether the error is internal or external 
** to Client-Library.
** <description> is the error description.
*/
fprintf(ERR_CH, "Client-Library Message: ");
fprintf(ERR_CH, "LAYER = (%ld) ORIGIN = (%ld) ",
(long)CS_LAYER(errmsg->msgnumber), (long)CS_ORIGIN(errmsg->msgnumber));

fprintf(ERR_CH, "SEVERITY = (%ld) NUMBER = (%ld)\n",
long)CS_SEVERITY(errmsg->msgnumber), (long)CS_NUMBER(errmsg->msgnumber));

fprintf(ERR_CH, "Message String: %s\n", errmsg->msgstring);
/*
** Operating system errors.
** ~~~~~~~~~~~~~~~~~~~~~~~
** Some exceptions reported by Client-Library are caused by exceptions
** in the underlying system software. When this occurs, Client-Library
** forwards the system error information to the application.
*/
if (errmsg->osstringlen > 0)
{
fprintf(ERR_CH, "Operating System Error: %s\n",
errmsg->osstring);
}/*
** Handler return values and their meaning.
** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** Client-Library error handlers must return CS_SUCCEED or CS_FAIL.

** Returning any other value "kills" the connection -- Client-

** Library responds by marking the connection "dead", which makes

** it unuseable. You can test for dead connections by retrieving

** the value of the CS_CON_STATUS connection property, which is

** a bit-masked value. The CS_CONSTAT_DEAD bit is set if the connection
** is dead. This functionality replaces DB-Library's DBDEAD() macro.
** Unlike the DB-Library error handler, there is no return code that

** causes Client-Library to exit to the operating system. The application
** must check return codes in the main-line code and abort from the
** main-line code.
*/
/* 
** (Optional) Test for specific error conditions.
** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** The ERROR_SNOL() macro is defined at the top of this file. 
** The component byte values of a message number (origin, layer, and 
** number) are defined in the Client-Library locales file.
*/
/*
** Test for timeout errors. Timeout errors will be received when you:
** -- are using a synchronous mode connection,
** -- have set the CS_TIMEOUT context property to a non-zero positive value 
** (representing a number of seconds).
** -- the server takes longer than the given time to respond to a command.
** For timeout errors, the command can be canceled with
** ct_cancel(CS_CANCEL_ATTN). Other ct_cancel() options are not 
** to be used in an error handler. If we return CS_SUCCEED
** without canceling, then Client-Library will wait for another
** timeout period, then call this error handler again. If the
** we return CS_FAIL, then Client-Library kills the 
** connection, making it unuseable.
*/
if (ERROR_SNOL(errmsg->msgnumber, CS_SV_RETRY_FAIL, 63, 2, 1))
{
/*
** Get the timeout period. This is not really neccessary, but 
** demonstrated to show the correlation between timeout errors
** and the CS_TIMEOUT context property.
*/
ret = ct_config(context, CS_GET, CS_TIMEOUT, CS_VOID *)&timeout_val, CS_UNUSED, (CS_INT *)NULL);
if (ret != CS_SUCCEED)
{
timeout_val = 0;
}
fprintf(ERR_CH, "\nServer has not responded in at least %ld seconds. Canceling.\n",(long)timeout_val);
(CS_VOID)ct_cancel(connection, (CS_COMMAND *)NULL, CS_CANCEL_ATTN);
}
return CS_SUCCEED;
} /* clientmsg_cb() */
/*
** cserror_cb() -- Callback handler for CS-Library errors.
** Parameters:
** context -- Pointer to the context structure passed to the CS-Library 
** call where the error occurred. The handler can retrieve any
** context property, and set the CS_USERDATA property.
** errmsg -- Pointer to a CS_CLIENTMSG structure that describes the 
** error. See the "CS_CLIENTMSG" topics page in the Client-Library
** reference manual for a description of the fields.
** Returns: CS_SUCCEED
** Side Effects: None
*/
CS_RETCODE CS_PUBLIC
cserror_cb(context, errmsg)
CS_CONTEXT     *context;
CS_CLIENTMSG   *errmsg;
{
/*
** Composition of error messages.
** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
** CS-Library message numbers are decoded the same way as Client-
** Library messages. See the comments in clientmsg_cb() for a 
** description.
*/
fprintf(ERR_CH, "CS-Library error: ");
fprintf(ERR_CH, "LAYER = (%ld) ORIGIN = (%ld) ", 
(long)CS_LAYER(errmsg->msgnumber), (long)CS_ORIGIN(errmsg->msgnumber));fprintf(ERR_CH, "SEVERITY = (%ld) NUMBER = (%ld)\n",
(long)CS_SEVERITY(errmsg->msgnumber), (long)CS_NUMBER(errmsg->msgnumber));fprintf(ERR_CH, "Message String: %s\n", errmsg->msgstring);/*
** Operating System Errors.
** ~~~~~~~~~~~~~~~~~~~~~~~
** If an operating system error occurred and CS-Library was notified,
** then CS-Library forwards the error information to the application.
*/
if (errmsg->osstringlen > 0)
{
 fprintf(ERR_CH, "Operating System Error: %s\n", errmsg->osstring);
}
/*
** Handler Return Values.
** ~~~~~~~~~~~~~~~~~~~~~
** CS-Library error handlers should return CS_SUCCEED.
*/
return CS_SUCCEED;
} /* cserror_cb */
/*
** servermsg_cb() -- Callback handler for server messages. The
** server sends messages to describe errors or significant
** events. Client-Library calls this function to forward
** server messages to the client program.
** Parameters:
** context -- Pointer to the context structure that is the parent of
** the connection. The handler can retrieve context properties 
** and set the CS_USERDATA property.
** connection -- Pointer to the connection on which the message was 
** received. The handler can retrieve any connection property, set 
** the CS_USERDATA property, and call ct_cancel(CS_CANCEL_ATTN) 
** on the connection. In addition, when the server sends 
** extended error data with a message, the handler can retrieve
** the data. This handler ignores extended error data.
** srvmsg -- Pointer to a CS_SERVERMSG structure that contains the 
** message info. See the "CS_SERVERMSG" topics page in the Client-
** Library reference manual for a description of the fields. All the
** information that the DB-Library message handler received as
** parameters is available in the CS_SERVERMSG structure.
** Returns: CS_SUCCEED
** Side Effects: None
*/
CS_RETCODE CS_PUBLIC
servermsg_cb(context, connection, srvmsg);
CS_CONTEXT     *context;
CS_CONNECTION  *connection;
CS_SERVERMSG   *srvmsg;
{
/*
** CS_SERVERMSG Fields.
** ~~~~~~~~~~~~~~~~~~~
** When connected to an Adaptive Server, most of the CS_SERVERMSG fields
** have corresponding columns in the sysmessages system table. When
** connected to an Open Server, it's up to the Open Server programmer
** to set the fields for the messages sent by the Open Server.
*/
fprintf(ERR_CH, "Server message: ");
/*
** For Adaptive Server connections, srvmsg->number and srvmsg->severity come 
** from the sysmessages system table, columns 'error' and 'severity', 
** respectively.
*/
fprintf(ERR_CH, "Number %ld, Severity %ld, ",
long)srvmsg->msgnumber, (long)srvmsg->severity);
/*
** For Adaptive Server connections, srvmsg->line is the line number 
** in a language batch, or, if srvmsg->proclen field is > 0, the 
** line number within the stored procedure named in srvmsg->proc.
** srvmsg->state is the Adaptive Server error state, which provides
** information to Sybase Technical Support about serious Adaptive
** Server errors.
*/
fprintf(ERR_CH, "State %ld, Line %ld\n",
(long)srvmsg->state, (long)srvmsg->line);/*
** For Adaptive Server connections, srvmsg->srvname is the value of
** the @@servername global variable. See the Adaptive Server documentation
** for information on how to set or change @@servername.
*/
if (srvmsg->svrnlen > 0)
{
fprintf(ERR_CH, "Server '%s'\n", srvmsg->svrname);
}
/*
** For Adaptive Server connections, srvmsg->proclen is > 0 if the message
** was raised while executing a stored procedure. srvmsg->proc is the
** procedure name in this case, and srvmsg->line is the line in the
** procedure's code where the error or condition was raised.
*/
if (srvmsg->proclen > 0)
{
 fprintf(ERR_CH, " Procedure '%s'\n", srvmsg->proc);
}
/*
** Finally, for Adaptive Server connections, srvmsg->text is the text of the 
** message from the 'description' column in sysmessages.
*/
 fprintf(ERR_CH, "Message String: %s\n", srvmsg->text);
/*
** The Client-Library message handler must return CS_SUCCEED.
** Returning any other value "kills" the connection -- Client-
** Library responds by marking the connection "dead", which makes
** it unuseable.
*/
return CS_SUCCEED;
} /* servermsg_cb() */