home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 5 / 05.iso / a / a025 / 11.ddi / TWOPHASE.C@ / TWOPHASE.bin
Encoding:
Text File  |  1992-09-15  |  5.5 KB  |  212 lines

  1. /*    Demo of Two-Phase Commit Service
  2. **
  3. **    This example uses the two-phase commit service
  4. **    to perform a simultaneous update on two servers.
  5. **    In this example, one of the servers participating
  6. **    in the distributed transaction also functions as
  7. **    the commit service.
  8. **
  9. **    In this particular example, the same update is
  10. **    performed on both servers. You can, however, use
  11. **    the commit server to perform completely different
  12. **    updates on each server.
  13. **
  14. */
  15.  
  16. #include <stdio.h>
  17. #include <sqlfront.h>
  18. #include <sqldb.h>
  19.  
  20. char    cmdbuf[256];
  21. char    xact_string[128];
  22.  
  23. /* Forward declarations of the error handler and message handler. 
  24. */
  25. int    err_handler();
  26. int    msg_handler();
  27.  
  28. main(argv,argc)
  29. int argc;
  30. char *argv[];
  31. {
  32.  
  33.     DBPROCESS    *dbproc_server1;
  34.     DBPROCESS    *dbproc_server2;
  35.     DBPROCESS    *dbproc_commit;
  36.     LOGINREC    *login;
  37.     DBINT    commid;
  38.  
  39.     RETCODE    ret_server1;
  40.     RETCODE    ret_server2;
  41.  
  42.     dberrhandle(err_handler);
  43.     dbmsghandle(msg_handler);
  44.  
  45.     printf("Demo of Two Phase Commit\n");
  46.  
  47.     /* Open connections with the servers and the commit service. */
  48.     login = dblogin();
  49.     DBSETLUSER(login, "user");
  50.     DBSETLPWD(login, "my_passwd");
  51.     DBSETLAPP(login, "example");
  52.     dbproc_server1 = dbopen (login, "sql_svr1");
  53.     dbproc_server2 = dbopen (login, "sql_svr2");
  54.     dbproc_commit = open_commit (login, "sql_svr1");
  55.  
  56.     if (dbproc_server1 == NULL ||
  57.         dbproc_server2 == NULL ||
  58.         dbproc_commit    == NULL)
  59.     {
  60.         printf (" Connections failed!\n");
  61.         exit (ERREXIT);
  62.     }
  63.  
  64.     /* Use the "pubs" database. */
  65.     dbuse(dbproc_server1, "pubs");
  66.     dbuse(dbproc_server2, "pubs");
  67.  
  68.     /* Start the distributed transaction on the commit service. */
  69.     commid = start_xact(dbproc_commit, "demo", "test", 2);
  70.  
  71.     /* Build the transaction name. */
  72.     build_xact_string ("test", "SERVICE", commid, xact_string);
  73.  
  74.     /* Build the first command buffer. */
  75.     sprintf(cmdbuf, "BEGIN TRANSACTION %s", xact_string);
  76.  
  77.     /* Begin the transactions on the different servers. */
  78.     dbcmd(dbproc_server1, cmdbuf);
  79.     dbsqlexec(dbproc_server1);
  80.     dbcmd(dbproc_server2, cmdbuf);
  81.     dbsqlexec(dbproc_server2);
  82.  
  83.     /* Do various updates. */
  84.     sprintf(cmdbuf, " update titles set price = $1.50 where");
  85.     strcat(cmdbuf, " title_id = 'BU1032'");
  86.     dbcmd(dbproc_server1, cmdbuf);
  87.     ret_server1 = dbsqlexec(dbproc_server1);
  88.     dbcmd(dbproc_server2, cmdbuf);
  89.     ret_server2 =dbsqlexec(dbproc_server2);
  90.     if (ret_server1 == FAIL || ret_server2 == FAIL)
  91.     {
  92.         /* Some part of the transaction failed. */
  93.         printf(" Transaction aborted -- dbsqlexec failed\n");
  94.         abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
  95.     }
  96.  
  97.     /* Find out if all servers can commit the transaction. */
  98.     sprintf(cmdbuf, "PREPARE TRANSACTION");
  99.     dbcmd(dbproc_server1, cmdbuf);
  100.     dbcmd(dbproc_server2, cmdbuf);
  101.     ret_server1 = dbsqlexec(dbproc_server1);
  102.     ret_server2 = dbsqlexec(dbproc_server2);
  103.     if (ret_server1 == FAIL || ret_server2 == FAIL)
  104.     {
  105.         /* One or both of the servers failed to prepare. */
  106.         printf(" Transaction aborted -- PREPARE failed\n");
  107.         abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
  108.     }
  109.  
  110.     /* Commit the transaction. */
  111.     if (commit_xact(dbproc_commit, commid) == FAIL)
  112.     {
  113.         /* The commit server failed to record the commit. */
  114.         printf( " Transaction aborted -- commit_xact failed\n");
  115.         abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
  116.         exit(ERREXIT);
  117.     }
  118.  
  119.     /* The transaction has successfully committed.    Inform the servers. 
  120. */
  121.     sprintf(cmdbuf, "COMMIT TRANSACTION");
  122.     dbcmd(dbproc_server1, cmdbuf);
  123.     if (dbsqlexec(dbproc_server1) != FAIL)
  124.         remove_xact(dbproc_commit, commid, 1);
  125.     dbcmd(dbproc_server2, cmdbuf);
  126.     if (dbsqlexec(dbproc_server2) != FAIL)
  127.         remove_xact(dbproc_commit, commid, 1);
  128.  
  129.     /* Close the connection to the commit server. */
  130.     close_commit(dbproc_commit);
  131.  
  132.     printf( "We made it!\n");
  133.     dbexit();
  134.     exit(STDEXIT);
  135. }
  136.  
  137. /* Function to abort the distributed transaction. */
  138.  
  139. abortall( dbproc_server1, dbproc_server2, dbproc_commit, commid )
  140. DBPROCESS    *dbproc_server1;
  141. DBPROCESS    *dbproc_server2;
  142. DBPROCESS    *dbproc_commit;
  143. DBINT    commid;
  144. {
  145.     /* Some part of the transaction failed. */
  146.  
  147.     /* Inform the commit server of the failure. */
  148.     abort_xact(dbproc_commit, commid);
  149.  
  150.     /* Roll back the transactions on the different servers. */
  151.     sprintf(cmdbuf, "ROLLBACK TRANSACTION");
  152.     dbcmd(dbproc_server1, cmdbuf);
  153.     if (dbsqlexec(dbproc_server1) != FAIL)
  154.         remove_xact(dbproc_commit, commid, 1);
  155.     dbcmd(dbproc_server2, cmdbuf);
  156.     if (dbsqlexec(dbproc_server2) != FAIL)
  157.         remove_xact(dbproc_commit, commid, 1);
  158.  
  159.     dbexit();
  160.     exit(ERREXIT);
  161. }
  162. /* Message and error handling functions. */
  163. int msg_handler(dbproc,msgno,msgstate, severity, msgtext)
  164. DBPROCESS    *dbproc;
  165. DBINT    msgno;
  166. int    msgstate;
  167. int    severity;
  168. char    *msgtext;
  169. {
  170.     /*    Msg 5701 is just a USE DATABASE message, so skip it.    */
  171.     if (msgno == 5701)
  172.         return (0);
  173.     /*    Print any severity 0 message as is, without extra stuff.    */
  174.     if (severity == 0)
  175.     {
  176.         printf ("%s\n",msgtext);
  177.         return (0);
  178.     }
  179.  
  180.     printf("SQL Server message %ld, severity %d:\n\t%s\n",
  181.         msgno, severity, msgtext);
  182.  
  183.     if (severity >>= 16)
  184.     {
  185.         printf("Program Terminated! Fatal SQL Server error.\n");
  186.         exit(ERREXIT);
  187.     }
  188.     return (0);
  189. }
  190.  
  191. int err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr)
  192. DBPROCESS    *dbproc;
  193. int    severity;
  194. int    dberr;
  195. int    oserr;
  196. char    *dberrstr;
  197. char    *oserrstr;
  198. {
  199.     if ((dbproc == NULL) || (DBDEAD(dbproc)))
  200.         return (INT_EXIT);
  201.     else
  202.     {
  203.         printf ("DB-LIBRARY error: \n\t%s\n", dberrstr);
  204.  
  205.         if (oserr != DBNOERR)
  206.             printf ("Operating system error:\n\t%s\n", oserrstr);
  207.     }
  208.     return (INT_CANCEL);
  209. }
  210.  
  211.  
  212.