Author: gnodet
Date: Tue Jul 24 12:54:45 2012
New Revision: 1365021
URL: http://svn.apache.org/viewvc?rev=1365021&view=rev
Log:
GERONIMO-6372: RecoveryImpl completing in-progress transactions, XidFactoryImpl needs to be
smarter with matching
Added:
geronimo/components/txmanager/trunk/geronimo-transaction/src/test/java/org/apache/geronimo/transaction/manager/XidFactoryImplTest.java
Modified:
geronimo/components/txmanager/trunk/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/XidFactoryImpl.java
Modified: geronimo/components/txmanager/trunk/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/XidFactoryImpl.java
URL: http://svn.apache.org/viewvc/geronimo/components/txmanager/trunk/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/XidFactoryImpl.java?rev=1365021&r1=1365020&r2=1365021&view=diff
==============================================================================
--- geronimo/components/txmanager/trunk/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/XidFactoryImpl.java
(original)
+++ geronimo/components/txmanager/trunk/geronimo-transaction/src/main/java/org/apache/geronimo/transaction/manager/XidFactoryImpl.java
Tue Jul 24 12:54:45 2012
@@ -17,10 +17,10 @@
package org.apache.geronimo.transaction.manager;
-import java.util.Random;
-import javax.transaction.xa.Xid;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import java.util.Random;
+import javax.transaction.xa.Xid;
/**
* Factory for transaction ids.
@@ -35,10 +35,11 @@ import java.net.UnknownHostException;
*/
public class XidFactoryImpl implements XidFactory {
private final byte[] baseId = new byte[Xid.MAXGTRIDSIZE];
- private long count = 1;
+ private final long start = System.currentTimeMillis();
+ private long count = start;
public XidFactoryImpl(byte[] tmId) {
- System.arraycopy(tmId, 0, baseId, 8, tmId.length);
+ System.arraycopy(tmId, 0, baseId, 8, tmId.length);
}
public XidFactoryImpl() {
@@ -68,14 +69,7 @@ public class XidFactoryImpl implements X
synchronized (this) {
id = count++;
}
- globalId[0] = (byte) id;
- globalId[1] = (byte) (id >>> 8);
- globalId[2] = (byte) (id >>> 16);
- globalId[3] = (byte) (id >>> 24);
- globalId[4] = (byte) (id >>> 32);
- globalId[5] = (byte) (id >>> 40);
- globalId[6] = (byte) (id >>> 48);
- globalId[7] = (byte) (id >>> 56);
+ insertLong(id, globalId, 0);
return new XidImpl(globalId);
}
@@ -85,6 +79,7 @@ public class XidFactoryImpl implements X
branchId[1] = (byte) (branch >>> 8);
branchId[2] = (byte) (branch >>> 16);
branchId[3] = (byte) (branch >>> 24);
+ insertLong(start, branchId, 4);
return new XidImpl(globalId, branchId);
}
@@ -97,14 +92,22 @@ public class XidFactoryImpl implements X
return false;
}
}
- return true;
+ // for recovery, only match old transactions
+ long id = extractLong(globalTransactionId, 0);
+ return (id < start);
}
public boolean matchesBranchId(byte[] branchQualifier) {
if (branchQualifier.length != Xid.MAXBQUALSIZE) {
return false;
}
- for (int i = 8; i < branchQualifier.length; i++) {
+ long id = extractLong(branchQualifier, 4);
+ if (id >= start) {
+ // newly created branch, not recoverable
+ return false;
+ }
+
+ for (int i = 12; i < branchQualifier.length; i++) {
if (branchQualifier[i] != baseId[i]) {
return false;
}
@@ -116,4 +119,26 @@ public class XidFactoryImpl implements X
return new XidImpl(formatId, globalTransactionid, branchQualifier);
}
+ static void insertLong(long value, byte[] bytes, int offset) {
+ bytes[offset + 0] = (byte) value;
+ bytes[offset + 1] = (byte) (value >>> 8);
+ bytes[offset + 2] = (byte) (value >>> 16);
+ bytes[offset + 3] = (byte) (value >>> 24);
+ bytes[offset + 4] = (byte) (value >>> 32);
+ bytes[offset + 5] = (byte) (value >>> 40);
+ bytes[offset + 6] = (byte) (value >>> 48);
+ bytes[offset + 7] = (byte) (value >>> 56);
+ }
+
+ static long extractLong(byte[] bytes, int offset) {
+ return (bytes[offset + 0] & 0xff)
+ + (((bytes[offset + 1] & 0xff)) << 8)
+ + (((bytes[offset + 2] & 0xff)) << 16)
+ + (((bytes[offset + 3] & 0xffL)) << 24)
+ + (((bytes[offset + 4] & 0xffL)) << 32)
+ + (((bytes[offset + 5] & 0xffL)) << 40)
+ + (((bytes[offset + 6] & 0xffL)) << 48)
+ + (((long) bytes[offset + 7]) << 56);
+ }
+
}
Added: geronimo/components/txmanager/trunk/geronimo-transaction/src/test/java/org/apache/geronimo/transaction/manager/XidFactoryImplTest.java
URL: http://svn.apache.org/viewvc/geronimo/components/txmanager/trunk/geronimo-transaction/src/test/java/org/apache/geronimo/transaction/manager/XidFactoryImplTest.java?rev=1365021&view=auto
==============================================================================
--- geronimo/components/txmanager/trunk/geronimo-transaction/src/test/java/org/apache/geronimo/transaction/manager/XidFactoryImplTest.java
(added)
+++ geronimo/components/txmanager/trunk/geronimo-transaction/src/test/java/org/apache/geronimo/transaction/manager/XidFactoryImplTest.java
Tue Jul 24 12:54:45 2012
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.geronimo.transaction.manager;
+
+import java.util.concurrent.TimeUnit;
+import javax.transaction.xa.Xid;
+
+import junit.framework.TestCase;
+
+public class XidFactoryImplTest extends TestCase {
+
+ public void testLong() {
+ byte[] buffer = new byte[64];
+ long l1 = 1343120074022l;
+ XidFactoryImpl.insertLong(l1, buffer, 4);
+ long l2 = XidFactoryImpl.extractLong(buffer, 4);
+ assertEquals(l1, l2);
+
+ l1 = 1343120074022l - TimeUnit.DAYS.toMillis(15);
+ XidFactoryImpl.insertLong(l1, buffer, 4);
+ l2 = XidFactoryImpl.extractLong(buffer, 4);
+ assertEquals(l1, l2);
+ }
+
+ public void testFactory() throws Exception {
+ XidFactory factory = new XidFactoryImpl("hi".getBytes());
+ Xid id1 = factory.createXid();
+ Xid id2 = factory.createXid();
+
+ assertFalse("Should not match new: " + id1, factory.matchesGlobalId(id1.getGlobalTransactionId()));
+ assertFalse("Should not match new: " + id2, factory.matchesGlobalId(id2.getGlobalTransactionId()));
+
+ Xid b_id1 = factory.createBranch(id1, 1);
+ Xid b_id2 = factory.createBranch(id2, 1);
+
+ assertFalse("Should not match new branch: " + b_id1, factory.matchesBranchId(b_id1.getBranchQualifier()));
+ assertFalse("Should not match new branch: " + b_id2, factory.matchesBranchId(b_id2.getBranchQualifier()));
+
+ Thread.sleep(5);
+
+ XidFactory factory2 = new XidFactoryImpl("hi".getBytes());
+ assertTrue("Should match old: " + id1, factory2.matchesGlobalId(id1.getGlobalTransactionId()));
+ assertTrue("Should match old: " + id2, factory2.matchesGlobalId(id2.getGlobalTransactionId()));
+
+ assertTrue("Should match old branch: " + b_id1, factory2.matchesBranchId(b_id1.getBranchQualifier()));
+ assertTrue("Should match old branch: " + b_id2, factory2.matchesBranchId(b_id2.getBranchQualifier()));
+ }
+
+}
|