Você está na página 1de 78

ASE103 Debugging Open Client and Open Server

Neal Stack Principal Product Support Engineer North America Customer Support and Service

Introduction and Course Contents

Dont gamble on resolving a problem without these debugging tips and techniques for Open Client and Open Server. Open Client and Open Server form the foundation of many Sybase products including OpenSwitch, DirectConnect, Replication Server, isql, bcp and the list goes on.

Introduction and Course Contents

For years, these APIs have allowed developers to retrieve and manipulate data from Adaptive Server Enterprise. Recent enhancements to the APIs will make life easier for developers debugging problems. Three major topics will be covered in this presentation:
Coding your Open Client application to use the new ct_debug(CS_DBG_PROTOCOL) API. A brief overview of Tabular Data Stream (TDS) How to code your Open Server to take advantage of recent enhancements to debugging APIs.

OPEN CLIENT & ct_debug(CS_DBG_PROTOCOL)


CS_DBG_PROTOCOL is a new trace flag which records all TDS tokens passed between a Sybase client and server without passing through an intermediate utility like Ribo.
This trace flag was added to OC 12.5.1 ESD#4 When is it appropriate to use this flag?
If you have a specific reproducible problem. If you are curious about what is happening!

Ribo might be more appropriate when you dont know which client will get an error or when the error might occur. It can add up to 30% overhead to the application but it is still generally quicker than using Ribo.

OPEN CLIENT & ct_debug(CS_DBG_PROTOCOL)


NOTE: Debug libraries ($SYBASE/$SYBASE_OCS/devlib) are not required to use CS_DBG_PROTOCOL unlike all of the other flags. It is available on all supported platforms.

OPEN CLIENT & ct_debug(CS_DBG_PROTOCOL)


Syntax overview for ct_debug()
CS_RETCODE ct_debug(context, connection, operation, flag, filename, fnamelen)
CS_CONTEXT CS_CONNECTION *context; *connection;
The CS_CONTEXT structure defines a Client-Library application context. A valid pointer to a CS_CONNECTION structure but no actual connection to a server is necessary to enable debug operations. When operation is CS_SET_PROTOCOL_FILE, connection must be supplied and context must be NULL.

CS_INT

operation;

The operation to perform (CS_SET_FLAG, CS_CLEAR_FLAG, CS_SET_DBG_FILE, CS_SET_PROTOCOL_FILE ).

OPEN CLIENT & ct_debug(CS_DBG_PROTOCOL)


Syntax overview for ct_debug() continued
CS_RETCODE ct_debug(context, connection, operation, flag, filename, fnamelen)
CS_INT flag;
A bitmask representing which operations to enable (CS_DBG_PROTOCOL, CS_SET_PROTOCOL_FILE, CS_DBG_API_STATES, CS_DBG_ASYNC, etc.).

CS_CHAR CS_INT

*filename; fnamelen;

The full path and name of the file to which ct_debug should write the generated debug information The length, in bytes, of filename, or CS_NULLTERM if filename is a nullterminated string

OPEN CLIENT & ct_debug(CS_DBG_PROTOCOL)


An example of ct_debug(CS_DBG_PROTOCOL)
Get a valid connection pointer and define the debug file:
/* ** First, allocate a connection structure. */ ret = ct_con_alloc(context, &connection); EXIT_ON_FAIL(context, ret, "ct_con_alloc() failed"); thread_id = pthread_self(); sprintf(tds_log_file, "./tds_thread_%d.tds", thread_id); ret = ct_debug(NULL, connection, CS_SET_PROTOCOL_FILE, CS_UNUSED, tds_log_file, CS_NULLTERM); EXIT_ON_FAIL(context, ret, "ct_debug PROTOCOL_FILE failed");

OPEN CLIENT & ct_debug(CS_DBG_PROTOCOL)


An example of ct_debug(CS_DBG_PROTOCOL) continued Enable the debug flag
ret = ct_debug(NULL, connection, CS_SET_FLAG, CS_DBG_PROTOCOL, NULL, CS_UNUSED); EXIT_ON_FAIL(context, ret, "ct_debug CS_DBG_PROTOCOL failed");

After recompiling, the application is ready to run. The output produced by the application is a raw binary format that must be converted to text. Next, we will look at the output from this flag during a brief overview of TDS.

OVERVIEW OF TABULAR DATA STREAM


Tabular Data Stream (TDS) is an application level protocol used to send requests and responses between clients and servers.
A clients request may contain multiple commands. The response from the server may return one or many result sets.
It is important to remember when looking at TDS, the REQUEST packet always comes from the client and the RESPONSE packet always comes from the server.

TDS provides support for login capability negotiation, authentication services, and support for both database specific and generic client commands. Responses to client commands are returned using a selfdescribing, table oriented protocol. Column name and data type information is returned to the client before the actual data.

OVERVIEW OF TABULAR DATA STREAM


A high level look at the TDS exchange between a client and server:

OVERVIEW OF TABULAR DATA STREAM


Detailed review of some TDS packets
Using the code sample from CS_DBG_PROTOCOL, we will review the output. Convert the raw TDS output from the sample to text
setenv RIBO_HOME /software/sybase125/jutils-2_0/ribo setenv JAVA_HOME /software/sybase125/shared-1_0/JRE-1_4 setenv CLASSPATH /software/sybase125/jConnect5_5/classes:/software/sybase125/jConnect5_5/classes/jconn2.jar:. cd $RIBO_HOME Ribo tds_thread_10.tds > tds_thread_10.txt

OVERVIEW OF TABULAR DATA STREAM


The TDS Login Packet:
Login Record; fixed length. Host Name [30]: "neals_solaris_box" Host Name Length [1]: 17 User Name [30]: root" User Name Length [1]: 4 Password [30]:rooter" Password Length [1]:6 Host Process [30]:"29096" Host Process Length [1]:5 Byte Ordering - int2 [1]: 2 Byte Ordering - int4 [1]: 0 Character Encoding [1]: 6 Float Format [1]: 4 Date Format [1]:8 Dialog Type [1]:0 Application Name [30]:Ghost" Application Name Length [1]:5 Service Name [30]:"stack1_125" Service Name Length [1]:10 Remote Passwords [255]: <universal>/<null> Remote Passwords Length [1]:2 TDS Version [4]:5.0.0.0 Prog Name [30]: "CT-Library" Prog Name Length [1]: 10 Prog Version [4]: 5.0.0.0 Convert Shorts [1]: 0 4-byte Float Format [1]:12 4-byte Date Format [1]: 16 Language [30]:"" Language Length [1]:0 Secure Login Flags [1]: UNUSED (0x00) Bulk Copy [1]:0 HA Login Flags [1]: 0x00 HA Session ID [6]:0x000000000000 Character Set [30]: "iso_1" Character Set Length [1]: 5 Packet Size [6]:3072 Packet Size Length [1]: 4

