DBLIB.CPP
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:13k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /* MS DTC Sample
  2. **
  3. ** This example uses MS DTC (distributed transaction
  4. ** coordinator) to perform simultaneous updates on two
  5. ** SQL servers.  The transaction in this example is 
  6. ** client initiated. The client also initiates the
  7. ** commit operation.
  8. **
  9. **  This sample uses the DBLib interface to communicate
  10. **  with both MS DTC and SQL server.
  11. **
  12. ** In this particular example, the pre-installed SQL server
  13. ** table "Authors" is used.
  14. **
  15. **  Build Instructions:
  16. **  This sample must link with the following files:  ntwdblib.lib, xolehlp.lib
  17. **
  18. **  Usage Instructions:
  19. **  Please run this program with the '-h' flag.
  20. **
  21. */
  22. //------------------------------------------------------------------------------
  23. // Include standard header files
  24. //------------------------------------------------------------------------------
  25. #include <windows.h>
  26. #include <stdio.h>
  27. #include <conio.h>
  28. #include <ctype.h>
  29. //------------------------------------------------------------------------------
  30. // Include MS DTC specific header files.
  31. //------------------------------------------------------------------------------
  32. #define INITGUID
  33. #include "txdtc.h"
  34. #include "xolehlp.h"
  35. //------------------------------------------------------------------------------
  36. // Include DBLib specific header files
  37. //------------------------------------------------------------------------------
  38. #ifndef DBNTWIN32
  39. #define DBNTWIN32
  40. #include <SQL.h>
  41. #include <SQLEXT.h>
  42. #include <sqlfront.h>
  43. #include <sqldb.h>
  44. #endif /* DBNTWIN32 */
  45. //------------------------------------------------------------------------------
  46. // Define constants
  47. //------------------------------------------------------------------------------
  48. #define STR_LEN 40
  49. #define TABLE_NAME "Authors"    
  50. //------------------------------------------------------------------------------
  51. // Define datatypes
  52. //------------------------------------------------------------------------------
  53. typedef struct DBCONN
  54. {
  55. TCHAR pszSrv [STR_LEN]; // data source name, configured through control panel
  56. TCHAR pszUser [STR_LEN]; // Login user name
  57. TCHAR pszPasswd[STR_LEN]; // Login user password
  58. TCHAR pszTableName[STR_LEN]; // not used - should remove.
  59. } DBCONN;
  60. //------------------------------------------------------------------------------
  61. // Define Globals
  62. //------------------------------------------------------------------------------
  63. static DBCONN gSrv1, gSrv2; // global DB connection struct for server 1 and 2
  64. static TCHAR gAuthorID[STR_LEN]; // use 11 chars only - per Authors table.
  65. static TCHAR gNewAddress[STR_LEN+1]; // max. address length in the Author's table.
  66. //-------------------------------------------------------------------------------
  67. //  DBLib specific global vars...
  68. //-------------------------------------------------------------------------------
  69. DBPROCESS *dbproc_server1;
  70. DBPROCESS *dbproc_server2;
  71. LOGINREC *login;
  72. //-------------------------------------------------------------------------------
  73. // Forward declaration of routines used.
  74. //-------------------------------------------------------------------------------
  75. void InitGlobals(int argc, char **argv);
  76. void LogonToDB(DBPROCESS **dbp, DBCONN *ptr);
  77. void Enlist(DBCONN *ptr,DBPROCESS *dbp, ITransaction *pTransaction);
  78. void ExecuteStatement(DBCONN *ptr, DBPROCESS *dbp, LPTSTR pszBuf);
  79. //-------------------------------------------------------------------------------
  80. // DBLib error and message handlers
  81. //-------------------------------------------------------------------------------
  82. int err_handler(DBPROCESS*, int, int, int, char*, char*);
  83. int msg_handler(DBPROCESS*, DBINT, int, int, char*);
  84. //-------------------------------------------------------------------------------
  85. // main()
  86. //-------------------------------------------------------------------------------
  87. void main(int argc, char **argv)
  88. {
  89. ITransactionDispenser *pTransactionDispenser;
  90. ITransaction *pTransaction;
  91. HRESULT hr = S_OK ;
  92. TCHAR SqlStatement[STR_LEN*2];
  93. // Initialize globals & validate command line arguments
  94. InitGlobals(argc,argv);
  95. // set error/msg handlers for this program
  96. dbmsghandle((DBMSGHANDLE_PROC)msg_handler);
  97. dberrhandle((DBERRHANDLE_PROC)err_handler);
  98. // initialize LOGINREC structure
  99. login = dblogin();
  100. // Obtain the ITransactionDispenser Interface pointer
  101. // by calling DtcGetTransactionManager()
  102. hr = DtcGetTransactionManager(  NULL,  // LPTSTR pszHost,
  103. NULL,  // LPTSTR pszTmName,
  104. IID_ITransactionDispenser, // /* in */ REFIID rid,
  105.     0, // /* in */ DWORD dwReserved1,
  106.     0,  // /* in */ WORD wcbReserved2,
  107.     0, // /* in */ void FAR * pvReserved2,
  108. (void **)&pTransactionDispenser // /*out */ void** ppvObject
  109. ) ;
  110. if (FAILED (hr))
  111.     {
  112. printf("DtcGetTransactionManager failed: %xn", hr);
  113.     exit (1);
  114.     }
  115. // Establish connection to database on server#1
  116. LogonToDB(&dbproc_server1,&gSrv1);
  117.  
  118. // Establish connection to database on server#2
  119. LogonToDB(&dbproc_server2,&gSrv2);
  120. // Loop performing distributed transactions
  121. for (INT i = 0; i < 5; i++)
  122. {
  123. // Initiate an MS DTC transaction
  124. hr = pTransactionDispenser->BeginTransaction( 
  125. NULL, // /* [in]  */ IUnknown __RPC_FAR *punkOuter,
  126. ISOLATIONLEVEL_ISOLATED, // /* [in]  */ ISOLEVEL isoLevel,
  127. ISOFLAG_RETAIN_DONTCARE, //  /* [in]  */ ULONG isoFlags,
  128. NULL, // /* [in]  */ ITransactionOptions *pOptions 
  129. &pTransaction // /* [out] */ ITransaction **ppTransaction
  130. ) ;
  131. if (FAILED (hr))
  132. {
  133. printf("BeginTransaction failed: %xn",hr);
  134. exit(1);
  135. }
  136. // Enlist each of the data sources on the transaction
  137. Enlist(&gSrv1,dbproc_server1,pTransaction);
  138. Enlist(&gSrv2,dbproc_server2,pTransaction);
  139. // Generate the SQL statement to execute on each of the databases
  140. sprintf(SqlStatement,
  141. "update authors set address = '%s_%d' where au_id = '%s'",
  142.  gNewAddress,i,gAuthorID);
  143. // Perform updates on both of the DBs participating in the transaction
  144. ExecuteStatement(&gSrv1,dbproc_server1,SqlStatement);
  145. ExecuteStatement(&gSrv2,dbproc_server2,SqlStatement);
  146. // Commit the transaction 
  147. hr = pTransaction->Commit(0,0,0);
  148. if (FAILED(hr))
  149. {
  150. printf("pTransaction->Commit() failed: %xn",hr);
  151. exit(1);
  152. }
  153. // At end of each transaction, pTransaction-Release() must be called.
  154. hr = pTransaction->Release();
  155. if (FAILED(hr))
  156. {
  157. printf("pTransaction->Release() failed: %xn",hr);
  158. exit(1);
  159. }
  160. printf("Successfully committed Transaction #%dn",i);
  161. } // for 
  162. // release the transaction dispenser
  163. pTransactionDispenser->Release();
  164. // release DBLib resources and exit
  165. dbexit();
  166. }
  167. //-------------------------------------------------------------------------------
  168. void InitGlobals(INT argc, char **argv)
  169. {
  170. TCHAR Usage[] = "n           [-S1  server_1] n"
  171. "           [-U1  user_name_1]n"
  172. "           [-P1  passwd_1]n"
  173. "           [-S2  server_2]n"
  174. "           [-U2  user_name_2]n"
  175. "           [-P2  passwd_2]n"
  176.         "           [-ID  au_id]n"
  177. "           [-Ad  new_addressn"
  178. "           [-h   Usage]n";
  179. // Init Table name 
  180. lstrcpy(gSrv1.pszTableName,TABLE_NAME);
  181. lstrcpy(gSrv2.pszTableName,TABLE_NAME);
  182. // Null login info, set defaults as appropriate
  183. lstrcpy(gSrv1.pszSrv,"");
  184. lstrcpy(gSrv1.pszUser,"sa");
  185. lstrcpy(gSrv1.pszPasswd,"");
  186. lstrcpy(gSrv2.pszSrv,"");
  187. lstrcpy(gSrv2.pszUser,"sa");
  188. lstrcpy(gSrv2.pszPasswd,"");
  189. lstrcpy(gAuthorID,"172-32-1176"); // default au_id value from authors table in pubs db.
  190. // scan command line arguments for user input.
  191. for (INT i = 1; i < argc; i++)
  192. {
  193. if (*argv[i] == '-' || *argv[i] == '/')
  194. {
  195. switch (argv[i][1])
  196. {
  197. // get the server or DSN name
  198. case 's':
  199. case 'S':
  200.  switch (argv[i][2])
  201.  {
  202.  case '1':
  203.  lstrcpy(gSrv1.pszSrv,argv[++i]);
  204.  break;
  205.  case '2':
  206.  lstrcpy(gSrv2.pszSrv,argv[++i]);
  207.  break;
  208.  default:
  209.  printf("Invalid Input %sn",argv[i]);
  210.  printf("nUsage: %s %s",argv[0],Usage);
  211.  exit(1);
  212.  };
  213.  break;
  214. // get user name
  215. case 'u':
  216. case 'U':
  217.  switch (argv[i][2])
  218.  {
  219.  case '1':
  220.  lstrcpy(gSrv1.pszUser,argv[++i]);
  221.  break;
  222.  case '2':
  223.  lstrcpy(gSrv2.pszUser,argv[++i]);
  224.  break;
  225.  default:
  226.  printf("Invalid Input %sn",argv[i]);
  227.  printf("nUsage: %s %s",argv[0],Usage);
  228.  exit(1);
  229.  };
  230.  break;
  231. // get password
  232. case 'p':
  233. case 'P':
  234.  switch (argv[i][2])
  235.  {
  236.  case '1':
  237.  lstrcpy(gSrv1.pszPasswd,argv[++i]);
  238.  break;
  239.  case '2':
  240.  lstrcpy(gSrv2.pszPasswd,argv[++i]);
  241.  break;
  242.  default:
  243.  printf("Invalid Input %sn",argv[i]);
  244.  printf("nUsage: %s %s",argv[0],Usage);
  245.  exit(1);
  246.    };
  247.  break;
  248. // get au_id, overriding default value.
  249. case 'i':
  250. case 'I':
  251. lstrcpy(gAuthorID,argv[++i]);
  252. break;
  253. // get new address to associate with the au_id
  254. case 'a':
  255. case 'A':
  256. lstrcpy(gNewAddress,argv[++i]);
  257. break;
  258. case '?':
  259. case 'h':
  260. case 'H':
  261. printf("nUsage: %s %s",argv[0],Usage);
  262. exit(1);
  263. break;
  264. default:
  265. printf("Invalid Input: %sn",argv[i]);
  266. printf("nUsage: %s %s",argv[0],Usage);
  267. exit(1);
  268. }
  269. }
  270. else 
  271. {
  272. printf("Illegal command line argument #%d, %sn",i,argv[i]);
  273. printf("nUsage: %s %s",argv[0],Usage);
  274. exit(1);
  275. }
  276. }
  277. printf("-----------------------------n");
  278. printf("MS DTC/DBLib Sample Configuration parametersn");
  279. printf( "server_1:      %sn"
  280. "user_name_1:   %sn"
  281. "passwd_1:      %sn"
  282. "server_2:      %sn"
  283. "user_name_2:   %sn"
  284. "passwd_2:      %sn",
  285. gSrv1.pszSrv,gSrv1.pszUser,gSrv1.pszPasswd,
  286. gSrv2.pszSrv,gSrv2.pszUser,gSrv2.pszPasswd);
  287. printf("-----------------------------n");
  288. }
  289. //-------------------------------------------------------------------------------
  290. void LogonToDB(DBPROCESS **dbp, DBCONN *ptr)
  291. {
  292. DBSETLUSER(login, ptr->pszUser);
  293. DBSETLPWD(login, ptr->pszPasswd);
  294. DBSETLAPP(login, "example");
  295. *dbp = dbopen (login, ptr->pszSrv);
  296. if (*dbp == NULL)
  297. {
  298. printf ("nLogin to server: %s failed, exiting!n",ptr->pszSrv);
  299. exit (ERREXIT);
  300. }
  301. /* Use the "pubs" database. */
  302. dbuse(*dbp, "pubs");
  303. }
  304. //-------------------------------------------------------------------------------
  305. void Enlist(DBCONN *ptr, DBPROCESS *dbp, ITransaction *pTransaction)
  306. {
  307. RETCODE rc = 0;
  308. rc = dbenlisttrans (dbp, pTransaction);
  309. if (FAIL == rc) 
  310. {
  311. printf("ndbenlisttrans() failed: %xn",rc);
  312. exit(1);
  313. }
  314. }
  315. // ---------------------------------------------------------------------------
  316. void ExecuteStatement(DBCONN *ptr, DBPROCESS *dbp, char *pszBuf)
  317. {
  318. RETCODE rc = 0;
  319. dbcmd(dbp,pszBuf);
  320. rc = dbsqlexec(dbp);
  321. if (FAIL == rc)
  322. {
  323. // one or both of the servers failed to prepare
  324. printf("dbsqlexec() failedn");
  325. exit(1);
  326. }
  327. rc = dbresults(dbp);
  328. if (rc != SUCCEED)
  329. {
  330. printf("dbresults() failed: %xn",rc);
  331. exit(1);
  332. }
  333. }
  334. // ---------------------------------------------------------------------------
  335. /* Message and error handling functions. */
  336. int msg_handler(DBPROCESS *dbproc, DBINT msgno, int msgstate, int severity, char *msgtext)
  337. {
  338. /* Msg 5701 is just a USE DATABASE message, so skip it. */
  339. if (msgno == 5701)
  340. return (0);
  341. /* Print any severity 0 message as is, without extra stuff. */
  342. if (severity == 0)
  343. {
  344. printf ("%sn",msgtext);
  345. return (0);
  346. }
  347. printf("SQL Server message %ld, severity %d:nt%sn",
  348. msgno, severity, msgtext);
  349. if (severity >>= 16)
  350. {
  351. printf("Program Terminated! Fatal SQL Server error.n");
  352. exit(ERREXIT);
  353. }
  354. return (0);
  355. }
  356. // ---------------------------------------------------------------------------
  357. int err_handler(DBPROCESS *dbproc, int severity, int dberr, int oserr, char *dberrstr, char *oserrstr)
  358.    
  359. {
  360. if ((dbproc == NULL) || (DBDEAD(dbproc)))
  361. return (INT_EXIT);
  362. else
  363. {
  364. printf ("DB-LIBRARY error: nt%sn", dberrstr);
  365. if (oserr != DBNOERR)
  366. printf ("Operating system error:nt%sn", oserrstr);
  367. }
  368. return (INT_CANCEL);
  369. }
  370. // ---------------------------------------------------------------------------