Hi,
A bit more details below. I haven't had time to look in detail at the
existing implementation.
Some points on the inner workings:
*** Collections ***
- Typically working with a shared resource is done by creating a map
with the resource values, and then instantiating an XAMap, passing the
shared map to it's constructor.
This creates a Map-specific specialization of the
AbstractResourceManager, that is capable of creating new transaction
scopes (individual internal transaction representations) as well as
provide an XAResource implementation.
- The XAMap instance implements the Map interface and can now be used
directly from surrounding code.
Calls to these interface methods are delegated to the transaction-local
Map representation which is which is an instance of the XAMapResource
implementation that also implements the Map interface (XAMapResource).
There is one of these for each active transaction.
- The XAResource implementation creates the data structures required to
hold transaction-scope specific data, when asked to do so by the
TransactionManager.
For the XAMapResource implementation the ProxyXAScope is used.
Invocations of Map-interface methods on the XAMapResource use this scope
instance for keeping track of changes.
- The scope implementation provides two important features: a
transaction log, and 'shadowing'. Initially it takes a full copy (clone)
of the shared resource - this could be improved substantially.
- Whenever a reading invocation occurs
1) The invocation is delegated to the scope-specific proxy, that can
also be considered a Map which reads from the shadow.
2) If a complex collection-backed instance is returned (such as the
key set or a ListIterator) it is wrapped for similar functionality.
Returned instances (elements) are also wrapped if they implement one of
the included XA-collection interfaces, such that nested collections
participate in the same transaction.
- Whenever a mutating invocation occurs
1) The resource is locked for mutation by others
2) The invocation is delegated to the scope-specific proxy, that can
also be considered a Map, which puts the invocation in the log and reads
from the shadow.
- Obvious improvements to the above:
- Better locking granularity or MVCC implementation
- Less wasteful shadow implementation. Copy-on-read.
*** Object model ***
- The XAObject implementation wraps all returned instances in a dynamic
proxy which intercepts all invocations, and similarly puts them in the
associated scope's transaction log and applies the method invication to
a cloned instance.
This implementation uses the IdentityXAScope instead and performs
copy-on-read-as-well-as-write. It also locks on instance granularity.
- Obvious improvements to the above:
- MVCC implementation
- Support direct field-modification (class instrumentation required)
- Disable cloning for more known immutable types
- Declarative read-only optimization - or perhaps even automatic
detection of whether an invocation is read or write (could be done with
field interceptors - again: requires class instrumentation).
I am unsure how resource enlistment to the TransactionManager should
work, as mentioned in a comment in jira. For now the collections enlist
themselves, when created. What's the best way to go about this? I guess
there must be some j2ee-mandated way of enlisting a resource?
Let me know what you think.
-dennis
---
The information in this email is confidential and may be legally protected.
-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]