⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ctxact.c

📁 sybase数据库ct library的开发,使用了所以有函数
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
**  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 + -