home *** CD-ROM | disk | FTP | other *** search
- /*
- ** twophase.c
- **
- ** Demo of Two-Phase Commit Service
- **
- ** This example uses the two-phase commit service
- ** to perform a simultaneous update on two servers.
- ** In this example, one of the servers participating
- ** in the distributed transaction also functions as
- ** the commit service.
- **
- ** In this particular example, the same update is
- ** performed on both servers. You can, however, use
- ** the commit server to perform completely different
- ** updates on each server.
- **
- */
-
- #include <stdio.h>
- #include <sybfront.h>
- #include <sybdb.h>
-
- int err_handler();
- int msg_handler();
-
- char cmdbuf[256];
- char xact_string[128];
-
- main()
- {
-
- DBPROCESS *dbproc_server1;
- DBPROCESS *dbproc_server2;
- DBPROCESS *dbproc_commit;
- LOGINREC *login;
- int commid;
-
- RETCODE ret_server1;
- RETCODE ret_server2;
-
- /* Initialize DB-Library. */
- if (dbinit() == FAIL)
- exit(ERREXIT);
-
- dberrhandle(err_handler);
- dbmsghandle(msg_handler);
-
- printf("Demo of Two Phase Commit\n");
-
- /* Open connections with the servers and the commit service. */
- login = dblogin();
- DBSETLPWD(login, "server_password");
- DBSETLAPP(login, "twophase");
-
- dbproc_server1 = dbopen (login, "SERVICE");
- dbproc_server2 = dbopen (login, "PRACTICE");
- dbproc_commit = open_commit (login, "SERVICE");
-
- if (dbproc_server1 == NULL ||
- dbproc_server2 == NULL ||
- dbproc_commit == NULL)
- {
- printf (" Connections failed!\n");
- exit (ERREXIT);
- }
-
- /* Use the "pubs" database. */
- sprintf(cmdbuf, "use pubs");
- dbcmd(dbproc_server1, cmdbuf);
- dbsqlexec(dbproc_server1);
- dbcmd(dbproc_server2, cmdbuf);
- dbsqlexec(dbproc_server2);
-
- /* Start the distributed transaction on the commit service. */
- commid = start_xact(dbproc_commit, "demo", "test", 2);
-
- /* Build the transaction name. */
- build_xact_string ("test", "SERVICE", commid, xact_string);
-
- /* Build the first command buffer. */
- sprintf(cmdbuf, "BEGIN TRANSACTION %s", xact_string);
-
- /* Begin the transactions on the different servers. */
- dbcmd(dbproc_server1, cmdbuf);
- dbsqlexec(dbproc_server1);
- dbcmd(dbproc_server2, cmdbuf);
- dbsqlexec(dbproc_server2);
-
- /* Do various updates. */
- sprintf(cmdbuf, " update titles set price = $1.50 where");
- strcat(cmdbuf, " title_id = 'BU1032'");
- dbcmd(dbproc_server1, cmdbuf);
- ret_server1 = dbsqlexec(dbproc_server1);
- dbcmd(dbproc_server2, cmdbuf);
- ret_server2 =dbsqlexec(dbproc_server2);
- if (ret_server1 == FAIL || ret_server2 == FAIL)
- {
- /* Some part of the transaction failed. */
- printf(" Transaction aborted -- dbsqlexec failed\n");
- abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
- }
-
- /* Find out if all servers can commit the transaction. */
- sprintf(cmdbuf, "PREPARE TRANSACTION");
- dbcmd(dbproc_server1, cmdbuf);
- dbcmd(dbproc_server2, cmdbuf);
- ret_server1 = dbsqlexec(dbproc_server1);
- ret_server2 = dbsqlexec(dbproc_server2);
- if (ret_server1 == FAIL || ret_server2 == FAIL)
- {
- /* One or both of the servers failed to prepare. */
- printf(" Transaction aborted -- PREPARE failed\n");
- abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
- }
-
- /* Commit the transaction. */
- if (commit_xact(dbproc_commit, commid) == FAIL)
- {
- /* The commit server failed to record the commit. */
- printf( " Transaction aborted -- commit_xact failed\n");
- abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
- exit(ERREXIT);
- }
-
- /* The transaction has successfully committed. Inform the servers. */
- sprintf(cmdbuf, "COMMIT TRANSACTION");
- dbcmd(dbproc_server1, cmdbuf);
- if (dbsqlexec(dbproc_server1) != FAIL)
- remove_xact(dbproc_commit, commid, 1);
- dbcmd(dbproc_server2, cmdbuf);
- if (dbsqlexec(dbproc_server2) != FAIL)
- remove_xact(dbproc_commit, commid, 1);
-
- /* Close the connection to the commit server. */
- close_commit(dbproc_commit);
-
- printf( "We made it!\n");
- dbexit();
- exit(STDEXIT);
- }
-
- /* Function to abort the distributed transaction. */
-
- abortall( dbproc_server1, dbproc_server2, dbproc_commit, commid )
- DBPROCESS *dbproc_server1;
- DBPROCESS *dbproc_server2;
- DBPROCESS *dbproc_commit;
- int commid;
- {
- /* Some part of the transaction failed. */
-
- /* Inform the commit server of the failure. */
- abort_xact(dbproc_commit, commid);
-
- /* Roll back the transactions on the different servers. */
- sprintf(cmdbuf, "ROLLBACK TRANSACTION");
- dbcmd(dbproc_server1, cmdbuf);
- if (dbsqlexec(dbproc_server1) != FAIL)
- remove_xact(dbproc_commit, commid, 1);
- dbcmd(dbproc_server2, cmdbuf);
- if (dbsqlexec(dbproc_server2) != FAIL)
- remove_xact(dbproc_commit, commid, 1);
-
- dbexit();
- exit(ERREXIT);
- }
-
- /* Message and error handling functions. */
-
- int msg_handler(dbproc, msgno, msgstate, severity, msgtext,
- servername, procname, line)
-
- DBPROCESS *dbproc;
- DBINT msgno;
- int msgstate;
- int severity;
- char *msgtext;
- char *servername;
- char *procname;
- DBUSMALLINT line;
-
- {
- /* Msg 5701 is just a USE DATABASE message, so skip it. */
- if (msgno == 5701)
- return (0);
-
- /* Print any severity 0 message as is, without extra stuff. */
- if (severity == 0)
- {
- printf ("%s\n",msgtext);
- return (0);
- }
-
- printf ("Msg %ld, Level %d, State %d\n",
- msgno, severity, msgstate);
-
- if (strlen(servername) > 0)
- printf ("Server '%s', ", servername);
- if (strlen(procname) > 0)
- printf ("Procedure '%s', ", procname);
- if (line > 0)
- printf ("Line %d", line);
-
- printf("\n\t%s\n", msgtext);
-
- if (severity >= 16)
- {
- printf("Program Terminated! Fatal SQL Server error.\n");
- exit(ERREXIT);
- }
-
- return (0);
- }
-
- int err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr)
- DBPROCESS *dbproc;
- int severity;
- int dberr;
- int oserr;
- char *dberrstr;
- char *oserrstr;
- {
- if ((dbproc == NULL) || (DBDEAD(dbproc)))
- return (INT_EXIT);
- else
- {
- printf ("DB-Library error: \n\t%s\n", dberrstr);
-
- if (oserr != DBNOERR)
- printf ("Operating system error:\n\t%s\n", oserrstr);
- }
-
- return (INT_CANCEL);
- }
-