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

中间件编程

开发平台:

Java

  1. /*
  2.  * JBoss, Home of Professional Open Source
  3.  * Copyright 2009, 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 "log4cxx/logger.h"
  19. #include "ThreadLocalStorage.h"
  20. #include "TxControl.h"
  21. #include "TxManager.h"
  22. #include "ace/OS_NS_time.h"
  23. #define TX_GUARD(msg, expect) { 
  24. FTRACE(txclogger, "ENTER"); 
  25. if (!isActive(msg, expect)) {   
  26. return TX_PROTOCOL_ERROR;   
  27. }}
  28. namespace atmibroker {
  29. namespace tx {
  30. log4cxx::LoggerPtr txclogger(log4cxx::Logger::getLogger("TxLogControl"));
  31. TxControl::TxControl(CosTransactions::Control_ptr ctrl, long timeout, int tid) :
  32. _rbonly(false), _ttl(timeout), _tid(tid), _ctrl(ctrl) {
  33. FTRACE(txclogger, "ENTER new TXCONTROL: " << this);
  34. _ctime = (long) (ACE_OS::gettimeofday().sec());
  35. if (timeout <= 0l)
  36. _ttl = -1l;
  37. }
  38. TxControl::~TxControl()
  39. {
  40. FTRACE(txclogger, "ENTER delete TXCONTROL: " << this);
  41. if (_cds.size() != 0) {
  42. LOG4CXX_ERROR(txclogger, (char*) "delete called with outstanding tp calls");
  43. }
  44. suspend();
  45. }
  46. int TxControl::end(bool commit, bool reportHeuristics)
  47. {
  48. TX_GUARD("end", true);
  49. if (_cds.size() != 0) {
  50. LOG4CXX_WARN(txclogger, (char*) "protocol error: there are outstanding tp calls");
  51. return TX_PROTOCOL_ERROR;
  52. }
  53. int outcome = TX_OK;
  54. CosTransactions::Terminator_var term;
  55. try {
  56. term = _ctrl->get_terminator();
  57. if (CORBA::is_nil(term)) {
  58. LOG4CXX_WARN(txclogger, (char*) "end: no terminator");
  59. outcome = TX_FAIL;
  60. }
  61. } catch (CosTransactions::Unavailable & e) {
  62. LOG4CXX_WARN(txclogger, (char*) "end: term unavailable: " << e._name());
  63. outcome = TX_FAIL;
  64. } catch (CORBA::OBJECT_NOT_EXIST & e) {
  65. LOG4CXX_DEBUG(txclogger, (char*) "end: term ex " << e._name() << " minor: " << e.minor());
  66. // transaction no longer exists (presumed abort)
  67. outcome = TX_ROLLBACK;
  68. } catch (...) {
  69. LOG4CXX_WARN(txclogger, (char*) "end: unknown error looking up terminator");
  70. outcome = TX_FAIL; // TM failed temporarily
  71. }
  72. if (outcome == TX_OK) {
  73. try {
  74. // ask the transaction service to end the tansaction
  75. (commit ? term->commit(reportHeuristics) : term->rollback());
  76. } catch (CORBA::TRANSACTION_ROLLEDBACK &e) {
  77. LOG4CXX_INFO(txclogger, (char*) "end: rolled back: " << e._name());
  78. outcome = TX_ROLLBACK;
  79. } catch (CosTransactions::Unavailable & e) {
  80. LOG4CXX_INFO(txclogger, (char*) "end: unavailable: " << e._name());
  81. outcome = TX_FAIL; // TM failed temporarily
  82. } catch (CosTransactions::HeuristicMixed &e) {
  83. LOG4CXX_INFO(txclogger, (char*) "end: HeuristicMixed: " << e._name());
  84. // can be thrown if commit_return characteristic is TX_COMMIT_COMPLETED
  85. outcome = TX_MIXED;
  86. } catch (CosTransactions::HeuristicHazard &e) {
  87. LOG4CXX_ERROR(txclogger, (char*) "end: HeuristicHazard: " << e._name());
  88. // can be thrown if commit_return characteristic is TX_COMMIT_COMPLETED
  89. outcome = TX_HAZARD;
  90. } catch (CORBA::SystemException & e) {
  91. LOG4CXX_WARN(txclogger, (char*) "end: " << e._name() << " minor: " << e.minor());
  92. outcome = TX_FAIL;
  93. } catch (...) {
  94. LOG4CXX_WARN(txclogger, (char*) "end: unknown error");
  95. outcome = TX_FAIL; // TM failed temporarily
  96. }
  97. }
  98. LOG4CXX_DEBUG(txclogger, (char*) "end: outcome: " << outcome);
  99. suspend();
  100. return outcome;
  101. }
  102. int TxControl::commit(bool reportHeuristics)
  103. {
  104. FTRACE(txclogger, "ENTER report " << reportHeuristics);
  105. return end(true, reportHeuristics);
  106. }
  107. int TxControl::rollback()
  108. {
  109. FTRACE(txclogger, "ENTER");
  110. return end(false, false);
  111. }
  112. int TxControl::rollback_only()
  113. {
  114. TX_GUARD("rollback_only", true);
  115. try {
  116. CosTransactions::Coordinator_var coord = _ctrl->get_coordinator();
  117. if (!CORBA::is_nil(coord.in())) {
  118. coord->rollback_only();
  119. return TX_OK;
  120. }
  121. } catch (CosTransactions::Unavailable & e) {
  122. // no coordinator
  123. LOG4CXX_WARN(txclogger, (char*) "rollback_only: unavailable: " << e._name());
  124. } catch (CORBA::OBJECT_NOT_EXIST & e) {
  125. // ought to be due to the txn timing out
  126. LOG4CXX_DEBUG(txclogger, (char*) "rollback_only: " << e._name() << " minor: " << e.minor());
  127. _rbonly = true;
  128. return TX_OK;
  129. } catch (CORBA::SystemException & e) {
  130. LOG4CXX_WARN(txclogger, (char*) "rollback_only: " << e._name() << " minor: " << e.minor());
  131. }
  132. return TX_FAIL;
  133. }
  134. CosTransactions::Status TxControl::get_ots_status()
  135. {
  136. FTRACE(txclogger, "ENTER");
  137. if (!isActive(NULL, false)) {
  138. return CosTransactions::StatusNoTransaction;
  139. }
  140. try {
  141. CosTransactions::Coordinator_var coord = _ctrl->get_coordinator();
  142. if (!CORBA::is_nil(coord.in()))
  143. return (coord->get_status());
  144. } catch (CosTransactions::Unavailable & e) {
  145. // no coordinator
  146. LOG4CXX_TRACE(txclogger, (char*) "unavailable: " << e._name());
  147. } catch (CORBA::OBJECT_NOT_EXIST & e) {
  148. LOG4CXX_DEBUG(txclogger, (char*) "status: " << e._name() << " minor: " << e.minor());
  149. // transaction no longer exists (presumed abort)
  150. return CosTransactions::StatusNoTransaction;
  151. } catch (CORBA::SystemException & e) {
  152. LOG4CXX_WARN(txclogger, (char*) "status: " << e._name() << " minor: " << e.minor());
  153. }
  154. return CosTransactions::StatusUnknown;
  155. }
  156. int TxControl::get_status()
  157. {
  158. FTRACE(txclogger, "ENTER");
  159. if (_rbonly)
  160. return TX_ROLLBACK_ONLY;
  161. CosTransactions::Status status = get_ots_status();
  162. switch (status) {
  163. case CosTransactions::StatusActive:
  164. case CosTransactions::StatusPreparing:
  165. case CosTransactions::StatusPrepared:
  166. case CosTransactions::StatusCommitting:
  167. case CosTransactions::StatusCommitted:
  168. return TX_ACTIVE;
  169. case CosTransactions::StatusRollingBack:
  170. case CosTransactions::StatusRolledBack:
  171. return TX_ACTIVE;
  172. case CosTransactions::StatusMarkedRollback:
  173. return TX_ROLLBACK_ONLY;
  174. // there is no way to detect TX_TIMEOUT_ROLLBACK_ONLY
  175. case CosTransactions::StatusUnknown:
  176. // only option is to assume its active
  177. return TX_ACTIVE;
  178. case CosTransactions::StatusNoTransaction:
  179. // Since XATMI thinks the txn exists but OTS says it doesn't then
  180. // it must have been due to a timeout (a rollback would have
  181. // deleted this TxControl object)
  182. return TX_TIMEOUT_ROLLBACK_ONLY;
  183. default:
  184. LOG4CXX_DEBUG(txclogger, (char*) "get_status default: " << status);
  185. return -1; // there is no #define for NO TX
  186. }
  187. }
  188. /**
  189.  * Return -1 if the txn is subject to timeouts
  190.  * otherwise return the remaining time to live
  191.  */
  192. long TxControl::ttl()
  193. {
  194. FTRACE(txclogger, "ENTER ttl=" << _ttl << " ctime=" << _ctime << " now=" << ACE_OS::gettimeofday().sec());
  195. if (_ttl == -1l)
  196. return -1l;
  197. long ttl = _ttl - (long) (ACE_OS::gettimeofday().sec()) + _ctime;
  198. LOG4CXX_TRACE(txclogger, (char*) "> ttl=" << ttl);
  199. return (ttl <= 0l ? 0l : ttl);
  200. }
  201. int TxControl::get_timeout(CORBA::ULong *timeout)
  202. {
  203. TX_GUARD(NULL, false);
  204. try {
  205. CosTransactions::PropagationContext* context = _ctrl->get_coordinator()->get_txcontext();
  206. *timeout = context->timeout;
  207. return TX_OK;
  208. } catch (CORBA::SystemException & e) {
  209. LOG4CXX_WARN(txclogger, (char*) "get timeout: " << e._name() << " minor: " << e.minor());
  210. return TX_FAIL;
  211. }
  212. }
  213. /**
  214.  * Return the OTS control for the current transaction.
  215.  * The caller is responsible for decrementing the ref count
  216.  * of the returned pointer.
  217.  */
  218. CosTransactions::Control_ptr TxControl::get_ots_control(long* ttlp)
  219. {
  220. FTRACE(txclogger, "ENTER");
  221. if (ttlp != NULL)
  222. *ttlp = ttl();
  223. return (CORBA::is_nil(_ctrl) ? NULL : CosTransactions::Control::_duplicate(_ctrl));
  224. }
  225. /**
  226.  * release the control and remove the tx to thread association
  227.  */
  228. void TxControl::suspend()
  229. {
  230. FTRACE(txclogger, "ENTER");
  231. if (!CORBA::is_nil(_ctrl)) {
  232. try { // c.f. TxManager::tx_suspend
  233. (void) CORBA::release(_ctrl);
  234. } catch (CORBA::SystemException & e) {
  235. LOG4CXX_WARN(txclogger, (char*) "end: error unref control: " << e._name() << " minor: " << e.minor());
  236. }
  237. }
  238. destroySpecific(TSS_KEY);
  239. _ctrl = NULL;
  240. }
  241. /**
  242.  * Test whether the OTS control represents a valid transaction
  243.  * If the transaction is expected to be active and its not
  244.  * or vica-versa then log the supplied msg (if its not NULL)
  245.  */
  246. bool TxControl::isActive(const char *msg, bool expect)
  247. {
  248. FTRACE(txclogger, "ENTER");
  249. bool c = (!CORBA::is_nil(_ctrl));
  250. if (c != expect && msg) {
  251. LOG4CXX_WARN(txclogger, (char*) "protocol violation: " << msg);
  252. }
  253. return c;
  254. }
  255. bool TxControl::isOriginator()
  256. {
  257. return (_tid != 0);
  258. }
  259. } // namespace tx
  260. } //namespace atmibroker