Skip to content
Browse files

import from https://svn.jboss.org/repos/labs/labs/jbosstm/trunk r37839

  • Loading branch information...
1 parent 85b3179 commit bc9a3668c4ed6e8c52f6b2c3d4596e115c12ccf8 @tomjenkinson tomjenkinson committed Jan 5, 2012
Showing with 13,201 additions and 0 deletions.
  1. +4 −0 ArjunaCore/Readme.txt
  2. +23 −0 ArjunaCore/arjuna/README/README.ObjectStore
  3. +22 −0 ArjunaCore/arjuna/README/README.properties
  4. +98 −0 ArjunaCore/arjuna/Readme.txt
  5. +396 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/AtomicAction.java
  6. +79 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/ObjectModel.java
  7. +77 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/ObjectStatus.java
  8. +78 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/ObjectType.java
  9. +1,394 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/StateManager.java
  10. +55 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/TopLevelAction.java
  11. +676 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/CoordinatorEnvironmentBean.java
  12. +73 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/CoordinatorEnvironmentBeanMBean.java
  13. +324 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/CoreEnvironmentBean.java
  14. +9 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/CoreEnvironmentBeanException.java
  15. +49 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/CoreEnvironmentBeanMBean.java
  16. +62 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/Mutex.java
  17. +517 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBean.java
  18. +65 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/ObjectStoreEnvironmentBeanMBean.java
  19. +584 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/RecoveryEnvironmentBean.java
  20. +57 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/RecoveryEnvironmentBeanMBean.java
  21. +761 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/Uid.java
  22. +57 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/arjPropertyManager.java
  23. +35 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/recoveryPropertyManager.java
  24. +677 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/AbstractRecord.java
  25. +436 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionHierarchy.java
  26. +95 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionInfo.java
  27. +118 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionManager.java
  28. +126 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionStatus.java
  29. +70 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/ActionType.java
  30. +76 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/AddOutcome.java
  31. +149 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/AsyncCommit.java
  32. +100 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/AsyncPrepare.java
  33. +3,593 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/BasicAction.java
  34. +68 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/CheckedAction.java
  35. +52 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/CheckedActionFactory.java
  36. +54 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/HeuristicInformation.java
  37. +61 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/HeuristicNotification.java
  38. +68 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/OnePhaseResource.java
  39. +53 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/Reapable.java
  40. +471 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/RecordList.java
  41. +73 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/RecordListIterator.java
  42. +338 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/RecordType.java
  43. +49 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/SynchronizationRecord.java
  44. +979 −0 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/coordinator/TransactionReaper.java
