You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2013/06/03 10:56:41 UTC

svn commit: r1488905 - in /db/derby/code/trunk/java/engine/org/apache/derby: ./ impl/store/raw/xact/

Author: kahatlen
Date: Mon Jun  3 08:56:40 2013
New Revision: 1488905

URL: http://svn.apache.org/r1488905
Log:
DERBY-6242: Merge ConcurrentXactFactory into XactFactory

Removed:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/ConcurrentTransactionMapFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/ConcurrentXactFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/TransactionMapFactory.java
Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/TransactionTable.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java
    db/derby/code/trunk/java/engine/org/apache/derby/modules.properties

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/TransactionTable.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/TransactionTable.java?rev=1488905&r1=1488904&r2=1488905&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/TransactionTable.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/TransactionTable.java Mon Jun  3 08:56:40 2013
@@ -35,13 +35,11 @@ import org.apache.derby.iapi.store.raw.l
 
 import org.apache.derby.iapi.store.raw.xact.RawTransaction;
 import org.apache.derby.iapi.store.raw.xact.TransactionId;
-import org.apache.derby.impl.store.raw.xact.TransactionTableEntry;
 
 import org.apache.derby.iapi.services.io.CompressedNumber;
 
 import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import java.io.ObjectOutput;
 import java.io.ObjectInput;
@@ -81,12 +79,7 @@ import java.io.IOException;
 	TransactionTable must be MT-safe it is called upon by many threads
 	simultaneously (except during recovery)
 
