Overview

Goal :
Write a low level TPM to test Oracle Custerwide Transaction Parallelize work where possilbe by using queues and threads
Currently the code runs with 3 Threads ( 1 TXProducer and 2 Worker threads)
using 3 queues ( Global receiver and 2 worker queues)
Wishlist - Not yet implementedUsing UCP connection pool to test more threads for a more cluster load test
Using xa_recover to test XA transaction recoveryStatus WARNING : This code isn't tested well - use it at you own risk and run it only on your test system -
and of course there is no SUPPORT !

What is coming next ?

For details see: WebLogic Server 12.1.3 New JTA feature description -XA Transaction without Transaction Logs- and OptimizationXA transaction layout sample ( run this in parallel )
Instance 1: xa_start DM xa_end BR 001
Instance 2: xa_start DM xa_end BR 002
Instance 3: xa_start DM xa_end BR 103 ( Note we flag branch with 10 )
--> This means Instance 3 is our Determiner Resource Manager flagged with branch prefix10Now run on the NON-Determiner Resource Manager Instance 1 and Instance 2 the xa_prepare ( run this in parallel )
Instance 1: xa_prepare BR 001
Instance 2: xa_prepare BR 002
Now run prepare on the Determiner RM
Instance 3: xa_prepare BR 103
--> When this goes through we that we need to commit the TX even the last prepare crashes before returning.After the crash we need to call xa_recover on all RMs.When we get back a flagged pending transaction we need to commit the data running xa_commit.Questions: Do we need call xa_commit on all instances as on RAC we only nned to commit the last branch?
Need test whether this us true for a recovered TX.
Note If we don't get back a flagged TX from a Determiner RM we need to rollback.

Short Code explanation of TXProducer and XAWorker class

TXProducer has a generic Queue and spawns up to 2 XAWorker threads for handling 2 XA branches in parallel.
The XAWorkers inherits the global queue receiver RQ from TXProducer and use that queue to send back status messages to the
TXProducer after running an specific XA operation. The local XAWorker queues are named LQ1 and LQ2.
The XAWorkers are reading from their local queue where they are waiting on worker requests assigned from the TXProducer thread .
Typical message protocol:
Loop :
TXProducer ---> write message | local Queue LQ1 created by XAWorker 1 | ---> XAWorker 1 reads from LQ1
---> write message | local Queue LQ2 created by XAWorker 2 | ---> XAWorker 2 reads from LQ2
++++ --> After XAWorker processed their job <--- ++++
TXProducer <--- reads messages | global Receive Queue RQ created by TXProdcuer | <--- XAWorker 1 writes processing status to RQ
| global Receive Queue RQ created by TXProdcuer | <--- XAWorker 2 writes processing status to RQ
+++ TXProduce reads XA status message and assigns next worker actions +++
To test clusterwide XA transaction XAWorker xaw[0] should connect to Instance 1 and XAWorker xaw[1] should connect to Instance 2.
But for performance testing you can point both connections to a single instance too.
TXProducer holds a message array: in_mesg[0] and in_mesg[1].
XAWorker process xaw[0] uses message array mesg[0] and xaw[1] uses message array mesg[2] - don't change the thread_id in these specific messages.
Each XAWorker has its own queue to communicate with the TXProducer instance. The TXProducer use write_message(Message out) to send a message
the the XAWorker.
Depending on the m.thread_id() the TXProducer picks up the right XAWorker queue by calling
s = xaw[ out.get_thread_id()-1].get_queue();
This way we can guarante the the write_message call will send the message to the correct queue.
write_message(in_mesg[0]) -> in_mesg[0].get_thread_id() returns 1 --> Queue 1 --> Thread 1
write_message(in_mesg[1]) -> in_mesg[0].get_thread_id() returns 2 --> Queue 2 --> Thread 1
For generic messages m you need to use m.set_thread_id() ( 1 or 2 ) to address the right queue
Note the write_message() API is not clustered and need to invoked for every worker thread you want to send an action.
The read_message() is different. As we need all branches for a XA transaction sychronized at a certain point ( after xa_end, after xa_prepare )
before we can schedule the next XA processing step the read message API needs to make sure that all outstanding branches/instances have
returned a corecet XA status code to the TXProducer thread.
A typical scenario
TXProducer sends a xa_prepare message mesg[0] to xa_worker xaw[0] by using queue xaw[0].get_queue() and message in_mesg[0]
TXProducer sends a xa_prepare message mesg[1] to xa_worker xaw[1] by using queue xaw[1].get_queue() and message in_mesg[1]
After the XAWorkers have finished their work they are sending back their reponse by using the global resceiver queue RQ.
This way of working is true for xa_processing ( thread of xa_start() DML xa_end () ) and for the xa_prepare step.
For the xa_commit step we send only a commit message to that node where have get return XA_OK (= 0 ) from the xa_prepare ( RAC specific )
We don't send an xa_commit to that instance returning XA_RDONLY ( -3 )

This website stores some user agent data. These data are used to provide a more personalized
experience and to track your whereabouts around our website in compliance with the European
General Data Protection Regulation. If you decide to opt-out of any future tracking, a cookie will be set up in your browser to remember this choice for one year. I Agree, Deny