Sorry, we could not display the entire diff because too many files (5,229) changed.
View
4 ArjunaCore/Readme.txt
@@ -0,0 +1,4 @@
+If you are going to use the ExecProcessId implementation to obtain a pid, rather than one of the other implementations,
+then you need to download getpids.exe if you are also running on Windows.
+
+Download from http://www.scheibli.com/projects/getpids/ and place it within your classpath.
View
23 ArjunaCore/arjuna/README/README.ObjectStore
@@ -0,0 +1,23 @@
+JBoss, Home of Professional Open Source
+Copyright 2006, Red Hat Middleware LLC, and individual contributors
+as indicated by the @author tags.
+See the copyright.txt in the distribution for a
+full listing of individual contributors.
+This copyrighted material is made available to anyone wishing to use,
+modify, copy, or redistribute it subject to the terms and conditions
+of the GNU Lesser General Public License, v. 2.1.
+This program is distributed in the hope that it will be useful, but WITHOUT A
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License,
+v.2.1 along with this distribution; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+MA 02110-1301, USA.
+
+(C) 2005-2006,
+@author JBoss Inc.
+Arjuna requires a minimum object store to save/load the states of
+transaction logs. The default location for this is the root of the
+Arjuna installation (the system will automatically create an
+ObjectStore subdirectory). For further details, see the
+Administator's Guide.
View
22 ArjunaCore/arjuna/README/README.properties
@@ -0,0 +1,22 @@
+#
+# JBoss, Home of Professional Open Source
+# Copyright 2006, Red Hat Middleware LLC, and individual contributors
+# as indicated by the @author tags.
+# See the copyright.txt in the distribution for a
+# full listing of individual contributors.
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU Lesser General Public License, v. 2.1.
+# This program is distributed in the hope that it will be useful, but WITHOUT A
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+# You should have received a copy of the GNU Lesser General Public License,
+# v.2.1 along with this distribution; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+# (C) 2005-2006,
+# @author JBoss Inc.
+#
+An example properties file is included in the etc directory of the
+installation. Please examine and change this where required.
View
98 ArjunaCore/arjuna/Readme.txt
@@ -0,0 +1,98 @@
+JBoss, Home of Professional Open Source
+Copyright 2006, Red Hat Middleware LLC, and individual contributors
+as indicated by the @author tags.
+See the copyright.txt in the distribution for a
+full listing of individual contributors.
+This copyrighted material is made available to anyone wishing to use,
+modify, copy, or redistribute it subject to the terms and conditions
+of the GNU Lesser General Public License, v. 2.1.
+This program is distributed in the hope that it will be useful, but WITHOUT A
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public License,
+v.2.1 along with this distribution; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+MA 02110-1301, USA.
+
+(C) 2005-2006,
+@author JBoss Inc.
+-> Configuration properties
+
+The Ant properties that can be set (and their defaults and possible values)
+are :
+
+ Property Values
+
+ com.hp.mw.ts.properties product.properties **
+ (property file to load properties (any filename)
+ from)
+
+ com.hp.mw.ts.date YYYY/MM/DD hh:mm **
+ (date of build) (any string)
+
+ com.hp.mw.ts.installationdirectory install **
+ (installation directory) (any directory) [1]
+
+ com.hp.mw.ts.sourceid unknown **
+ (source identifier) (any string)
+
+ com.hp.mw.ts.version unknown **
+ (product version) (any string)
+
+ com.hp.mw.ts.builder Hewlett Packard [user] (OS) **
+ (product builder) (any string)
+
+ com.hp.mw.ts.notes <empty> **
+ (any notes) (any string)
+
+ com.hp.mw.ts.arjuna.objectstore.cloudscape36.compile
+ (add Cloudscape 3.6 support) no **
+ yes
+
+ com.hp.mw.ts.arjuna.objectstore.sequelink51.compile
+ (add Sequelink 5.1 support) yes **
+ no
+
+ com.hp.mw.ts.arjuna.objectstore.oracle81.compile
+ (add Oracle 8.1 support) no **
+ yes
+
+ com.hp.mw.ts.arjuna.objectstore.oracle81.compile
+ (add Oracle 9.0 support) no **
+ yes
+
+ com.hp.mw.ts.arjuna.tests.compile no **
+ (compile tests) yes
+
+ com.hp.mw.ts.arjuna.tests.install no **
+ (install tests) yes
+
+ com.hp.mw.ts.arjuna.utilities.compile yes **
+ (compile utilities) no
+
+ com.hp.mw.ts.arjuna.utilities.install yes **
+ (install utilities) no
+
+
+-> Build targets
+
+The arjuna 'build.xml' file contains the targets :
+
+ Long name Short name
+
+ com.hp.mw.ts.arjuna.compile compile
+ (compile java classes)
+
+ com.hp.mw.ts.arjuna.jar jar **
+ (generate module jar file)
+
+ com.hp.mw.ts.arjuna.install install
+ (install module)
+
+ com.hp.mw.ts.arjuna.clean clean
+ (clean generated files)
+
+
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+ $Id: Readme.txt 2342 2006-03-30 13:06:17Z $
View
396 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/AtomicAction.java
@@ -0,0 +1,396 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+/*
+ * Copyright (C) 1998, 1999, 2000,
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id: AtomicAction.java 2342 2006-03-30 13:06:17Z $
+ */
+
+package com.arjuna.ats.arjuna;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.coordinator.ActionStatus;
+import com.arjuna.ats.arjuna.coordinator.BasicAction;
+import com.arjuna.ats.arjuna.coordinator.TransactionReaper;
+import com.arjuna.ats.arjuna.coordinator.TwoPhaseCoordinator;
+import com.arjuna.ats.arjuna.coordinator.TxControl;
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.internal.arjuna.thread.ThreadActionData;
+
+/**
+ * This is a user-level transaction class, unlike BasicAction. AtomicAction
+ * takes care of thread-to-action scoping. This is a "one-shot" object, i.e.,
+ * once terminated, the instance cannot be re-used for another transaction.
+ *
+ * An instance of this class is a transaction that can be started and terminated
+ * (either committed or rolled back). There are also methods to allow
+ * participants (AbstractRecords) to be enlisted with the transaction and to
+ * associate/disassociate threads with the transaction.
+ *
+ * @author Mark Little (mark@arjuna.com)
+ * @version $Id: AtomicAction.java 2342 2006-03-30 13:06:17Z $
+ * @since JTS 1.0.
+ */
+
+public class AtomicAction extends TwoPhaseCoordinator
+{
+
+ public static final int NO_TIMEOUT = -1;
+
+ /**
+ * Create a new transaction. If there is already a transaction associated
+ * with the thread then this new transaction will be automatically nested.
+ * The transaction is *not* running at this point.
+ *
+ * No timeout is associated with this transaction, i.e., it will not be
+ * automatically rolled back by the system.
+ */
+
+ public AtomicAction ()
+ {
+ super();
+ }
+
+ /**
+ * AtomicAction constructor with a Uid. This constructor is for recreating
+ * an AtomicAction, typically during crash recovery.
+ */
+
+ public AtomicAction (Uid objUid)
+ {
+ super(objUid);
+ }
+
+ /**
+ * Start the transaction running.
+ *
+ * If the transaction is already running or has terminated, then an error
+ * code will be returned. No timeout is associated with the transaction.
+ *
+ * @return <code>ActionStatus</code> indicating outcome.
+ */
+
+ public int begin ()
+ {
+ return begin(AtomicAction.NO_TIMEOUT);
+ }
+
+ /**
+ * Start the transaction running.
+ *
+ * If the transaction is already running or has terminated, then an error
+ * code will be returned.
+ *
+ * @param timeout the timeout associated with the transaction. If the
+ * transaction is still active when this timeout elapses, the
+ * system will automatically roll it back.
+ *
+ * @return <code>ActionStatus</code> indicating outcome.
+ */
+
+ public int begin (int timeout)
+ {
+ int status = super.start();
+
+ if (status == ActionStatus.RUNNING)
+ {
+ /*
+ * Now do thread/action tracking.
+ */
+
+ ThreadActionData.pushAction(this);
+
+ _timeout = timeout;
+
+ if (_timeout == 0)
+ _timeout = TxControl.getDefaultTimeout();
+
+ if (_timeout > 0)
+ TransactionReaper.transactionReaper().insert(this, _timeout);
+ }
+
+ return status;
+ }
+
+ /**
+ * Commit the transaction, and have heuristic reporting. Heuristic reporting
+ * via the return code is enabled.
+ *
+ * @return <code>ActionStatus</code> indicating outcome.
+ */
+
+ public int commit ()
+ {
+ return commit(true);
+ }
+
+ /**
+ * Commit the transaction. The report_heuristics parameter can be used to
+ * determine whether or not heuristic outcomes are reported.
+ *
+ * If the transaction has already terminated, or has not begun, then an
+ * appropriate error code will be returned.
+ *
+ * @return <code>ActionStatus</code> indicating outcome.
+ */
+
+ public int commit (boolean report_heuristics)
+ {
+ int status = super.end(report_heuristics);
+
+ /*
+ * Now remove this thread from the action state.
+ */
+
+ ThreadActionData.popAction();
+
+ TransactionReaper.transactionReaper().remove(this);
+
+ return status;
+ }
+
+ /**
+ * Abort (rollback) the transaction.
+ *
+ * If the transaction has already terminated, or has not been begun, then an
+ * appropriate error code will be returned.
+ *
+ * @return <code>ActionStatus</code> indicating outcome.
+ */
+
+ public int abort ()
+ {
+ int status = super.cancel();
+
+ /*
+ * Now remove this thread from the action state.
+ */
+
+ ThreadActionData.popAction();
+
+ TransactionReaper.transactionReaper().remove(this);
+
+ return status;
+ }
+
+ public int end (boolean report_heuristics)
+ {
+ int outcome = super.end(report_heuristics);
+
+ /*
+ * Now remove this thread from the reaper. Leave
+ * the thread-to-tx association though.
+ */
+
+ TransactionReaper.transactionReaper().remove(this);
+
+ return outcome;
+ }
+
+ public int cancel ()
+ {
+ int outcome = super.cancel();
+
+ /*
+ * Now remove this thread from the reaper. Leave
+ * the thread-to-tx association though.
+ */
+
+ TransactionReaper.transactionReaper().remove(this);
+
+ return outcome;
+ }
+
+ /*
+ * @return the timeout associated with this instance.
+ */
+
+ public final int getTimeout ()
+ {
+ return _timeout;
+ }
+
+ /**
+ * The type of the class is used to locate the state of the transaction log
+ * in the object store.
+ *
+ * Overloads BasicAction.type()
+ *
+ * @return a string representation of the hierarchy of the class for storing
+ * logs in the transaction object store.
+ */
+
+ public String type ()
+ {
+ return "/StateManager/BasicAction/TwoPhaseCoordinator/AtomicAction";
+ }
+
+ /**
+ * Register the current thread with the transaction. This operation is not
+ * affected by the state of the transaction.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
+
+ public boolean addThread ()
+ {
+ return addThread(Thread.currentThread());
+ }
+
+ /**
+ * Register the specified thread with the transaction. This operation is not
+ * affected by the state of the transaction.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
+
+ public boolean addThread (Thread t)
+ {
+ if (t != null)
+ {
+ ThreadActionData.pushAction(this);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Unregister the current thread from the transaction. This operation is not
+ * affected by the state of the transaction.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
+
+ public boolean removeThread ()
+ {
+ return removeThread(Thread.currentThread());
+ }
+
+ /**
+ * Unregister the specified thread from the transaction. This operation is
+ * not affected by the state of the transaction.
+ *
+ * @return <code>true</code> if successful, <code>false</code>
+ * otherwise.
+ */
+
+ public boolean removeThread (Thread t)
+ {
+ if (t != null)
+ {
+ ThreadActionData.purgeAction(this, t);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Suspend all transaction association from the invoking thread. When this
+ * operation returns, the thread will be associated with no transactions.
+ *
+ * If the current transaction is not an AtomicAction then this method will
+ * not suspend.
+ *
+ * @return a handle on the current AtomicAction (if any) so that the thread
+ * can later resume association if required.
+ *
+ */
+
+ public static final AtomicAction suspend ()
+ {
+ BasicAction curr = ThreadActionData.currentAction();
+
+ if (curr != null)
+ {
+ if (curr instanceof AtomicAction)
+ ThreadActionData.purgeActions();
+ else {
+ tsLogger.i18NLogger.warn_ats_atomicaction_1(curr.toString());
+
+ curr = null;
+ }
+ }
+
+ return (AtomicAction) curr;
+ }
+
+ /**
+ * Resume transaction association on the current thread. If the specified
+ * transaction is null, then this is the same as doing a suspend. If the
+ * current thread is associated with transactions then those associations
+ * will be lost.
+ *
+ * @param act the transaction to associate. If this is a nested
+ * transaction, then the thread will be associated with all of
+ * the transactions in the hierarchy.
+ *
+ * @return <code>true</code> if association is successful,
+ * <code>false</code> otherwise.
+ */
+
+ public static final boolean resume (AtomicAction act)
+ {
+ if (act == null)
+ {
+ suspend();
+ }
+ else
+ ThreadActionData.restoreActions(act);
+
+ return true;
+ }
+
+ /**
+ * Create a new transaction of the specified type.
+ */
+
+ protected AtomicAction (int at)
+ {
+ super(at);
+ }
+
+ /**
+ * By default the BasicAction class only allows the termination of a
+ * transaction if it's the one currently associated with the thread. We
+ * override this here.
+ *
+ * @return <code>true</code> to indicate that this transaction can only be
+ * terminated by the right thread.
+ */
+
+ protected boolean checkForCurrent ()
+ {
+ return true;
+ }
+
+ private int _timeout = NO_TIMEOUT;
+
+}
View
79 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/ObjectModel.java
@@ -0,0 +1,79 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+/*
+ * Copyright (C) 1998, 1999, 2000,
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id: ObjectModel.java 2342 2006-03-30 13:06:17Z $
+ */
+
+package com.arjuna.ats.arjuna;
+
+import java.io.PrintWriter;
+
+/**
+ * An enumeration of the types of object model supported. Based upon the model
+ * type, certain optimisations may be used.
+ *
+ * @author Mark Little (mark@arjuna.com)
+ * @version $Id: ObjectModel.java 2342 2006-03-30 13:06:17Z $
+ * @since JTS 1.0.
+ */
+
+public class ObjectModel
+{
+
+ /**
+ * In the SINGLE model, it is assumed that only a single instance of the
+ * object will exist within a single JVM.
+ */
+
+ public static final int SINGLE = 0;
+
+ /**
+ * In the MULTIPLE model, it is assumed that multiple instances of the
+ * object may exist in different JVMs concurrently.
+ */
+
+ public static final int MULTIPLE = 1;
+
+ /**
+ * Print out a human-readable form of the model type.
+ */
+
+ public static void print (PrintWriter strm, int os)
+ {
+ switch (os)
+ {
+ case SINGLE:
+ strm.print("SINGLE");
+ break;
+ case MULTIPLE:
+ strm.print("MULTIPLE");
+ break;
+ }
+ }
+
+}
View
77 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/ObjectStatus.java
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+/*
+ * Copyright (C) 1998, 1999, 2000,
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id: ObjectStatus.java 2342 2006-03-30 13:06:17Z $
+ */
+
+package com.arjuna.ats.arjuna;
+
+import java.io.PrintWriter;
+
+/**
+ * A transactional object may go through a number of different states
+ * once it has been created.
+ *
+ * @author Mark Little (mark@arjuna.com)
+ * @version $Id: ObjectStatus.java 2342 2006-03-30 13:06:17Z $
+ * @since JTS 1.0.
+ */
+
+public class ObjectStatus
+{
+ public static final int PASSIVE = 0;
+ public static final int PASSIVE_NEW = 1;
+ public static final int ACTIVE = 2;
+ public static final int ACTIVE_NEW = 3;
+ public static final int DESTROYED = 4;
+ public static final int UNKNOWN_STATUS = 5;
+
+ public static void print (PrintWriter strm, int os)
+ {
+ strm.print(toString(os));
+ }
+
+ public static String toString(int os)
+ {
+ switch (os)
+ {
+ case PASSIVE:
+ return "PASSIVE";
+ case PASSIVE_NEW:
+ return "PASSIVE_NEW";
+ case ACTIVE:
+ return "ACTIVE";
+ case ACTIVE_NEW:
+ return "ACTIVE_NEW";
+ case DESTROYED:
+ return "DESTROYED";
+ default:
+ return "UNKNOWN_STATUS";
+ }
+ }
+}
View
78 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/ObjectType.java
@@ -0,0 +1,78 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+/*
+ * Copyright (C) 1998, 1999, 2000, 2001,
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id: ObjectType.java 2342 2006-03-30 13:06:17Z $
+ */
+
+package com.arjuna.ats.arjuna;
+
+import java.io.PrintWriter;
+
+/**
+ * The various types of StateManager object which can exist.
+ *
+ * @author Mark Little (mark@arjuna.com)
+ * @version $Id: ObjectType.java 2342 2006-03-30 13:06:17Z $
+ * @since JTS 1.0.
+ */
+
+public class ObjectType
+{
+
+ public static final int RECOVERABLE = 0;
+
+ public static final int ANDPERSISTENT = 1;
+
+ public static final int NEITHER = 2;
+
+ public static final int UNKNOWN_TYPE = 3;
+
+ /**
+ * Print a human-readable form of the object type.
+ */
+
+ public static void print (PrintWriter strm, int ot)
+ {
+ strm.print(toString(ot));
+ }
+
+ public static String toString(int ot)
+ {
+ switch (ot)
+ {
+ case RECOVERABLE:
+ return "RECOVERABLE";
+ case ANDPERSISTENT:
+ return"ANDPERSISTENT";
+ case NEITHER:
+ return"NEITHER";
+ default:
+ return"UNKNOWN_TYPE";
+ }
+ }
+}
View
1,394 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/StateManager.java
@@ -0,0 +1,1394 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+/*
+ * Copyright (C) 1998, 1999, 2000, 2001,
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id: StateManager.java 2342 2006-03-30 13:06:17Z $
+ */
+
+package com.arjuna.ats.arjuna;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.arjuna.common.arjPropertyManager;
+import com.arjuna.ats.arjuna.coordinator.AbstractRecord;
+import com.arjuna.ats.arjuna.coordinator.ActionStatus;
+import com.arjuna.ats.arjuna.coordinator.ActionType;
+import com.arjuna.ats.arjuna.coordinator.AddOutcome;
+import com.arjuna.ats.arjuna.coordinator.BasicAction;
+import com.arjuna.ats.arjuna.coordinator.RecordType;
+import com.arjuna.ats.arjuna.exceptions.FatalError;
+import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
+import com.arjuna.ats.arjuna.logging.tsLogger;
+import com.arjuna.ats.arjuna.objectstore.ParticipantStore;
+import com.arjuna.ats.arjuna.objectstore.StateType;
+import com.arjuna.ats.arjuna.objectstore.StoreManager;
+import com.arjuna.ats.arjuna.state.InputObjectState;
+import com.arjuna.ats.arjuna.state.OutputObjectState;
+import com.arjuna.ats.arjuna.utils.Utility;
+import com.arjuna.ats.internal.arjuna.Header;
+import com.arjuna.ats.internal.arjuna.abstractrecords.ActivationRecord;
+import com.arjuna.ats.internal.arjuna.abstractrecords.CadaverActivationRecord;
+import com.arjuna.ats.internal.arjuna.abstractrecords.CadaverRecord;
+import com.arjuna.ats.internal.arjuna.abstractrecords.DisposeRecord;
+import com.arjuna.ats.internal.arjuna.abstractrecords.PersistenceRecord;
+import com.arjuna.ats.internal.arjuna.abstractrecords.RecoveryRecord;
+import com.arjuna.ats.internal.arjuna.common.BasicMutex;
+import com.arjuna.ats.internal.arjuna.common.UidHelper;
+
+/**
+ * The root of the Arjuna class hierarchy. This class provides state management
+ * facilities than can be automatically used by other classes by inheritance.
+ *
+ * @author Mark Little (mark@arjuna.com)
+ * @version $Id: StateManager.java 2342 2006-03-30 13:06:17Z $
+ * @since JTS 1.0.
+ */
+
+public class StateManager
+{
+
+ /**
+ * These methods must be used by a derived class. They are responsible for
+ * packing and unpacking an object's state to/from a state buffer.
+ * StateManager calls them at appropriate times during the lifetime of the
+ * object, and may then pass the buffer to a persistent object store for
+ * saving.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+
+ public boolean save_state (OutputObjectState os, int ot)
+ {
+ /*
+ * Only pack additional information if this is for a persistent state
+ * modification.
+ */
+
+ if (ot == ObjectType.ANDPERSISTENT)
+ {
+ try
+ {
+ BasicAction action = BasicAction.Current();
+
+ if (action == null)
+ packHeader(os, new Header(null, Utility.getProcessUid()));
+ else
+ packHeader(os, new Header(action.get_uid(), Utility.getProcessUid()));
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * These methods must be provided by a derived class. They are responsible
+ * for packing and unpacking an object's state to/from a state buffer.
+ * StateManager calls them at appropriate times during the lifetime of the
+ * object, and may then pass the buffer to a persistent object store for
+ * saving.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+
+ public boolean restore_state (InputObjectState os, int ot)
+ {
+ if (ot == ObjectType.ANDPERSISTENT)
+ {
+ try
+ {
+ unpackHeader(os, new Header());
+ }
+ catch (IOException e)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * This operation activates an object. Activation of an object may entail
+ * loading its passive state from the object store and unpacking it into the
+ * memory resident form, or it may simply be a no-op. Full activation is
+ * only necessary if the object is currently marked as being PASSIVE (that
+ * is, the object was constructed as being of type ANDPERSISTENT with an
+ * existing uid and has not already been activated). Objects that are not of
+ * type ANDPERSISTENT or are persistent but have not yet been saved in an
+ * object store (so-called new persistent objects) are unaffected by this
+ * function. Returns false if PASSIVE object cannot be loaded from object
+ * store, true otherwise. The root of the object store is taken as
+ * <code>null</code>.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ * @see com.arjuna.ats.arjuna.objectstore.ObjectStore
+ */
+
+ public boolean activate ()
+ {
+ return activate(null);
+ }
+
+ /**
+ * This operation activates an object. Activation of an object may entail
+ * loading its passive state from the object store and unpacking it into the
+ * memory resident form, or it may simply be a no-op. Full activation is
+ * only necessary if the object is currently marked as being PASSIVE (that
+ * is, the object was constructed as being of type ANDPERSISTENT with an
+ * existing uid and has not already been activated). Objects that are not of
+ * type ANDPERSISTENT or are persistent but have not yet been saved in an
+ * object store (so-called new persistent objects) are unaffected by this
+ * function. Returns false if PASSIVE object cannot be loaded from object
+ * store, true otherwise.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ * @see com.arjuna.ats.arjuna.objectstore.ObjectStore
+ */
+
+ public synchronized boolean activate (String rootName)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::activate( "
+ + ((rootName != null) ? rootName : "null")
+ + ") for object-id " + objectUid);
+ }
+
+ if (myType == ObjectType.NEITHER)
+ {
+ return true;
+ }
+
+ if (currentStatus == ObjectStatus.DESTROYED)
+ return false;
+
+ BasicAction action = null;
+ int oldStatus = currentStatus;
+ boolean result = true; /* assume 'succeeds' */
+ boolean forceAR = false;
+
+ /*
+ * Check if this action has logged its presence before. If not we force
+ * creation of an ActivationRecord so that each thread/action tree has
+ * an ActivationRecord in it. This allows us to passivate the object
+ * when the last thread has finished with it, i.e., when the last
+ * ActivationRecord is gone.
+ */
+
+ action = BasicAction.Current();
+
+ if ((action != null) && (action.status() == ActionStatus.RUNNING))
+ {
+ /*
+ * Only check for top-level action. This is sufficient because
+ * activation records are propagated to the parent on nested
+ * transaction commit, and dropped when the (nested) action aborts.
+ * Thus, an object remains active as long as a single
+ * ActivationRecord is being used, and we don't need to create a new
+ * record for each transaction in the same hierarchy. Once
+ * activated, the object remains active until the action commits or
+ * aborts (at which time it may be passivated, and then reactivated
+ * later by the creation of a new ActivationRecord.)
+ */
+
+ synchronized (mutex)
+ {
+ if (usingActions.get(action.get_uid()) == null)
+ {
+ /*
+ * May cause us to add parent as well as child.
+ */
+
+ usingActions.put(action.get_uid(), action);
+ forceAR = true;
+ }
+ }
+ }
+
+ if (forceAR || (currentStatus == ObjectStatus.PASSIVE)
+ || (currentStatus == ObjectStatus.PASSIVE_NEW))
+ {
+ /*
+ * If object is recoverable only, then no need to set up the object
+ * store.
+ */
+
+ if (loadObjectState())
+ {
+ setupStore(rootName);
+ }
+
+ /* Only really activate if object is PASSIVE */
+
+ if (currentStatus == ObjectStatus.PASSIVE)
+ {
+ /*
+ * If the object is shared between different processes, then we
+ * must load the state each time a top-level action accesses it.
+ * Otherwise we can continue to use the last state as in
+ * Dharma/ArjunaII.
+ */
+
+ if (loadObjectState())
+ {
+ InputObjectState oldState = null;
+
+ try
+ {
+ oldState = participantStore
+ .read_committed(objectUid, type());
+ }
+ catch (ObjectStoreException e)
+ {
+ oldState = null;
+ }
+
+ if (oldState != null)
+ {
+ if ((result = restore_state(oldState,
+ ObjectType.ANDPERSISTENT)))
+ {
+ currentStatus = ObjectStatus.ACTIVE;
+ }
+
+ oldState = null;
+ }
+ else {
+ tsLogger.i18NLogger.warn_StateManager_2(objectUid, type());
+
+ return false;
+ }
+ }
+ else
+ {
+ if (currentStatus == ObjectStatus.PASSIVE_NEW)
+ currentStatus = ObjectStatus.ACTIVE_NEW;
+ else
+ currentStatus = ObjectStatus.ACTIVE;
+ }
+ }
+ else
+ {
+ if (currentStatus == ObjectStatus.PASSIVE_NEW)
+ currentStatus = ObjectStatus.ACTIVE_NEW;
+ else
+ currentStatus = ObjectStatus.ACTIVE;
+ }
+
+ /*
+ * Create ActivationRecord if status changed Passive->Active or if
+ * object is a new persistent object.
+ */
+
+ if (forceAR
+ || ((currentStatus == ObjectStatus.ACTIVE) || (currentStatus == ObjectStatus.PASSIVE_NEW))
+ && (action != null))
+ {
+ int arStatus = AddOutcome.AR_ADDED;
+ ActivationRecord ar = new ActivationRecord(oldStatus, this,
+ action);
+
+ if ((arStatus = action.add(ar)) != AddOutcome.AR_ADDED)
+ {
+ ar = null;
+
+ if (forceAR)
+ {
+ synchronized (mutex)
+ {
+ usingActions.remove(action.get_uid());
+ }
+ }
+
+ if (arStatus == AddOutcome.AR_REJECTED)
+ result = false;
+ }
+ else
+ {
+ /*
+ * We never reset activated, so we can optimise state
+ * loading/unloading in the case of SINGLE object model
+ */
+
+ currentlyActivated = activated = true;
+ }
+ }
+ else
+ {
+ if (currentStatus == ObjectStatus.ACTIVE_NEW)
+ currentlyActivated = activated = true;
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * This operation deactivates a persistent object. It behaves in a similar
+ * manner to the activate operation, but has an extra argument which defines
+ * whether the object's state should be committed or written as a shadow.
+ * The root of the object store is <code>null</code>. It is assumed that
+ * this is being called during a transaction commit.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+
+ public boolean deactivate ()
+ {
+ return deactivate(null);
+ }
+
+ /**
+ * This operation deactivates a persistent object. It behaves in a similar
+ * manner to the activate operation, but has an extra argument which defines
+ * whether the object's state should be commited now or not. It is assumed
+ * that this is being called during a transaction commit.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+
+ public boolean deactivate (String rootName)
+ {
+ return deactivate(rootName, true);
+ }
+
+ /**
+ * This operation deactivates a persistent object. It behaves in a similar
+ * manner to the activate operation, but has an extra argument which defines
+ * whether the object's state should be commited now or not.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+
+ public synchronized boolean deactivate (String rootName, boolean commit)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::deactivate("
+ + ((rootName != null) ? rootName : "null") + ", "
+ + commit + ") for object-id " + objectUid);
+ }
+
+ boolean result = false;
+
+ if ((currentlyActivated && (myType == ObjectType.ANDPERSISTENT))
+ || loadObjectState())
+ {
+ setupStore(rootName);
+
+ if ((currentStatus == ObjectStatus.ACTIVE_NEW)
+ || (currentStatus == ObjectStatus.ACTIVE))
+ {
+ String tn = type();
+ OutputObjectState newState = new OutputObjectState(objectUid,
+ tn);
+
+ /*
+ * Call save_state again to possibly get a persistent
+ * representation of the object.
+ */
+
+ if (save_state(newState, myType))
+ {
+ try
+ {
+ if (commit)
+ result = participantStore.write_committed(objectUid, tn,
+ newState);
+ else
+ result = participantStore.write_uncommitted(objectUid,
+ tn, newState);
+ }
+ catch (ObjectStoreException e) {
+ tsLogger.i18NLogger.warn_StateManager_3(e);
+
+ result = false;
+ }
+ }
+ else {
+ tsLogger.i18NLogger.warn_StateManager_4();
+ }
+
+ /*
+ * Not needed any more because activation record does this when
+ * all actions are forgotten. if (result) currentStatus =
+ * ObjectStatus.PASSIVE;
+ */
+ }
+ }
+ else
+ {
+ result = true;
+ }
+
+ return result;
+ }
+
+ /**
+ * @return the object's current status (active, passive, ...)
+ */
+
+ public synchronized int status ()
+ {
+ return currentStatus;
+ }
+
+ /**
+ * @return the type of the object (persistent, recoverable, ...)
+ */
+
+ public synchronized int objectType ()
+ {
+ return myType;
+ }
+
+ public int getObjectModel ()
+ {
+ return objectModel;
+ }
+
+ /**
+ * @return the object's unique identifier.
+ */
+
+ public final Uid get_uid ()
+ {
+ return objectUid;
+ }
+
+ /**
+ * Destroy the object (e.g., remove its state from the persistent store.)
+ * Calls to destroy for volatile objects (ones not maintained within the
+ * volatile object store) are ignored, and FALSE is returned.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+
+ public synchronized boolean destroy ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::destroy for object-id "+objectUid);
+ }
+
+ boolean result = false;
+
+ if (participantStore != null)
+ {
+ BasicAction action = BasicAction.Current();
+
+ if (action != null) // add will fail if the status is wrong!
+ {
+ DisposeRecord dr = new DisposeRecord(participantStore, this);
+
+ if (action.add(dr) != AddOutcome.AR_ADDED) {
+ dr = null;
+
+ tsLogger.i18NLogger.warn_StateManager_6(action.get_uid());
+ }
+ else
+ result = true;
+ }
+ else
+ {
+ try
+ {
+ result = participantStore.remove_committed(get_uid(), type());
+
+ /*
+ * Once destroyed, we can never use the object again.
+ */
+
+ if (result)
+ destroyed();
+ }
+ catch (Exception e) {
+ tsLogger.i18NLogger.warn_StateManager_7(e);
+
+ result = false;
+ }
+ }
+ }
+ else {
+ /*
+ * Not a persistent object!
+ */
+
+ tsLogger.i18NLogger.warn_StateManager_8();
+ }
+
+ return result;
+ }
+
+ /**
+ * The following function disables recovery for an object by setting the
+ * ObjectType to NEITHER (RECOVERABLE or ANDPERSISTENT). The value of this
+ * variable is checked in the modified operation so that no recovery
+ * information is created if myType is set to NEITHER.
+ */
+
+ public synchronized void disable ()
+ {
+ myType = ObjectType.NEITHER;
+ }
+
+ /**
+ * Print out information about the object.
+ */
+
+ public void print (PrintWriter strm)
+ {
+ strm.println("Uid: " + objectUid);
+ strm.println("Type: " + type());
+ }
+
+ /**
+ * The object's type. Derived classes should override this to reflect their
+ * type structure. Typically this string is used for locating the object
+ * state in an object store, and reflects the hierarchy structure of the
+ * object.
+ */
+
+ public String type ()
+ {
+ return "/StateManager";
+ }
+
+ /**
+ * @return the root of the object store this instance will use if it has to
+ * save the state of the object to storage.
+ */
+
+ public final String getStoreRoot ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::getStoreRoot ()");
+ }
+
+ return storeRoot;
+ }
+
+ /**
+ * @return the object store this instance will used if it has to save the
+ * state of the object to storage.
+ */
+
+ public ParticipantStore getStore ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::getStore ()");
+ }
+
+ if (participantStore == null)
+ setupStore();
+
+ return participantStore;
+ }
+
+ /**
+ * Pack the necessary information for crash recovery.
+ *
+ * @since JTS 2.1.
+ */
+
+ protected void packHeader (OutputObjectState os, Header hdr)
+ throws IOException
+ {
+ /*
+ * If there is a transaction present than pack the process Uid of this
+ * JVM and the tx id. Otherwise pack a null Uid.
+ */
+
+ Uid txId = ((hdr == null) ? null : hdr.getTxId());
+ Uid processUid = ((hdr == null) ? null : hdr.getProcessId());
+
+ try
+ {
+ // pack the marker first.
+
+ os.packString(StateManager.marker);
+
+ /*
+ * Only pack something if there is a transaction. Otherwise the
+ * application is driving this object manually, and all bets are
+ * off!
+ */
+
+ if (txId != null)
+ {
+ UidHelper.packInto(txId, os);
+ UidHelper.packInto(processUid, os);
+ }
+ else
+ UidHelper.packInto(Uid.nullUid(), os);
+
+ long birthDate = System.currentTimeMillis();
+
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager.packHeader for object-id " + get_uid()
+ + " birth-date " + birthDate);
+ }
+
+ os.packLong(birthDate);
+ }
+ catch (IOException ex)
+ {
+ throw ex;
+ }
+ catch (Exception e)
+ {
+ IOException ioException = new IOException(e.toString());
+ ioException.initCause(e);
+ throw ioException;
+ }
+ }
+
+ /**
+ * Unpack the crash recovery state header information and return it.
+ *
+ * @since JTS 2.1.
+ * @param txId
+ * the identity of the transaction that last caused the state to
+ * be written to the object store.
+ */
+
+ protected void unpackHeader (InputObjectState os, Header hdr)
+ throws IOException
+ {
+ try
+ {
+ if (hdr == null)
+ throw new NullPointerException();
+
+ Uid txId = null;
+ Uid processUid = null;
+
+ String myState = os.unpackString();
+
+ if (myState.equals(StateManager.marker))
+ {
+ txId = UidHelper.unpackFrom(os);
+
+ /*
+ * Is there going to be a Uid to unpack?
+ */
+
+ if (!txId.equals(Uid.nullUid()))
+ processUid = UidHelper.unpackFrom(os);
+ }
+ else {
+ tsLogger.i18NLogger.warn_StateManager_9();
+
+ throw new IOException(tsLogger.i18NLogger.get_StateManager_15());
+ }
+
+ long birthDate = os.unpackLong();
+
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager.unpackHeader for object-id " + get_uid()
+ + " birth-date " + birthDate);
+ }
+
+ hdr.setTxId(txId);
+ hdr.setProcessId(processUid);
+ }
+ catch (IOException ex)
+ {
+ throw ex;
+ }
+ catch (final Throwable e)
+ {
+ IOException ioException = new IOException(e.toString());
+ ioException.initCause(e);
+ throw ioException;
+ }
+ }
+
+ /**
+ * The following function checks to see if the object is going out of scope
+ * while an action is still running.
+ */
+
+ protected void terminate ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::terminate() for object-id " + get_uid());
+ }
+
+ cleanup(true);
+ }
+
+ protected final synchronized void setStatus (int s)
+ {
+ currentStatus = s;
+ }
+
+ /**
+ * Create object with specific uid. This constructor is primarily used when
+ * recreating an existing object. The object type is set to 'ANDPERSISTENT'
+ * this is equivalent to invoking persist in the object constructor.
+ */
+
+ protected StateManager(Uid objUid)
+ {
+ this(objUid, ObjectType.ANDPERSISTENT, ObjectModel.SINGLE);
+ }
+
+ protected StateManager(Uid objUid, int ot)
+ {
+ this(objUid, ot, ObjectModel.SINGLE);
+ }
+
+ protected StateManager (Uid objUid, int ot, int om)
+ {
+ objectModel = om;
+
+ if (ot == ObjectType.NEITHER)
+ {
+ modifyingActions = null;
+ usingActions = null;
+ }
+ else
+ {
+ modifyingActions = new Hashtable();
+ usingActions = new Hashtable();
+ }
+
+ activated = false;
+ currentlyActivated = false;
+ currentStatus = ObjectStatus.PASSIVE;
+ initialStatus = ObjectStatus.PASSIVE;
+ myType = ot;
+ participantStore = null;
+ storeRoot = null;
+
+ objectUid = objUid;
+
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::StateManager( " + get_uid() + " )");
+ }
+ }
+
+ protected StateManager()
+ {
+ this(ObjectType.RECOVERABLE);
+ }
+
+ protected StateManager(int ot)
+ {
+ this(ot, ObjectModel.SINGLE);
+ }
+
+ protected StateManager (int ot, int om)
+ {
+ objectModel = om;
+
+ if (ot == ObjectType.NEITHER)
+ {
+ modifyingActions = null;
+ usingActions = null;
+ }
+ else
+ {
+ modifyingActions = new Hashtable();
+ usingActions = new Hashtable();
+ }
+
+ activated = false;
+ currentlyActivated = false;
+ currentStatus = (((objectModel == ObjectModel.SINGLE) && (ot == ObjectType.RECOVERABLE)) ? ObjectStatus.ACTIVE
+ : ObjectStatus.PASSIVE_NEW);
+ initialStatus = currentStatus;
+ myType = ot;
+ participantStore = null;
+ storeRoot = null;
+
+ objectUid = new Uid();
+
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::StateManager( " + ot + ", " + om + " )");
+ }
+ }
+
+ /*
+ * Protected non-virtual functions.
+ */
+
+ /**
+ * The object's state is about to be modified, and StateManager should take
+ * a snapshot of the state if the object is being used within a transaction.
+ *
+ * @return <code>true</code> on success, <code>false</code> otherwise.
+ */
+
+ protected synchronized boolean modified ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::modified() for object-id " + get_uid());
+ }
+
+ BasicAction action = BasicAction.Current();
+ RecoveryRecord record = null;
+
+ if ((myType == ObjectType.NEITHER)
+ || (currentStatus == ObjectStatus.DESTROYED)) /*
+ * NEITHER => no
+ * recovery info
+ */
+ {
+ return true;
+ }
+
+ if (currentStatus == ObjectStatus.PASSIVE) {
+ tsLogger.i18NLogger.warn_StateManager_10();
+
+ activate();
+ }
+
+ /*
+ * Need not have gone through active if new object.
+ */
+
+ if (currentStatus == ObjectStatus.PASSIVE_NEW)
+ currentStatus = ObjectStatus.ACTIVE_NEW;
+
+ if (action != null)
+ {
+ /*
+ * Check if this is the first call to modified in this action.
+ * BasicList insert returns FALSE if the entry is already present.
+ */
+
+ synchronized (modifyingActions)
+ {
+ if ((modifyingActions.size() > 0)
+ && (modifyingActions.get(action.get_uid()) != null))
+ {
+ return true;
+ }
+ else
+ modifyingActions.put(action.get_uid(), action);
+ }
+
+ /* If here then its a new action */
+
+ OutputObjectState state = new OutputObjectState(objectUid, type());
+ int rStatus = AddOutcome.AR_ADDED;
+
+ if (save_state(state, ObjectType.RECOVERABLE))
+ {
+ if ((myType == ObjectType.RECOVERABLE)
+ && (objectModel == ObjectModel.SINGLE))
+ {
+ record = new RecoveryRecord(state, this);
+ }
+ else
+ record = new PersistenceRecord(state, participantStore, this);
+
+ if ((rStatus = action.add(record)) != AddOutcome.AR_ADDED)
+ {
+ synchronized (modifyingActions)
+ {
+ modifyingActions.remove(action.get_uid()); // remember
+ // to
+ // unregister
+ // with
+ // action
+ }
+
+ record = null;
+
+ return false;
+ }
+ }
+ else
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * The persist function changes the type of the object from RECOVERABLE to
+ * ANDPERSISTENT. No changes are made unless the status of the object is
+ * ACTIVE, so it is not possible to change the type of the object if it has
+ * been modified.
+ */
+
+ protected final synchronized void persist ()
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::persist() for object-id " + get_uid());
+ }
+
+ if (currentStatus == ObjectStatus.ACTIVE)
+ {
+ currentStatus = ObjectStatus.PASSIVE_NEW;
+ myType = ObjectType.ANDPERSISTENT;
+ }
+ }
+
+ /**
+ * Object cleanup. Attempt sane cleanup when object is deleted. Handle
+ * perverse cases where multiple actions are still active as object dies.
+ *
+ * @param fromTerminate
+ * indicates whether this method is being called from the
+ * <code>terminate</code> method, or from elsewhere.
+ * @see StateManager#terminate
+ */
+
+ protected final synchronized void cleanup (boolean fromTerminate)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::cleanup() for object-id " + get_uid());
+ }
+
+ if (myType == ObjectType.NEITHER)
+ return;
+
+ BasicAction action = null;
+
+ synchronized (mutex)
+ {
+ if (usingActions.size() > 0)
+ {
+ Enumeration e = usingActions.keys();
+
+ while (e.hasMoreElements())
+ {
+ action = (BasicAction) usingActions.remove(e.nextElement());
+
+ if (action != null)
+ {
+ /*
+ * Pop actions off using list. Don't check if action is
+ * running below so that cadavers can be created in
+ * commit protocol too.
+ */
+
+ AbstractRecord record = null;
+ int rStatus = AddOutcome.AR_ADDED;
+
+ if ((currentStatus == ObjectStatus.ACTIVE_NEW)
+ || (currentStatus == ObjectStatus.ACTIVE)) {
+ OutputObjectState state = null;
+
+ tsLogger.i18NLogger.warn_StateManager_11(objectUid, type());
+
+ /*
+ * If we get here via terminate its ok to do a
+ * save_state.
+ */
+
+ if (fromTerminate) {
+ state = new OutputObjectState(objectUid, type());
+
+ if (!save_state(state, myType)) {
+ tsLogger.i18NLogger.warn_StateManager_12();
+ /* force action abort */
+
+ action.preventCommit();
+ }
+ } else {
+ /* otherwise force action abort */
+
+ action.preventCommit();
+ }
+
+ /*
+ * This should be unnecessary - but just in case.
+ */
+
+ setupStore(storeRoot);
+
+ record = new CadaverRecord(state, participantStore, this);
+
+ if ((rStatus = action.add(record)) != AddOutcome.AR_ADDED)
+ record = null;
+ }
+
+ if (currentlyActivated
+ && (currentStatus != ObjectStatus.DESTROYED))
+ {
+ record = new CadaverActivationRecord(this);
+
+ if ((rStatus = action.add(record)) == AddOutcome.AR_ADDED)
+ {
+ currentStatus = ObjectStatus.PASSIVE;
+ }
+ else {
+ tsLogger.i18NLogger.warn_StateManager_6(action.get_uid());
+
+ record = null;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Here the object must be either RECOVERABLE or PERSISTENT. Whether or
+ * not an action exists we still need to reset the object status to
+ * avoid possible later confusion. What it gets set to is not important
+ * really as long as it gets changed from ACTIVE_NEW which might cause
+ * any running action to abort.
+ */
+
+ if (currentStatus == ObjectStatus.ACTIVE_NEW)
+ {
+ if ((myType == ObjectType.RECOVERABLE)
+ && (objectModel == ObjectModel.SINGLE))
+ {
+ currentStatus = ObjectStatus.ACTIVE;
+ }
+ else
+ {
+ currentStatus = ObjectStatus.PASSIVE;
+ }
+ }
+
+ currentlyActivated = false;
+ }
+
+ /**
+ * Make sure the object store is set up, if required. The root of the object
+ * store is assumed to be <code>null</code>.
+ */
+
+ protected final void setupStore ()
+ {
+ setupStore(null);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected synchronized void setupStore (String rootName)
+ {
+ setupStore(rootName, arjPropertyManager.getObjectStoreEnvironmentBean()
+ .getObjectStoreType());
+ }
+
+ /**
+ * Make sure the object store is set up, if required.
+ *
+ * @param rootName
+ * indicates the root of the object store.
+ */
+
+ @SuppressWarnings("unchecked")
+ protected synchronized void setupStore (String rootName,
+ String objectStoreType)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::setupStore ( "
+ + ((rootName != null) ? rootName : "null") + " )");
+ }
+
+ if (!loadObjectState())
+ return;
+
+ /*
+ * Already setup? Assume type will not change once object is created.
+ */
+
+ if (participantStore != null)
+ return;
+
+ if (rootName == null)
+ rootName = arjPropertyManager.getObjectStoreEnvironmentBean()
+ .getLocalOSRoot();
+
+ /* Check if we have a store */
+
+ if (storeRoot != null)
+ {
+ /* Attempting to reuse it ? */
+
+ if ((rootName == null) || (rootName.compareTo("") == 0)
+ || (rootName.compareTo(storeRoot) == 0))
+ {
+ return;
+ }
+
+ /* No - destroy old store and create new */
+
+ participantStore = null;
+ }
+
+ if (rootName == null)
+ {
+ rootName = "";
+ }
+
+ /* Create store now */
+
+ storeRoot = new String(rootName);
+
+ if ((myType == ObjectType.ANDPERSISTENT)
+ || (myType == ObjectType.NEITHER))
+ {
+ int sharedStatus = ((objectModel == ObjectModel.SINGLE) ? StateType.OS_UNSHARED
+ : StateType.OS_SHARED);
+
+ participantStore = StoreManager.setupStore(rootName, sharedStatus);
+ }
+ else {
+ /*
+ * Currently we should never get here! However, since Arjuna
+ * supports a volatile (in memory) object store we will also
+ * eventually, probably through a set of native methods.
+ */
+
+ tsLogger.i18NLogger.warn_StateManager_13();
+
+ throw new FatalError(tsLogger.i18NLogger.get_StateManager_14());
+
+ // participantStore = new
+ // ObjectStore(ArjunaNames.Implementation_ObjectStore_VolatileStore
+ // (), storeRoot);
+ }
+ }
+
+ /**
+ * Do we need to load the object's state?
+ *
+ * @return <code>true</code> if the object state should be loaded,
+ * <code>false</code> otherwise.
+ */
+
+ protected final boolean loadObjectState ()
+ {
+ boolean load = (objectModel != ObjectModel.SINGLE);
+
+ /*
+ * MULTIPLE object model requires loading of state every time, even if
+ * we are RECOVERABLE - we use the volatile store.
+ */
+
+ if (!load)
+ {
+ /*
+ * Must be SINGLE object model. So, is this the first time? If so,
+ * load state.
+ */
+
+ if ((myType != ObjectType.RECOVERABLE) && (!activated))
+ load = true;
+ }
+
+ return load;
+ }
+
+ /*
+ * Called ONLY by ActivationRecords!
+ */
+
+ /**
+ * Remove action from list of using actions. If the action list empties
+ * reset state to PASSIVE. The second param tells why the action should be
+ * forgotten. This aids in resetting the state correctly.
+ */
+
+ protected final synchronized boolean forgetAction (BasicAction action,
+ boolean committed, int recordType)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::forgetAction("
+ + ((action != null) ? action.get_uid() : Uid
+ .nullUid()) + ")" + " for object-id "
+ + objectUid);
+ }
+
+ synchronized (modifyingActions)
+ {
+ modifyingActions.remove(action.get_uid());
+ }
+
+ if (recordType != RecordType.RECOVERY)
+ {
+ synchronized (mutex)
+ {
+ if (usingActions != null)
+ {
+ usingActions.remove(action.get_uid());
+
+ if (usingActions.size() == 0)
+ {
+ if (committed)
+ {
+ if ((myType == ObjectType.RECOVERABLE)
+ && (objectModel == ObjectModel.SINGLE) || (action.typeOfAction() == ActionType.NESTED))
+ {
+ initialStatus = currentStatus = ObjectStatus.ACTIVE;
+ }
+ else
+ {
+ initialStatus = currentStatus = ObjectStatus.PASSIVE;
+ }
+ }
+ else
+ currentStatus = initialStatus;
+ }
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Remember that the specified transaction is using the object.
+ */
+
+ protected final synchronized boolean rememberAction (BasicAction action,
+ int recordType, int state)
+ {
+ if (tsLogger.logger.isTraceEnabled()) {
+ tsLogger.logger.trace("StateManager::rememberAction("
+ + ((action != null) ? action.get_uid() : Uid
+ .nullUid()) + ")" + " for object-id "
+ + objectUid);
+ }
+
+ boolean result = false;
+
+ if (recordType != RecordType.RECOVERY)
+ {
+ if ((action != null) && (action.status() == ActionStatus.RUNNING))
+ {
+ synchronized (mutex)
+ {
+ if (usingActions.get(action.get_uid()) == null)
+ usingActions.put(action.get_uid(), action);
+ }
+ }
+
+ if ((currentStatus == ObjectStatus.PASSIVE) || (currentStatus == ObjectStatus.PASSIVE_NEW))
+ currentStatus = state;
+
+ result = true;
+ }
+
+ return result;
+ }
+
+ /**
+ * @return the mutex object used to lock this object.
+ * @since JTS 2.1.
+ */
+
+ protected final BasicMutex getMutex ()
+ {
+ return mutex;
+ }
+
+ /**
+ * @return the result of the attempt to lock this object.
+ * @since JTS 2.1.
+ */
+
+ protected final boolean lockMutex ()
+ {
+ if (mutex.lock() == BasicMutex.LOCKED)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * @return the result of the attempt to unlock this object.
+ * @since JTS 2.1.
+ */
+
+ protected final boolean unlockMutex ()
+ {
+ if (mutex.unlock() == BasicMutex.UNLOCKED)
+ return true;
+ else
+ return false;
+ }
+
+ /**
+ * @return <code>true</code> if the object was locked, <code>false</code> if
+ * the attempt would cause the thread to block.
+ * @since JTS 2.1.
+ */
+
+ protected final boolean tryLockMutex ()
+ {
+ if (mutex.tryLock() == BasicMutex.LOCKED)
+ return true;
+ else
+ return false;
+ }
+
+ /*
+ * Package scope.
+ */
+
+ /*
+ * Set the status of the object to destroyed so that we can no longer use
+ * it.
+ */
+
+ synchronized final void destroyed ()
+ {
+ currentStatus = ObjectStatus.DESTROYED;
+ }
+
+ protected Hashtable modifyingActions;
+
+ protected Hashtable usingActions;
+
+ protected final Uid objectUid;
+
+ protected int objectModel = ObjectModel.SINGLE;
+
+ private boolean activated;
+
+ private boolean currentlyActivated;
+
+ private int currentStatus;
+
+ private int initialStatus;
+
+ private int myType;
+
+ private ParticipantStore participantStore;
+
+ private String storeRoot;
+
+ private BasicMutex mutex = new BasicMutex();
+
+ private static final String marker = "#ARJUNA#";
+}
View
55 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/TopLevelAction.java
@@ -0,0 +1,55 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2006, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2005-2006,
+ * @author JBoss Inc.
+ */
+/*
+ * Copyright (C) 1998, 1999, 2000,
+ *
+ * Arjuna Solutions Limited,
+ * Newcastle upon Tyne,
+ * Tyne and Wear,
+ * UK.
+ *
+ * $Id: TopLevelAction.java 2342 2006-03-30 13:06:17Z $
+ */
+
+package com.arjuna.ats.arjuna;
+
+import com.arjuna.ats.arjuna.coordinator.ActionType;
+
+/**
+ * This class provides a (nested) top-level transaction. So, no matter how
+ * deeply nested a thread may be within a transaction hierarchy, creating an
+ * instance of this class will always start a new top-level transaction. Derived
+ * from AtomicAction so we can get the action-to-thread tracking.
+ *
+ * @author Mark Little (mark@arjuna.com)
+ * @version $Id: TopLevelAction.java 2342 2006-03-30 13:06:17Z $
+ * @since JTS 1.0.
+ */
+
+public class TopLevelAction extends AtomicAction
+{
+
+ public TopLevelAction()
+ {
+ super(ActionType.TOP_LEVEL);
+ }
+
+}
View
676 ArjunaCore/arjuna/classes/com/arjuna/ats/arjuna/common/CoordinatorEnvironmentBean.java
@@ -0,0 +1,676 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2009, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2009,
+ * @author JBoss, a division of Red Hat.
+ */
+package com.arjuna.ats.arjuna.common;
+
+import com.arjuna.ats.arjuna.coordinator.CheckedActionFactory;
+import com.arjuna.ats.arjuna.coordinator.TransactionReaper;
+import com.arjuna.ats.internal.arjuna.common.ClassloadingUtility;
+import com.arjuna.ats.internal.arjuna.objectstore.HashedActionStore;
+import com.arjuna.common.internal.util.propertyservice.FullPropertyName;
+import com.arjuna.common.internal.util.propertyservice.PropertyPrefix;
+
+/**
+ * A JavaBean containing configuration properties for the core transaction coordinator.
+ *
+ * @author Jonathan Halliday (jonathan.halliday@redhat.com)
+ */
+@PropertyPrefix(prefix = "com.arjuna.ats.arjuna.coordinator.")
+public class CoordinatorEnvironmentBean implements CoordinatorEnvironmentBeanMBean
+{
+ private volatile boolean asyncCommit = false;
+ private volatile boolean asyncPrepare = false;
+ private volatile boolean asyncRollback = false;
+ private volatile boolean commitOnePhase = true;
+ private volatile boolean maintainHeuristics = true;
+ private volatile boolean transactionLog = false; // rename to useTransactionLog ?
+
+ // public static final String TRANSACTION_LOG_REMOVAL_MARKER = "com.arjuna.ats.arjuna.coordinator.transactionLog.removalMarker";
+ //private String removalMarker;
+
+ @FullPropertyName(name = "com.arjuna.ats.arjuna.coordinator.transactionLog.writeOptimisation")
+ private volatile boolean writeOptimisation = false;
+
+ private volatile boolean readonlyOptimisation = true;
+ private volatile boolean classicPrepare = false;
+ private volatile boolean enableStatistics = false;
+ private volatile boolean sharedTransactionLog = false;
+ private volatile boolean startDisabled = false; // rename/repurpose to 'enable'?
+ private volatile String txReaperMode = "DYNAMIC"; // rename bool txReaperModeDynamic?
+
+ private volatile long txReaperTimeout = TransactionReaper.defaultCheckPeriod;
+ private volatile long txReaperCancelWaitPeriod = TransactionReaper.defaultCancelWaitPeriod;
+ private volatile long txReaperCancelFailWaitPeriod = TransactionReaper.defaultCancelFailWaitPeriod;
+ private volatile int txReaperZombieMax = TransactionReaper.defaultZombieMax;
+
+ private volatile int defaultTimeout = 60; // seconds
+ private volatile boolean transactionStatusManagerEnable = true;
+
+ @FullPropertyName(name = "com.arjuna.ats.coordinator.beforeCompletionWhenRollbackOnly")
+ private volatile boolean beforeCompletionWhenRollbackOnly = false;
+
+ @FullPropertyName(name = "com.arjuna.ats.coordinator.checkedActionFactory")
+ private volatile String checkedActionFactoryClassName = "com.arjuna.ats.internal.arjuna.coordinator.CheckedActionFactoryImple";
+ private volatile CheckedActionFactory checkedActionFactory = null;
+
+ private volatile boolean alternativeRecordOrdering = false;
+
+ private volatile String communicationStore = HashedActionStore.class.getName();
+
+ private volatile boolean finalizeBasicActions = false;
+
+ /**
+ * Returns true if anynchronous commit behaviour is enabled.
+ *
+ * Default: false
+ * Equivalent deprecated property: com.arjuna.ats.arjuna.coordinator.asyncCommit
+ *
+ * @return true if asynchronous commit is enabled, value otherwise.
+ */
+ public boolean isAsyncCommit()
+ {
+ return asyncCommit;
+ }
+
+ /**
+ * Sets if asynchronous commit behaviour should be enabled or not.
+ * Note: heuristics cannot be reported programatically if asynchronous commit is used.
+ *
+ * @param asyncCommit true to enable asynchronous commit, false to disable.
+ */
+ public void setAsyncCommit(boolean asyncCommit)
+ {
+ this.asyncCommit = asyncCommit;
+ }
+
+ /**
+ * Returns true if asynchronous prepare behaviour is enabled.
+ *
+ * Default: false
+ * Equivalent deprecated property: com.arjuna.ats.arjuna.coordinator.asyncPrepare
+ *
+ * @return true if asynchronous prepare is enabled, false otherwise.
+ */
+ public boolean isAsyncPrepare()
+ {
+ return asyncPrepare;
+ }
+
+ /**
+ * Sets if asynchronous prepare behaviour should be enabled or not.
+ *
+ * @param asyncPrepare true to enable asynchronous prepare, false to disable.
+ */
+ public void setAsyncPrepare(boolean asyncPrepare)
+ {
+ this.asyncPrepare = asyncPrepare;
+ }
+
+ /**
+ * Returns true if asynchronous rollback behaviour is enabled.
+ *
+ * Default: false
+ * Equivalent deprecated property: com.arjuna.ats.arjuna.coordinator.asyncRollback
+ *
+ * @return true if asynchronous rollback is enabled, false otherwise.
+ */
+ public boolean isAsyncRollback()
+ {
+ return asyncRollback;
+ }
+
+ /**
+ * Sets if asynchronous rollback behaviour should be enabled or not.
+ *
+ * @param asyncRollback true to enable asynchronous rollback, false to disable.
+ */
+ public void setAsyncRollback(boolean asyncRollback)
+ {
+ this.asyncRollback = asyncRollback;
+ }
+
+ /**
+ * Returns true if one phase commit optimization is to be used.
+ *
+ * Default: true
+ * Equivalent deprecated property: com.arjuna.ats.arjuna.coordinator.commitOnePhase
+ *
+ * @return true if one phase commit is enabled, false otherwise.
+ */
+ public boolean isCommitOnePhase()
+ {
+ return commitOnePhase;
+ }
+
+ /**
+ * Sets if one phase commit behaviour is enabled or not.
+ *
+ * @param commitOnePhase true to enable, false to disable.
+ */
+ public void setCommitOnePhase(boolean commitOnePhase)
+ {
+ this.commitOnePhase = commitOnePhase;
+ }
+
+ /**
+ * Returns true if heuristic outcomes should be recorded.
+ *
+ * Default: true
+ * Equivalent deprecated property: com.arjuna.ats.arjuna.coordinator.maintainHeuristics
+ *
+ * @return true if heuristics should be recorded, false otherwise.
+ */
+ public boolean isMaintainHeuristics()
+ {
+ return maintainHeuristics;
+ }
+
+ /**
+ * Sets if heuristics should be recorded or not.
+ *
+ * @param maintainHeuristics true to enable recording of heuristics, false to disable.
+ */
+ public void setMaintainHeuristics(boolean maintainHeuristics)
+ {
+ this.maintainHeuristics = maintainHeuristics;
+ }
+
+ /**
+ * Returns true if write optimisation protocol should be used for PersistenceRecord.
+ *
+ * Default: false
+ * Equivalent deprecated property: com.arjuna.ats.arjuna.coordinator.transactionLog.writeOptimisation
+ *
+ * @return true if write optimisation is enabled, false otherwise.
+ */
+ public boolean isWriteOptimisation()
+ {
+ return writeOptimisation;
+ }
+
+ /**
+ * Sets if write optimization protocol should be used for PersistenceRecord.
+ *
+ * @param writeOptimisation true to enable write optimization, false to disable.
+ */
+ public void setWriteOptimisation(boolean writeOptimisation)
+ {
+ this.writeOptimisation = writeOptimisation;
+ }
+
+ /**
+ * Returns true if handling of read only resources should be optimized.
+ *
+ * Default: true
+ * Equivalent deprecated property: com.arjuna.ats.arjuna.coordinator.readonlyOptimisation
+ *
+ * @return true if read only optimization is enabled, false otherwise.