1 /* 2 3 Derby - Class org.apache.derby.iapi.jdbc.ResourceAdapter 4 5 Licensed to the Apache Software Foundation (ASF) under one or more 6 contributor license agreements. See the NOTICE file distributed with 7 this work for additional information regarding copyright ownership. 8 The ASF licenses this file to you under the Apache License, Version 2.0 9 (the "License"); you may not use this file except in compliance with 10 the License. You may obtain a copy of the License at 11 12 http://www.apache.org/licenses/LICENSE-2.0 13 14 Unless required by applicable law or agreed to in writing, software 15 distributed under the License is distributed on an "AS IS" BASIS, 16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 See the License for the specific language governing permissions and 18 limitations under the License. 19 20 */ 21 22 package org.apache.derby.iapi.jdbc; 23 24 import javax.transaction.xa.XAException; 25 import org.apache.derby.iapi.services.context.ContextService; 26 import org.apache.derby.iapi.store.access.xa.XAResourceManager; 27 import org.apache.derby.iapi.store.access.xa.XAXactId; 28 import org.apache.derby.iapi.error.StandardException; 29 30 /** 31 The resource adapter is the clearing house for managing connections, 32 transactions, and XAResources in a JDBC based resource manager living in 33 the distributed transaction processing environment. 34 35 <P> There is one instance of ResourceAdapter per Resource Manager (database). 36 The ResourceAdapter is responsible for keeping track of all run time global 37 transactions and their state. The resource adapter only knows of run time 38 global transactions, i.e., it does not know of in-doubt global transactions 39 re-created by recovery. 40 41 <P> The following is an overall design of the JTA implementation in Derby, 42 most of it has little to do with the ResourceAdapter interface itself. 43 <P><B>Design Overview </B> 44 45 <P>The overriding design principle is that existing code should be disturbed 46 as little as possible. This is so that DTP code will not add to the bloat 47 and drag of a normal, local, embbeded system. The second design principle 48 is that as much of the JDBC 2.0 extension functionality is to be 49 implemented in the Connectivity layer and not in the underlying storage 50 system as possible. Ideally, the additional storage interface will 51 implement no more than what is necessary to support the XAResource 52 interface. 53 54 <P>Language and replication code should not be touched, or have very 55 minimal API changes. The API changes are confined to passing XA calls down 56 to the store. 57 58 <P>Some change will be made to existing Connectivity code and new XA 59 modules will be added. This collection of code is hereby referred to as 60 the "blob of mysterious connectivity code", or the "resource adapter", or 61 "RA" for short. In the JTA doc, the resource adapter is considered to be 62 part of the JDBC driver. This RA means "some connectivity code", it 63 doesn't mean the object that implements the ResourceAdapter interface. 64 65 <P>The most important difference, in terms of implementation, between a 66 Connection that deals with a local transaction and a Connection that deals 67 with a global transaction is that in a global transaction, 2 or more 68 objects and threads can influence it - maybe concurrently. The normal JDBC 69 interaction goes thru the Connection, but transaction demarcation comes 70 from an XAResource object(s). The RA will channel all XAResource calls 71 that deal with a run time XA transaction (i.e., commit, end, forget, 72 prepare, start) thru the TransactionController that represents the real 73 transaction underneath. Furthermore, the RA will make sure that all calls 74 thru a Connection or thru any XAResource objects must pass thru some sort 75 of synchronized object before it can get to the underlying transaction 76 object. This is so that there is only one path to change the state of a 77 run time transaction and the transaction object and the context manager can 78 remain single thread access. 79 80 <P>In-doubt transaction (i.e., transactions re-created by recovery) 81 management and concurrency control is the responsibiliy of store. Moreover, 82 since the RA does not know the identities of the list of in-doubt 83 transactions, store must deal with (throw exception) when someone wants to 84 start a transaction with the same Xid as an existing in-doubt transaction. 85 86 <P>In terms of what this means to the app server that is calling us: if the 87 Connection and the XAResource that represents a global transaction is being 88 accessed by 2 different threads, they will access the database serially and 89 not concurrently. An in-doubt transaction gotten thru recovery has no 90 transaction object that is ever visible to the RA - because there is no 91 connection that was ever made to it. Therefore it is safe to influence the 92 state of an in-doubt transaction directly thru some store factory interface 93 - and have that go thru the transaction table underneath to find the actual 94 transaction object and context manager etc. 95 96 <P>One new functionality of a Connection is the ability to switch around 97 with different transactions. Before JTA, the lifetime of a transaction is 98 bounded by a connection, and a transaction cannot migrate from one 99 connection to another. In JTA, a global transaction can be detached from a 100 Connection. A transaction can move around and be attached to different 101 connections and its lifetime is not confine to the connection that started 102 it. From the Connection's point of view, before JTA, a (local) transaction 103 is always started and ended in the same connection. With JTA, it needs to 104 "take on" existing global transactions that was started by some other 105 connections. 106 107 <P>The RA will have the responsibility of 108 <OL> 109 <LI>setting up a Context with the appropriate transaction before calling 110 store to do work.</LI> 111 <LI>handling error on the context.</LI> 112 <LI>restoring a previous context if it was switched out due to an XAResouce 113 call to commit a transaction that is not what the XAResoruce is currently 114 attached to. </LI> 115 </OL> 116 117 <P>Because of all these switching around, a Connection may be in a 118 transaction-less state. This happens between an XAResource.end call that 119 detached the current global transaction from the Connection, and the next 120 XAResource.start call that attach the next global transaction with the 121 Connection. 122 123 <BR>An (inferior) implementation is for the Connection object to start a 124 local connection once it is detached from a global transaction. If the 125 user then uses the Connection immediately without a XAResource.start call, 126 then this Connection behaves just like it did before JTA, i.e., with a 127 local transaction. If, on the other hand, an XAResource.start call happens 128 next, then either the local transaction is "morphed" into a global 129 transaction, or, if the start call is to attach the connection to a 130 pre-existing global transaction, then the local transaction is thrown away 131 and the Connection will take on the pre-exising global transaction. 132 133 <BR>Another (superior) implementation is to make it possible for a 134 Connection to be transaction-less. When a Connection is first created by 135 XAConnection.getConnection, or when a XAResource.end call detached a global 136 transaction from the Connection, it is left in a transaction-less state. 137 If a XAResource.start call happens next, then the Connection either start a 138 new global transaction or it takes on an existing one. If a call is made 139 directly on the Connection before XAResource.start call happens, then the 140 Connection starts a new local transaction. This only affects Connections 141 that was gotten thru the XAConnection.getConnection(). Connections gotten 142 thru the DriverManager or a DataSource will have a local transaction 143 automatically started, as is the behavior today. When a Connection with a 144 local transaction commits, the transaction is still around but it is chain 145 to the next one - this is the current behavior. This behavior is very 146 desirable from a performance point of view, so it should be retained. 147 However, a local transaction cannot "morph" into a global transaction, 148 therefore when this Connection is attached to a global transaction, the 149 local transaction is thrown away and a global one started 150 151 <P>The RA will need to keep track of all global transactions. This is done 152 by (yet another) transaction table that lives in the RA. This transaction 153 table maps Xid to the ContextManager of the global transaction and whatever 154 else a connection needs to talk to the transaction - I assume the 155 Connection object currently have tendrils into various contexts and objects 156 and these are things that need to be detached and attached when a 157 Connection is hooked up with another transaction. The reason for yet 158 another transaction table instead of the one in store is because the one in 159 store keeps track of local and internal transactions and is really quite 160 overworked already. 161 162 <P><B>Detailed design</B> 163 164 <BR> First some ugly pictures. Some links are not shown to reduce 165 clutter. Externally visible object is in <B>bold</B>. 166 167 <P><PRE> 168 * 169 * When user ask for an XAConnection via a XADataSource, the following objects 170 * exists 171 * <BR> 172 * 173 * |-------------| 174 * |======= produces=>| <B>XAResource</B> | 175 * || |-------------| 176 * || | 177 * || has A 178 * || | 179 * || |--------------------- 180 * || V 181 * |--------------| produces |--------------| 182 * | <B>XADataSource</B> |=========>| <B>XAConnection</B> 183 * |--------------| |--------------| 184 * | | 185 * extends extends 186 * | | 187 * | |-----------------------| |----------------------| 188 * | | DB2jPooledConnection |==>| BrokeredConnection | 189 * | |-----------------------| |----------------------| 190 * | | ^ | 191 * | has A | has A 192 * | | | | 193 * |-----------------| | -------------------- 194 * | EmbeddedDataSource | | 195 * |-----------------| | 196 * | | 197 * has A | 198 * | | 199 * V V 200 * |------------| |----------------------| |-----------------------| 201 * | JDBCDriver |=produces=>| DetachableConnection |==>| XATransactionResource | 202 * | LocalDriver| |----------------------| | | 203 * |------------| | | points to : | 204 * | |XATransactionController| 205 * | | ContextManager | 206 * | | LCC | 207 * | | .. etc .. | 208 * | |-----------------------| 209 * | | 210 * extends extends 211 * | | 212 * |-----------------| |-----------------------| 213 * | EmbedConnection |-- ?-->| TransactionResource | 214 * |-----------------| |-----------------------| 215 * 216 * 217 * <BR><BR> 218 * When user ask for a PooledConnection via a PooledDataSource, the following 219 * objects exists 220 * <BR> 221 * |-------------------------------| 222 * | <B>EmbeddedConnectionPoolDataSource</B> | 223 * |-------------------------------| 224 * | || 225 * | || 226 * extends produces 227 * | || 228 * | \/ 229 * | |-----------------------| |----------------------| 230 * | | <B>DB2jPooledConnection</B> |==>| <B>BrokeredConnection</B> | 231 * | |-----------------------| |----------------------| 232 * | | ^ | 233 * | has A | has A 234 * | | | | 235 * |-----------------| | -------------------- 236 * | EmbeddedDataSource | | 237 * |-----------------| | 238 * | | 239 * has A | 240 * | | 241 * V V 242 * |------------| |----------------------| |-----------------------| 243 * | JDBCDriver |=produces=>| EmbedConnection |==>| TransactionResource | 244 * | LocalDriver| |----------------------| |-----------------------| 245 * |------------| 246 * 247 * 248 * 249 * <BR><BR> 250 * When user ask for a (normal) Connection via a DataSource, the following 251 * objects exists. The EmbeddedDataSource is just a wrapper for the JDBCDriver. 252 * <BR> 253 * |-----------------| 254 * | <B>EmbeddedDataSource</B> | 255 * |-----------------| 256 * | 257 * has A 258 * | 259 * V 260 * |------------| |-----------------| |-----------------------| 261 * | JDBCDriver |==produces=>| <B>EmbedConnection</B> |- ?->| TransactionResource | 262 * | LocalDriver| |-----------------| |-----------------------| 263 * |------------| 264 265 </PRE> 266 267 <P>XADataSource inherits DataSource methods from EmbeddedDataSource. It also 268 implements ResourceAdapter, whose main job is to keep track of run time 269 global transactions. A global transaction table maps XIDs to 270 XATransactionResource. XADataSource also has a XAResourceManager, which 271 implements XAResource functionality in the Store. 272 273 <P>XAConnection is the one thing that unites a global connection and the 274 XAResource that delineates the global transaction. This is where the real 275 XAResource functionality is implemented. All XAResource calls to the 276 XAResource object as well as Connection call to the BrokeredConnection 277 channels thrus the XAConnection, which makes sure only one thread can be 278 accessing the DB2jPooledConnection at any given time. 279 280 <P>XAResource and BrokeredConnection[23]0 are the two objects we give back 281 to the TM and the user application respectively to control a distributed 282 transaction. According to the XA spec, the app server is supposed to make 283 sure that these objects are not used the same time by multiple threads, but 284 we don't trust the app server. Therefore, we channel everthing back to the 285 XAConnection. 286 287 <P>The MT consideration is actually more complicated than this, 288 because a XAResource is allowed to control any transaction, not just the 289 one its XAConnection is current attached to. So it is not sufficient to 290 just synchronized on XAConnection to guarentee single thread access to the 291 underlying transaction context. To control some arbitrary global 292 transaction, the TM can call XAResource to prepare any Xid. To do that, 293 the XAResource pass the request to the XAConnection, the XAConnection ask 294 the XADataSource to find the XATransactionResource, sets up the thread's 295 context, and call ask the XATransactionResource to prepare. The 296 XATransactionResource is synchronized to prevent some other thread from 297 attaching, commiting, and in any way calling on the the same transaction 298 context. If any error is thrown, it is handled with the context of the 299 transaction being prepared. After the error is handled, the old context 300 (the one where the XAResource is really attached to), is restored. While 301 this monkey business is going on, the thread that holds the connection the 302 XAConnection is supposed to be attached to is blocked out. It can resume 303 after its XAConnection restored its context. (Here is where I am not 304 really sure what happens since that thread obviously doesn't know about all 305 these hanky panky caused by the thread holding the XAResource commiting, 306 preparing and rolling back some other irrelavant transactions, so how would 307 its context be affected in any way?). 308 309 <P>DB2jPooledConnection implements PooledConnection, is hands out these 310 connection handles which allows some app server to do connection pooling. 311 This is a very thin layer. A connection handle implements a Connection by 312 passing thru all calls to the underlaying connection. In this case, it 313 passes Connection call thru the DB2jPooledConnection to the 314 DetachableConnection underneath. 315 316 <P>EmbeddedDataSource implements JNDI and is a replacement for Driver. 317 318 <P>The LocalDriver can now produce a DetachableConnection as well as a 319 EmbedConnection (which is the pre-JTA Connection that cannot detach and 320 attach to different transactions). The way the LocalDriver knows to create 321 a DetachableConnection versus a EmbedConnection is thru some extremely 322 hackish URL settings. This thing is very ugly and a more elegant way can 323 (and should) no doubt be found. 324 325 <P>DetachableConnection is a connection which can detach and attach to 326 different XATransactionResource, and can be totally unattached to any 327 transaction. 328 329 <P>XATransactionResource is a bundle of things that sets up a connection 330 with all the stuff it needs to actually talk to the database, do error 331 handling, etc. It is also the object that lives in the transaction table 332 managed by the ResourceAdapter (XADataSource). A XAResource (which may or 333 may not be attached to a transaction) can commit, prepare, or rollback any 334 global transaction that is not attached to an XAConnection. To do that, 335 the ResourceAdapter fishes out the XATransactionResource, set up the 336 context, and do the commit processing/error handling on the current 337 thread. 338 339 <P>Local Connection is the same old local Connection except one 340 difference. Pre-JTA, a localConnection uses itself (or a root Connection) 341 as the object to synchronized upon so that multiple threads getting hold of 342 the same Connection object cannot simultaneously issue calls to the 343 underlying transaction or context (since those things must be single thread 344 access). With JTA, the object of synchronization is the 345 TransactionResource itself. This part has not been well thought through 346 and is probably wrong. 347 348 <P>TransactionResource is a base class for XATransactionResource. For a 349 local transaction which cannot be detached from a connection, there is no 350 need to encapsulate a bundle of things to set up a connection, so a 351 TransactionResource (probably misnamed) has nothing and is used only for 352 synchronization purposes. This part has not been well thought throught and 353 is probably wrong. 354 355 <P>The non-XA PooledConnection is just a thin veneer over the normal 356 connection. I now have it over a Detachable connection just to simplify 357 the inheritence (XAConnection need to extend PooledConnection and XAConnect 358 needs to be detachable. However, PooledConnection itself need not be 359 detachable). It could be changed around to have LocalDriver producing 360 either EmbedConnection or XAConnection, and have the XAConnection 361 implements detachable. But the current way is simpler. 362 363 */ 364 public interface ResourceAdapter { 365 366 /** 367 If a run time global transaction exists, the resource adapter will find 368 it and return a capsule of information so that a Connection can be 369 attached to the transaction. 370 371 @param xid the global transaction id 372 @return the transaction resource if the xid correspond to a run 373 time transaction, otherwise return null 374 */ 375 //XATransactionResource findTransaction(XAXactId xid); 376 377 /** 378 Start a run time global transaction. Add this to the list of 379 transactions managed by this resource adapter. 380 381 @return true if transaction can be added, otherwise false (dupid). 382 383 */ 384 //boolean addTransaction(XATransactionResource tr); 385 386 /** 387 Terminates a run time global transction. Remove this from the list of 388 transactions managed by this resource adapter. 389 */ 390 //void removeTransaction(XATransactionResource tr); 391 392 /** 393 Let a xaResource get the XAResourceManager to commit or rollback an 394 in-doubt transaction. 395 */ 396 XAResourceManager getXAResourceManager(); 397 398 /** 399 Get the context service factory. 400 */ 401 //ContextService getContextServiceFactory(); 402 403 /** 404 Is the Resource Manager active 405 */ 406 boolean isActive(); 407 408 public Object findConnection(XAXactId xid); 409 410 public boolean addConnection(XAXactId xid, Object conn); 411 412 public Object removeConnection(XAXactId xid); 413 414 /** 415 * Cancel the XA transaction identified by the specified xid. The 416 * method will atomically cancel any running statement on behalf 417 * of the transaction, end the transaction association with the 418 * XAResource instance, and rollback of the global transaction. 419 * @param xid tranaction id to cancel 420 * @param messageId error to report when canceling 421 */ 422 public void cancelXATransaction(XAXactId xid, String messageId) 423 throws XAException; 424 }