OVERVIEW OF TABULAR DATA STREAM


The TDS_LANGUAGE packet
Token used to send language commands
LANGUAGE Token (0x21); variable length. Length [4]: Status [1]: Text Length [0]: Text [85]: 86 UNUSED (0x00) [85] "select au_lname, city from pubs2..authors where state = 'CA'

Status indicates if parameters follow this token.


0x01 indicates that the command is parameterized and that PARAMFMT/PARAM tokens follow.

OVERVIEW OF TABULAR DATA STREAM


The TDS_ROWFMT2 packet
The token for describing the data type, length, and status of row data.
ROWFMT2 Token (0x61); Length [4]: 60 Number of Columns [2]: Column 1

Column Name Length [1]: Column Name [8]: Status [4]: (0x00000010) User Type [4]: Data Type [1]: Length [1]: Locale Length [1]:

8 "au_lname"

Column Label Length [1]: 8 Column Label [8]: "au_lname" Catalog Name Length [1]: 0 Schema Length [1]: 0 Table Name Length [1]: 7 Table Name [7]: "authors"

ROW_UPDATABLE 0x00000002 VARCHAR 40 0

OVERVIEW OF TABULAR DATA STREAM


The TDS_ROW packet
Token containing a row of data.
ROW Token (0xD1); variable length. Column 1 Length [1]: Row data [5]: Column 2 Length [1]: Row data [10]: 10 "Menlo Park" (0x4D656E6C6F205061726B) 5 "White" (0x5768697465)

OVERVIEW OF TABULAR DATA STREAM


The TDS_DONE packet
Indicates completion status of a command
DONE Token (0xFD); fixed length. Length [0]: [8] Status [2]: TranState [2]: Count [4]: DONE_COUNT (0x0010) TDS_TRAN_PROGRESS (0x0002) 15

Status indicates the completion status


TDS_DONE_FINAL, TDS_DONE_MORE, TDS_DONE_ERROR, TDS_DONE_INXACT, TDS_DONE_PROC, TDS_DONE_COUNT, TDS_DONE_ATTN, TDS_DONE_EVENT

TranState indicates the current transaction status


TDS_NOT_IN_TRAN, TDS_TRAN_SUCCEED, TDS_TRAN_PROGRESS, TDS_STMT_ABORT, TDS_TRAN_ABORT

Count indicates the number of rows affected (if any).

OVERVIEW OF TABULAR DATA STREAM


The TDS_DBRPC packet
Describes the data stream which contains a data base remote procedure call request.
DBRPC Token (0xE6); variable length. Length [2]: Name Length [1]: Name [10]: Options [2]: 13 10 "sample_rpc RPC_PARAMS (0x0002)

Options are options related to this RPC


TDS_RPC_UNUSED, TDS_RPC_RECOMPILE, TDS_RPC_PARAMS

OVERVIEW OF TABULAR DATA STREAM


The TDS_PARAMFMT packet
Token describing the data type, length, and status of TDS_PARAMS data.
PARAMFMT Token (0xEC); variable length. Length [2]: 138 Number of Params [2]: 7 Param 1 Name Length [1]: 9 Name [9]: "@intparam" Status [1]: <unrecognized> (0x00) User Type [4]: 0 Data Type [1]: INTN Length [1]: 4 Locale Length [1]: 0

OVERVIEW OF TABULAR DATA STREAM


The TDS_PARAMFMT packet continued
Token describing the data type, length, and status of TDS_PARAMS data.
Number of params indicates the number of parameters in the stream
Status describes any non-datatype characteristics of the data. TDS_PARAM_RETURN, TDS_PARAM_COLUMNSTATUS, TDS_PARAM_NULLALLOWED

OVERVIEW OF TABULAR DATA STREAM


The TDS_PARAMS packet
Token containing the actual parameter data
PARAMS Token (0xD7); variable length. Param 1 Length [1]: Param data [4]: Param 2 Length [1]: Param data [2]: Param 3 Length [1]: Param data [8]: 8 0.12 (0x0000000000000000) 2 234 (0x00EA) 4 2 (0x00000002)

OPEN SERVER DEBUGGING TIPS

The Open Server API srv_dbg_stack() was enhanced in 12.5.1 to support multithreaded Open Server applications. The section will provide a code sample illustrating how to use this API to capture a stack trace when a specific error occurs.

OPEN SERVER DEBUGGING TIPS

This section will also present a code sample illustrating how to enable some debug flags in Open Server that will record TDS via the srv_props(SRV_S_TRACEFLAG) API.

OPEN SERVER DEBUGGING TIPS

srv_dbg_stack() has been available for non-SMP platforms for a long time. The 12.5.1 enhancement makes it available to SMP Open Servers on Solaris and Linux.
srv_dbg_stack() displays the call stack of a thread Excellent API for capturing a stack trace when an Open Server encounters a specific error.

OPEN SERVER DEBUGGING TIPS

Syntax overview for srv_dbg_stack()


CS_RETCODE srv_dbg_stack(spp, depth, funcp)
SRV_PROC CS_INT CS_RETCODE *spp; depth; (*funcp)();
A pointer to an internal server thread control structure. The maximum number of call stack levels to display. If depth is -1, all levels are displayed. A pointer to a function that you provide to process each line of the call stack display. Your function is called with a pointer to a null terminated string and an integer that is the length of the string. The string contains the program counter and the routine's parameters formatted in hexadecimal. If your function returns CS_FAIL, the stack trace is terminated. If it returns anything else, the stack trace continues until all of the routines on the call stack are processed or until depth stack frames are processed. If funcp is NULL, Open Server writes the call stack contents to stderr.

OPEN SERVER DEBUGGING TIPS

An example of srv_dbg_stack()
Check to see if srv_dbg_stack() is currently supported:
printf("srv_dbg_stack supported? = %s\n", (srv_capability(SRV_C_DEBUG)?"YES":"NO"));

Invoke the srv_dbg_stack() API in your error handler:


if (errornum == 16331) srv_dbg_stack(srvproc, -1, NULL); if (errornum == 16269) srv_dbg_stack((SRV_PROC *)-1, -1, (CS_RETCODE(*)())callstack_display); if (errornum == 16240) srv_dbg_stack(srvproc, -1, NULL);

OPEN SERVER DEBUGGING TIPS

An example of srv_dbg_stack() continued


CS_RETCODE CS_PUBLIC callstack_display(linebuf, length) CS_CHAR *linebuf; CS_INT length; { /* ** Output each line of the stack trace to stderr and record it in the log file. */ fprintf(stderr,"%s\n", linebuf); srv_log(NULL, CS_FALSE, linebuf, length); srv_log(NULL, CS_FALSE, "\n", 1); return(CS_SUCCEED); }

OPEN SERVER DEBUGGING TIPS

Output of Open Server error 16240 in Open Server error log without using srv_dbg_stack():
Jul 26 12:15:11 2005: Sybase Server-Library/12.5.1/P-EBF11883-11882 ESD #3/DRV.12.5.1.1/SPARC/Solaris 2.8 Native Threads/BUILD1251-036/OPT/Wed May 5 21:21:44 2004Jul 26 12:15:11 2005: Sybase Client-Library/12.5.1/P-EBF11882 ESD #3/DRV.12.5.1.1/SPARC/Solaris 2.8 Native Threads/BUILD1251-036/OPT/Wed May 5 21:20:14 2004 Jul 26 12:15:48 2005: Server Message: nstackpc2 - 5704/10/1: Changed client character set setting to 'iso_1'. Jul 26 12:15:48 2005: Server Message: nstackpc2 - 5701/10/2: Changed database context to 'master'. Jul 26 12:15:48 2005: Server Message: nstackpc2 - 5703/10/1: Changed language setting to 'us_english'. Jul 26 12:17:22 2005: SRVLIB Message: WINGNUT_SWITCH1 - 16240/10/0: Net-Library routine failed in srv__io_check Network error: status = 32 - Net-Lib protocol driver call to read data failed Jul 26 12:17:22 2005: [error.c/639] ctos_sendinfo(): Thread's I/O is dead! Jul 26 12:17:22 2005: [results.c/726] ctos_procrows(): srv_xferdata(CS_SET) failed!

OPEN SERVER DEBUGGING TIPS

Output of Open Server error 16240 in Open Server error log with srv_dbg_stack():
Jul 26 12:15:11 2005: Sybase Server-Library/12.5.1/P-EBF11883-11882 ESD #3/DRV.12.5.1.1/SPARC/Solaris 2.8 Native Threads/BUILD1251-036/OPT/Wed May 5 21:21:44 2004Jul 26 12:15:11 2005: Sybase Client-Library/12.5.1/P-EBF11882 ESD #3/DRV.12.5.1.1/SPARC/Solaris 2.8 Native Threads/BUILD1251-036/OPT/Wed May 5 21:20:14 2004 Jul 26 12:15:48 2005: Server Message: nstackpc2 - 5704/10/1: Changed client character set setting to 'iso_1'. Jul 26 12:15:48 2005: Server Message: nstackpc2 - 5701/10/2: Changed database context to 'master'. Jul 26 12:15:48 2005: Server Message: nstackpc2 - 5703/10/1: Changed language setting to 'us_english'.

OPEN SERVER DEBUGGING TIPS

Jul 26 12:17:22 2005: SRVLIB Message: WINGNUT_SWITCH1 - 16240/10/0: Net-Library routine failed in srv__io_check Network error: status = 32 - Net-Lib protocol driver call to read data failed Jul 26 12:17:22 2005: [error.c/639] ctos_sendinfo(): Thread's I/O is dead! Open Server Process ID: 0, SRV_PROC address 0xdd380 Start of stack trace for spid 0. Native thread #7, FramePointer: 0xfe8fb840 0xfefb4c8c setitimer (0x5, 0x0, 0xfe8fba68, 0xff14b060, 0x0, 0x0) +0xfc 0xfefafadc sema_post (0xfee30a00, 0x7, 0xfefc7820, 0xfe8fba68, 0x0, 0x5) +0x510 0xfefafca8 sema_post (0xfee30a00, 0x0, 0xfe8fba68, 0xfefc6000, 0x0, 0x5) +0x6dc 0xfefb2448 _cond_init (0x1, 0x4feab0, 0x0, 0xfee4ea80, 0x0, 0xfefc6000) +0x1ac 0xfefb2bcc cond_wait (0x4feaa0, 0x4feab0, 0x4feaa0, 0x0, 0x0, 0x0) +0x10 0xfefb2c08 pthread_cond_wait (0x4feaa0, 0x4feab0, 0xfe8fbed0, 0xfe8fbea4, 0x4fea78, 0x0) +0x8 0xff13fe04 comn_waitfor_event (0x4fea98, 0xffffd8f1, 0xfe8fbf38, 0xfe8fbf0c, 0x0, 0x0) +0x1e4 0xff262b30 srv__dq_event (0xdd380, 0xffffd8f1, 0x0, 0x0, 0x0, 0x0) +0x40 0xff262e98 srv__start_function (0xdd380, 0xfee30a00, 0x0, 0x0, 0x0, 0x0) +0x1c0 0xfefb4934 _resume_ret (0x0, 0x0, 0x0, 0x0, 0x0, 0x0) +0x298 End of stack trace for spid 0.

OPEN SERVER DEBUGGING TIPS

Open Server Process ID: 2, SRV_PROC address 0xddba8 Start of stack trace for spid 2. Native thread #9, FramePointer: 0xfe67b8c0 0xfefb4c8c setitimer (0x5, 0x0, 0xfe67bae8, 0xff14b060, 0x0, 0x0) +0xfc 0xfefafadc sema_post (0xfee30e00, 0x9, 0xfefc7820, 0xfe67bae8, 0x0, 0x5) +0x510 0xfefafca8 sema_post (0xfee30e00, 0x0, 0xfe67bae8, 0xfefc6000, 0x0, 0x5) +0x6dc 0xfefada58 poll (0xfe67be90, 0xfee30e00, 0x3e8, 0x1, 0xfe67be90, 0x505171) +0x5c 0xff1c57d0 sybnet__complete_io (0xff1d792c, 0x92c80, 0x0, 0x50513c, 0xfe67bf04, 0x0) +0x194 0xff221c44 srv__conservice (0x505b28, 0xffffd8f1, 0x0, 0x0, 0x0, 0x0) +0x8c 0xff262e98 srv__start_function (0xddba8, 0xfee30e00, 0x0, 0x0, 0x0, 0x0) +0x1c0 0xfefb4934 _resume_ret (0x0, 0x0, 0x0, 0x0, 0x0, 0x0) +0x298 End of stack trace for spid 2.

OPEN SERVER DEBUGGING TIPS

Open Server Process ID: 3, SRV_PROC address 0xddfbc Start of stack trace for spid 3. Native thread #10, FramePointer: 0xfe57b768 0xfefb4c8c setitimer (0x5, 0x0, 0xfe57b990, 0xff14b060, 0x0, 0x0) +0xfc 0xfefafadc sema_post (0xfee31000, 0xa, 0xfefc7820, 0xfe57b990, 0x0, 0x5) +0x510 0xfefafca8 sema_post (0xfee31000, 0x0, 0xfe57b990, 0xfefc6000, 0x0, 0x5) +0x6dc 0xfefb2448 _cond_init (0x1, 0x5009d8, 0x0, 0xfee48e40, 0x0, 0xfefc6000) +0x1ac 0xfefb2bcc cond_wait (0x5009c8, 0x5009d8, 0x5009c8, 0xff3e2628, 0x2962c, 0xff3c2a64) +0x10 0xfefb2c08 pthread_cond_wait (0x5009c8, 0x5009d8, 0xfe57bdf8, 0xfe57bdcc, 0xff3e2628, 0x0) +0x8 0xff13fe04 comn_waitfor_event (0x5009c0, 0xffffd8f1, 0x0, 0xff2f0384, 0x0, 0xff2041ad) +0x1e4 0xff22fa00 srv__obj_sleep (0xddfbc, 0xa3080, 0xffffd8f1, 0x40, 0x0, 0xfee31098) +0x68 0xff22e3e0 srv_getmsgq (0xddfbc, 0xfe57bf34, 0x10, 0xfe57bf30, 0xfffffff7, 0x0) +0x268 0xff2246dc srv__rundef (0xddfbc, 0xffffd8f1, 0x0, 0x0, 0x0, 0x0) +0x38 0xff262e98 srv__start_function (0xddfbc, 0xfee31000, 0x0, 0x0, 0x0, 0x0) +0x1c0 0xfefb4934 _resume_ret (0x0, 0x0, 0x0, 0x0, 0x0, 0x0) +0x298 End of stack trace for spid 3.

OPEN SERVER DEBUGGING TIPS

Open Server Process ID: 5, SRV_PROC address 0xde7e4 Start of stack trace for spid 5. Native thread #12, FramePointer: 0xfe47b2b8 0xfefb4c8c setitimer (0x5, 0x0, 0xfe47b4e0, 0xff14b060, 0x0, 0x0) +0xfc 0xfefafadc sema_post (0xfee31200, 0xc, 0xfefc7820, 0xfe47b4e0, 0x0, 0x5) +0x510 0xfefafca8 sema_post (0xfee31200, 0x0, 0xfe47b4e0, 0xfefc6000, 0x0, 0x5) +0x6dc 0xfefb1500 mutex_init (0xfee31200, 0xfefc6b6c, 0x500ca8, 0xfefc6000, 0x1, 0x500cb0) +0x1068 0xfefb1bdc mutex_init (0x500ca8, 0xfee31200, 0x500ca8, 0x74, 0x0, 0xfe47b8b9) +0x1744 0xff13f8a8 comn_take_mutex (0x500ca0, 0x56d830, 0x51fa48, 0x22, 0x25a044, 0x0) +0x50 0xff24c898 srv__st_transition (0xde7e4, 0x1d, 0x3e9, 0x0, 0xff254f84, 0x0) +0x50 0xff254f98 srv_xferdata (0xde7e4, 0x22, 0x2, 0xfffe7961, 0x0, 0x56ed68) +0xf0 0x0002a994 ctos_procrows (0x22, 0x2, 0x6, 0xfe47bd68, 0xfffe7961, 0x0) +0x6b4 0x00029998 ctos_results (0xde7e4, 0x51e850, 0x94, 0x0, 0xfe47bd68, 0x0) +0x498 0x000271d0 ctos_language_passthru (0xde7e4, 0x508540, ..., 0x0) +0x3f0 0x00026700 ctos_language_handler (0xde7e4, 0x16bc, 0x39c30, , , 0xfee31298) +0x270 0xff25bbcc srv__exechandler (0xde7e4, 0x3, 0x10, 0xfe47be40, 0x0, 0xfe47bdc0) +0x104 0xff25b7f0 srv__runclient (0x0, 0xff27aac0, 0xde7e4, 0x238778, 0x238790, 0x238760) +0x2e8 0xff233a48 srv__connhandle (0xde7e4, 0xffffd8f1, 0x0, 0x0, 0x0, 0x0) +0x3b0 0xff262e98 srv__start_function (0xde7e4, 0xfee31200, 0x0, 0x0, 0x0, 0x0) +0x1c0 0xfefb4934 _resume_ret (0x0, 0x0, 0x0, 0x0, 0x0, 0x0) +0x298 End of stack trace for spid 5. Jul 26 12:17:22 2005: [results.c/726] ctos_procrows(): srv_xferdata(CS_SET) failed!

OPEN SERVER DEBUGGING TIPS

Syntax overview for the srv_props(SRV_S_TRACEFLAG) API


CS_RETCODE srv_props(cp, cmd, property, bufp, buflen, outlenp)
CS_CONTEXT *cp;
A pointer to a CS_CONTEXT structure previously allocated using cs_ctx_alloc.

CS_INT cmd;
The action to take (CS_GET, CS_SET, CS_CLEAR)

CS_INT property;
Which property to apply the action to.

OPEN SERVER DEBUGGING TIPS

Syntax overview for the srv_props(SRV_S_TRACEFLAG) API


