📄 ex_alib.c
字号:
/*
** Example async library built on top of CT-Lib
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctpublic.h>
#include "example.h"
#include "exasync.h"
#if !lint
static char Sccsid[] = {"%Z% %M% %I% %G%"};
#endif /* !lint */
/*****************************************************************************
**
** defines used
**
*****************************************************************************/
/*
** Memory alignment boundary in bytes
*/
#ifndef MEM_BOUNDRY
#define MEM_BOUNDRY (CS_INT)8
#endif
/*
** alignment macro for memory
*/
#ifndef MEM_SIZE_ALIGN
#define MEM_SIZE_ALIGN(S) ( (((S) + MEM_BOUNDRY - 1) \
/ MEM_BOUNDRY) * MEM_BOUNDRY )
#endif
/*
** Internal state defines used
*/
#define EX_ASEND (CS_INT)1
#define EX_ARESULTS (CS_INT)2
#define EX_AFETCH (CS_INT)3
#define EX_ACANCEL_CURRENT (CS_INT)4
#define EX_ACANCEL_ALL (CS_INT)5
#ifdef HAFAILOVER
extern CS_INT hafailoversucceed;
#endif /* HAFAILOVER */
/*****************************************************************************
**
** typedefs used
**
*****************************************************************************/
/*
** callback handle typedef
*/
typedef CS_RETCODE (CS_INTERNAL * EX_CB_FUNC)PROTOTYPE((
CS_CONNECTION *connection,
CS_COMMAND *cmd,
CS_INT function,
CS_RETCODE status
));
/*
** Define the internal async handle we use
*/
typedef struct _ex_async
{
/*
** Used defined input area
*/
EX_RESULTS *results; /* place to keep results */
CS_BYTE *mempool; /* pointer to user pmemory pool */
CS_INT maxpool; /* number of bytes available in pool */
CS_BYTE *memcurpool; /* current pointer in mempool */
CS_INT poolsize; /* current number of bytes available */
CS_CONNECTION *connection; /* connection to use */
/*
** Internal info
*/
CS_INT state; /* what state our library is in */
EX_CB_FUNC completion_cb; /* store user callback here */
CS_BOOL didfetch; /* CS_TRUE if we have already fetched
** rows from the server
*/
CS_INT res_type; /* passed to ct_results() */
CS_COMMAND *cmd; /* command handle we allocate */
} ExAsync;
/*****************************************************************************
**
** prototypes used
**
*****************************************************************************/
CS_STATIC CS_VOID CS_INTERNAL ex_apanic PROTOTYPE((
char *msg
));
CS_STATIC CS_RETCODE CS_INTERNAL ex_adone_comp PROTOTYPE((
ExAsync *ex_async,
CS_CONNECTION *connection,
CS_COMMAND *cmd,
CS_INT function,
CS_RETCODE status
));
CS_STATIC CS_RETCODE CS_INTERNAL ex_aerror PROTOTYPE((
ExAsync *ex_async,
CS_CONNECTION *connection,
CS_COMMAND *cmd,
CS_INT function,
CS_RETCODE status
));
CS_STATIC CS_VOID * CS_INTERNAL ex_amalloc PROTOTYPE((
ExAsync *ex_async,
CS_INT size
));
CS_STATIC CS_RETCODE CS_INTERNAL ex_abind PROTOTYPE((
ExAsync *ex_async,
CS_COMMAND *cmd
));
CS_STATIC CS_RETCODE CS_INTERNAL ex_asend_comp PROTOTYPE((
ExAsync *ex_async,
CS_CONNECTION *connection,
CS_COMMAND *cmd,
CS_INT function,
CS_RETCODE status
));
CS_STATIC CS_RETCODE CS_INTERNAL ex_aresults_comp PROTOTYPE((
ExAsync *ex_async,
CS_CONNECTION *connection,
CS_COMMAND *cmd,
CS_INT function,
CS_RETCODE status
));
CS_STATIC CS_RETCODE CS_INTERNAL ex_afetch_comp PROTOTYPE((
ExAsync *ex_async,
CS_CONNECTION *connection,
CS_COMMAND *cmd,
CS_INT function,
CS_RETCODE status
));
CS_RETCODE CS_PUBLIC ex_acompletion_cb PROTOTYPE((
CS_CONNECTION *connection,
CS_COMMAND *cmd,
CS_INT function,
CS_RETCODE status
));
/*****************************************************************************
**
** functions
**
*****************************************************************************/
/*
** ex_apanic()
**
** Type of function:
** internal example async lib
**
** Purpose:
** Reports a string message to stderr, and exits program.
**
** Returns:
** nothing
**
** Side Effects:
** Terminates program
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_STATIC CS_VOID CS_INTERNAL
ex_apanic(msg)
char *msg;
{
fprintf(stderr, "\n\nex_apanic: FATAL ERROR: %s\n", msg);
fflush(stderr);
exit(ERROR_EXIT);
}
/*
** ex_aerror()
**
** Type of function:
** internal example async lib
**
** Purpose:
** Error function which is called when ct_results or ct_fetch fails.
** It attempts to force a wakeup of the user api callback.
**
** Returns:
** Status passed in.
**
** Side Effects:
** None.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_STATIC CS_RETCODE CS_INTERNAL
ex_aerror(ex_async, connection, cmd, function, status)
ExAsync *ex_async;
CS_CONNECTION *connection;
CS_COMMAND *cmd;
CS_INT function;
CS_RETCODE status;
{
if (status == CS_CANCELED)
{
fprintf(stderr, "\nex_aerror: client lib returned canceled\n");
}
else
{
fprintf(stderr, "\nex_aerror: client lib error encountered\n");
}
fprintf(stderr, "function %d, status = %d\n", function, status);
fflush(stderr);
/*
** Try and force a wakeup
*/
(void)ex_adone_comp(ex_async, connection, cmd, function, status);
return status;
}
/*
** ex_amalloc()
**
** Type of function:
** internal example async lib
**
** Purpose:
** returns a chunk of memory from the memory pool
**
** Returns:
** ptr to memory or NULL
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_STATIC CS_VOID * CS_INTERNAL
ex_amalloc(ex_async, size)
ExAsync *ex_async;
CS_INT size;
{
CS_VOID *buff;
size = MEM_SIZE_ALIGN(size);
if (size > ex_async->poolsize)
{
return NULL;
}
buff = (CS_VOID *)ex_async->memcurpool;
ex_async->memcurpool += size;
ex_async->poolsize -= size;
return buff;
}
/*
** ex_abind()
**
** Type of function:
** internal example async lib
**
** Purpose:
** Allocated row data from the user define memory pool and bind the
** memory via ct_bind(). It uses the array binding feature of ct_lib
** to cut down the number of async operations needed.
**
** Returns:
** CS_SUCCEED If ok.
** CS_MEM_ERROR If the memory pool is exhausted.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_STATIC CS_RETCODE CS_INTERNAL
ex_abind(ex_async, cmd)
ExAsync *ex_async;
CS_COMMAND *cmd;
{
EX_RESULTS *results = ex_async->results;
CS_RETCODE retstat;
CS_INT size;
CS_INT i;
CS_INT maxrows; /* number of rows to fetch */
/*
** Determine the number of columns.
*/
retstat = ct_res_info(cmd, CS_NUMDATA, &results->numcols, CS_UNUSED, NULL);
if (retstat != CS_SUCCEED)
{
return retstat;
}
/*
** Allocate column description and data pointers from memory pool
*/
size = sizeof (CS_DATAFMT) * results->numcols;
results->colfmts = (CS_DATAFMT *)ex_amalloc(ex_async, size);
if (results->colfmts == NULL)
{
return CS_MEM_ERROR;
}
size = sizeof (CS_BYTE *) * results->numcols;
results->data = (CS_BYTE **)ex_amalloc(ex_async, size);
if (results->data == NULL)
{
return CS_MEM_ERROR;
}
size = sizeof (CS_INT *) * results->numcols;
results->datalen = (CS_INT **)ex_amalloc(ex_async, size);
if (results->datalen == NULL)
{
return CS_MEM_ERROR;
}
size = sizeof (CS_INT *) * results->numcols;
results->indicator = (CS_INT **)ex_amalloc(ex_async, size);
if (results->indicator == NULL)
{
return CS_MEM_ERROR;
}
/*
** For each column, get the description, and calculation the total
** size needed for a row. Note that the MEM_SIZE_ALIGN() is needed,
** but does represent a worst case scenario for memory usage.
*/
size = 0;
for (i = 0; i < results->numcols; i++)
{
/*
** Get the column description
*/
retstat = ct_describe(cmd, i + 1, &results->colfmts[i]);
if (retstat != CS_SUCCEED)
{
return retstat;
}
size += MEM_SIZE_ALIGN(results->colfmts[i].maxlength);
size += MEM_SIZE_ALIGN(sizeof (CS_INT));
size += MEM_SIZE_ALIGN(sizeof (CS_SMALLINT));
}
/*
** size now represents the maximum number of bytes needed to
** process a row. Here we set maxrows to best optimize the
** space left in the memory pool.
*/
maxrows = ex_async->poolsize / size;
/*
** Allocate space for the column data.
*/
for (i = 0; i < results->numcols; i++)
{
results->colfmts[i].count = maxrows;
results->data[i] = (CS_BYTE *)ex_amalloc(ex_async,
results->colfmts[i].maxlength *
maxrows);
if (results->data[i] == NULL)
{
return CS_MEM_ERROR;
}
results->datalen[i] = (CS_INT *)ex_amalloc(ex_async,
sizeof (CS_INT) * maxrows);
if (results->datalen[i] == NULL)
{
return CS_MEM_ERROR;
}
results->indicator[i] = (CS_INT *)ex_amalloc(ex_async,
sizeof (CS_INT) * maxrows);
if (results->indicator[i] == NULL)
{
return CS_MEM_ERROR;
}
/*
** Bind the results to the variable.
*/
retstat = ct_bind(cmd, i + 1, &results->colfmts[i],
results->data[i],
results->datalen[i],
(CS_SMALLINT *)results->indicator[i]);
if (retstat != CS_SUCCEED)
{
return retstat;
}
}
return CS_SUCCEED;
}
/*
** ex_adone_comp()
**
** Type of function:
** internal example async lib
**
** Purpose:
** Re-installs the user complete callback and calls wakeup to invoke
** the callback.
**
** Returns:
** CS_SUCCEED
**
** Side Effects:
** None.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_STATIC CS_RETCODE CS_INTERNAL
ex_adone_comp(ex_async, connection, cmd, function, status)
ExAsync *ex_async;
CS_CONNECTION *connection;
CS_COMMAND *cmd;
CS_INT function;
CS_RETCODE status;
{
CS_RETCODE retstat;
CS_BOOL pollprop;
/*
** Re-install user completion routine
*/
retstat = ct_callback(NULL, connection, CS_SET, CS_COMPLETION_CB,
(CS_VOID *)ex_async->completion_cb);
if (retstat != CS_SUCCEED)
{
return retstat;
}
/*
** Enable polling
*/
pollprop = CS_FALSE;
retstat = ct_con_props(connection, CS_SET, CS_DISABLE_POLL,
&pollprop, CS_UNUSED, NULL);
if (retstat != CS_SUCCEED)
{
return retstat;
}
/*
** Force a wakeup on the connection handle
*/
retstat = ct_wakeup(connection, NULL, EX_ASYNC_QUERY, status);
if (retstat != CS_SUCCEED)
{
return retstat;
}
return CS_SUCCEED;
}
/*
** ex_asend_comp()
**
** Type of function:
** internal example async lib
**
** Purpose:
** This function will change the async state to results, and issue a
** ct_results()
**
** Returns:
** return of ct_results()
**
** Side Effects:
** None.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_STATIC CS_RETCODE CS_INTERNAL
ex_asend_comp(ex_async, connection, cmd, function, status)
ExAsync *ex_async;
CS_CONNECTION *connection;
CS_COMMAND *cmd;
CS_INT function;
CS_RETCODE status;
{
/*
** check status to see what happened in last command. If
** an error occurred, call ex_aerror() to clean up.
*/
switch ((int)status)
{
case CS_SUCCEED:
break;
#ifdef HAFAILOVER
case CS_RET_HAFAILOVER:
return ex_adone_comp(ex_async, connection, cmd, function, CS_SUCCEED);
#endif /* HAFAILOVER */
default:
return ex_aerror(ex_async, connection, cmd, function, status);
}
ex_async->state = EX_ARESULTS;
return ct_results(cmd, &ex_async->res_type);
}
/*
** ex_aresults_comp()
**
** Type of function:
** internal example async lib
**
** Purpose:
** This function will process the result type from a ct_results(). If
** rows are to be fetched, the async state is updated and a ct_fetch()
** is done.
**
** Returns:
** return of ct_results()
**
** Side Effects:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -