📄 twophase.c
字号:
/*
**
** 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 + -