CS_RETCODE srv_props(cp, cmd, property, bufp, buflen, outlenp)
CS_VOID *bufp;
A pointer to the Open Server application data buffer where property value information is placed (CS_SET) or property value information is retrieved (CS_GET).

CS_INT buflen;
The length, in bytes, of the buffer.

CS_INT *outlenp;
A pointer to a CS_INT variable, which Open Server will set to the size, in bytes, of the property value retrieved. This argument is only used when cmd is CS_GET, and is optional.

OPEN SERVER DEBUGGING TIPS

An example of srv_props(SRV_S_TRACEFLAG)
This example will illustrate how to enable trace flags dynamically. We will create a registered procedure that a user can call to enable/disable the flags.
1> WINGNUT_SWITCH1...rp_traceflag a, 1 2> go

Function prototype:
CS_RETCODE CS_PUBLIC rp_traceflag PROTOTYPE(( SRV_PROC* ));

Global variable representing flag bitmask:


CS_INT srv_trace_flags=0;

OPEN SERVER DEBUGGING TIPS


Data structure used in program:
static struct { CS_INT flag; CS_CHAR flag_name; CS_CHAR *flag_description; } sg_flagtable[] = { { SRV_TR_ATTN, 'a', { SRV_TR_EVENT, 'e', { SRV_TR_TDSDATA, 'd', { SRV_TR_TDSHDR, 'h', { 0, ' ', };

"Attention Acknowledgement", }, "Event Handling", }, "TDS Data Packets", }, "TDS Header Packets", }, NULL, },

OPEN SERVER DEBUGGING TIPS

The definition of the rp_traceflag() function:


CS_RETCODE rp_traceflag(srvproc) SRV_PROC *srvproc; { CS_CHAR CS_INT CS_DATAFMT CS_INT CS_SMALLINT flag_name[30], flag_description[30]; flag_on_off; charfmt, intfmt, return_row; flag_name_len, on_off_len, flag_desc_len; flag_name_null, on_off_null, flag_desc_null;

CS_CONTEXT *context; CTOS_CTX *ctos_ctx; CS_INT i;

OPEN SERVER DEBUGGING TIPS


Definition of rp_traceflag() function continued:
srv_bzero( (CS_VOID*)&charfmt, CS_SIZEOF(charfmt) ); srv_descfmt(srvproc, CS_GET, SRV_RPCDATA, 1, &charfmt); flag_name_len = charfmt.maxlength; if (srv_bind( srvproc, CS_GET, SRV_RPCDATA, 1, &charfmt, (CS_BYTE*)flag_name, &flag_name_len, NULL) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_bind(flag_name) failed!"); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS


Definition of rp_traceflag() function continued:
srv_bzero( (CS_VOID*)&intfmt, CS_SIZEOF(intfmt) ); srv_descfmt(srvproc, CS_GET, SRV_RPCDATA, 2, &intfmt); on_off_len = intfmt.maxlength; if (srv_bind( srvproc, CS_GET, SRV_RPCDATA, 2, &intfmt, (CS_BYTE*)&flag_on_off, &on_off_len, NULL) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_bind(flag_on_off) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS


Definition of rp_traceflag() function continued:
/* Transfer parameters from the client to the Open Server. */ if (srv_xferdata( srvproc, CS_GET, SRV_RPCDATA ) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_xferdata(CS_GET, SRV_RPCDATA) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS


Definition of rp_traceflag() function continued:
/* Determine which flag was sent and add it to bit mask. */ switch (flag_name[0]) { case 'd': if (flag_on_off == 1) srv_trace_flags |= SRV_TR_TDSDATA; else srv_trace_flags &= ~(SRV_TR_TDSDATA); break; case 'h': if (flag_on_off == 1) srv_trace_flags |= SRV_TR_TDSHDR; else srv_trace_flags &= ~(SRV_TR_TDSHDR); break;

OPEN SERVER DEBUGGING TIPS


Definition of rp_traceflag() function continued:
case 'e': if (flag_on_off == 1) srv_trace_flags |= SRV_TR_EVENT; else srv_trace_flags &= ~(SRV_TR_EVENT); break; case 'a': if (flag_on_off == 1) srv_trace_flags |= SRV_TR_ATTN; else srv_trace_flags &= ~(SRV_TR_ATTN); break; default: break; }

OPEN SERVER DEBUGGING TIPS


Definition of rp_traceflag() function continued:
/* Grab CS_CONTEXT pointer and set bit mask. */ if (ctos_context(&ctos_ctx) == CS_SUCCEED) { context = ctos_ctx->cx_context; } if (srv_props(context, CS_SET, SRV_S_TRACEFLAG, &srv_trace_flags, CS_SIZEOF(CS_INT), (CS_INT *)NULL) != CS_SUCCEED) { fprintf(stderr,"Failed to set SRV_S_TRACEFLAG.\n"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return CS_FAIL; }

OPEN SERVER DEBUGGING TIPS


Definition of rp_traceflag() function continued:
/* Initialize first return columns to let user know which (if any flags are enabled. */ strcpy( (char*)return_row.name, "flag" ); return_row.namelen = 4; return_row.status = CS_CANBENULL; return_row.datatype = CS_CHAR_TYPE; return_row.maxlength = 1; return_row.format = CS_FMT_UNUSED; return_row.count = 1; return_row.locale = NULL;

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


if (srv_descfmt( srvproc, CS_SET, SRV_ROWDATA, (CS_INT)1, &return_row ) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_descfmt(CS_SET, SRV_ROWDATA) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


if (srv_bind( srvproc, CS_SET, SRV_ROWDATA, (CS_INT)1, &return_row, (CS_BYTE*)flag_name, &flag_name_len, &flag_name_null ) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_bind(CS_SET, SRV_ROWDATA) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Initialize second return column. */ strcpy( (char*)return_row.name, "description" ); return_row.namelen = 11; return_row.status = CS_CANBENULL; return_row.datatype = CS_CHAR_TYPE; return_row.maxlength = CS_SIZEOF(flag_description); return_row.format return_row.locale return_row.count = CS_FMT_UNUSED; = NULL; = 1;

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Describe second return column to client. */ if (srv_descfmt( srvproc, CS_SET, SRV_ROWDATA, (CS_INT)2, &return_row ) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_descfmt(CS_SET, SRV_ROWDATA) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Bind program data to second return column. */ if (srv_bind( srvproc, CS_SET, SRV_ROWDATA, (CS_INT)2, &return_row, (CS_BYTE*)flag_description, &flag_desc_len, &flag_desc_null ) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_bind(CS_SET, SRV_ROWDATA) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Initialize third return column. */ strcpy( (char*)return_row.name, "state" ); return_row.namelen = 5; return_row.status = CS_CANBENULL; return_row.datatype = CS_INT_TYPE; return_row.maxlength = CS_SIZEOF(CS_INT); return_row.format return_row.locale return_row.count = CS_FMT_UNUSED; = NULL; = 1;

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Describe third column */ if (srv_descfmt( srvproc, CS_SET, SRV_ROWDATA, (CS_INT)3, &return_row ) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_descfmt(CS_SET, SRV_ROWDATA) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Bind program data to third column. */ if (srv_bind( srvproc, CS_SET, SRV_ROWDATA, (CS_INT)3, &return_row, (CS_BYTE*)&flag_on_off, &on_off_len, &on_off_null ) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_bind(CS_SET, SRV_ROWDATA) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Start sending rows of data back to client. */ for (i = 0; sg_flagtable[i].flag_description != NULL; i++) { flag_name[0] = sg_flagtable[i].flag_name; flag_name_len = 1; flag_name_null = CS_GOODDATA; strcpy(flag_description, sg_flagtable[i].flag_description); flag_desc_len = strlen(flag_description); flag_desc_null = CS_GOODDATA;

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


on_off_len = CS_SIZEOF(CS_INT); on_off_null = CS_GOODDATA; if (sg_flagtable[i].flag & srv_trace_flags) flag_on_off = 1; else flag_on_off = 0;

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Actual send of the data. */ if (srv_xferdata( srvproc, CS_SET, SRV_ROWDATA ) != CS_SUCCEED) { CTOS_RAISEERROR("rp_traceflag", "srv_xferdata(CS_GET, SRV_RPCDATA) failed!"); (CS_VOID)srv_senddone(srvproc, SRV_DONE_ERROR, CS_TRAN_UNDEFINED, 0); return (CS_FAIL); } }

OPEN SERVER DEBUGGING TIPS

Definition of rp_traceflag() function continued:


/* Sending of rows complete. Tell client we are done and the number of rows we sent. */ srv_senddone( srvproc, SRV_DONE_MORE|SRV_DONE_COUNT, CS_TRAN_UNDEFINED, 1 ); srv_sendstatus( srvproc, 0 ); srv_senddone( srvproc, SRV_DONE_FINAL, CS_TRAN_UNDEFINED, 0 ); }

OPEN SERVER DEBUGGING TIPS


Register rp_traceflag procedure and it's parameters for enabling and disabling trace flags.
if (srv_regdefine(srvproc, "rp_traceflag", CS_NULLTERM, (SRV_EVENTHANDLE_FUNC)rp_traceflag) != CS_SUCCEED) { CTOS_RAISEERROR("ctos_installregproc", "srv_regdefine(rp_traceflag) failed!"); return (CS_FAIL); } if (srv_regparam(srvproc, "@flag_name", CS_NULLTERM, CS_CHAR_TYPE, SRV_NODEFAULT, (CS_BYTE *)NULL) != CS_SUCCEED) { CTOS_RAISEERROR("ctos_installregproc", "srv_regdefine(rp_traceflag) failed!"); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS


Registering the rp_traceflag procedure continued...
if (srv_regparam(srvproc, "@flag_on_off", CS_NULLTERM, CS_INT_TYPE, SRV_NODEFAULT, (CS_BYTE *)NULL) != CS_SUCCEED) { CTOS_RAISEERROR("ctos_installregproc", "srv_regdefine(rp_traceflag) failed!"); return (CS_FAIL); } if (srv_regcreate(srvproc, NIL(CS_INT *)) != CS_SUCCEED) { CTOS_RAISEERROR("ctos_installregproc", "srv_regcreate(rp_traceflag) failed!"); return (CS_FAIL); }

OPEN SERVER DEBUGGING TIPS


Example of rp_traceflag in action:
Log into ASE and send the command to the Open Server:
% isql Usa P SASE 1> WINGNUT_SWITCH1...rp_traceflag a, 1 2> go flag description state ---- ------------------------------------------------------------ ----------a Attention Acknowledgement 1 e Event Handling 0 d TDS Data Packets 0 h TDS Header Packets 0 (1 row affected) (return status = 0)

OPEN SERVER DEBUGGING TIPS

Understanding rp_traceflag output


rp_traceflag h,1 (SRV_TR_TDSHDR)
Displays header information from each packet spid 7 - read: login, not eom, len=512, chan=0, pack=0, win=0, client spid 7 - read: login, eom, len=99, chan=0, pack=0, win=0 spid 8 - read: normal, eom, len=76, chan=0, pack=0, win=0 spid 8 - write: normal, not eom, len=512, chan=0, pack=1, win=0 spid 8 - write: normal, not eom, len=512, chan=0, pack=1, win=0 spid 8 - write: normal, eom, len=64, chan=0, pack=1, win=0

OPEN SERVER DEBUGGING TIPS


Understanding rp_traceflag output
Compare that output to what we get from Ribo:
PDU Header TDS Packet Type [1]: BUF_LOGIN (0x02) Status [1]: BUFSTAT_BEGIN (0x00) Length [2]: 512 Channel [2]: 0 Packet No. [1]: 0 Window [1]: 0 Capture Record Header Source [4]: REQUEST (0x00000001) Length [4]: 99 PDU Header TDS Packet Type [1]: BUF_LOGIN (0x02) Status [1]: BUFSTAT_EOM (0x01) Length [2]: 99 Channel [2]: 0 Packet No. [1]: 0 Window [1]: 0

OPEN SERVER DEBUGGING TIPS

Understanding rp_traceflag output


rp_traceflag d,1 (SRV_TR_TDSDATA)
Displays data received from client & server
========================================================================== 0x2100 0x0000 0x0b00 0x7573 0x6520 0x7075 0x6273 0x320a | ! use pubs2 ========================================================================== Jul 28 13:22:13 2005: Server Message: nstackpc2 - 5701/10/1: Changed database context to 'pubs2'. 0xe500 0x4300 0x0016 0x4501 0x0a05 0x5a5a 0x5a5a 0x5a00 | C E ZZZZZ 0x0000 0x0025 0x4368 0x616e 0x6765 0x6420 0x6461 0x7461 | %Changed data 0x6261 0x7365 0x2063 0x6f6e 0x7465 0x7874 0x2074 0x6f20 | base context to 0x2770 0x7562 0x7332 0x272e 0x0a09 0x6e73 0x7461 0x636b | 'pubs2'. nstack 0x7063 0x3200 0x0001 0xfd00 0x0000 0x0000 0x0000 0x00.. | pc2 ==========================================================================

OPEN SERVER DEBUGGING TIPS


Understanding rp_traceflag output
Compared to Ribo output:
LANGUAGE Token (0x21); variable length. Length [4]: 11 Status [1]: UNUSED (0x00) Text Length [0]: [10] Text [10]: "use pubs2" Capture Record Header Source [4]: RESPONSE (0x00000002) Length [4]: 105 ENVCHANGE Token (0xE3); variable length. Length [2]: 14 Type [1]: ENV_DB (0x01) Length of New Value [1]: 5 New Value [5]: "pubs2" Length of Old Value [1]: 6 Old Value [6]: "master"

OPEN SERVER DEBUGGING TIPS

Understanding rp_traceflag output


rp_traceflag h,1 (SRV_TR_EVENT)
Displays event handler information
Jul 26 15:10:38 2005: spid 8 - Returned from SRV_CONNECT event handler. Jul 26 15:10:45 2005: spid 8 - Calling the SRV_LANGUAGE event handler. Jul 26 15:10:46 2005: spid 9 - Calling the SRV_CONNECT event handler. Jul 26 15:10:46 2005: spid 9 - Returned from SRV_CONNECT event handler. Jul 26 15:10:46 2005: spid 9 - Calling the registered procedure sp_who handler. Jul 26 15:10:46 2005: spid 9 - Returned from the handler. Jul 26 15:10:46 2005: spid 9 - Calling the SRV_DISCONNECT event handler. Jul 26 15:10:46 2005: spid 9 - Returned from SRV_DISCONNECT event handler. Jul 26 15:10:46 2005: spid 8 - Returned from SRV_LANGUAGE event handler. Jul 26 15:10:47 2005: spid 8 - Calling the SRV_DISCONNECT event handler. Jul 26 15:10:47 2005: spid 8 - Returned from SRV_DISCONNECT event handler.

OPEN SERVER DEBUGGING TIPS

Understanding rp_traceflag output


rp_traceflag h,1 (SRV_TR_ATTN)
Displays attention receipt and acknowledgement from cancel requests.

Jul 26 15:14:18 2005: Attention received by thread spid=7 Jul 26 15:14:20 2005: srv_senddone(): Sending attention acknowledgement: spid=7

OPEN SERVER DEBUGGING TIPS


Understanding rp_traceflag output
Compared to Ribo output:
DONE Token (0xFD); fixed length. Length [0]: [8] Status [2]: DONE_COUNT + DONE_ATTN (0x0030) TranState [2]: TDS_TRAN_PROGRESS (0x0002) Count [4]: 2630 Capture Record Header Source [4]: REQUEST (0x00000001) Length [4]: 8 PDU Header TDS Packet Type [1]: BUF_ATTN (0x06) Status [1]: BUFSTAT_EOM (0x01) Length [2]: 8 Channel [2]: 0 Packet No. [1]: 0 Window [1]: 0

MISCELLANEOUS TIPS AND TRICKS

On different platforms, there are other various utilities that can aid in debugging Open Client and Server problems.
Ethereal network protocol analyzer
Can be obtained free under GNU license at www.ethereal.com Available on just about any platform. From Apple to Suse Linux to Microsoft Windows. Can capture live network data or read network dumps from other network trace utilities like snoop. It has built in filters for dissecting many protocols including Sybase TDS.

MISCELLANEOUS TIPS AND TRICKS

Solaris has several utilities that are very helpful.


The proc family of commands: pflags, pcred, pmap, pldd, psig, pstack, pfiles, pwdx, pstop, prun, pwait, ptree, ptime An example of pstack on a running process. It can also be run on a core file of an application that crashed.

MISCELLANEOUS TIPS AND TRICKS

Solaris has several utilities that are very helpful.


% pstack 1589 1589: ctos ----------------- lwp# 1 / thread# 4 -------------------- ff19e5c8 read ----------------- lwp# 2 / thread# 2 ------------------- ----------------- lwp# 3 / thread# 10 -------------------ff19d344 poll (fe40fb4c, 1, 3e8) 00223ed4 sybnet__complete_io (b2d8fc, fffffffd, ffffd8f1, 0, 0, b2d931) + 284 00216f7c sybnet_accept (b2d888, b2bab8, fe40fc58, b6940, fe40fc58, 0) + 254 00126908 srv__conservice (420ad0, ffffd8f1, 0, 0, 0, 0) + 140 00101298 srv__start_function (496ab0, ff0e5d10, 0, 5, 1,ffe401000) + 3c8 ff25b744 _thread_start (496ab0, 0, 0, 0, 0, 0) + 40 (3, fee0bd0f, 1)

MISCELLANEOUS TIPS AND TRICKS

Solaris has several utilities that are very helpful.


-------------------------- thread# 1 -------------------ff24826c cond_wait (409d30, 0, 0, ff26e000, 0, b27610) + 13c ff248110 pthread_cond_wait (b27600, b27610, ffffffff, ffbeebe0, fffffffe, 0) + 8 002bc7c4 comn_waitfor_event (b275f8, ffffd8f1, 0, 0, 0, 0) + 2e4 00100968 srv__hibernate (1, 8800, 10c2b0, 496ec4, 8, 0) + a0 000f856c srv_run (0, 406cc0, ff1c3a4c, ff1bfc70, 0, 0) + 2d4 000794b8 main (1, ffbef1cc, ffbef1d4, 33bc00, 0, 0) + 200 00074100 _start (0, 0, 0, 0, 0, 0) + 108 ----------------- lwp# 5 / thread# 13 -------------------ff19d344 poll (fe20b134, 1, 3e8) 00223ed4 sybnet__complete_io (b2bb60, fffffffd, ffffd8f1, fffffff8, 0, b2bb95) + 284 00217ce8 sybnet_write (b2bab8, 4978c8, 121c20, 4976ec, ffffd8f1, 1) + 370

MISCELLANEOUS TIPS AND TRICKS

0012045c srv__write_packet (1, 1, 0, 4, 20, 51a8fe) + 314 0011fed4 srv__sendclient (4976ec, b55188, 71, 441, d1, 51a8f1) + fc 000fa38c srv__putchar (4976ec, 2, b55188, 71, b55188, fe20b4ac) + 1dc 000fa0b0 srv__sendchar (4976ec, b54b8c, b55188, 71, 0, fe20b559) + 6f8 000ddba8 srv__tds_senddata (4976ec, d1, b53968, 22, 25a044, 0) + 450 000f3ff4 srv__rowsetxfer (4976ec, 2, 22, 3e9, 22, 3a7a44) + 2c4 000f5210 srv_xferdata (4976ec, 22, 2, fffe7961, 0, b566c0) + 148 000870e4 ctos_procrows (22, 2, 6, fe20ba50, fffe7961, 0) + 6b4 000860e8 ctos_results (4976ec, b51c18, 94, 0, fe20ba50, 0) + 488 00082dd0 ctos_language_passthru (4976ec, b311f0, fe20ba50, b2a110, b29f40, 0) + 3f0 00082300 ctos_language_handler (4976ec, ff26e000, 1, b292d8, 0, 0) + 270 000f9118 srv__exechandler (4976ec, 3, 10, fe20bb54, b2f595, 5) + 1b0 000f8ac0 srv__runclient (4976ec, 4976ec, 0, fffff800, 0, 409b11) + 508 0012cf64 srv__connhandle (4976ec, ffffd8f1, 0, 0, 0, 0) + 5fc 00101298 srv__start_function (4976ec, ff0e5d10, 0, 5, 1, fe401000) + 3c8 ff25b744 _thread_start (4976ec, 0, 0, 0, 0, 0) + 40

MISCELLANEOUS TIPS AND TRICKS

Another useful utility traces programs while they are running. The name and capabilities of the utility vary from platform to platform:
The truss utility is available on Solaris.
Unlike the trace utilities on other platforms, truss can display the function calls made by the application as well as the Sybase libraries it loads. Example syntax: truss -fdD -u"a.out,libct_r,libsrv_r" -o test.txt -p 1589

MISCELLANEOUS TIPS AND TRICKS

Example truss output


If you were only looking for something related to connection establishment, you might grep i connect test.txt:
1589/14: 1589/14: 1589/14: 1589/14: 1589/14: 1589/14: 1589/14: 1589/14: 1589/14: 1589/14: 1589/14: 1589/14: 11.4888 0.0005 11.5252 0.0005 11.5274 0.0005 11.5531 0.0005 11.5809 0.0004 11.6058 0.0005 11.6114 0.0005 11.6136 0.0005 16.4259 0.0005 16.4363 0.0005 16.4403 0.0005 16.4409 0.0006 -> ct_connect(0xb311f0, 0xffbefaec, 0xfffffff7, 0xfe20b8ac) -> ct__pchk_connect(0xb311f0, 0xffbefaec, 0xfffffff7, 0xd) <- ct__pchk_connect() = 1 -> ct__api_connect_async(0xb311f0, , 0xfffffff7, 0xd) -> ct_tds_connect(0xb311f0, 0x1, 0x9, 0x4201d0) -> np_io_connect(0xb35778, 0xb48858, , 0xb368e0) <- np_io_connect() = 1 <- ct_tds_connect() = 1 -> np__conn_doconnect(0xb35778, , , 0x1) -> sybnet_connect(0xb4dbf8, , 0x0, 0xb35778) -> sybnet_connect_localize_driver() <- sybnet_connect_localize_driver() = 0

MISCELLANEOUS TIPS AND TRICKS

1589/14: 16.6854 0.0005 -> sybnet__connect_call() 1589/14: 16.6860 0.0006 -> sybnet__flt_connect() 1589/14: 16.6866 0.0006 -> sybtcp_connect() 1589: 16.7042 0.0008 connect(259, 0x00B4DCF0, 16, 4) =0 1589/14: 16.7285 0.0005 <- sybtcp_connect() = 0 1589/14: 21.2336 0.0005 <- sybnet__flt_connect() = 0 1589/14: 21.2341 0.0005 <- sybnet__connect_call() = 0 1589/14: 21.2361 0.0005 <- sybnet_connect() = 0 1589/14: 21.2382 0.0005 <- np__conn_doconnect() = 1 1589/14: 21.2397 0.0005 -> np__conn_evalconnect() 1589/14: 21.2981 0.0005 <- np__conn_evalconnect() = 1 1589/14: 32.9057 0.0005 -> ct__50cont_connect() 1589/14: 32.9162 0.0005 <- ct__50cont_connect() = 1 1589/14: 32.9835 0.0005 <- ct__api_connect_async() = 1 1589/14: 32.9856 0.0005 <- ct_connect() = 1

MISCELLANEOUS TIPS AND TRICKS

Additional trace utilities available on other platforms:


On HP there is the tusc utility.
It does not have the ability to trace application or library function calls. Example syntax:
tusc -o <filename> -f -l -n -p -v -T "%H:%M:%S" <pid>

Linux has strace.


It also does not trace function calls. Example syntax:
strace o <filename> -ff tt p <pid>

AIX has its own truss utility but does not trace function calls either. Example syntax:
truss -f -a -e -o test.txt -p 113888

IN CONCLUSION

If you wait until a problem arises before you add these APIs, you could lose precious days if your company has QA cycles that your product must go through before any changes are allowed to go into production. So dont gamble that a problem wont happen and that you wont need to use these APIs, tips and tricks!!!

IN CONCLUSION

New APIs like ct_debug(CS_DBG_PROTOCOL) make it quick and easy to record Sybase TDS when you encounter a problem. It eliminates the need (in most cases) to run the client application through an intermediate utility like Ribo. Updated debugging APIs like srv_props(SRV_S_TRACEFLAG) give more developers more details on problems than ever before. It takes some time and practice to understand the output created by these APIs. However, if you take the time to add them to your application during the development phase, you can save yourself and your company time in the long run.