Manages in-line error handling.
CS_RETCODE ct_diag(connection, compiler, operation, msgtype, index, buffer); CS_CONNECTION *connection; CS_INT operation CS_INT msgtype CS_INT index CS_BYTE *buffer;
(I) Handle for this connection. This connection handle must already be allocated with ct_con_alloc.
(I) Operation to perform. Assign this argument one of the following values:
Value |
Meaning |
---|---|
CS_GET (33) |
Retrieves a specific message. |
CS_CLEAR (35) |
Clears message information for this connection. |
CS_INIT (36) |
Initializes in-line error handling. |
CS_STATUS (37) |
Returns the current number of stored messages. |
CS_MSGLIMIT (38) |
Sets the maximum number of messages to store. |
(I) Type of message or structure on which the operation is to be performed. One of the following symbolic values:
Value |
Meaning |
---|---|
CS_CLIENTMSG_TYPE (4700) |
A CS_CLIENTMSG structure. Indicates Client-Library messages. |
CS_SERVERMSG_TYPE (4701) |
A CS_SERVERMSG structure. Indicates messages sent by Mainframe ClientConnect or another server. |
CS_ALLMSG (4702) |
Operation is performed on both Client-Library and server messages. |
SQLCA_TYPE (4703) |
A SQLCA structure. |
SQLCODE_TYPE (4704) |
A SQLCODE structure. |
(I) Index number of the message being retrieved. Messages are numbered sequentially: the first message has an index of 1, the second an index of 2, and so forth.
If msgtype is CS_CLIENTMSG_TYPE, then index refers to Client-Library messages only.
If msgtype is CS_SERVERMSG_TYPE, then index refers to server messages only.
If msgtype is CS_ALLMSG_TYPE, then index refers to both Client-Library and server messages.
index should be initialized to 1.
(I/O) An integer or a variable (“buffer”) that contains the message. See Table 3-7 below, to learn the relationship between buffer and other arguments.
This argument is typically either CS_CHAR, a SQLCA structure, or a CS_CLIENTMSG or CS_SERVERMSG structure.
It is the responsibility of the programmer to provide
a buffer large enough to hold the largest possible message.
ct_diag returns one of the following values:
Value |
Meaning |
---|---|
CS_SUCCEED (-1) |
The routine completed successfully. |
CS_FAIL (-2) |
The routine failed. Common reasons for a ct_diag failure include:
|
CS_NOMSG (-207) |
The application attempted to retrieve a message for which the index number is greater than the number of messages in the queue. For example, the application attempted to retrieve message number 3, when only 2 messages are queued. |
The following example uses ct_diag to prepare to receive messages. This example is taken from the sample program SYCTSAA6 in Appendix A, “Sample Language Application.”
/********************************************************************/ /* */ /* Subroutine to process input data */ /* */ /********************************************************************/ void proces_input () { CS_INT rc; CS_INT *outlen; CS_INT buf_len; CS_INT msglimit; CS_INT netdriver; /*------------------------------------------------------------*/ /* Allocate a connection to the server */ /*------------------------------------------------------------*/ rc = ct_con_alloc (context, &connection); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_CONALLOC failed", msg_size); no_errors_sw = FALSE ; error_out (rc); }
/*------------------------------------------------------------*/ /* Alter properties of the connection for user-id */ /*------------------------------------------------------------*/ buf_len = user_size; rc = ct_con_props (connection, (long)CS_SET, (long)CS_USERNAME, username, buf_len, outlen); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_CON_PROPS for user-id failed", msg_size); no_errors_sw = FALSE ; error_out (rc); } /*------------------------------------------------------------*/ /* Alter properties of the connection for password */ /*------------------------------------------------------------*/ buf_len = pwd_size; rc = ct_con_props (connection, (long)CS_SET, (long)CS_PASSWORD, pwd, buf_len, outlen); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_CON_PROPS for password failed", msg_size); no_errors_sw = FALSE ; error_out (rc); } /*------------------------------------------------------------*/ /* Alter properties of the connection for transaction */ /*------------------------------------------------------------*/ buf_len = tran_size; rc = ct_con_props (connection, (long)CS_SET, (long)CS_TRANSACTION_NAME, tran, buf_len, outlen); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_CON_PROPS for transaction failed", msg_size); no_errors_sw = FALSE ; error_out (rc); }
/*------------------------------------------------------------*/ /* Alter properties of the connection for network driver */ /*------------------------------------------------------------*/ netdriver = 9999; /* default value for non-regconized driver name */ /* if no netdriver entered, default is LU62 */ if (strncmp(driver," ",9) == 0 ?? strncmp(driver,"LU62",4) == 0) netdriver = CS_LU62; else if (strncmp(driver,"INTERLINK",8) == 0) netdriver = CS_INTERLINK; else if (strncmp(driver,"IBMTCPIP",8) == 0) netdriver = CS_TCPIP; else if (strncmp(driver,"CPIC",4) == 0) netdriver = CS_NCPIC; rc = ct_con_props (connection, (long)CS_SET, (long)CS_NET_DRIVER, (long) netdriver, CS_UNUSED, outlen); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_CON_PROPS for network driver failed", msg_size); no_errors_sw = FALSE ; error_out (rc); } /*------------------------------------------------------------*/ /* Setup retrieval of All Messages */ /*------------------------------------------------------------*/ rc = ct_diag (connection, CS_INIT, CS_UNUSED, CS_UNUSED, CS_NULL); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_DIAG CS_INIT failed", msg_size); no_errors_sw = FALSE ; error_out (rc); } /*------------------------------------------------------------*/ /* Set the upper limit of number of messages */ /*------------------------------------------------------------*/ msglimit = 5 ; rc = ct_diag (connection, CS_MSGLIMIT, CS_ALLMSG_TYPE, CS_UNUSED, &msglimit); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_DIAG CS_MSGLIMIT failed", msg_size); no_errors_sw = FALSE ; error_out (rc); } /*------------------------------------------------------------*/ /* Open connection to the server or CICS region */ /*------------------------------------------------------------*/ rc = ct_connect (connection, servname, server_size); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_CONNECT failed", msg_size); no_errors_sw = FALSE ; error_out (rc); }
The following example uses ct_diag to retrieve diagnostic messages. This example is taken from the sample program SYCTSAA6 in Appendix A, “Sample Language Application.”
/********************************************************************/ /* */ /* Subroutine to retrieve any diagnostic messages */ /* */ /**********************************************************************/
void get_diag_messages() { CS_SMALLINT cnt; CS_INT num_of_msgs = 0; CS_INT rc; /*------------------------------------------------------------------*/ /* Disable calls to this subroutine */ /*------------------------------------------------------------------*/ diag_msgs_initialized = FALSE ;
/*------------------------------------------------------------------*/ /* First, get client messages */ /*------------------------------------------------------------------*/ rc = ct_diag (connection, CS_STATUS, CS_CLIENTMSG_TYPE, CS_UNUSED, #_of_msgs); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_DIAG CS_STATUS CLIENTMSG_TYPE failed", msg_size); error_out(rc) ; } else if (num_of_msgs > 0) { for (cnt = 1; cnt <= num_of_msgs; ++cnt) get_client_msgs (); } /*------------------------------------------------------------------*/ /* Then, get server messages */ /*------------------------------------------------------------------*/ rc = ct_diag (connection, CS_STATUS, CS_SERVERMSG_TYPE, CS_UNUSED, #_of_msgs); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_DIAG CS_STATUS SERVERMSG_TYPE failed", msg_size); error_out(rc) ; } else if (num_of_msgs > 0) { for (cnt = 1; cnt <= num_of_msgs; ++cnt) get_server_msgs (); } } /* end get_diag_messages */
/********************************************************************/ /* */ /* Subroutine to retrieve diagnostic messages from client */ /* */ /********************************************************************/ void get_client_msgs() { CS_INT rc; CS_INT i; CS_CHAR *txtpos; CS_INT textleft; CS_INT msgno = 1; CS_CHAR blank_13[13] = " "; CS_CLIENTMSG clientmsg; struct { char msgno_hdr[13]; char msgno_data[8]; char severity_hdr[13]; char severity_data[6]; } client_msg; rc = ct_diag (connection, CS_GET, CS_CLIENTMSG_TYPE, msgno, &clientmsg); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_DIAG CS_GET CS_CLIENTMSG_TYPE failed", msg_size); error_out(rc) ; } /*------------------------------------------------------------------*/ /* display message text */ /*------------------------------------------------------------------*/ i = 1 ; strncpy (RS[i].rsltno, "Client Message:"); i = 3 ; memset(&client_msg, ' ', sizeof(client_msg)); strcpy (client_msg.msgno_hdr, " OC MsgNo: "); strcpy (client_msg.severity_hdr, " Severity: "); cvtleft = 8; /* Digits to the left */ cvtright = 0; /* Digits to the right */ SYCVTD(clientmsg.msgnumber, client_msg.msgno_data, cvtleft, cvtright, cvtwork, cvtdbl, CS_TRUE); cvtleft = 6; /* Digits to the left */ SYCVTD(clientmsg.severity, client_msg.severity_data, cvtleft, cvtright, cvtwork, cvtdbl, CS_TRUE); memcpy (RS[i].rsltno, &client_msg, sizeof(client_msg)); i += 1 ; /* get number of Client msgs */ if (clientmsg.msgnumber != 0) { strcpy (RS[i].rsltno, " OC MsgTx: "); strncat (RS[i].rsltno, clientmsg.msgstring, 66); i += 1 ; txtpos = clientmsg.msgstring + 66; textleft = clientmsg.msgstringlen - 66; while (textleft > 0) { strncpy (RS[i].rsltno, blank_13, 13); strncat (RS[i].rsltno, txtpos, 66); i += 1; txtpos += 66; textleft -= 66; } } else { strncpy (RS[i].rsltno, " OC MsgTx: No Message!", text_size); i += 1 ; } /* get number of Server msgs */ memset(&client_msg, ' ', sizeof(client_msg)); strcpy (client_msg.msgno_hdr, " OS MsgNo: "); cvtleft = 8; /* Digits to the left */ cvtright = 0; /* Digits to the right */ SYCVTD(clientmsg.osnumber, client_msg.msgno_data, cvtleft, cvtright, cvtwork, cvtdbl, CS_TRUE); memcpy (RS[i].rsltno, &client_msg, sizeof(client_msg)); i += 1 ; if (clientmsg.osnumber != 0) { strcpy (RS[i].rsltno, " OS MsgTx: "); strncat (RS[i].rsltno, clientmsg.osstring, 66); i += 1 ; txtpos = clientmsg.osstring + 66; textleft = clientmsg.osstringlen - 66; while (textleft > 0) { strncpy (RS[i].rsltno, blank_13, 13); strncat (RS[i].rsltno, txtpos, 66); i += 1; txtpos += 66; textleft -= 66; } } else { strncpy (RS[i].rsltno, " OS MsgTx: No Message!", text_size); i += 1 ; } } /* end get_client_msgs */
/*------------------------------------------------------------------*/ /* */ /* Subroutine to retrieve diagnostic messages from server */ /* */ /*------------------------------------------------------------------*/ void get_server_msgs() { CS_INT rc; CS_INT i; CS_CHAR *txtpos; CS_INT textleft; CS_INT msgno = 1; CS_C HAR blank_13[13] = " "; CS_C HAR proc_id_data[66]; CS_CHAR svrname_data[66]; CS_SERVERMSG servermsg; struct { char msg_no_hdr[13]; char msg_no_data[6]; char severity_hdr[14]; char severity_data[6]; char state_hdr[14]; char state_data[4]; char line_no_hdr[13]; char line_no_data[4]; } serv_msg; memset(&serv_msg, ' ', sizeof(serv_msg)); rc = ct_diag (connection, CS_GET, CS_SERVERMSG_TYPE, msgno, &servermsg); if (rc != CS_SUCCEED) { strncpy (msgstr, "CT_DIAG CS_GET CS_SERVERMSG_TYPE failed", msg_size); error_out (rc) ; } /*------------------------------------------------------------------*/ /* display message text */ /*------------------------------------------------------------------*/ strcpy (serv_msg.msg_no_hdr, " Message#: "); strcpy (serv_msg.severity_hdr, ", Severity: "); strcpy (serv_msg.state_hdr, ", State No: "); strcpy (serv_msg.line_no_hdr, " Line No: "); cvtleft = 6; /* Digits to the left */ cvtright = 0; /* Digits to the right */ SYCVTD(servermsg.msgnumber, serv_msg.msg_no_data, cvtleft, cvtright, cvtwork, cvtdbl, CS_TRUE); SYCVTD(servermsg.severity, serv_msg.severity_data, cvtleft, cvtright, cvtwork, cvtdbl, CS_TRUE); cvtleft = 4; /* Digits to the left */ SYCVTD(servermsg.state, serv_msg.state_data, cvtleft, cvtright, cvtwork, cvtdbl, CS_TRUE); SYCVTD(servermsg.line, serv_msg.line_no_data, cvtleft, cvtright, cvtwork, cvtdbl, CS_TRUE); if (servermsg.svrnlen > 66) { strncpy (svrname_data, servermsg.svrname, 63); strcat (svrname_data, "..."); } else strncpy (svrname_data, servermsg.svrname, 66); if (servermsg.proclen > 66) { strncpy (proc_id_data, servermsg.proc, 63); strcat (proc_id_data, "..."); } else strncpy (proc_id_data, servermsg.proc, 66); strncpy (RS[1].rsltno, "Server Message:", text_size); memcpy (RS[3].rsltno, &serv_msg, sizeof(serv_msg)); strcpy (RS[5].rsltno, " Serv Nam: "); strcat (RS[5].rsltno, svrname_data); strcpy (RS[6].rsltno, " Proc ID : "); strcat (RS[6].rsltno, proc_id_data); strcpy (RS[7].rsltno, " Message : "); strncat (RS[7].rsltno, servermsg.text, 66); i = 8 ; txtpos = servermsg.text + 66; textleft = servermsg.textlen - 66; while (textleft > 0) { strncpy (RS[i].rsltno, blank_13, 13); strncat (RS[i].rsltno, txtpos, 66); i += 1; txtpos += 66; textleft -= 66; } } /* end get_server_msgs */
Table 3-7 lists a summary of arguments for ct_diag.
Operation |
ct_diag action |
msgtype value |
index value |
buffer value |
---|---|---|---|---|
CS_INIT |
Initializes in-line error handling. An application must callct_diag with a CS_INIT operation before it can process error messages in line. |
CS_UNUSED |
CS_UNUSED |
Ignored. |
CS_CLEAR |
Clears message information for this connection. If buffer is not zeroes and msgtype is not CS_ALLMSG_ TYPE, ct_diag clears the buffer by initializing it with blanks or zeroes. |
One of the legal msgtype values.
|
CS_UNUSED |
A buffer whose type is defined by msgtype. |
CS_GET |
Retrieves a specific message. |
Any legal msgtype value except CS_ALLMSG_TYPE.
|
The index number of the message to retrieve. |
A buffer whose type is defined by msgtype. |
CS_MSGLIMIT |
Sets the maximum number of messages to store. |
CS_CLIENTMSG_TYPE to limit Client-Library messages only. CS_SERVERMSG_TYPE to limit server messages only. CS_ALLMSG_TYPE to limit the total number of Client-Library and server messages combined. |
CS_UNUSED |
An integer value. |
CS_STATUS |
Returns the current number of stored messages. |
CS_CLIENTMSG_TYPE to retrieve the number of Client-Library messages. CS_SERVERMSG_TYPE to retrieve the number of server messages. CS_ALLMSG_TYPE to retrieve the total number of Client-Library and server messages combined. |
CS_UNUSED |
An integer variable. |
ct_diag manages in-line message handling for a specific connection. If an application has more than one connection, it must make separate ct_diag calls for each connection.
Open ClientConnect applications always use ct_diag to handle Client-Library and server messages. Applications built with Open Client can offer alternative message-handling facilities.
An application can perform operations on Client-Library messages, server messages, or both.
For example, an application can clear Client-Library messages without affecting server messages:
rc = ct_diag (connection, CS_UNUSED, CS_CLEAR, CS_CLIENTMSG, CS_UNUSED, MSGBUFFER);
ct_diag allows an application to retrieve message information into standard Client-Library structures (CS_CLIENTMSG, CS_SERVERMSG, SQLCA or SQLCODE).
When retrieving messages, ct_diag assumes that buffer points to a structure of the type indicated by msgtype.
An application that retrieves messages into a SQLCA or SQLCODE structure must set the Client-Library property CS_EXTRA_INF to CS_TRUE. This is because the SQL structures require information that is not ordinarily returned by the Client-Library error handling mechanism.
Use ct_con_props or cs_config to set CS_EXTRA_INF.
An application that does not use the SQLCA or SQLCODE structures can also set CS_EXTRA_INF to CS_TRUE. In this case, the extra information returns as standard Client-Library messages.
For more about CS_EXTRA_INF, see “Remote procedure calls (RPCs)” and the reference pages for ct_con_props and cs_config.
WARNING! If ct_diag does not have sufficient internal storage space in which to save a new message, it throws away all unread messages and stops saving messages. The next time it is called with operation as CS_GET, it returns a message to indicate the space problem. After returning this message, ct_diag starts saving messages again.
An application must initialize in-line error handling before it can retrieve any errors. To initialize in-line error handling, call ct_diag with operation as CS_INIT.
Generally, if a connection uses in-line error handling, the application should call ct_diag to initialize in-line error handling for a connection immediately after allocating it with ct_con_alloc.
To clear message information for a connection, an application calls operation as CS_CLEAR.
To clear Client-Library messages only, set msgtype to CS_CLIENTMSG_TYPE.
To clear server messages only, set msgtype to CS_SERVERMSG_TYPE.
To clear both Client-Library and server messages, set msgtype to SQLCA, SQLCODE, or CS_ALLMSG_TYPE.
If operation is CS_CLEAR and msgtype is not CS_ALLMSG_TYPE:
ct_diag assumes that buffer is a structure of type msgtype.
ct_diag clears the buffer by setting it to blanks or zeroes, as appropriate.
Message information is not cleared until an application explicitly calls ct_diag with operation as CS_CLEAR. Retrieving a message does not remove it from the message queue.
To retrieve message information, an application calls ct_diag with operation as CS_GET, msgtype as the type of structure in which to retrieve the message, index as the index number of the message of interest, and buffer as an integer or a variable, as appropriate.
If msgtype is CS_CLIENTMSG_TYPE, index refers only to Client-Library messages.
If msgtype is CS_SERVERMSG_TYPE, index refers only to server messages.
If msgtype has any other value, index refers to the collective “queue” of both types of messages combined.
ct_diag creates a message queue in the buffer and fills the buffer with message information. It returns messages to the client in the order in which they are received.
If an application attempts to retrieve a message for which the index is higher than the highest valid index, ct_diag returns CS_NOMSG to indicate that no message is available.
The Client-Library default behavior is to save an unlimited number of messages. Applications running on platforms with limited memory may want to limit the number of messages that Client-Library saves. The default for MVS is 25.
An application can limit the number of saved Client-Library messages, the number of saved server messages, and the total number of saved messages.
To limit the number of saved messages, an application calls ct_diag with operation as CS_MSGLIMIT and msgtype as CS_CLIENTMSG_TYPE, CS_SERVERMSG_TYPE, or CS_ALLMSG_TYPE:
If msgtype is CS_CLIENTMSG_TYPE, the number of Client-Library messages is limited.
If msgtype is CS_SERVERMSG_TYPE, the number of server messages is limited.
If msgtype is CS_ALLMSG_TYPE, the total number of Client-Library and server messages combined is limited.
When a specific message limit is reached, Client-Library discards any new messages of that type. When a combined message limit is reached, Client-Library discards any new messages.
To find out how many messages were retrieved, an application calls ct_diag with operation as CS_STATUS and msgtype as the type of message of interest.
Related topics