-	<P><B> This class depends on Hashtable synchronization!! </B>
-    To allow thread-safe iteration over the values in the Hashtable, callers
-    must synchronize on the Hashtable while iterating. The method {@link
-    #visitEntries(EntryVisitor)} abstracts the synchronization and iteration
-    so that the callers don't need to synchronize explicitly when they go
-    through the contents of the table. Methods that are only called during
+    <P>Methods that are only called during
     recovery don't need to take MT considerations, and can safely use iterators
     with no additional synchronization.
 
@@ -98,8 +91,7 @@ public class TransactionTable implements
 	 * Fields
 	 */
 
-    private final TransactionMapFactory mapFactory;
-	private final Map<TransactionId,TransactionTableEntry> trans;
+    private final ConcurrentHashMap<TransactionId, TransactionTableEntry> trans;
 
 	private TransactionId largestUpdateXactId;
 
@@ -108,8 +100,7 @@ public class TransactionTable implements
 	*/
 	public TransactionTable()
 	{
-        mapFactory = XactFactory.getMapFactory();
-        trans = mapFactory.newMap();
+        trans = new ConcurrentHashMap<TransactionId, TransactionTableEntry>();
 	}
 
 	/*************************************************************
@@ -177,7 +168,13 @@ public class TransactionTable implements
      * @param visitor the visitor to apply on each transaction table entry
      */
     void visitEntries(EntryVisitor visitor) {
-        mapFactory.visitEntries(trans, visitor);
+        for (Object entry : trans.values()) {
+            if (!visitor.visit((TransactionTableEntry) entry)) {
+                // The visitor returned false, meaning that it's done with
+                // all of its work and we can stop the scan.
+                break;
+            }
+        }
     }
 
 
@@ -380,19 +377,14 @@ public class TransactionTable implements
 	public ContextManager findTransactionContextByGlobalId(
     final GlobalXactId global_id)
 	{
-        final ContextManager[] cm = new ContextManager[1];
-
-        visitEntries(new EntryVisitor() {
-            public boolean visit(TransactionTableEntry entry) {
-                GlobalTransactionId entry_gid = entry.getGid();
-                if (entry_gid != null && entry_gid.equals(global_id)) {
-                    cm[0] = entry.getXact().getContextManager();
-                }
-                return cm[0] == null; // continue until context is found
+        for (TransactionTableEntry entry : trans.values()) {
+            GlobalTransactionId entry_gid = entry.getGid();
+            if (entry_gid != null && entry_gid.equals(global_id)) {
+                return entry.getXact().getContextManager();
             }
-        });
+        }
 
-        return cm[0];
+        return null;
 	}
 
 
@@ -411,56 +403,14 @@ public class TransactionTable implements
 	{
 		synchronized (this)
 		{
-            UpdateTransactionCounter counter =
-                    new UpdateTransactionCounter(true);
-            visitEntries(counter);
-            return counter.getCount() > 0;
-		}
-	}
-
-    /**
-     * Visitor class that counts update transactions. Note that update
-     * transactions may be added or removed concurrently unless the caller
-     * synchronizes on "this" (the {@code TransactionTable} instance) while
-     * applying the visitor.
-     */
-    private static class UpdateTransactionCounter implements EntryVisitor
-    {
-        private final boolean stopOnFirst;
-        private int count;
-
-        /**
-         * Create an instance of this visitor.
-         *
-         * @param stopOnFirst if {@code true}, stop the scan as soon as we
-         * have found one update transaction (useful if all we care about is
-         * whether or not the transaction table contains an update transaction);
-         * otherwise, scan the entire transaction table
-         */
-        UpdateTransactionCounter(boolean stopOnFirst) {
-            this.stopOnFirst = stopOnFirst;
-        }
-
-        /**
-         * Check if the entry represents an update transaction, and update
-         * the counter accordingly.
-         */
-        public boolean visit(TransactionTableEntry entry) {
-            if (entry.isUpdate()) {
-                count++;
+            for (TransactionTableEntry entry : trans.values()) {
+                if (entry.isUpdate()) {
+                    return true;
+                }
             }
-            // Continue the scan if a full scan was requested, or if no update
-            // transactions have been found yet.
-            return !stopOnFirst || (count == 0);
         }
 
-        /**
-         * Get the number of update transactions seen by this visitor
-         * @return number of update transactions
-         */
-        int getCount() {
-            return count;
-        }
+        return false;
     }
 
 	/************************************************************
@@ -490,11 +440,12 @@ public class TransactionTable implements
 
 		synchronized(this)
         {
-            UpdateTransactionCounter counter =
-                    new UpdateTransactionCounter(false);
-            visitEntries(counter);
-
-            int count = counter.getCount();
+            int count = 0;
+            for (TransactionTableEntry entry : trans.values()) {
+                if (entry.isUpdate()) {
+                    count++;
+                }
+            }
 
             CompressedNumber.writeInt(out, count);
 
@@ -502,36 +453,21 @@ public class TransactionTable implements
             if (count > 0)
             {
                 // Count the number of writes in debug builds.
-                final int[] writeCount =
-                        SanityManager.DEBUG ? new int[1] : null;
-
-                final IOException[] thrownException = new IOException[1];
+                int writeCount = 0;
 
-                visitEntries(new EntryVisitor() {
-                    public boolean visit(TransactionTableEntry entry) {
-                        try {
-                            if (entry.isUpdate()) {
-                                // only write out update transactions
-                                out.writeObject(entry);
-                                if (SanityManager.DEBUG) {
-                                    writeCount[0]++;
-                                }
-                            }
-                        } catch (IOException ioe) {
-                            thrownException[0] = ioe;
-                            return false; // stop on error
+                for (TransactionTableEntry entry : trans.values()) {
+                    if (entry.isUpdate()) {
+                        // only write out update transactions
+                        out.writeObject(entry);
+                        if (SanityManager.DEBUG) {
+                            writeCount++;
                         }
-                        return true; // go through entire table
                     }
-                });
-
-                if (thrownException[0] != null) {
-                    throw thrownException[0];
                 }
 
                 // Verify that we wrote the expected number of transactions.
                 if (SanityManager.DEBUG) {
-                    SanityManager.ASSERT(count == writeCount[0]);
+                    SanityManager.ASSERT(count == writeCount);
                 }
 			}
 		}
@@ -597,10 +533,8 @@ public class TransactionTable implements
 	*/
 	public boolean hasRollbackFirstTransaction()
 	{
-		for (Iterator<TransactionTableEntry> it = trans.values().iterator(); it.hasNext(); )
+        for (TransactionTableEntry ent : trans.values())
 		{
-			TransactionTableEntry ent = it.next();
-
 			if (ent != null && ent.isRecovery() && 
 				(ent.getTransactionStatus() & 
                      Xact.RECOVERY_ROLLBACK_FIRST) != 0)
@@ -649,10 +583,8 @@ public class TransactionTable implements
 
     private boolean hasPreparedXact(boolean recovered)
     {
-        for (Iterator<TransactionTableEntry> it = trans.values().iterator(); it.hasNext(); )
+        for (TransactionTableEntry ent : trans.values())
         {
-            TransactionTableEntry ent = it.next();
-
             if (ent != null && 
                 (ent.getTransactionStatus() & Xact.END_PREPARED) != 0)
             {
@@ -691,10 +623,8 @@ public class TransactionTable implements
 		}
 
 		TransactionId id = null;
-		for (Iterator<TransactionTableEntry> it = trans.values().iterator(); it.hasNext(); )
+        for (TransactionTableEntry ent : trans.values())
 		{
-			TransactionTableEntry ent = it.next();
-
 			if (ent != null && ent.isUpdate() && ent.isRecovery() &&
 				(ent.getTransactionStatus() & Xact.RECOVERY_ROLLBACK_FIRST) != 0)
 			{
@@ -745,10 +675,8 @@ public class TransactionTable implements
 
         if (!trans.isEmpty())
 		{
-			for (Iterator<TransactionTableEntry> it = trans.values().iterator(); it.hasNext() ; )
+            for (TransactionTableEntry ent : trans.values())
 			{
-				TransactionTableEntry ent = it.next();
-
 				if (ent != null         && 
                     ent.isUpdate()      && 
                     ent.isRecovery()    && 
@@ -784,10 +712,8 @@ public class TransactionTable implements
                 else
                 {
                     // all transactions in the table must be prepared.
-                    for (Iterator<TransactionTableEntry> it = trans.values().iterator(); it.hasNext();)
+                    for (TransactionTableEntry ent : trans.values())
                     {
-                        TransactionTableEntry ent =
-                            it.next();
                         SanityManager.ASSERT(ent.isPrepared());
                     }
                 }
@@ -840,12 +766,9 @@ public class TransactionTable implements
 		{
             TransactionId           id          = null;
             GlobalTransactionId     gid         = null;
-            TransactionTableEntry   ent;
 
-			for (Iterator<TransactionTableEntry> it = trans.values().iterator(); it.hasNext(); )
+            for (TransactionTableEntry ent : trans.values())
 			{
-				ent = it.next();
-
 				if (ent != null         && 
                     ent.isRecovery()    && 
                     ent.isPrepared())
@@ -867,10 +790,8 @@ public class TransactionTable implements
                     // if no entry's were found then the transaction table
                     // should have the passed in idle tran, and the rest should
                     // be non-recover, prepared global transactions.
-                    for (Iterator<TransactionTableEntry> it = trans.values().iterator(); it.hasNext();)
+                    for (TransactionTableEntry ent : trans.values())
                     {
-                        ent = it.next();
-
                         if (XactId.compare(ent.getXid(), tran.getId()) != 0)
                         {
                             SanityManager.ASSERT(
@@ -921,27 +842,17 @@ public class TransactionTable implements
 		// assume for now that it is acceptable to return null if a transaction
 		// starts right in the middle of this call.
 
-		if (trans.isEmpty())
-        {
-			return null;
-        }
-		else
-		{
-            final LogInstant[] logInstant = new LogInstant[1];
-            visitEntries(new EntryVisitor() {
-                public boolean visit(TransactionTableEntry entry) {
-                    if (entry.isUpdate()) {
-                        if ((logInstant[0] == null) ||
-                                entry.getFirstLog().lessThan(logInstant[0])) {
-                            logInstant[0] = entry.getFirstLog();
-                        }
-                    }
-                    return true; // scan entire transaction table
+        LogInstant logInstant = null;
+        for (TransactionTableEntry entry : trans.values()) {
+            if (entry.isUpdate()) {
+                if (logInstant == null ||
+                        entry.getFirstLog().lessThan(logInstant)) {
+                    logInstant = entry.getFirstLog();
                 }
-            });
+            }
+        }
 
-            return logInstant[0];
-		}
+        return logInstant;
 	}
 
 	/**
@@ -1002,15 +913,11 @@ public class TransactionTable implements
         final ArrayList<TransactionTableEntry> tinfo = new ArrayList<TransactionTableEntry>();
 
         // Get clones of all the entries in the transaction table.
-        visitEntries(new EntryVisitor() {
-            public boolean visit(TransactionTableEntry entry) {
-                tinfo.add( (TransactionTableEntry) entry.clone());
-                return true; // scan entire transaction table
-            }
-        });
+        for (TransactionTableEntry entry : trans.values()) {
+            tinfo.add((TransactionTableEntry) entry.clone());
+        }
 
-        return (TransactionTableEntry[])
-                tinfo.toArray(new TransactionTableEntry[tinfo.size()]);
+        return tinfo.toArray(new TransactionTableEntry[tinfo.size()]);
 	}
 
 	public String toString()
@@ -1024,31 +931,25 @@ public class TransactionTable implements
 				append(" largestUpdateXactId = ").append(largestUpdateXactId).
 				append("\n");
 
-            final boolean[] hasReadOnlyTransaction = new boolean[1];
+            boolean hasReadOnlyTransaction = false;
 
-            visitEntries(new EntryVisitor() {
-                public boolean visit(TransactionTableEntry entry) {
-                    if (entry.isUpdate()) {
-                        str.append(entry.toString());
-                    } else {
-                        hasReadOnlyTransaction[0] = true;
-                    }
-                    return true; // scan the entire transaction table
+            for (TransactionTableEntry entry : trans.values()) {
+                if (entry.isUpdate()) {
+                    str.append(entry);
+                } else {
+                    hasReadOnlyTransaction = true;
                 }
-            });
+            }
 
-            if (hasReadOnlyTransaction[0])
+            if (hasReadOnlyTransaction)
 			{
 				str.append("\n READ ONLY TRANSACTIONS \n");
 
-                visitEntries(new EntryVisitor() {
-                    public boolean visit(TransactionTableEntry entry) {
-                        if (!entry.isUpdate()) {
-                            str.append(entry.toString());
-                        }
-                        return true; // scan the entire transaction table
+                for (TransactionTableEntry entry : trans.values()) {
+                    if (!entry.isUpdate()) {
+                        str.append(entry);
                     }
-                });
+                }
 			}
 			str.append("---------------------------");
 			return str.toString();

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java?rev=1488905&r1=1488904&r2=1488905&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/xact/XactFactory.java Mon Jun  3 08:56:40 2013
@@ -98,57 +98,14 @@ public class XactFactory implements Tran
 	private long     backupBlockingOperations = 0;
 	private boolean  inBackup = false;
 
-    /**
-     * An instance of a helper class that provides maps with different
-     * concurrency properties depending on the platform. Used by
-     * {@code TransactionTable}.
-     */
-    private static TransactionMapFactory mapFactory;
-
 	/*
 	** Constructor
 	*/
 
 	public XactFactory() {
 		super();
-        setMapFactory();
 	}
 
-    /**
-     * Create a {@code TransactionMapFactory} instance. This method can be
-     * overridden by sub-classes in order to provide a factory that produces
-     * maps that give higher concurrency, if supported by the platform.
-     *
-     * @return a {@code TransactionMapFactory} suitable for this platform
-     */
-    TransactionMapFactory createMapFactory() {
-        return new TransactionMapFactory();
-    }
-
-    /**
-     * Set the default map factory to use for this system, if it's not already
-     * set. The value will be stored in a static variable so that it will only
-     * be set by the first {@code XactFactory} that's booted.
-     */
-    private void setMapFactory() {
-        synchronized (XactFactory.class) {
-            if (mapFactory == null) {
-                mapFactory = createMapFactory();
-            }
-        }
-    }
-
-    /**
-     * Get the map factory for this platform. This can be used by {@code
-     * TransactionTable} in order to produce the sort of map that has the best
-     * concurrency properties available on this platform.
-     *
-     * @return a map factory
-     */
-    static synchronized TransactionMapFactory getMapFactory() {
-        return mapFactory;
-    }
-
 	/*
 	** Methods of ModuleControl
 	*/

Modified: db/derby/code/trunk/java/engine/org/apache/derby/modules.properties
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/modules.properties?rev=1488905&r1=1488904&r2=1488905&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/modules.properties (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/modules.properties Mon Jun  3 08:56:40 2013
@@ -323,14 +323,8 @@ cloudscape.config.rawStore.data.genericJ
 derby.module.rawStore.log=org.apache.derby.impl.store.raw.log.LogToFile
 cloudscape.config.rawStore.log=derby
 
-derby.module.rawStore.transactionJ1=org.apache.derby.impl.store.raw.xact.XactFactory
-derby.env.jdk.rawStore.transactionJ1=1
-cloudscape.config.rawStore.transactionJ1=derby
-
-derby.module.rawStore.transactionJ6=org.apache.derby.impl.store.raw.xact.ConcurrentXactFactory
-derby.env.jdk.rawStore.transactionJ6=6
-derby.env.classes.rawStore.transactionJ6=java.util.concurrent.ConcurrentHashMap
-cloudscape.config.rawStore.transactionJ6=derby
+derby.module.rawStore.transaction=org.apache.derby.impl.store.raw.xact.XactFactory
+cloudscape.config.rawStore.transaction=derby
 
 derby.module.rawStore=org.apache.derby.impl.store.raw.RawStore
 cloudscape.config.rawStore=derby