[jboss-svn-commits] JBL Code SVN: r37570 - in labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta: classes/com/arjuna/ats/internal/jta/recovery/arjunacore and 1 other directory.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Oct 17 06:26:49 EDT 2011
Author: jhalliday
Date: 2011-10-17 06:26:49 -0400 (Mon, 17 Oct 2011)
New Revision: 37570
Modified:
labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/
labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/RecoveryXids.java
labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java
Log:
Backport XAResource recovery scan timing improvement. JBTM-842
Property changes on: labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta
___________________________________________________________________
Added: svn:mergeinfo
+ /labs/jbosstm/branches/JBOSSTS_4_15_0_Final/ArjunaJTA/jta:37161
/labs/jbosstm/trunk/ArjunaJTA/jta:36765
Modified: labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/RecoveryXids.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/RecoveryXids.java 2011-10-17 07:57:21 UTC (rev 37569)
+++ labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/RecoveryXids.java 2011-10-17 10:26:49 UTC (rev 37570)
@@ -1,20 +1,20 @@
/*
* JBoss, Home of Professional Open Source
- * Copyright 2006, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags.
+ * 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.
+ * 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
+ * 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,
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
- *
+ *
* (C) 2005-2006,
* @author JBoss Inc.
*/
@@ -31,14 +31,8 @@
package com.arjuna.ats.internal.jta.recovery.arjunacore;
-import com.arjuna.ats.jta.recovery.*;
+import com.arjuna.ats.jta.xa.XidImple;
-import com.arjuna.ats.jta.utils.XAHelper;
-
-import com.arjuna.ats.internal.jta.resources.arjunacore.XAResourceRecord;
-
-import com.arjuna.ats.arjuna.common.*;
-
import java.util.*;
import javax.transaction.xa.*;
@@ -49,7 +43,7 @@
{
_xares = xares;
}
-
+
public boolean equals (Object obj)
{
if (obj instanceof RecoveryXids)
@@ -66,88 +60,57 @@
return false;
}
+ /**
+ * Update our tracking with results of a new recovery scan pass
+ * @param trans the Xids seen during the new scan.
+ */
public final void nextScan (Xid[] trans)
{
- /*
- * Rather than recover now, wait until the next scan to
- * give any transactions a chance to finish.
- */
+ long currentTime = System.currentTimeMillis();
- _scanHoldNumber++;
+ // record the new information:
+ if(trans != null) {
+ for(Xid xid : trans) {
+ XidImple xidImple = new XidImple(xid);
+ if(!_whenFirstSeen.containsKey(xidImple)) {
+ _whenFirstSeen.put(xidImple, currentTime);
+ }
+ _whenLastSeen.put(xidImple, currentTime);
+ }
+ }
- /*
- * We keep a list of all Xids that are returned from all
- * XAResource instances. Because we never know when exactly we
- * can get rid of them (because of the multi-pass approach to
- * determining those that need to be recovered), we only keep the
- * cache for a maximum number of scans. After that, we zero it and
- * start from scratch again. This may mean that we take an extra pass
- * to recover some transactions.
- */
-
- if (_scanHoldNumber > MAX_SCAN_HOLD)
- _scanM = null;
-
- if (_scanM == null)
- _scanM = _scanN;
- else
- {
- if ((_scanM != null) && (_scanN != null))
- {
- int newArraySize = _scanM.length + _scanN.length;
- Xid[] copy = new Xid[newArraySize];
-
- System.arraycopy(_scanM, 0, copy, 0, _scanM.length);
- System.arraycopy(_scanN, 0, copy, _scanM.length, _scanN.length);
-
- _scanM = copy;
- }
- }
-
- _scanN = trans;
+ // garbage collect the stale information:
+ Set<XidImple> candidates = new HashSet<XidImple>(_whenFirstSeen.keySet());
+ for(XidImple candidate : candidates) {
+ if(_whenLastSeen.get(candidate) != currentTime) {
+ // seen it previously but it's gone now so we can forget it:
+ _whenFirstSeen.remove(candidate);
+ _whenLastSeen.remove(candidate);
+ }
+ }
+ // gc note: transient errors in distributed RMs may cause values to disappear in one scan and then reappear later.
+ // under the current model we'll recover Xids only if they stick around for enough consecutive scans to
+ // span the safely interval. In the unlikely event that causes problems, we'll need to postpone gc for a given
+ // interval and take care to include only Xids seen in the most recent scan when returning candidates for recovery.
}
- /*
- * Go through the current list of inflight transactions and look for
- * the same entries in the previous scan. If we find them, then we will
- * try to recover them. Then move the current list into the old list
- * for next time. We could prune out those transactions we manage to
- * recover, but this will happen automatically at the next scan since
- * they won't appear in the next new list of inflight transactions.
- */
- public final java.lang.Object[] toRecover ()
+ /**
+ * Return any Xids that should be considered for recovery.
+ * @return Xids that are old enough to be eligible for recovery.
+ */
+ public final Xid[] toRecover ()
{
- final int numScanN = (_scanN == null ? 0 : _scanN.length) ;
- final int numScanM = (_scanM == null ? 0 : _scanM.length) ;
- final int numScan = Math.min(numScanN, numScanM) ;
+ List<Xid> oldEnoughXids = new LinkedList<Xid>();
+ long currentTime = System.currentTimeMillis();
- if (numScan == 0)
- {
- return null ;
- }
-
- final List<Xid> workingList = new ArrayList<Xid>(numScanN) ;
-
- for(int i = 0; i < numScanN; i++)
- {
- // JBTM-823 / JBPAPP-5195 : don't assume list order/content match.
- // the list is (hopefully) small and we don't entirely trust 3rd party
- // Xid hashcode behaviour, so we just do this the brute force way...
- for(int j = 0; j < numScanM; j++)
- {
- if (XAHelper.sameXID(_scanN[i], _scanM[j]))
- {
- workingList.add(_scanN[i]);
- // any given id should be in _scanN only once, but _scanM may have dupls as
- // it's actually a combination of prev runs, per the array copy in nextScan.
- // we drop out here as we want each Xid only once in the return set:
- break;
- }
+ for(Map.Entry<XidImple,Long> entry : _whenFirstSeen.entrySet()) {
+ if(entry.getValue() + safetyIntervalMillis <= currentTime) {
+ oldEnoughXids.add(entry.getKey());
}
}
- return workingList.toArray(new Xid[workingList.size()]);
+ return oldEnoughXids.toArray(new Xid[oldEnoughXids.size()]);
}
public final boolean isSameRM (XAResource xares)
@@ -164,30 +127,14 @@
return false;
}
}
-
+
public boolean contains (Xid xid)
{
- if (_scanN != null)
- {
- for (int i = 0; i < _scanN.length; i++)
- {
- if (XAHelper.sameXID(xid, _scanN[i]))
- return true;
- }
- }
-
- if (_scanM != null)
- {
- for (int i = 0; i < _scanM.length; i++)
- {
- if (XAHelper.sameXID(xid, _scanM[i]))
- return true;
- }
- }
+ XidImple xidImple = new XidImple(xid);
- return false;
+ return _whenFirstSeen.containsKey(xidImple);
}
-
+
/**
* If supplied xids contains any values seen on prev scans, replace the existing
* XAResource with the supplied one and return true. Otherwise, return false.
@@ -217,11 +164,12 @@
return false;
}
- private Xid[] _scanN;
- private Xid[] _scanM;
+ // record when we first saw and most recently saw a given Xid. time in system clock (milliseconds).
+ // since we don't trust 3rd party hashcode/equals we convert to our own wrapper class.
+ private final Map<XidImple,Long> _whenFirstSeen = new HashMap<XidImple, Long>();
+ private final Map<XidImple,Long> _whenLastSeen = new HashMap<XidImple, Long>();
+
private XAResource _xares;
- private int _scanHoldNumber;
- private static final int MAX_SCAN_HOLD = 10; // number of scans we hold the cache for before flushing;
-
-}
+ private static final int safetyIntervalMillis = 10000; // may eventually want to make this configurable?
+}
\ No newline at end of file
Modified: labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java
===================================================================
--- labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java 2011-10-17 07:57:21 UTC (rev 37569)
+++ labs/jbosstm/branches/JBOSSTS_4_6_1_GA_CP/ArjunaJTA/jta/classes/com/arjuna/ats/internal/jta/recovery/arjunacore/XARecoveryModule.java 2011-10-17 10:26:49 UTC (rev 37570)
@@ -810,7 +810,7 @@
else
{
refreshXidScansForEquivalentXAResourceImpl(xares, trans);
-
+
xidsToRecover = _xidScans.get(xares);
if (xidsToRecover == null)
@@ -847,7 +847,7 @@
xidsToRecover.nextScan(trans);
- Object[] xids = xidsToRecover.toRecover();
+ Xid[] xids = xidsToRecover.toRecover();
if (xids != null)
{
@@ -875,7 +875,7 @@
{
// is the xid known to be one that couldn't be recovered
- recordUid = previousFailure((Xid) xids[j]);
+ recordUid = previousFailure(xids[j]);
if ((recordUid == null) && (foundTransaction))
break; // end
@@ -903,7 +903,7 @@
}
String nodeName = XAUtils
- .getXANodeName((Xid) xids[j]);
+ .getXANodeName(xids[j]);
boolean doRecovery = false;
if (jtaLogger.loggerI18N.isDebugEnabled())
@@ -1011,7 +1011,7 @@
{
if (doRecovery)
{
- if (!transactionLog((Xid) xids[j]))
+ if (!transactionLog(xids[j]))
{
if (jtaLogger.loggerI18N.isInfoEnabled())
{
@@ -1020,10 +1020,10 @@
"com.arjuna.ats.internal.jta.recovery.info.rollingback",
new Object[]
{ XAHelper
- .xidToString((Xid) xids[j]) });
+ .xidToString(xids[j]) });
}
- xares.rollback((Xid) xids[j]);
+ xares.rollback(xids[j]);
}
else
{
@@ -1034,7 +1034,7 @@
"com.arjuna.ats.internal.jta.recovery.info.rollingbackignore",
new Object[]
{ XAHelper
- .xidToString((Xid) xids[j]) });
+ .xidToString(xids[j]) });
}
/*
@@ -1052,7 +1052,7 @@
"com.arjuna.ats.internal.jta.recovery.info.notrollback",
new Object[]
{ XAHelper
- .xidToString((Xid) xids[j]) });
+ .xidToString(xids[j]) });
}
}
}
More information about the jboss-svn-commits
mailing list