home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / sql / dblib / c / twophase / twophase.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-03  |  6.1 KB  |  227 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. #if defined(DBNTWIN32)
  17. #include <windows.h>
  18. #endif
  19.  
  20. #include <stdio.h>
  21. #include <sqlfront.h>
  22. #include <sqldb.h>
  23.  
  24. char    cmdbuf[256];
  25. char    xact_string[128];
  26.  
  27. /* Forward declarations of the error handler and message handler. 
  28. */
  29. int err_handler(DBPROCESS*, int, int, int, char*, char*);
  30. int msg_handler(DBPROCESS*, DBINT, int, int, char*);
  31. void abortall (DBPROCESS * dbproc_server1, DBPROCESS * dbproc_server2, DBPROCESS * dbproc_commit, DBINT commid);
  32.  
  33. void main(argv,argc)
  34. int argc;
  35. char *argv[];
  36. {
  37.  
  38.     DBPROCESS    *dbproc_server1;
  39.     DBPROCESS    *dbproc_server2;
  40.     DBPROCESS    *dbproc_commit;
  41.     LOGINREC    *login;
  42.     DBINT    commid;
  43.  
  44.     RETCODE    ret_server1;
  45.     RETCODE    ret_server2;
  46.  
  47.     // set error/msg handlers for this program
  48.     dbmsghandle((DBMSGHANDLE_PROC)msg_handler);
  49.     dberrhandle((DBERRHANDLE_PROC)err_handler);
  50.  
  51.  
  52.     /* Open connections with the servers and the commit service. */
  53.     printf("Demo of Two Phase Commit\n");
  54.     login = dblogin();
  55.     DBSETLUSER(login, "user");
  56.     DBSETLPWD(login, "my_passwd");
  57.     DBSETLAPP(login, "example");
  58.     DBSETLVERSION(login, DBVER60);
  59.     
  60.     dbproc_server1 = dbopen (login, "my_server1");
  61.     dbproc_server2 = dbopen (login, "my_server2");
  62.     dbproc_commit = open_commit (login, "my_commitsrv");
  63.  
  64.     if (dbproc_server1 == NULL ||
  65.         dbproc_server2 == NULL ||
  66.         dbproc_commit    == NULL)
  67.     {
  68.         printf (" Connections failed!\n");
  69.         exit (ERREXIT);
  70.     }
  71.  
  72.     /* Use the "pubs" database. */
  73.     dbuse(dbproc_server1, "pubs");
  74.     dbuse(dbproc_server2, "pubs");
  75.  
  76.     /* Start the distributed transaction on the commit service. */
  77.     commid = start_xact(dbproc_commit, "demo", "test", 2);
  78.  
  79.     /* Build the transaction name. */
  80.     build_xact_string ("test", "my_commitsrv", commid, xact_string);
  81.  
  82.     /* Build the first command buffer. */
  83.     sprintf(cmdbuf, "BEGIN TRANSACTION %s", xact_string);
  84.  
  85.     /* Begin the transactions on the different servers. */
  86.     dbcmd(dbproc_server1, cmdbuf);
  87.     dbsqlexec(dbproc_server1);
  88.     dbcmd(dbproc_server2, cmdbuf);
  89.     dbsqlexec(dbproc_server2);
  90.  
  91.     dbcancel(dbproc_server1);
  92.     dbcancel(dbproc_server2);
  93.  
  94.     /* Do various updates. */
  95.     sprintf(cmdbuf, " update titles set price = $1.50 where");
  96.     strcat(cmdbuf, " title_id = 'BU1032'");
  97.     dbcmd(dbproc_server1, cmdbuf);
  98.     ret_server1 = dbsqlexec(dbproc_server1);
  99.     dbcmd(dbproc_server2, cmdbuf);
  100.     ret_server2 =dbsqlexec(dbproc_server2);
  101.     if (ret_server1 == FAIL || ret_server2 == FAIL)
  102.     {
  103.         /* Some part of the transaction failed. */
  104.         printf(" Transaction aborted -- dbsqlexec failed\n");
  105.         abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
  106.     }
  107.  
  108.     dbcancel(dbproc_server1);
  109.     dbcancel(dbproc_server2);
  110.  
  111.     /* Find out if all servers can commit the transaction. */
  112.     sprintf(cmdbuf, "PREPARE TRANSACTION");
  113.     dbcmd(dbproc_server1, cmdbuf);
  114.     dbcmd(dbproc_server2, cmdbuf);
  115.     ret_server1 = dbsqlexec(dbproc_server1);
  116.     ret_server2 = dbsqlexec(dbproc_server2);
  117.     if (ret_server1 == FAIL || ret_server2 == FAIL)
  118.     {
  119.         /* One or both of the servers failed to prepare. */
  120.         printf(" Transaction aborted -- PREPARE failed\n");
  121.         abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
  122.     }
  123.  
  124.     dbcancel(dbproc_server1);
  125.     dbcancel(dbproc_server2);
  126.  
  127.     /* Commit the transaction. */
  128.     if (commit_xact(dbproc_commit, commid) == FAIL)
  129.     {
  130.         /* The commit server failed to record the commit. */
  131.         printf( " Transaction aborted -- commit_xact failed\n");
  132.         abortall(dbproc_server1, dbproc_server2, dbproc_commit, commid);
  133.         exit(ERREXIT);
  134.     }
  135.  
  136.     /* The transaction has successfully committed.    Inform the servers. 
  137. */
  138.     sprintf(cmdbuf, "COMMIT TRANSACTION");
  139.     dbcmd(dbproc_server1, cmdbuf);
  140.     if (dbsqlexec(dbproc_server1) != FAIL)
  141.         remove_xact(dbproc_commit, commid, 1);
  142.     dbcmd(dbproc_server2, cmdbuf);
  143.     if (dbsqlexec(dbproc_server2) != FAIL)
  144.         remove_xact(dbproc_commit, commid, 1);
  145.  
  146.     /* Close the connection to the commit server. */
  147.     close_commit(dbproc_commit);
  148.  
  149.     printf( "We made it!\n");
  150.     dbexit();
  151.     exit(STDEXIT);
  152. }
  153.  
  154. /* Function to abort the distributed transaction. */
  155.  
  156. void abortall( dbproc_server1, dbproc_server2, dbproc_commit, commid )
  157. DBPROCESS    *dbproc_server1;
  158. DBPROCESS    *dbproc_server2;
  159. DBPROCESS    *dbproc_commit;
  160. DBINT    commid;
  161. {
  162.     /* Some part of the transaction failed. */
  163.  
  164.     /* Inform the commit server of the failure. */
  165.     abort_xact(dbproc_commit, commid);
  166.  
  167.     /* Roll back the transactions on the different servers. */
  168.     sprintf(cmdbuf, "ROLLBACK TRANSACTION");
  169.     dbcmd(dbproc_server1, cmdbuf);
  170.     if (dbsqlexec(dbproc_server1) != FAIL)
  171.         remove_xact(dbproc_commit, commid, 1);
  172.     dbcmd(dbproc_server2, cmdbuf);
  173.     if (dbsqlexec(dbproc_server2) != FAIL)
  174.         remove_xact(dbproc_commit, commid, 1);
  175.  
  176.     dbexit();
  177.     exit(ERREXIT);
  178. }
  179. /* Message and error handling functions. */
  180. int msg_handler(dbproc,msgno,msgstate, severity, msgtext)
  181. DBPROCESS    *dbproc;
  182. DBINT    msgno;
  183. int    msgstate;
  184. int    severity;
  185. char    *msgtext;
  186. {
  187.     /*    Msg 5701 is just a USE DATABASE message, so skip it.    */
  188.     if (msgno == 5701)
  189.         return (0);
  190.     /*    Print any severity 0 message as is, without extra stuff.    */
  191.     if (severity == 0)
  192.     {
  193.         printf ("%s\n",msgtext);
  194.         return (0);
  195.     }
  196.  
  197.     printf("SQL Server message %ld, severity %d:\n\t%s\n",
  198.         msgno, severity, msgtext);
  199.  
  200.     if (severity >>= 16)
  201.     {
  202.         printf("Program Terminated! Fatal SQL Server error.\n");
  203.         exit(ERREXIT);
  204.     }
  205.     return (0);
  206. }
  207.  
  208. int err_handler(dbproc, severity, dberr, oserr, dberrstr, oserrstr)
  209. DBPROCESS    *dbproc;
  210. int    severity;
  211. int    dberr;
  212. int    oserr;
  213. char    *dberrstr;
  214. char    *oserrstr;
  215. {
  216.     if ((dbproc == NULL) || (DBDEAD(dbproc)))
  217.         return (INT_EXIT);
  218.     else
  219.     {
  220.         printf ("DB-LIBRARY error: \n\t%s\n", dberrstr);
  221.  
  222.         if (oserr != DBNOERR)
  223.             printf ("Operating system error:\n\t%s\n", oserrstr);
  224.     }
  225.     return (INT_CANCEL);
  226. }
  227.