TestTransactions.cxx
上传用户:xfwatch
上传日期:2020-12-14
资源大小:872k
文件大小:14k
源码类别:

中间件编程

开发平台:

Java

  1.  /*
  2.  * JBoss, Home of Professional Open Source
  3.  * Copyright 2008, Red Hat, Inc., and others contributors as indicated
  4.  * by the @authors tag. All rights reserved.
  5.  * See the copyright.txt in the distribution for a
  6.  * full listing of individual contributors.
  7.  * This copyrighted material is made available to anyone wishing to use,
  8.  * modify, copy, or redistribute it subject to the terms and conditions
  9.  * of the GNU Lesser General Public License, v. 2.1.
  10.  * This program is distributed in the hope that it will be useful, but WITHOUT A
  11.  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
  12.  * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
  13.  * You should have received a copy of the GNU Lesser General Public License,
  14.  * v.2.1 along with this distribution; if not, write to the Free Software
  15.  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  16.  * MA  02110-1301, USA.
  17.  */
  18. #include <string>
  19. #include <sstream>
  20. #include "TestAssert.h"
  21. #include "TestTransactions.h"
  22. #include "txi.h"
  23. #include "tx.h"
  24. #include "testrm.h"
  25. #include "ThreadLocalStorage.h"
  26. #include "userlogc.h"
  27. #include "testTxAvoid.h"
  28. #ifndef WIN32
  29. #include "ace/OS_NS_stdlib.h"
  30. #include "ace/OS_NS_stdio.h"
  31. #include "ace/OS_NS_string.h"
  32. #endif
  33. //check_info(const char *msg, int rv, COMMIT_RETURN cr, TRANSACTION_CONTROL tc, TRANSACTION_TIMEOUT tt, TRANSACTION_STATE ts)
  34. #define CHECKINFO(msg, rv, cr, tc, tt, ts) {
  35. TXINFO txi;
  36. BT_ASSERT_MESSAGE(msg, rv == tx_info(&txi));
  37. userlogc_debug("TestTransactions::check_info begin %ld=%ld %ld=%ld %ld=%ld %ld=%ld",
  38. txi.when_return, (long) (cr),
  39. txi.transaction_control, (long) (tc),
  40. txi.transaction_timeout, (long) (tt),
  41. txi.transaction_state, (long) (ts));
  42. if ((long) (cr) >= 0l) BT_ASSERT_MESSAGE(msg, txi.when_return == (long) (cr));
  43. if ((long) (tc) >= 0l) BT_ASSERT_MESSAGE(msg, txi.transaction_control == (long) (tc));
  44.     if ((long) (tt) >= 0l) BT_ASSERT_MESSAGE(msg, txi.transaction_timeout == (long) (tt));
  45.     if ((long) (ts) >= 0l) BT_ASSERT_MESSAGE(msg, txi.transaction_state == (long) (ts));}
  46. void TestTransactions::setUp()
  47. {
  48. init_ace();
  49. txx_stop();
  50. initEnv();
  51. TestFixture::setUp();
  52. // previous tests may have left a txn on the thread
  53. destroySpecific(TSS_KEY);
  54. }
  55. void TestTransactions::tearDown()
  56. {
  57. txx_stop();
  58. TestFixture::tearDown();
  59. destroyEnv();
  60. }
  61. void TestTransactions::test_rclog()
  62. {
  63. doOne();
  64. }
  65. void TestTransactions::test_basic()
  66. {
  67. doTwo();
  68. }
  69. // sanity check
  70. void TestTransactions::test_transactions()
  71. {
  72. userlogc_debug("TestTransactions::test_transactions begin");
  73. BT_ASSERT_EQUAL(TX_OK, tx_open());
  74. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  75. BT_ASSERT_EQUAL(TX_OK, tx_commit());
  76. BT_ASSERT_EQUAL(TX_OK, tx_close());
  77. userlogc("TestTransactions::test_transactions pass");
  78. }
  79. // check for protocol errors in a transactions lifecycle
  80. void TestTransactions::test_protocol()
  81. {
  82. userlogc_debug("TestTransactions::test_protocol begin");
  83. // should not be able to begin or complete a transaction before calling tx_open
  84. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_begin());
  85. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_commit());
  86. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_rollback());
  87. // tx close succeeds if was never opened
  88. BT_ASSERT_EQUAL(TX_OK, tx_close());
  89. // open should succeed
  90. BT_ASSERT_EQUAL(TX_OK, tx_open());
  91. // open second should should be idempotent
  92. BT_ASSERT_EQUAL(TX_OK, tx_open());
  93. // should not be able to complete a transaction before calling tx_begin
  94. BT_ASSERT(tx_commit() != TX_OK);
  95. BT_ASSERT(tx_rollback() != TX_OK);
  96. // should be able to close if a transaction hasn't been started
  97. BT_ASSERT_EQUAL(TX_OK, tx_close());
  98. // reopen the transaction - begin should succeed
  99. BT_ASSERT_EQUAL(TX_OK, tx_open());
  100. userlogc_debug("TestTransactions::test_protocol 2nd begin");
  101. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  102. // should not be able to close a transaction before calling tx_commit or tx_rollback
  103. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_close());
  104. // rollback should succeed
  105. BT_ASSERT_EQUAL(TX_OK, tx_rollback());
  106. // should not be able to commit or rollback a transaction after it has already completed
  107. BT_ASSERT(tx_commit() != TX_OK);
  108. BT_ASSERT(tx_rollback() != TX_OK);
  109. // begin should succeed after terminating a transaction
  110. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  111. BT_ASSERT_EQUAL(TX_OK, tx_commit());
  112. // close should succeed
  113. BT_ASSERT_EQUAL(TX_OK, tx_close());
  114. // tx_begin should return TX_PROTOCOL_ERROR if caller is already in transaction mode
  115. BT_ASSERT_EQUAL(TX_OK, tx_open());
  116. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  117. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_begin());
  118. BT_ASSERT_EQUAL(TX_OK, tx_commit());
  119. BT_ASSERT_EQUAL(TX_OK, tx_close());
  120. BT_ASSERT_EQUAL(TX_OK, tx_open());
  121. /* cause RM 102 start to fail */
  122. fault_t fault = {0, 102, O_XA_START, XAER_RMERR};
  123. (void) dummy_rm_add_fault(&fault);
  124. // tx_begin should return TX_ERROR if rm return errors, and the caller is not in transaction mode
  125. BT_ASSERT_EQUAL(TX_ERROR, tx_begin());
  126. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_commit());
  127. /* cleanup */
  128. (void) dummy_rm_del_fault(fault.id);
  129. BT_ASSERT_EQUAL(TX_OK, tx_close());
  130. userlogc( (char*) "TestTransactions::test_protocol pass");
  131. }
  132. void TestTransactions::test_info()
  133. {
  134. userlogc_debug("TestTransactions::test_info begin");
  135. BT_ASSERT_EQUAL(TX_OK, tx_open());
  136. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  137. // verify that the initial values are correct
  138. // do not test for the initial value of info.when_return since it is implementation dependent
  139. // if the second parameter is 1 then test that we are in transaction mode
  140. CHECKINFO("initial values", 1, TX_COMMIT_DECISION_LOGGED, TX_UNCHAINED, 0l, TX_ACTIVE);
  141. BT_ASSERT_EQUAL(TX_OK, tx_commit());
  142. // if the second parameter is 0 then test that we are not in transaction mode
  143. CHECKINFO("not in tx context", 0, TX_COMMIT_DECISION_LOGGED, TX_UNCHAINED, 0l, -1l);
  144. (void) tx_set_commit_return(TX_COMMIT_COMPLETED);
  145. (void) tx_set_transaction_control(TX_CHAINED);
  146. (void) tx_set_transaction_timeout(10l);
  147. // begin another transaction
  148. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  149. // verify that the new values are correct and that there is a running transaction
  150. CHECKINFO("modified values", 1, TX_COMMIT_COMPLETED, TX_CHAINED, 10l, TX_ACTIVE);
  151. // commit the transaction
  152. userlogc_debug("TestTransactions::test_info commit chained tx");
  153. BT_ASSERT_EQUAL(TX_OK, tx_commit());
  154. // transaction control mode is TX_CHAINED so there should be an active transaction after a commit
  155. CHECKINFO("TX_CHAINED after commit", 1, TX_COMMIT_COMPLETED, TX_CHAINED, 10l, TX_ACTIVE);
  156. // rollback the chained transaction
  157. BT_ASSERT_EQUAL(TX_OK, tx_rollback());
  158. // transaction control mode is TX_CHAINED so there should be an active transaction after a rollback
  159. CHECKINFO("XX", 1, TX_COMMIT_COMPLETED, TX_CHAINED, 10l, TX_ACTIVE);
  160. // stop chaining transactions
  161. (void) tx_set_transaction_control(TX_UNCHAINED);
  162. BT_ASSERT_EQUAL(TX_OK, tx_rollback());
  163. // transaction control mode should now be TX_UNCHAINED so there should not be an active transaction after a rollback
  164. CHECKINFO("TX_UNCHAINED after rollback", 0, TX_COMMIT_COMPLETED, TX_UNCHAINED, 10l, -1l);
  165. BT_ASSERT_EQUAL(TX_OK, tx_close());
  166. // If info is null, no TXINFO structure is returned
  167. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_info(NULL));
  168. userlogc( (char*) "TestTransactions::test_info pass");
  169. }
  170. // test for transaction timeout behaviour
  171. void TestTransactions::test_timeout()
  172. {
  173. long timeout = 4;
  174. long delay = 8;
  175. userlogc_debug("TestTransactions::test_timeout begin");
  176. // cause RMs to sleep during 2PC
  177. fault_t fault1 = {0, 102, O_XA_COMMIT, XA_OK, F_DELAY, (void*)&delay};
  178. fault_t fault2 = {0, 100, O_XA_PREPARE, XA_OK, F_DELAY, (void*)&delay};
  179. BT_ASSERT_EQUAL(TX_OK, tx_open());
  180. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  181. // set timeout - the value should not have any effect until the next call to tx_begin
  182. BT_ASSERT_EQUAL(TX_OK, tx_set_transaction_timeout(timeout));
  183. doThree(delay);
  184. BT_ASSERT_EQUAL(TX_OK, tx_commit());
  185. // start another transaction
  186. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  187. // sleep for longer than the timeout
  188. userlogc_debug("TestTransactions::test_timeout sleeping");
  189. doSix(delay);
  190. userlogc_debug("TestTransactions::test_timeout testing for rollback on commit");
  191. BT_ASSERT_EQUAL(TX_ROLLBACK, tx_commit());
  192. // cause the RM to delay for delay seconds during commit processing
  193. (void) dummy_rm_add_fault(&fault1);
  194. (void) dummy_rm_add_fault(&fault2);
  195. userlogc_debug("TestTransactions::test_timeout injecting delay after phase 1");
  196. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  197. // once the transaction has started 2PC any further delays (beyond the timeout period) should have no effect
  198. userlogc_debug("TestTransactions::test_timeout validating that the delay was ignored");
  199. BT_ASSERT_EQUAL(TX_OK, tx_commit());
  200. /* cleanup */
  201. (void) dummy_rm_del_fault(fault1.id);
  202. (void) dummy_rm_del_fault(fault2.id);
  203. BT_ASSERT_EQUAL(TX_OK, tx_close());
  204. userlogc( (char*) "TestTransactions::test_timeout pass");
  205. }
  206. void TestTransactions::test_rollback()
  207. {
  208. // TODO check the behaviour when a real RM is used.
  209. userlogc_debug("TestTransactions::test_rollback begin");
  210. fault_t fault1 = {0, 102, O_XA_COMMIT, XA_HEURHAZ};
  211. /* cause RM 102 start to fail */
  212. fault_t fault2 = {0, 102, O_XA_START, XAER_RMERR};
  213. BT_ASSERT_EQUAL(TX_OK, tx_open());
  214. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  215. doFour();
  216. CHECKINFO("set_rollback_only", 1, TX_COMMIT_DECISION_LOGGED, TX_UNCHAINED, 0l, TX_ROLLBACK_ONLY);
  217. BT_ASSERT_EQUAL(TX_ROLLBACK, tx_commit());
  218. BT_ASSERT_EQUAL(TX_OK, tx_set_transaction_control(TX_CHAINED));
  219. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  220. (void) dummy_rm_add_fault(&fault2);
  221. doFour();
  222. BT_ASSERT_EQUAL(TX_ROLLBACK_NO_BEGIN, tx_commit());
  223. (void) dummy_rm_del_fault(fault2.id);
  224. BT_ASSERT_EQUAL(TX_OK, tx_set_commit_return(TX_COMMIT_COMPLETED));
  225. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  226. (void) dummy_rm_add_fault(&fault1);
  227. (void) dummy_rm_add_fault(&fault2);
  228. BT_ASSERT_EQUAL(TX_HAZARD_NO_BEGIN, tx_commit());
  229. (void) dummy_rm_del_fault(fault1.id);
  230. (void) dummy_rm_del_fault(fault2.id);
  231. BT_ASSERT_EQUAL(TX_OK, tx_close());
  232. userlogc( (char*) "TestTransactions::test_rollback pass");
  233. }
  234. void TestTransactions::test_RM()
  235. {
  236. /* cause RM 102 to generate a mixed heuristic */
  237. fault_t fault1 = {0, 102, O_XA_COMMIT, XA_HEURMIX};
  238. /* cause RM 102 start to fail */
  239. fault_t fault2 = {0, 102, O_XA_START, XAER_RMERR};
  240. userlogc_debug("TestTransactions::test_RM begin");
  241. /* inject a commit fault in Resource Manager with rmid 102 */
  242. (void) dummy_rm_add_fault(&fault1);
  243. BT_ASSERT_EQUAL(TX_OK, tx_open());
  244. /* turn on heuristic reporting (ie the commit does not return until 2PC is complete) */
  245. BT_ASSERT_EQUAL(TX_OK, tx_set_commit_return(TX_COMMIT_COMPLETED));
  246. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  247. /* since we have added a XA_HEURMIX fault tx_commit should return an mixed error */
  248. userlogc_debug("TestTransactions::test_RM expecting TX_MIXED");
  249. BT_ASSERT_EQUAL(TX_MIXED, tx_commit());
  250. /*
  251.  * repeat the test but with chained transactions and heuristic reporting enabled
  252.  */
  253. BT_ASSERT_EQUAL(TX_OK, tx_set_transaction_control(TX_CHAINED));
  254. BT_ASSERT_EQUAL(TX_OK, tx_set_commit_return(TX_COMMIT_COMPLETED));
  255. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  256. /* inject a fault that will cause the chained tx_begin to fail */
  257. (void) dummy_rm_add_fault(&fault2);
  258. /*
  259.  * commit should fail with a heuristic and the attempt to start a chained transaction should fail
  260.  * since we have just injected a start fault
  261.  */
  262. BT_ASSERT_EQUAL(TX_MIXED_NO_BEGIN, tx_commit());
  263. /* clean up */
  264. (void) dummy_rm_del_fault(fault1.id);
  265. (void) dummy_rm_del_fault(fault2.id);
  266. /* should still be able to clean up after failing to commit a chained transaction */
  267. BT_ASSERT_EQUAL(TX_OK, tx_close());
  268. userlogc( (char*) "TestTransactions::test_RM pass");
  269. }
  270. /**
  271.  * Test that XIDs are recovered via the XA spec xa_recover method.
  272.  * This functionality covers the following failure scenario:
  273.  * - server calls prepare on a RM
  274.  * - RM prepares but the the server fails before it can write to its transaction recovery log
  275.  * In this case the RM will have a pending transaction branch which does not appear in
  276.  * the recovery log. Calling xa_recover on the RM will return the 'missing' XID which the
  277.  * recovery scan will replay.
  278.  */
  279. void TestTransactions::test_RM_recovery_scan()
  280. {
  281. long nbranches = 2l;
  282. fault_t fault1 = {0, 102, O_XA_RECOVER, XA_OK, F_ADD_XIDS, &nbranches, 0};
  283. userlogc_debug("TestTransactions::test_RM_recovery_scan begin");
  284. /* tell the Resource Manager with rmid 102 to remember prepared XID's */
  285. (void) dummy_rm_add_fault(&fault1);
  286. /* tx_open() should trigger a recovery scan (see XAResourceManagerFactory::run_recovery() */
  287. BT_ASSERT_EQUAL(TX_OK, tx_open());
  288. // all resources should have been recovered
  289. BT_ASSERT_EQUAL(nbranches, (long)fault1.res);
  290. // and the number that were recovered should also be nbranches
  291. BT_ASSERT_EQUAL(nbranches, (long)fault1.res2);
  292. // atmibroker::tx::TxManager::get_instance()->getRMFac().run_recovery();
  293. /* clean up */
  294. (void) dummy_rm_del_fault(fault1.id);
  295. BT_ASSERT_EQUAL(TX_OK, tx_close());
  296. userlogc("TestTransactions::test_RM_recovery_scan pass");
  297. }
  298. /*
  299.  * Test whether enlisting a resource with a remote transaction manager works
  300.  * This test attempts to simulate what XAResourceManager does.
  301.  * The real test for interacting with resource managers happens as a side effect
  302.  * of begining and completing a transactions provided some Resouce Managers
  303.  * have been configured in btconfig.xml
  304.  */
  305. void TestTransactions::test_register_resource()
  306. {
  307. userlogc_debug("TestTransactions::test_register_resource begin");
  308. // start a transaction running
  309. BT_ASSERT_EQUAL(TX_OK, tx_open());
  310. BT_ASSERT_EQUAL(TX_OK, tx_begin());
  311. void* ra = doFive();
  312. // commit the transaction
  313. BT_ASSERT_EQUAL(TX_OK, tx_commit());
  314. doSeven(ra);
  315. // clean up
  316. BT_ASSERT_EQUAL(TX_OK, tx_close());
  317. userlogc("TestTransactions::test_register_resource pass");
  318. }
  319. /*
  320.  * Test tx_set_commit_return(), tx_set_transaction_control(), tx_set_transaction_timeout()
  321.  */
  322. void TestTransactions::test_tx_set()
  323. {
  324. userlogc("TestTransactions::test_tx_set begin");
  325. // tx_set_* return TX_PROTOCOL_ERROR if not call tx_open
  326. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_set_transaction_control(TX_CHAINED));
  327. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_set_commit_return(TX_COMMIT_COMPLETED));
  328. BT_ASSERT_EQUAL(TX_PROTOCOL_ERROR, tx_set_transaction_timeout(10l));
  329. BT_ASSERT_EQUAL(TX_OK, tx_open());
  330. BT_ASSERT_EQUAL(TX_EINVAL, tx_set_transaction_control(2l));
  331. BT_ASSERT_EQUAL(TX_EINVAL, tx_set_commit_return(2l));
  332. BT_ASSERT_EQUAL(TX_EINVAL, tx_set_transaction_timeout(-1l));
  333. BT_ASSERT_EQUAL(TX_OK, tx_close());
  334. userlogc("TestTransactions::test_tx_set pass");
  335. }