You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2012/07/24 11:08:42 UTC

svn commit: r1364947 - in /aries/trunk/transaction/transaction-manager: ./ src/main/java/org/apache/aries/transaction/ src/test/ src/test/java/ src/test/java/org/ src/test/java/org/apache/ src/test/java/org/apache/aries/ src/test/java/org/apache/aries/...

Author: gnodet
Date: Tue Jul 24 09:08:41 2012
New Revision: 1364947

URL: http://svn.apache.org/viewvc?rev=1364947&view=rev
Log:
[ARIES-880] When recovering transactions, only recover old branches to avoid rollback of in-progress transactions

Added:
    aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/XidFactoryImpl.java
    aries/trunk/transaction/transaction-manager/src/test/
    aries/trunk/transaction/transaction-manager/src/test/java/
    aries/trunk/transaction/transaction-manager/src/test/java/org/
    aries/trunk/transaction/transaction-manager/src/test/java/org/apache/
    aries/trunk/transaction/transaction-manager/src/test/java/org/apache/aries/
    aries/trunk/transaction/transaction-manager/src/test/java/org/apache/aries/transaction/
    aries/trunk/transaction/transaction-manager/src/test/java/org/apache/aries/transaction/XidFactoryImplTest.java
Modified:
    aries/trunk/transaction/transaction-manager/pom.xml
    aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/TransactionManagerService.java

Modified: aries/trunk/transaction/transaction-manager/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-manager/pom.xml?rev=1364947&r1=1364946&r2=1364947&view=diff
==============================================================================
--- aries/trunk/transaction/transaction-manager/pom.xml (original)
+++ aries/trunk/transaction/transaction-manager/pom.xml Tue Jul 24 09:08:41 2012
@@ -114,6 +114,12 @@
             <artifactId>slf4j-api</artifactId>
             <scope>provided</scope>
         </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <version>4.10</version>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

Modified: aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/TransactionManagerService.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/TransactionManagerService.java?rev=1364947&r1=1364946&r2=1364947&view=diff
==============================================================================
--- aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/TransactionManagerService.java (original)
+++ aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/TransactionManagerService.java Tue Jul 24 09:08:41 2012
@@ -33,7 +33,6 @@ import org.apache.geronimo.transaction.m
 import org.apache.geronimo.transaction.manager.RecoverableTransactionManager;
 import org.apache.geronimo.transaction.manager.TransactionLog;
 import org.apache.geronimo.transaction.manager.XidFactory;
-import org.apache.geronimo.transaction.manager.XidFactoryImpl;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.cm.ConfigurationException;

Added: aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/XidFactoryImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/XidFactoryImpl.java?rev=1364947&view=auto
==============================================================================
--- aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/XidFactoryImpl.java (added)
+++ aries/trunk/transaction/transaction-manager/src/main/java/org/apache/aries/transaction/XidFactoryImpl.java Tue Jul 24 09:08:41 2012
@@ -0,0 +1,120 @@
+/**
+ *  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.aries.transaction;
+
+import javax.transaction.xa.Xid;
+import org.apache.geronimo.transaction.manager.XidFactory;
+import org.apache.geronimo.transaction.manager.XidImpl;
+
+/**
+ * Factory for transaction ids that are ever increasing
+ * allowing determination of new transactions
+ * The Xid is constructed of two parts:
+ * <ol><li>8 byte id (LSB first)</li>
+ * <li>base id</li>
+ * <ol>
+ * can't easily extend geronimo XidFactoryImpl b/c count is private
+ */
+public class XidFactoryImpl implements XidFactory {
+    private final byte[] baseId = new byte[Xid.MAXGTRIDSIZE];
+    private final long start = System.currentTimeMillis();
+    private long count = start;
+
+    public XidFactoryImpl(byte[] tmId) {
+        System.arraycopy(tmId, 0, baseId, 8, tmId.length);
+    }
+
+    public Xid createXid() {
+        byte[] globalId = (byte[]) baseId.clone();
+        long id;
+        synchronized (this) {
+            id = count++;
+        }
+        insertLong(id, globalId, 0);
+        return new XidImpl(globalId);
+    }
+
+    public Xid createBranch(Xid globalId, int branch) {
+        byte[] branchId = (byte[]) baseId.clone();
+        branchId[0] = (byte) branch;
+        branchId[1] = (byte) (branch >>> 8);
+        branchId[2] = (byte) (branch >>> 16);
+        branchId[3] = (byte) (branch >>> 24);
+        insertLong(start, branchId, 4);
+        return new XidImpl(globalId, branchId);
+    }
+
+    public boolean matchesGlobalId(byte[] globalTransactionId) {
+        if (globalTransactionId.length != Xid.MAXGTRIDSIZE) {
+            return false;
+        }
+        for (int i = 8; i < globalTransactionId.length; i++) {
+            if (globalTransactionId[i] != baseId[i]) {
+                return false;
+            }
+        }
+        // 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;
+        }
+        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;
+            }
+        }
+        return true;
+    }
+
+    public Xid recover(int formatId, byte[] globalTransactionid, byte[] branchQualifier) {
+        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: aries/trunk/transaction/transaction-manager/src/test/java/org/apache/aries/transaction/XidFactoryImplTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/transaction/transaction-manager/src/test/java/org/apache/aries/transaction/XidFactoryImplTest.java?rev=1364947&view=auto
==============================================================================
--- aries/trunk/transaction/transaction-manager/src/test/java/org/apache/aries/transaction/XidFactoryImplTest.java (added)
+++ aries/trunk/transaction/transaction-manager/src/test/java/org/apache/aries/transaction/XidFactoryImplTest.java Tue Jul 24 09:08:41 2012
@@ -0,0 +1,71 @@
+/**
+ *  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.aries.transaction;
+
+import java.util.concurrent.TimeUnit;
+import javax.transaction.xa.Xid;
+
+import org.apache.geronimo.transaction.manager.XidFactory;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class XidFactoryImplTest {
+
+    @Test
+    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);
+    }
+
+    @Test
+    public void testAriesFactory() 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()));
+    }
+
+}