📄 ex_alib.c
字号:
** None.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_STATIC CS_RETCODE CS_INTERNAL
ex_aresults_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;
/*
** check status to see what happened in last ct_results(). If
** completed, call ex_adone_comp() 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 */
case CS_END_RESULTS:
return ex_adone_comp(ex_async, connection, cmd, function, CS_SUCCEED);
default:
return ex_aerror(ex_async, connection, cmd, function, status);
}
switch ((int)ex_async->res_type)
{
case CS_ROW_RESULT:
if (ex_async->didfetch == CS_TRUE)
{
/*
** We don't handle multiple result sets. Issue a
** cancel_all. The cancel attention should not be
** used here. Instead, it would be used in the main
** line code to cancel this library's processing.
*/
fprintf(stderr, "\nMultiple result sets not supported\n");
fflush(stderr);
ex_async->state = EX_ACANCEL_ALL;
retstat = ct_cancel(NULL, cmd, CS_CANCEL_ALL);
}
else
{
/*
** Now we are in a fetching state. If the bind fails
** (most likely not enough memory was provided). We
** still need to continue async processing, since
** ex_abind() is not async. Since we can't process
** the results, we just throw them away.
*/
retstat = ex_abind(ex_async, cmd);
if (retstat == CS_SUCCEED)
{
ex_async->state = EX_AFETCH;
retstat = ct_fetch(cmd, CS_UNUSED,
CS_UNUSED, CS_UNUSED,
&ex_async->results->numrows);
}
else
{
fprintf(stderr, "\nError: ex_abind() failed\n");
fflush(stderr);
ex_async->state = EX_ACANCEL_ALL;
retstat = ct_cancel(NULL, cmd, CS_CANCEL_ALL);
}
}
break;
case CS_CMD_SUCCEED:
case CS_CMD_DONE:
case CS_CMD_FAIL:
/*
** This means no rows were returned, remain in the result
** state and call results again.
*/
retstat = ct_results(cmd, &ex_async->res_type);
break;
case CS_STATUS_RESULT:
/*
** throw the status value away.
*/
ex_async->state = EX_ACANCEL_CURRENT;
retstat = ct_cancel(NULL, cmd, CS_CANCEL_CURRENT);
break;
case CS_PARAM_RESULT:
case CS_COMPUTE_RESULT:
default:
fprintf(stderr, "\nUnexpected result type encountered\n");
fflush(stderr);
ex_async->state = EX_ACANCEL_ALL;
retstat = ct_cancel(NULL, cmd, CS_CANCEL_ALL);
break;
}
return retstat;
}
/*
** ex_afetch_comp()
**
** Type of function:
** internal example async lib
**
** Purpose:
** This function will determine if all the rows have been fetched. If so,
** the async state is switched backed to results, and a call to
** ct_results() is made.
**
** Returns:
** return of ct_results() or
** return of ct_fetch()
**
** Side Effects:
** None.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_STATIC CS_RETCODE CS_INTERNAL
ex_afetch_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;
/*
** check status to see what happened in last ct_fetch(). If
** completed, call ct_results() to continue processing.
*/
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 */
case CS_END_DATA:
ex_async->state = EX_ARESULTS;
ex_async->didfetch = CS_TRUE;
return ct_results(cmd, &ex_async->res_type);
default:
return ex_aerror(ex_async, connection, cmd, function, status);
}
/*
** The fetch was supposed to be a one shot deal. Here we clear the
** binds and call fetch again to return CS_END_DATA. Note that this
** is not the best way to handle this. Multiple fetchs may cause
** recursion on the process stack. The code was left the way it is to
** demonstrate that multiple fetchs are possible.
**
** The best way to handle this would be to use:
**
** ex_async->state = EX_ACANCEL_CURRENT;
** return ct_cancel(NULL, cmd, CS_CANCEL_CURRENT);
*/
retstat = ct_bind(cmd, CS_UNUSED, NULL, NULL, NULL, NULL);
if (retstat != CS_SUCCEED)
{
return retstat;
}
return ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, NULL);
}
/*
** ex_acompletion_cb()
**
** Type of function:
** internal example async lib
**
** Purpose:
** Installed as a callback into Open Client. It will dispatch to the
** appropriate completion processing routine based on async state.
**
** Another approach to callback processing is to have each completion
** routine install the completion callback for the next step in
** processing. We use one dispatch point to aid in debugging the
** async processing (only need to set one breakpoint).
**
** Returns:
** return of completion processing routine.
**
** Side Effects:
** None
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_RETCODE CS_PUBLIC
ex_acompletion_cb(connection, cmd, function, status)
CS_CONNECTION *connection;
CS_COMMAND *cmd;
CS_INT function;
CS_RETCODE status;
{
CS_RETCODE retstat;
ExAsync *ex_async;
CS_INT hafail;
fprintf(stdout, "\nex_acompletion_cb: function %d Completed",
function);
fflush(stdout);
#ifdef HAFAILOVER
/*
** If HA failover has succeeded then it has to go back to the
** connected state. Need to send a query now
*/
ct_con_props(connection, CS_GET, CS_HAFAILOVER,
&hafail, CS_UNUSED, NULL);
if((hafail) && (status == CS_RET_HAFAILOVER))
{
hafailoversucceed = CS_TRUE;
return(CS_HAFAILOVER);
}
if ((hafail) && (status == CS_SUCCEED) && function == CT_CLOSE)
{
return(CS_SUCCEED);
}
#endif /* HAFAILOVER */
/*
** Extract the user area out of the command handle.
*/
retstat = ct_cmd_props(cmd, CS_GET, CS_USERDATA, &ex_async,
CS_SIZEOF(ex_async), NULL);
if (retstat != CS_SUCCEED)
{
return retstat;
}
/*
** Based on async state, do the right thing
*/
switch ((int)ex_async->state)
{
case EX_ASEND:
case EX_ACANCEL_CURRENT:
retstat = ex_asend_comp(ex_async, connection, cmd,
function, status);
break;
case EX_ARESULTS:
retstat = ex_aresults_comp(ex_async, connection, cmd,
function, status);
break;
case EX_AFETCH:
retstat = ex_afetch_comp(ex_async, connection, cmd,
function, status);
break;
case EX_ACANCEL_ALL:
retstat = ex_adone_comp(ex_async, connection, cmd,
function, status);
break;
default:
ex_apanic("ex_acompletion_cb: unexpected async state");
break;
}
return retstat;
}
/*
** ex_async_query()
**
** Type of function:
** example async lib api
**
** Purpose:
** This routine will asynchronously send a query to a server and
** retrieve any rows sent back.
**
** Returns:
** CS_PENDING
**
** Side Effects:
** Will install a different async completion callback.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_RETCODE CS_PUBLIC
ex_async_query(ex_handle, query, querylen)
EX_ASYNC *ex_handle;
CS_CHAR *query;
CS_INT querylen;
{
ExAsync *ex_async;
CS_RETCODE retstat;
CS_BOOL pollprop;
/*
** set up async handle for query
*/
ex_async = (ExAsync *)ex_handle;
ex_async->poolsize = ex_async->maxpool;
ex_async->memcurpool = ex_async->mempool;
ex_async->didfetch = CS_FALSE;
/*
** clear results area
*/
ex_async->results->numrows = 0;
ex_async->results->numcols = 0;
ex_async->results->colfmts = NULL;
ex_async->results->data = NULL;
ex_async->results->datalen = NULL;
ex_async->results->indicator = NULL;
/*
** Extract the user completion callback for this connection
*/
retstat = ct_callback(NULL, ex_async->connection, CS_GET,
CS_COMPLETION_CB,
(CS_VOID *)&ex_async->completion_cb);
if (retstat != CS_SUCCEED)
{
return retstat;
}
/*
** Install our completion callback for this connection. Since this
** will overwrite the user installed callback, all subsequent error
** processing should make sure to call ex_aerror() to recover from
** the error.
*/
retstat = ct_callback(NULL, ex_async->connection, CS_SET,
CS_COMPLETION_CB,
(CS_VOID *)ex_acompletion_cb);
if (retstat != CS_SUCCEED)
{
return retstat;
}
/*
** Disable polling. We do this to insure that the ct_poll() routine
** will not report a completion for this connection until we call the
** user installed callback.
*/
pollprop = CS_TRUE;
retstat = ct_con_props(ex_async->connection, CS_SET, CS_DISABLE_POLL,
&pollprop, CS_UNUSED, NULL);
if (retstat != CS_SUCCEED)
{
return ex_aerror(ex_async, ex_async->connection, ex_async->cmd,
EX_ASYNC_QUERY, retstat);
}
/*
** Install the exhandle into the user area of the command handle.
*/
retstat = ct_cmd_props(ex_async->cmd, CS_SET, CS_USERDATA, &ex_async,
CS_SIZEOF(ex_async), NULL);
if (retstat != CS_SUCCEED)
{
return ex_aerror(ex_async, ex_async->connection, ex_async->cmd,
EX_ASYNC_QUERY, retstat);
}
/*
** Tell Open Client about the query we want to send.
*/
retstat = ct_command(ex_async->cmd, CS_LANG_CMD, query,
querylen, CS_UNUSED);
if (retstat != CS_SUCCEED)
{
return ex_aerror(ex_async, ex_async->connection, ex_async->cmd,
EX_ASYNC_QUERY, retstat);
}
/*
** The async manager can be debugged by the following api. This is
** mostly useful for developers who are working with the internal async
** routines.
*/
#if EX_ASYNC_DEBUG
{
CS_CONTEXT *context;
ct_con_props(ex_async->connection, CS_GET, CS_PARENT_HANDLE,
&context, CS_UNUSED, NULL);
ct_debug(context, NULL, CS_SET_FLAG, CS_DBG_ASYNC, NULL, CS_UNUSED);
}
#endif
/*
** Now send the query to the server.
*/
ex_async->state = EX_ASEND;
retstat = ct_send(ex_async->cmd);
if (retstat != CS_PENDING)
{
return ex_aerror(ex_async, ex_async->connection, ex_async->cmd,
EX_ASYNC_QUERY, retstat);
}
return retstat;
}
/*
** ex_async_alloc()
**
** Type of function:
** example async lib api
**
** Purpose:
** This routine will allocate and initialize a async handle
**
** Returns:
** CS_SUCCEED
**
** Side Effects:
** None.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_RETCODE CS_PUBLIC
ex_async_alloc(connection, results, mempool, maxpool, ex_handle)
CS_CONNECTION *connection;
EX_RESULTS *results;
CS_VOID *mempool;
CS_INT maxpool;
EX_ASYNC **ex_handle;
{
ExAsync *ex_async;
CS_RETCODE retstat;
/*
** allocate and initialize the async data area to store async
** information.
*/
ex_async = (ExAsync *)malloc(sizeof (ExAsync));
if (ex_async == NULL)
{
return CS_MEM_ERROR;
}
ex_async->results = results;
ex_async->mempool = (CS_BYTE *)mempool;
ex_async->maxpool = maxpool;
ex_async->connection = connection;
/*
** get a command handle.
*/
retstat = ct_cmd_alloc(connection, &ex_async->cmd);
if (retstat != CS_SUCCEED)
{
return retstat;
}
*ex_handle = (CS_VOID *)ex_async;
return CS_SUCCEED;
}
/*
** ex_async_free()
**
** Type of function:
** example async lib api
**
** Purpose:
** Free the async handle passed in.
**
** Returns:
** CS_PENDING
**
** Side Effects:
** None.
**
** History:
** 11/12/92: Otto Lind : Created
*/
CS_RETCODE CS_PUBLIC
ex_async_free(ex_handle)
EX_ASYNC *ex_handle;
{
ExAsync *ex_async;
CS_RETCODE retstat;
/*
** free allocate and initialize the async data area to store async
** information.
*/
ex_async = (ExAsync *)ex_handle;
/*
** drop the command handle.
*/
retstat = ct_cmd_drop(ex_async->cmd);
if (retstat != CS_SUCCEED)
{
return retstat;
}
/*
** Free the async handle
*/
memset(ex_async, 0, sizeof (*ex_async));
free(ex_async);
return CS_SUCCEED;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -