📄 ctxact.c
字号:
/*
** ctxact.c
**
** Confidential property of Sybase, Inc.
** (c) Copyright Sybase, Inc. 1985 to 1994.
** All rights reserved
**
**
** This file contains functions for two phase committ.
**
*/
#include <stdio.h>
#include <string.h>
#include "ctxact.h"
#if (USE_SCCSID)
static char Sccsid[] = {"%I% %M% %G% %Z%"};
#endif /* (USE_SCCSID) */
/*
** The name that will show up in sysprocesses
*/
#define PROCESSNAME "Commit"
#define DEF_COMMITNAME "DSCOMMIT"
CS_STATIC CS_RETCODE handle_results PROTOTYPE ((
CS_COMMAND *cmd
));
/*
** open_commit()
**
** Purpose:
** Open_commit establishs a network connection for use
** by other commit service calls.
**
** Parameters
** conn Connection structure initialized with the username,
** password etc.
** service name to look up commit service in interfaces file
** if NULL, use "DSCOMMIT"
**
** Returns
** CS_SUCCEED | CS_FAIL
**
**
** Side Effects
**
** On failure, the connection structure passed in is NOT deallocated;
** this is left to the caller.
*/
CS_RETCODE
open_commit(conn, service, service_len)
CS_CONNECTION *conn;
CS_CHAR *service;
CS_INT service_len;
{
CS_RETCODE ret;
if ((service == (CS_CHAR *)NULL) || (service_len == 0))
{
service = DEF_COMMITNAME;
service_len = CS_NULLTERM;
}
/* Set the application name to 'Commit' */
if (ct_con_props(conn, CS_SET, CS_APPNAME, (CS_VOID *)PROCESSNAME,
CS_NULLTERM, (CS_INT *)NULL) != CS_SUCCEED)
{
return (CS_FAIL);
}
/* Connect to the commit server */
ret = ct_connect(conn, service, service_len);
return (ret);
}
/*
** close_commit()
**
** Purpose:
** Close_commit shuts down network connection previous opened with
** open_commit.
**
** Parameters
** conn CS_CONNECTION for connection to be shut down
**
**
** Returns
** CS_SUCCEED | CS_FAIL
**
**
** Side Effects
** Closes a network connection.
**
** The connection structure is not dropped; this is left to the user.
**
*/
CS_RETCODE
close_commit(conn)
CS_CONNECTION *conn;
{
CS_RETCODE ret;
ret = ct_close(conn, CS_FORCE_CLOSE);
return (ret);
}
/*
** build_xact_string()
**
** Purpose:
** Build_xact_string builds a string of the form:
**
** "commid:service.xact_name"
**
** Parameters
** xact_name Transaction name
** xact_len Length of the transaction name
** service Server name
** service_len Length of the server name
** commid The commit id returned by start_xact
** result The buffer to put the string in.
** result_len The length of the result buffer.
** outlen The length written to the result buffer
**
** Returns
** none.
**
** Side Effects
** none.
**
*/
CS_RETCODE
build_xact_string(xact_name, xact_len, service, service_len, commid,
result, result_len, outlen)
CS_CHAR *xact_name;
CS_INT xact_len;
CS_CHAR *service;
CS_INT service_len;
CS_INT commid;
CS_CHAR *result;
CS_INT result_len;
CS_INT *outlen;
{
CS_INT len;
CS_CHAR tmp_xact[CS_MAX_NAME +1];
CS_CHAR tmp_service[CS_MAX_NAME +1];
/* Initialization */
len = 0;
if ((service == (CS_CHAR *)NULL) || (service_len == 0))
{
service = DEF_COMMITNAME;
service_len = CS_NULLTERM;
}
/* Null terminate the service name */
if (service_len == CS_NULLTERM)
{
len += strlen(service);
}
else if (service_len > CS_MAX_NAME)
{
(CS_VOID)fprintf(stderr, "Service name too long...\n");
return (CS_FAIL);
}
else
{
strncpy(tmp_service, service, service_len);
tmp_service[service_len] = '\0';
service = tmp_service;
len += service_len;
}
/* Null terminate the transaction name */
if (xact_len == CS_NULLTERM)
{
len += strlen(xact_name);
}
else if (xact_len > CS_MAX_NAME)
{
(CS_VOID)fprintf(stderr, "Transaction name too long...\n");
return (CS_FAIL);
}
else
{
strncpy(tmp_xact, xact_name, xact_len);
tmp_xact[xact_len] = '\0';
xact_name = tmp_xact;
len += xact_len;
}
/* Make sure there is room in the result buffer */
if (result_len <= (len + 8))
{
(CS_VOID)fprintf(stderr,
"Result buffer too small...(need %d)\n", (len + 9));
return (CS_FAIL);
}
(CS_VOID)sprintf(result, "%ld:%s.%s", commid, service, xact_name);
if (outlen != (CS_INT *)NULL)
{
*outlen = strlen(result);
}
return (CS_SUCCEED);
}
/*
** start_xact()
**
** Purpose:
** Start_xact creates an entry for this transaction in the commit
** service table. Mark the entry as state BEGIN, with 'count'
** sites participating. Return an id 'commid' used for identifying
** the transaction when communicating with the service. The application
** and xact names are not essential but are used for debugging or
** monitoring the state of transactions.
**
** Parameters
** conn The CS_CONNECTION used to communicate via ctlib
** app_name The application name
** app_len The length of the application name
** xact_name The transaction name
** xact_len The length of the transaction name
** count Number of sites participating
**
** Returns
** commid id used to identify xact to service
** or zero if failure.
**
** Side Effects
** Changes commit table.
**
*/
CS_INT
start_xact(conn, app_name, app_len, xact_name, xact_len, count)
CS_CONNECTION *conn;
CS_CHAR *app_name;
CS_INT app_len;
CS_CHAR *xact_name;
CS_INT xact_len;
CS_INT count;
{
CS_INT ret;
CS_INT commid;
CS_RETCODE retcode;
CS_DATAFMT fmt;
CS_COMMAND *cmd;
/* Initialization */
commid = 0;
(CS_VOID)memset((char *)&fmt, 0, sizeof(CS_DATAFMT));
/* Allocate a command handle */
if (ct_cmd_alloc(conn, &cmd) != CS_SUCCEED)
{
return (0);
}
if (ct_command(cmd, CS_RPC_CMD, "sp_start_xact", CS_NULLTERM,
CS_UNUSED) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
/* Prepare the application name parameter */
strcpy(fmt.name, "@applname");
fmt.namelen = strlen(fmt.name);
fmt.datatype = CS_CHAR_TYPE;
fmt.maxlength = 30;
fmt.status = CS_INPUTVALUE;
if (ct_param(cmd, &fmt, (CS_VOID *)app_name, app_len, 0) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
/* Prepare the xact parameter */
strcpy(fmt.name, "@xactname");
fmt.namelen = strlen(fmt.name);
fmt.datatype = CS_CHAR_TYPE;
fmt.maxlength = 30;
fmt.status = CS_INPUTVALUE;
if (ct_param(cmd, &fmt, (CS_VOID *)xact_name, xact_len, 0)
!= CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
/* Prepare the count parameter */
strcpy(fmt.name, "@count");
fmt.namelen = strlen(fmt.name);
fmt.datatype = CS_INT_TYPE;
fmt.maxlength = CS_SIZEOF(CS_INT);
fmt.status = CS_INPUTVALUE;
if (ct_param(cmd, &fmt, (CS_VOID *)&count, CS_UNUSED, 0) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
/* Send to server */
if (ct_send(cmd) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
/*
** Get the result (a smallint commid)
**
** Someday, this sproc will return a 4-byte commid. Until then, we
** have to do a little dance.
*/
while ((retcode = ct_results(cmd, &ret)) == CS_SUCCEED)
{
switch ((int)ret)
{
case CS_ROW_RESULT:
/*
** Could do a ct_describe() to ensure proper
** data type/num columns being returned.
*/
fmt.namelen = 0;
fmt.datatype = CS_INT_TYPE;
fmt.maxlength = CS_SIZEOF(CS_INT);
fmt.status = 0;
if (ct_bind(cmd, 1, &fmt, (CS_VOID *)&commid,
(CS_INT *)NULL, (CS_SMALLINT *)NULL)
!= CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL,
cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
while ((retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED,
CS_UNUSED, NULL)) == CS_SUCCEED)
{
continue;
}
if (retcode != CS_END_DATA)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL,
cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
break;
case CS_CMD_FAIL:
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL,
cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
case CS_STATUS_RESULT:
default:
if (ct_cancel((CS_CONNECTION *)NULL, cmd,
CS_CANCEL_CURRENT) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL,
cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
break;
}
}
if (retcode != CS_END_RESULTS)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (0);
}
/* Free the command buffer */
if (ct_cmd_drop(cmd) != CS_SUCCEED)
{
return (0);
}
return (commid);
}
/*
** commit_xact()
**
** Purpose:
** Mark this transaction as committed in the commit table so any
** subsequent call to probe_xact() for this commid will return
** 'commit'.
**
** Parameters
** conn The CS_CONNECTION used to communicate
** commid id used to identify xact to service
**
** Returns
** CS_SUCCEED or CS_FAIL
**
**
** Side Effects
** Changes commit table.
**
*/
CS_RETCODE
commit_xact(conn, commid)
CS_CONNECTION *conn;
CS_INT commid;
{
CS_INT ret;
CS_RETCODE retcode;
CS_DATAFMT fmt;
CS_COMMAND *cmd;
CS_INT p_result;
/* Initialization */
p_result = -1;
(CS_VOID)memset((char *)&fmt, 0, sizeof(CS_DATAFMT));
/* Allocate a command handle */
if (ct_cmd_alloc(conn, &cmd) != CS_SUCCEED)
{
return (CS_FAIL);
}
if (ct_command(cmd, CS_RPC_CMD, "sp_commit_xact", CS_NULLTERM,
CS_UNUSED) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (CS_FAIL);
}
/* Prepare the count parameter */
strcpy(fmt.name, "@commid");
fmt.namelen = strlen(fmt.name);
fmt.datatype = CS_INT_TYPE;
fmt.maxlength = CS_SIZEOF(CS_INT);
fmt.status = CS_INPUTVALUE;
if (ct_param(cmd, &fmt, (CS_VOID *)&commid, CS_UNUSED, 0) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (CS_FAIL);
}
/* Send to server */
if (ct_send(cmd) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL, cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (CS_FAIL);
}
/* Process the result from the commit */
while ((retcode = ct_results(cmd, &ret)) == CS_SUCCEED)
{
switch ((int)ret)
{
case CS_ROW_RESULT:
/*
** Could do a ct_describe() to ensure proper
** data type/num columns being returned.
*/
fmt.namelen = 0;
fmt.datatype = CS_INT_TYPE;
fmt.maxlength = CS_SIZEOF(CS_INT);
fmt.status = 0;
if (ct_bind(cmd, 1, &fmt, (CS_VOID *)&p_result,
(CS_INT *)NULL, (CS_SMALLINT *)NULL)
!= CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL,
cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (CS_FAIL);
}
while ((retcode = ct_fetch(cmd, CS_UNUSED, CS_UNUSED,
CS_UNUSED, NULL)) == CS_SUCCEED)
{
continue;
}
if (retcode != CS_END_DATA)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL,
cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (CS_FAIL);
}
break;
case CS_CMD_FAIL:
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL,
cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (CS_FAIL);
case CS_STATUS_RESULT:
default:
if (ct_cancel((CS_CONNECTION *)NULL, cmd,
CS_CANCEL_CURRENT) != CS_SUCCEED)
{
(CS_VOID)ct_cancel((CS_CONNECTION *)NULL,
cmd, CS_CANCEL_ALL);
(CS_VOID)ct_cmd_drop(cmd);
return (CS_FAIL);
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -