📄 thrdutil.c
字号:
/*
**
** Description
** -----------
** This example file contains utility routines which are used by
** multithreaded sample program. It demonstrates how an application can
** hide some of the implementation details of CT-Lib from higher level
** programs.
**
** Routines Used
** -------------
** cs_ctx_alloc
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctpublic.h>
#include "example.h"
#include "thrdutil.h"
#include "thrdfunc.h"
#if !lint
static char Sccsid[] = {"%Z% %M% %I% %G%"};
#endif /* !lint */
/*****************************************************************************
**
** display functions
**
*****************************************************************************/
/*
** ex_display_dlen()
**
** Type of function:
** example program api
**
** Purpose:
**
** Returns:
** Nothing.
**
** Side Effects:
** None
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_INT CS_PUBLIC
ex_display_dlen(column)
CS_DATAFMT *column;
{
CS_INT len;
switch ((int) column->datatype)
{
case CS_CHAR_TYPE:
case CS_VARCHAR_TYPE:
case CS_TEXT_TYPE:
case CS_IMAGE_TYPE:
len = MIN(column->maxlength, MAX_CHAR_BUF);
break;
case CS_BINARY_TYPE:
case CS_VARBINARY_TYPE:
len = MIN((2 * column->maxlength) + 2, MAX_CHAR_BUF);
break;
case CS_BIT_TYPE:
case CS_TINYINT_TYPE:
len = 3;
break;
case CS_SMALLINT_TYPE:
len = 6;
break;
case CS_INT_TYPE:
len = 11;
break;
case CS_REAL_TYPE:
case CS_FLOAT_TYPE:
len = 20;
break;
case CS_MONEY_TYPE:
case CS_MONEY4_TYPE:
len = 24;
break;
case CS_DATETIME_TYPE:
case CS_DATETIME4_TYPE:
len = 30;
break;
case CS_NUMERIC_TYPE:
case CS_DECIMAL_TYPE:
len = (CS_MAX_PREC + 2);
break;
default:
len = 12;
break;
}
return MAX(strlen(column->name) + 1, len);
}
/*
** ex_display_header()
**
** Type of function:
** example program api
**
** Purpose:
** Displays header. Caller should protect this using global mutex
** to avoid output from different threads being mixed up.
**
** Returns:
** Nothing.
**
** Side Effects:
** None
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_RETCODE CS_PUBLIC
ex_display_header(threadnum, numcols, columns)
CS_INT threadnum;
CS_INT numcols;
CS_DATAFMT columns[];
{
CS_INT i;
CS_INT l;
CS_INT j;
CS_INT disp_len;
fprintf(stdout, "\nThread_%d:", threadnum);
for (i = 0; i < numcols; i++)
{
disp_len = ex_display_dlen(&columns[i]);
fprintf(stdout, "%s", columns[i].name);
fflush(stdout);
l = disp_len - strlen(columns[i].name);
for (j = 0; j < l; j++)
{
fputc(' ', stdout);
fflush(stdout);
}
}
fprintf(stdout, "\nThread_%d:", threadnum);
fflush(stdout);
for (i = 0; i < numcols; i++)
{
disp_len = ex_display_dlen(&columns[i]);
l = disp_len - 1;
for (j = 0; j < l; j++)
{
fputc('-', stdout);
}
fputc(' ', stdout);
}
fputc('\n', stdout);
return CS_SUCCEED;
}
/*
** ex_display_column()
**
** Type of function:
** example program api
**
** Purpose:
** Displays a column. Caller should protect this using global mutex
** to avoid output from different threads being mixed up.
**
** Returns:
** Nothing.
**
** Side Effects:
** None
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_RETCODE CS_PUBLIC
ex_display_column(threadnum, context, colfmt, data, datalength, indicator)
CS_INT threadnum;
CS_CONTEXT *context;
CS_DATAFMT *colfmt;
CS_VOID *data;
CS_INT datalength;
CS_INT indicator;
{
char *null = "NULL";
char *nc = "NO CONVERT";
char *cf = "CONVERT FAILED";
CS_DATAFMT srcfmt;
CS_DATAFMT destfmt;
CS_INT olen;
CS_CHAR wbuf[MAX_CHAR_BUF];
CS_BOOL res;
CS_INT i;
CS_INT disp_len;
if (indicator == CS_NULLDATA)
{
olen = strlen(null);
strcpy(wbuf, null);
}
else
{
cs_will_convert(context, colfmt->datatype, CS_CHAR_TYPE, &res);
if (res != CS_TRUE)
{
olen = strlen(nc);
strcpy(wbuf, nc);
}
else
{
srcfmt.datatype = colfmt->datatype;
srcfmt.format = colfmt->format;
srcfmt.locale = colfmt->locale;
srcfmt.maxlength = datalength;
memset(&destfmt, 0, sizeof(destfmt));
destfmt.maxlength = MAX_CHAR_BUF;
destfmt.datatype = CS_CHAR_TYPE;
destfmt.format = CS_FMT_NULLTERM;
destfmt.locale = NULL;
if (cs_convert(context, &srcfmt, data, &destfmt,
wbuf, &olen) != CS_SUCCEED)
{
olen = strlen(cf);
strcpy(wbuf, cf);
}
else
{
/*
** output length include null
** termination
*/
olen -= 1;
}
}
}
fprintf(stdout, "%s", wbuf);
fflush(stdout);
disp_len = ex_display_dlen(colfmt);
for (i = 0; i < (disp_len - olen); i++)
{
fputc(' ', stdout);
}
fflush(stdout);
return CS_SUCCEED;
}
/*
** ex_display_rows()
**
** Type of function:
** example program api
**
** Purpose:
** Display a set of row data. It also displays the header first.
**
** Returns:
** CS_SUCCEED always
**
** Side Effects:
** This acquires global mutex to display the rows as a single
** undivided sequence.
**
*/
CS_RETCODE CS_PUBLIC
ex_display_rows(threadnum, numrows, numcols, colfmt, coldata)
CS_INT threadnum;
CS_INT numrows;
CS_INT numcols;
CS_DATAFMT *colfmt;
EX_COLUMN_DATA *coldata;
{
CS_INT row, col, j;
CS_INT disp_len;
if (ex_take_global_mutex() != CS_SUCCEED)
{
fprintf(stdout, "Thread_%d:ex_take_global_mutex() failed.\n",
threadnum);
return CS_FAIL;
}
/* display header first */
(void)ex_display_header(threadnum, numcols, colfmt);
for (row = 0; row < numrows; row++)
{
/*
** We have a row. Loop through the columns
** displaying the column values.
*/
for (col = 0; col < numcols; col++)
{
/*
** Display the column value
*/
if (col == 0)
{
fprintf(stdout, "Thread_%d:",
threadnum);
}
fprintf(stdout, "%s",
EX_GET_COLUMN_VALUE(coldata, row,
col, colfmt));
fflush(stdout);
/*
** If not last column, Print out spaces
** between this column and next one.
*/
if (col != numcols - 1)
{
disp_len = ex_display_dlen(&colfmt[col]);
disp_len -= coldata[col].valuelen[row] - 1;
for (j = 0; j < disp_len; j++)
{
fputc(' ', stdout);
}
}
}
fprintf(stdout, "\n");
fflush(stdout);
}
(void)ex_release_global_mutex();
return (CS_SUCCEED);
}
/*****************************************************************************
**
** error functions
**
*****************************************************************************/
/*
** ex_panic()
**
** Type of function:
** example program utility api
**
** Purpose:
** Reports a string message to EX_ERROR_OUT, and exits program.
**
** Returns:
** nothing
**
** Side Effects:
** Terminates program
*/
CS_VOID CS_PUBLIC
ex_panic(threadnum, msg)
CS_INT threadnum;
char *msg;
{
EX_GLOBAL_PROTECT(fprintf(EX_ERROR_OUT,
"Thread_%d:ex_panic: FATAL ERROR: %s\n",
threadnum, msg));
fflush(EX_ERROR_OUT);
exit(EX_EXIT_FAIL);
}
/*
** ex_error()
**
** Type of function:
** example program utility api
**
** Purpose:
** Reports a string message to EX_ERROR_OUT.
**
** Returns:
** nothing
**
** Side Effects:
** none.
*/
CS_VOID CS_PUBLIC
ex_error(threadnum, msg)
CS_INT threadnum;
char *msg;
{
EX_GLOBAL_PROTECT(fprintf(EX_ERROR_OUT,
"Thread_%d:ERROR: %s\n", threadnum, msg));
fflush(EX_ERROR_OUT);
}
/*****************************************************************************
**
** callback functions
**
*****************************************************************************/
/*
** ex_clientmsg_cb()
**
** Type of function:
** example program client message handler
**
** Purpose:
** Installed as a callback into Open Client.
**
** Returns:
** CS_SUCCEED
**
** Side Effects:
** None
*/
CS_RETCODE CS_PUBLIC
ex_clientmsg_cb(context, connection, errmsg)
CS_CONTEXT *context;
CS_CONNECTION *connection;
CS_CLIENTMSG *errmsg;
{
CS_INT threadnum = 0;
/*
** Get Connection specific data - get thread number from the
** user data stored in connection structure
*/
(void)ex_get_threadnum(context, connection, &threadnum);
/* take global lock to print error msg. undivided */
if (ex_take_global_mutex() != CS_SUCCEED)
{
fprintf(stdout, "Thread_%d:ex_take_global_mutex() failed.\n",
threadnum);
return CS_FAIL;
}
fprintf(EX_ERROR_OUT, "\nThread_%d:Open Client Message:\n", threadnum);
fprintf(EX_ERROR_OUT,
"Thread_%d:Message number: LAYER = (%d) ORIGIN = (%d) ",
threadnum,
CS_LAYER(errmsg->msgnumber), CS_ORIGIN(errmsg->msgnumber));
fprintf(EX_ERROR_OUT, "SEVERITY = (%d) NUMBER = (%d)\n",
CS_SEVERITY(errmsg->msgnumber), CS_NUMBER(errmsg->msgnumber));
fprintf(EX_ERROR_OUT, "Thread_%d:Message String: %s\n", threadnum,
errmsg->msgstring);
if (errmsg->osstringlen > 0)
{
fprintf(EX_ERROR_OUT, "Thread_%d:Operating System Error: %s\n",
threadnum, errmsg->osstring);
}
fflush(EX_ERROR_OUT);
(void)ex_release_global_mutex();
return CS_SUCCEED;
}
/*
** ex_servermsg_cb()
**
** Type of function:
** example program server message handler
**
** Purpose:
** Installed as a callback into Open Client.
**
** Returns:
** CS_SUCCEED
**
** Side Effects:
** None
*/
CS_RETCODE CS_PUBLIC
ex_servermsg_cb(context, connection, srvmsg)
CS_CONTEXT *context;
CS_CONNECTION *connection;
CS_SERVERMSG *srvmsg;
{
CS_INT threadnum = 0;
/*
** Get Connection specific data - get thread number from the
** user data stored in connection structure
*/
(void)ex_get_threadnum(context, connection, &threadnum);
/* take global lock to print error msg. undivided */
if (ex_take_global_mutex() != CS_SUCCEED)
{
fprintf(stdout, "Thread_%d:ex_take_global_mutex() failed.\n",
threadnum);
return CS_FAIL;
}
fprintf(EX_ERROR_OUT, "\nThread_%d:Server message:\n", threadnum);
fprintf(EX_ERROR_OUT, "Thread_%d:Message number: %d, Severity %d, ",
threadnum, srvmsg->msgnumber, srvmsg->severity);
fprintf(EX_ERROR_OUT, "State %d, Line %d\n",
srvmsg->state, srvmsg->line);
if (srvmsg->svrnlen > 0)
{
fprintf(EX_ERROR_OUT, "Thread_%d:Server '%s'\n",
threadnum, srvmsg->svrname);
}
if (srvmsg->proclen > 0)
{
fprintf(EX_ERROR_OUT, "Thread_%d: Procedure '%s'\n",
threadnum, srvmsg->proc);
}
fprintf(EX_ERROR_OUT, "Thread_%d:Message String: %s\n",
threadnum, srvmsg->text);
fflush(EX_ERROR_OUT);
(void)ex_release_global_mutex();
return CS_SUCCEED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -