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

📄 twophase.c

📁 sybase数据库ct library的开发,使用了所以有函数
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
**
**	Sybase Open Two Phase Commit Application
**	Confidential Property of Sybase, Inc.
**	(c) Copyright Sybase, Inc. 1991, 1992
**	All rights reserved
**
**  TWOPHASE
**	This program tests CTLIB two phase commit library 
**
**  Usage:
**	twophase
**	
**  Returns:
**	1 on error or 0
*/

#include	<stdio.h>
#include	"example.h"
#include	"ctxact.h"

#if     (USE_SCCSID)
static char 	Sccsid[] = {"%Z% %M% %I% %G%"};
#endif  /* (USE_SCCSID) */


#define SERVER1		"snoopy"
#define SERVER2		"woodstock"
#define COMMIT		"snoopy"
#define	USERNAME	"sa"
#define	PASSWORD	""
#define	QUERY		"update titles set price = $1.50 where title_id = 'BU1032'"

/*
** Function decls.
*/
CS_CONNECTION	*init_conn PROTOTYPE((
		CS_CONTEXT      *cp,
		CS_CHAR		*username,
		CS_CHAR		*password
		));
CS_RETCODE	open_conns PROTOTYPE((
		CS_CONTEXT	*cp,
		CS_CONNECTION	**conn1,
		CS_CONNECTION	**conn2,
		CS_CONNECTION	**commit
		));
CS_RETCODE	exec_conn PROTOTYPE((
		CS_CONNECTION	*conn,
		CS_CHAR		*query
		));
CS_RETCODE	close_conn PROTOTYPE((
		CS_CONNECTION	*conn
		));
CS_RETCODE	perform_twophase PROTOTYPE((
		CS_CONNECTION	*conn1,
		CS_CONNECTION	*conn2,
		CS_CONNECTION	*commit,
		CS_CHAR		*query
		));
CS_VOID		abort_all PROTOTYPE((
		CS_CONNECTION	*conn1,
		CS_CONNECTION	*conn2,
		CS_CONNECTION	*commit,
		CS_INT		commid
		));

CS_RETCODE 	cs_err_handler PROTOTYPE ((      /* CS-Library handler     */
		CS_CONTEXT      *cp,
		CS_CLIENTMSG    *msg
		));

CS_RETCODE 	client_err_handler PROTOTYPE ((  /* Client handler         */
		CS_CONNECTION   *chp,
		CS_COMMAND      *cmdp,
		CS_CLIENTMSG    *emsgp
		));

CS_RETCODE	server_err_handler PROTOTYPE ((  /* Server handler       */
		CS_CONTEXT      *cp,
		CS_CONNECTION   *chp,
		CS_SERVERMSG    *msgp
		));

int		main PROTOTYPE((
		int		argc,
		char		*argv[]
		));

int	main(argc, argv)
int	argc;
char	*argv[];
{
	CS_CONTEXT	*cp;
	CS_CONNECTION	*conn1, *conn2, *commit;

	/* allocate memory for the context structure			*/
	if (cs_ctx_alloc(EX_CTLIB_VERSION, &cp) != CS_SUCCEED)
	{
		(CS_VOID)fprintf(stderr, 
			"%s: Context allocate failed. Exiting.\n", argv[0]);

		exit(1);
	}

	/* Install a CS-Library error handler.                          */
	if (cs_config(cp, CS_SET, CS_MESSAGE_CB, (CS_VOID *)cs_err_handler,
		CS_UNUSED, NULL) != CS_SUCCEED)
	{
		/* Release the context structure.			*/
		(CS_VOID)cs_ctx_drop(cp);

		(CS_VOID)fprintf(stderr, 
			"%s: Can't init CSLIB handlers. Exiting\n", argv[0]);
		exit(1);
	}

	/* Initialize Open Client version.				*/
	if (ct_init(cp, EX_CTLIB_VERSION) != CS_SUCCEED)
	{
		/* Release the context structure.			*/
		(CS_VOID)cs_ctx_drop(cp);

		(CS_VOID)fprintf(stderr, 
			"%s: Can't init CTLIB version. Exiting\n", argv[0]);
		exit(1);
	}

	/*
	** Install message and error handlers.
	*/
	if (ct_callback(cp, (CS_CONNECTION *)NULL, CS_SET, CS_CLIENTMSG_CB, 
		(CS_VOID *)client_err_handler) != CS_SUCCEED)
	{
		/* Release the context structure.			*/
		(CS_VOID)ct_exit(cp, CS_FORCE_EXIT);
		(CS_VOID)cs_ctx_drop(cp);

		(CS_VOID)fprintf(stderr, 
			"%s: Can't init message handlers. Exiting\n", argv[0]);
		exit(1);
	}
	if (ct_callback(cp, (CS_CONNECTION *)NULL, CS_SET, CS_SERVERMSG_CB, 
		(CS_VOID *)server_err_handler) != CS_SUCCEED)
	{
		/* Release the context structure.			*/
		(CS_VOID)ct_exit(cp, CS_FORCE_EXIT);
		(CS_VOID)cs_ctx_drop(cp);

		(CS_VOID)fprintf(stderr, 
			"%s: Can't init error handlers. Exiting\n", argv[0]);
		exit(1);
	}

	/* Allocate/initialize the connection handles 			*/
	if (open_conns(cp, &conn1, &conn2, &commit) != CS_SUCCEED)
	{
		/* Release the context structure.			*/
		(CS_VOID)ct_exit(cp, CS_FORCE_EXIT);
		(CS_VOID)cs_ctx_drop(cp);

		(CS_VOID)fprintf(stderr, 
			"%s: Can't open all connections. Exiting\n", argv[0]);
		exit(1);
	}

	/* Use the "pubs2" database.					*/
	if ((exec_conn(conn1, "use pubs2") != CS_SUCCEED) ||
	    (exec_conn(conn2, "use pubs2") != CS_SUCCEED))
	{
		/* Release the context structure.			*/
		(CS_VOID)ct_exit(cp, CS_FORCE_EXIT);
		(CS_VOID)cs_ctx_drop(cp);

		(CS_VOID)fprintf(stderr, 
			"%s: Can't issue 'use pubs2' on connections. Exiting\n",
			argv[0]);
		exit(1);
	}


	if (perform_twophase(conn1, conn2, commit, QUERY) != CS_SUCCEED)
	{
		(CS_VOID)fprintf(stderr, 
			"perform_twophase() failed for '%s'\n", QUERY);

		(CS_VOID)ct_exit(cp, CS_FORCE_EXIT);
		(CS_VOID)cs_ctx_drop(cp);
		exit(1);
	}

	/* Close the connections used					*/
	if ((close_conn(conn1) != CS_SUCCEED) ||
	    (close_conn(conn2) != CS_SUCCEED) ||
	    (close_commit(commit) != CS_SUCCEED))
	{
		(CS_VOID)fprintf(stderr, "Failure closing connections...\n");

		(CS_VOID)ct_exit(cp, CS_FORCE_EXIT);
		(CS_VOID)cs_ctx_drop(cp);
		exit(1);
	}

	/* Release allocated control structures				*/
	(CS_VOID)ct_exit(cp, CS_FORCE_EXIT);
	(CS_VOID)cs_ctx_drop(cp);

	exit(0);
}

/*
**  PERFORM_TWOPHASE - 
**	Perform two phase commit.
**
**  Parameters:
**	conn1		Pointer to the first connection.
**	conn2		Pointer to the second connection.
**	commit		Pointer to the commit connection.
**	query1		Query to perform on.
**
**  Returns:
**	CS_SUCCEED | CS_FAIL
**
*/
CS_RETCODE	perform_twophase(conn1, conn2, commit, query)
CS_CONNECTION	*conn1;
CS_CONNECTION	*conn2;
CS_CONNECTION	*commit;
CS_CHAR		*query;
{
	CS_INT		commid;
	CS_INT		outlen;
	CS_CHAR		xact_string[CS_MAX_MSG + 1];
	CS_CHAR		command[CS_MAX_MSG];

	/* Start the distributed transaction on the commit service.	*/
	if ((commid = start_xact(commit, "demo", CS_NULLTERM, "Twophase", 
		CS_NULLTERM, 2)) <= 0)
	{
		return (CS_FAIL);
	}

	/* Build the transaction name. 					*/
	if (build_xact_string ("Twophase", CS_NULLTERM, SERVER2, CS_NULLTERM,
		commid, xact_string, CS_MAX_MSG, &outlen) != CS_SUCCEED)
	{
		(CS_VOID)fprintf(stderr, "Build transaction failed...\n");
		abort_xact(commit, commid);
		(CS_VOID)remove_xact(commit, commid, 2);
		return (CS_FAIL);
	}
	xact_string[outlen] = '\0';

	/* Build the first command buffer. 				*/
	(CS_VOID)sprintf(command, "BEGIN TRANSACTION %s", xact_string);

	/* Begin the transaction on the different servers		*/
	if ((exec_conn(conn1, command) != CS_SUCCEED) ||
	    (exec_conn(conn2, command) != CS_SUCCEED))
	{
		(CS_VOID)fprintf(stderr, "Begin transaction failed...\n");
		abort_xact(commit, commid);
		(CS_VOID)remove_xact(commit, commid, 2);
		return (CS_FAIL);
	}

	/* Scan for the transaction					*/
	if (scan_xact(commit, commid) != CS_SUCCEED)
	{
		(CS_VOID)fprintf(stderr, "Scan transaction failed...\n");
		abort_all(conn1, conn2, commit, commid);
		return (CS_FAIL);
	}

	/* Perform update						*/
	if ((exec_conn(conn1, query) != CS_SUCCEED) ||
	    (exec_conn(conn2, query) != CS_SUCCEED))
	{
		(CS_VOID)fprintf(stderr, "Update query failed...\n");
		abort_all(conn1, conn2, commit, commid);
		return (CS_FAIL);
	}

	/* Find out if all servers can commit the transaction. 		*/
	if ((exec_conn(conn1, "PREPARE TRANSACTION") != CS_SUCCEED) ||
	    (exec_conn(conn2, "PREPARE TRANSACTION") != CS_SUCCEED))
	{
		(CS_VOID)fprintf(stderr, "PREPARE transaction failed...\n");
		abort_all(conn1, conn2, commit, commid);
		return (CS_FAIL);
	}

	/* Commit the transaction. 					*/
	if (commit_xact(commit, commid) != CS_SUCCEED)
	{
		/* The commit server failed to record the commit. 	*/
		fprintf(stderr, "Transaction aborted -- commit_xact failed\n");
		abort_all(conn1, conn2, commit, commid);
		return (CS_FAIL);
	}

	/* 
	** The transaction has successfully committed.  
	** Inform the servers. 
	*/
	if (exec_conn(conn1, "COMMIT TRANSACTION") == CS_SUCCEED)
		(CS_VOID)remove_xact(commit, commid, 1);
	if (exec_conn(conn2, "COMMIT TRANSACTION") == CS_SUCCEED)
		(CS_VOID)remove_xact(commit, commid, 1);

	return (CS_SUCCEED);
}

/*
**  ABORT_ALL - 
**	Abort the connections.
**
**  Parameters:
**	conn1		Pointer to the first connection.
**	conn2		Pointer to the second connection.
**	commit		Pointer to the commit connection.
**	commid		The commit id.
**
**  Returns:
**	none.
**
*/
CS_VOID		abort_all(conn1, conn2, commit, commid)
CS_CONNECTION	*conn1;
CS_CONNECTION	*conn2;
CS_CONNECTION	*commit;
CS_INT		commid;
{
	/* Inform the commit server of the failure			*/
	abort_xact(commit, commid);

	/* Roll back the transactions on the different servers. */
	(CS_VOID)exec_conn(conn1, "ROLLBACK TRANSACTION");
	(CS_VOID)exec_conn(conn2, "ROLLBACK TRANSACTION");
	(CS_VOID)remove_xact(commit, commid, 2);
}

/*
**  OPEN_CONNS - 
**	Initialize/Open the three connections needed.
**
**  Parameters:
**	cp		The application context.
**	conn1		Pointer to the first connection.
**	conn2		Pointer to the second connection.
**	commit		Pointer to the commit connection.
**
**  Returns:
**	CS_SUCCEED | CS_FAIL
**
**  Side Effects:
** 	Performs no clean-up of connection handles on failure.
**
*/
CS_RETCODE	open_conns(cp, conn1, conn2, commit)
CS_CONTEXT	*cp;
CS_CONNECTION	**conn1;
CS_CONNECTION	**conn2;
CS_CONNECTION	**commit;
{
	if ((*conn1 = init_conn(cp, USERNAME, PASSWORD)) 
		== (CS_CONNECTION *)NULL)
	{
		return (CS_FAIL);
	}
	if ((*conn2 = init_conn(cp, USERNAME, PASSWORD)) 
		== (CS_CONNECTION *)NULL)
	{
		return (CS_FAIL);
	}
	if ((*commit = init_conn(cp, USERNAME, PASSWORD)) 
		== (CS_CONNECTION *)NULL)
	{
		return (CS_FAIL);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -