You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jena.apache.org by an...@apache.org on 2012/08/18 12:39:27 UTC

svn commit: r1374552 - in /jena/trunk/jena-tdb: ./ src/main/java/com/hp/hpl/jena/tdb/ src/main/java/com/hp/hpl/jena/tdb/store/ src/main/java/com/hp/hpl/jena/tdb/sys/ src/main/java/com/hp/hpl/jena/tdb/transaction/ src/test/java/com/hp/hpl/jena/tdb/migra...

Author: andy
Date: Sat Aug 18 10:39:26 2012
New Revision: 1374552

URL: http://svn.apache.org/viewvc?rev=1374552&view=rev
Log:
+ Fix caching of last read trasnaction. JENA-299
+ Read txns do not now flush the delayed write queue immediately.
+ Add StoreConnection.flush()
    forces a the delayed write queue to main database if no transactions active.

Modified:
    jena/trunk/jena-tdb/ReleaseNotes.txt
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/StoreConnection.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/store/DatasetGraphTDB.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBInternal.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBMaker.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetBuilderTxn.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTransaction.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTxn.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/JournalControl.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/Transaction.java
    jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/TransactionManager.java
    jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/migrate/AbstractTestTransaction.java
    jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/transaction/AbstractTestTransSeq.java

Modified: jena/trunk/jena-tdb/ReleaseNotes.txt
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/ReleaseNotes.txt?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/ReleaseNotes.txt (original)
+++ jena/trunk/jena-tdb/ReleaseNotes.txt Sat Aug 18 10:39:26 2012
@@ -1,9 +1,15 @@
 ChangeLog for TDB
 =================
 
+==== TDB 0.9.4
+
++ Cache read transaction datastructures and reuse view when possible.
++ Add StoreConnection flush() operation to push delayed writer-commits if possible.    
++ JENA-290 - TDB txn creation touched stats unnecessarily, causing slow down. 
+
 ==== TDB 0.9.3
 
-+ Batching of writer-commits to inprove write trasnaction performance.
++ Batching of writer-commits to improve write transaction performance.
 
 ==== TDB 0.9.2
 

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/StoreConnection.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/StoreConnection.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/StoreConnection.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/StoreConnection.java Sat Aug 18 10:39:26 2012
@@ -83,16 +83,6 @@ public class StoreConnection
         return baseDSG.getLocation() ;
     }
 
-//    /**
-//     * Return the associated transaction manager - do NOT use to manipulate
-//     * transactions
-//     */
-//    public TransactionManager getTransMgr()
-//    {
-//        checkValid() ;
-//        return transactionManager ;
-//    }
-
     /** Return a description of the transaction manager state */
     public SysTxnState getTransMgrState()
     {
@@ -114,16 +104,7 @@ public class StoreConnection
 
 
     /**
-     * Begin a transact//    public static Graph _createGraph()
-//    { return factory.createDatasetGraph().getDefaultGraph() ; }
-//
-//    public static Graph _createGraph(Location loc)
-//    {
-//        // The code to choose the optimizer is in GraphTDBFactory.chooseOptimizer
-//        return factory.createDatasetGraph(loc).getDefaultGraph() ;
-//    }
-
-ion, giving it a label. Terminate a write transaction
+     * Begin a transaction, giving it a label. Terminate a write transaction
      * with {@link Transaction#commit()} or {@link Transaction#abort()}.
      * Terminate a write transaction with {@link Transaction#close()}.
      */
@@ -135,8 +116,10 @@ ion, giving it a label. Terminate a writ
     }
 
     /**
-     * testing operation - do not use the base dataset without knowing how the
-     * transaction system uses it
+     * Testing operation - do not use the base dataset without knowing how the
+     * transaction system uses it. The base dataset may not reflect the true state
+     * if pending commits are queued.
+     * @see #flush
      */
     public DatasetGraphTDB getBaseDataset()
     {
@@ -144,6 +127,27 @@ ion, giving it a label. Terminate a writ
         return baseDSG ;
     }
     
+    /** Flush the delayed write queue to th ebase storage.
+     *  This can only be done if there are no active transactions.
+     *  If there are active transactions, nothing is done but this is safe to call. 
+     */ 
+    public void flush()
+    {
+        if ( ! haveUsedInTransaction() )
+            return ;
+        checkValid() ;
+        transactionManager.flush() ;
+    }
+    
+    /** Indicate whether there are any active transactions.
+     *  @see #getTransMgrState
+     */
+    public boolean activeTransactions()
+    { 
+        checkValid() ;
+        return transactionManager.activeTransactions() ; 
+    }
+    
     /** Flush the journal regardless - use with great case - do not use when transactions may be active. */ 
     public void forceRecoverFromJournal()
     {

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/store/DatasetGraphTDB.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/store/DatasetGraphTDB.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/store/DatasetGraphTDB.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/store/DatasetGraphTDB.java Sat Aug 18 10:39:26 2012
@@ -45,7 +45,7 @@ import com.hp.hpl.jena.tdb.transaction.D
 import com.hp.hpl.jena.update.GraphStore ;
 import com.hp.hpl.jena.update.UpdateRequest ;
 
-/** TDB Dataset - this is the class that creates a dataset over the storage via
+/** This is the class that creates a dataset over the storage via
  *  TripleTable, QuadTable and prefixes. These may be transactional.
  *  
  *  See also:
@@ -54,6 +54,7 @@ import com.hp.hpl.jena.update.UpdateRequ
  *  <li>{@link DatasetGraphTransaction} &ndash; class that provides the application with the right DatasetGraphTDB (base or transaction).</li>
  *  </ul>
  */
+final
 public class DatasetGraphTDB extends DatasetGraphCaching
                              implements /*DatasetGraph,*/ Sync, Closeable, GraphStore, Session
 {

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBInternal.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBInternal.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBInternal.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBInternal.java Sat Aug 18 10:39:26 2012
@@ -88,11 +88,15 @@ public class TDBInternal
     
     /**
      * Return the DatasetGraphTDB for a DatasetGraph, or null.
+     * May not be up-to-date.
      */
     public static DatasetGraphTDB getDatasetGraphTDB(DatasetGraph dsg)
     {
         if ( dsg instanceof DatasetGraphTransaction )
-            return ((DatasetGraphTransaction)dsg).getBaseDatasetGraph() ;
+            // Latest.
+            return ((DatasetGraphTransaction)dsg).getDatasetGraphToQuery() ;
+            // Core.
+            //.getBaseDatasetGraph() ;
         
         if ( dsg instanceof DatasetGraphTDB )
             return (DatasetGraphTDB)dsg ;

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBMaker.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBMaker.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBMaker.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/sys/TDBMaker.java Sat Aug 18 10:39:26 2012
@@ -105,7 +105,7 @@ public class TDBMaker
         }
     }
     
-    /** The StoreConenction-cached base DatasetGraphTDB.*/ 
+    /** The StoreConnection-cached base DatasetGraphTDB.*/ 
     private static class BuilderStoreConnectionBase implements DatasetGraphMakerTDB
     {
         @Override

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetBuilderTxn.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetBuilderTxn.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetBuilderTxn.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetBuilderTxn.java Sat Aug 18 10:39:26 2012
@@ -58,23 +58,23 @@ public class DatasetBuilderTxn
 
     public DatasetBuilderTxn(TransactionManager txnMgr) { this.txnMgr = txnMgr ; }
     
-    public DatasetGraphTDB build(Transaction transaction, ReadWrite mode, DatasetGraphTDB dsg)
+    public DatasetGraphTxn build(Transaction transaction, ReadWrite mode, DatasetGraphTDB dsg)
     {
         this.blockMgrs = dsg.getConfig().blockMgrs ;
         this.nodeTables = dsg.getConfig().nodeTables ;
         this.txn = transaction ;
         this.dsg = dsg ;
         
-        DatasetGraphTDB dsgTxn ;
+        DatasetGraphTDB dsgTDB ;
             
         switch(mode)
         {
-            case READ : dsgTxn = buildReadonly() ; break ;
-            case WRITE : dsgTxn = buildWritable() ;  break ;
-            default: dsgTxn = null ;  // Silly Java.
+            case READ : dsgTDB = buildReadonly() ; break ;
+            case WRITE : dsgTDB = buildWritable() ;  break ;
+            default: dsgTDB = null ;  // Silly Java.
         }
         
-        dsgTxn = new DatasetGraphTxn(dsgTxn, txn) ;
+        DatasetGraphTxn dsgTxn = new DatasetGraphTxn(dsgTDB, txn) ;
         // Copy context. Changes not propagated back to the base dataset. 
         dsgTxn.getContext().putAll(dsg.getContext()) ;
         return dsgTxn ;

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTransaction.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTransaction.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTransaction.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTransaction.java Sat Aug 18 10:39:26 2012
@@ -41,7 +41,6 @@ public class DatasetGraphTransaction ext
     // Two per-thread state variables:
     //   txn: ThreadLocalTxn -- the transactional , one time use dataset
     //   isInTransactionB: ThreadLocalBoolean -- flags true between begin and commit/abort, and end for read transactions.
-    
 
     static class ThreadLocalTxn extends ThreadLocal<DatasetGraphTxn>
     {
@@ -97,7 +96,7 @@ public class DatasetGraphTransaction ext
             DatasetGraphTxn dsgTxn = txn.get() ;
             if ( dsgTxn == null )
                 throw new TDBTransactionException("In a transaction but no transactional DatasetGraph") ;
-            return dsgTxn ;
+            return dsgTxn.getView() ;
         }
         
         if ( sConn.haveUsedInTransaction() )

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTxn.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTxn.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTxn.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/DatasetGraphTxn.java Sat Aug 18 10:39:26 2012
@@ -18,14 +18,15 @@
 
 package com.hp.hpl.jena.tdb.transaction;
 
+import com.hp.hpl.jena.sparql.core.DatasetGraphWrapper ;
 import com.hp.hpl.jena.tdb.store.DatasetGraphTDB ;
 
-/** A DatasetGraph that is a singe transaction.
+/** A DatasetGraph that is a single transaction.
  * It does not support transactions, it is a transaction (single use).
  */
-public class DatasetGraphTxn extends DatasetGraphTDB
+public class DatasetGraphTxn extends DatasetGraphWrapper
 {
-    private final Transaction transaction ;
+    private Transaction transaction ;
 
     public DatasetGraphTxn(DatasetGraphTDB dsg, Transaction txn)
     {
@@ -35,6 +36,9 @@ public class DatasetGraphTxn extends Dat
 
     public Transaction getTransaction() { return transaction ; }
     
+    /** Return the view (storage) for this transaction */ 
+    public DatasetGraphTDB getView() { return (DatasetGraphTDB)getWrapped() ; }
+    
     public void commit()
     {
         transaction.commit() ;
@@ -53,6 +57,7 @@ public class DatasetGraphTxn extends Dat
     {
         if ( transaction != null )
             transaction.close() ;
+        transaction = null ;
     }
 
 }

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/JournalControl.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/JournalControl.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/JournalControl.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/JournalControl.java Sat Aug 18 10:39:26 2012
@@ -67,12 +67,6 @@ public class JournalControl
     /** Recover a base storage DatasetGraph */
     public static void recovery(DatasetGraphTDB dsg)
     {
-        if ( dsg instanceof DatasetGraphTxn )
-            throw new TDBTransactionException("Recovery works on the base dataset, not a transactional one") ;
-        // Later we may have ...
-//        if ( dsg instanceof DatasetGraphTransaction )
-//            throw new TDBTransactionException("Recovery works on the base dataset, not a transactional one") ; 
-        
         if ( dsg.getLocation().isMem() )
             return ;
         
@@ -114,9 +108,6 @@ public class JournalControl
      */
     public static void recoverFromJournal(DatasetGraphTDB dsg, Journal jrnl )
     {
-        if ( dsg instanceof DatasetGraphTxn )
-            throw new TDBTransactionException("Recovery works on the base dataset, not a transactional one") ;
-
         if ( jrnl.isEmpty() )
             return ;
         

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/Transaction.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/Transaction.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/Transaction.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/Transaction.java Sat Aug 18 10:39:26 2012
@@ -222,7 +222,12 @@ public class Transaction
     public DatasetGraphTxn getActiveDataset()       { return activedsg ; }
 
     public void setActiveDataset(DatasetGraphTxn activedsg)
-    { this.activedsg = activedsg ; }
+    { 
+        this.activedsg = activedsg ;
+        if ( activedsg.getTransaction() != this )
+            Log.warn(this, "Active DSG does not point to this transaction; "+this) ;
+    }
+        
 
     public Journal getJournal()                     { return journal ; }
 

Modified: jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/TransactionManager.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/TransactionManager.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/TransactionManager.java (original)
+++ jena/trunk/jena-tdb/src/main/java/com/hp/hpl/jena/tdb/transaction/TransactionManager.java Sat Aug 18 10:39:26 2012
@@ -46,9 +46,6 @@ import com.hp.hpl.jena.tdb.sys.SystemTDB
 
 public class TransactionManager
 {
-    // TODO Don't keep counters, keep lists.
-    // TODO Useful logging.
-    
     private static boolean checking = true ;
     
     private static Logger log = LoggerFactory.getLogger(TransactionManager.class) ;
@@ -90,16 +87,20 @@ public class TransactionManager
     AtomicLong activeReaders = new AtomicLong(0) ; 
     AtomicLong activeWriters = new AtomicLong(0) ; // 0 or 1
     
+    public long getCountActiveReaders()     { return activeReaders.get() ; }
+    public long getCountActiveWriters()     { return activeWriters.get() ; }
+    
     // Misc stats
     AtomicLong finishedReaders = new AtomicLong(0) ;
     AtomicLong committedWriters = new AtomicLong(0) ;
     AtomicLong abortedWriters = new AtomicLong(0) ;
     
-    // This is the last read-transaction created
-    // The read DatasetGraphTxn can be used by all the readers seeing the same view.
-    // A write transaction clears this when it commits; future readers see the new state;
-    // the first reader of a particular state creates teh view datasetgraph and sets the  lastreader.
-    private AtomicReference<DatasetGraphTxn> lastreader = new AtomicReference<DatasetGraphTxn>(null) ;
+    // This is the DatasetGraphTDB for the first read-transaction created for
+    // a particular view.  The read DatasetGraphTDB can be used by all the readers
+    // seeing the same view.
+    // A write transaction clears this when it commits; the first reader of a 
+    // particular state creates the view datasetgraph and sets the  lastreader.
+    private AtomicReference<DatasetGraphTDB> currentReaderView = new AtomicReference<DatasetGraphTDB>(null) ;
     
     // Ensure single writer.
     private Semaphore writersWaiting = new Semaphore(1, true) ;
@@ -111,13 +112,6 @@ public class TransactionManager
     private DatasetGraphTDB baseDataset ;
     private Journal journal ;
     
-    /* Various policies:
-     * + MRSW : writer locks to write back; blocks until let trhough.  Every reader takes an read lock.
-     * + Writers write if free, else queue for a reader or writer to clearup.
-     * + Async: there is a thread whose job it is to flush tot he base dataset (with an MRSW lock). 
-     */
-    
-    // Add queue unqueue?
     /*
      * The order of calls is: 
      * 1/ transactionStarts
@@ -129,7 +123,6 @@ public class TransactionManager
     
     private interface TSM
     {
-        // Quert unqueue?
         void transactionStarts(Transaction txn) ;
         void transactionFinishes(Transaction txn) ;
         void transactionCloses(Transaction txn) ;
@@ -154,6 +147,7 @@ public class TransactionManager
     
     class TSM_Logger extends TSM_Base
     {
+        TSM_Logger() {}
         @Override public void readerStarts(Transaction txn)         { log("start", txn) ; }
         @Override public void readerFinishes(Transaction txn)       { log("finish", txn) ; }
         @Override public void writerStarts(Transaction txn)         { log("begin", txn) ; }
@@ -164,6 +158,7 @@ public class TransactionManager
     /** More detailed */
     class TSM_LoggerDebug extends TSM_Base
     {
+        TSM_LoggerDebug() {}
         @Override public void readerStarts(Transaction txn)         { logInternal("start",  txn) ; }
         @Override public void readerFinishes(Transaction txn)       { logInternal("finish", txn) ; }
         @Override public void writerStarts(Transaction txn)         { logInternal("begin",  txn) ; }
@@ -174,6 +169,7 @@ public class TransactionManager
     
     class TSM_Counters implements TSM
     {
+        TSM_Counters() {}
         @Override public void transactionStarts(Transaction txn)    { activeTransactions.add(txn) ; }
         @Override public void transactionFinishes(Transaction txn)  { activeTransactions.remove(txn) ; }
         @Override public void transactionCloses(Transaction txn)    { }
@@ -200,15 +196,17 @@ public class TransactionManager
         // Safe mode.
         // Take a READ lock over the base dataset.
         // Write-back takes a WRITE lock.
-        @Override public void readerStarts(Transaction txn)    { txn.getBaseDataset().getLock().enterCriticalSection(Lock.READ) ; }
-        @Override public void writerStarts(Transaction txn)    { txn.getBaseDataset().getLock().enterCriticalSection(Lock.READ) ; }
+        @Override public void readerStarts(Transaction txn)     { txn.getBaseDataset().getLock().enterCriticalSection(Lock.READ) ; }
+        
+        @Override public void writerStarts(Transaction txn)     { txn.getBaseDataset().getLock().enterCriticalSection(Lock.READ) ; }
         
         // Currently, the writer semaphore is managed explicitly in the main code.
         
         @Override public void readerFinishes(Transaction txn)       
         { 
             txn.getBaseDataset().getLock().leaveCriticalSection() ;
-            processDelayedReplayQueue(txn) ;
+            if ( queue.size() >= QueueBatchSize )
+                processDelayedReplayQueue(txn) ;
         }
         
         @Override public void writerCommits(Transaction txn)
@@ -245,7 +243,8 @@ public class TransactionManager
         @Override public void writerAborts(Transaction txn)
         { 
             txn.getBaseDataset().getLock().leaveCriticalSection() ;
-            processDelayedReplayQueue(txn) ;
+            if ( queue.size() >= QueueBatchSize )
+                processDelayedReplayQueue(txn) ;
         }
     }
     
@@ -299,7 +298,7 @@ public class TransactionManager
         processDelayedReplayQueue(null) ;
         journal.close() ;
     }
-    
+
     public DatasetGraphTxn begin(ReadWrite mode)
     {
         return begin(mode, null) ;
@@ -307,6 +306,9 @@ public class TransactionManager
     
     
     public /*for testing only*/ static final boolean DEBUG = false ; 
+    
+    /** Control logging - the logger must be set as well */
+    //public /*for testing only*/ static boolean LOG = false ;
 
     public DatasetGraphTxn begin(ReadWrite mode, String label)
     {
@@ -351,7 +353,7 @@ public class TransactionManager
         if ( ! commitedAwaitingFlush.isEmpty() )
         {  
             if ( DEBUG ) System.out.print(commitedAwaitingFlush.size()) ;
-            dsg = commitedAwaitingFlush.get(commitedAwaitingFlush.size()-1).getActiveDataset() ;
+            dsg = commitedAwaitingFlush.get(commitedAwaitingFlush.size()-1).getActiveDataset().getView() ;
         }
         else 
         {
@@ -361,15 +363,16 @@ public class TransactionManager
         
         log("begin$", txn) ;
         
-        DatasetGraphTxn dsgTxn = createDSGTxn(dsg,txn, mode) ;
+        DatasetGraphTxn dsgTxn = createDSGTxn(dsg, txn, mode) ;
+
         txn.setActiveDataset(dsgTxn) ;
 
         // Empty for READ ; only WRITE transactions have components that need notifiying.
         List<TransactionLifecycle> components = dsgTxn.getTransaction().lifecycleComponents() ;
-
+        
         if ( mode == ReadWrite.READ )
         {
-            // Consistency check.
+            // ---- Consistency check.  View caching does not reset components.
             if ( components.size() != 0 )
                 log.warn("read transaction, non-empty lifecycleComponents list") ;
         }
@@ -387,28 +390,31 @@ public class TransactionManager
         return txn ;
     }
 
-    
     private DatasetGraphTxn createDSGTxn(DatasetGraphTDB dsg, Transaction txn, ReadWrite mode)
     {
         // A read transaction (if it has no lifecycle components) can be shared over all
         // read transactions at the same commit level. 
         //    lastreader
         
-        DatasetGraphTxn dsgTxn ;
-        
         if ( mode == ReadWrite.READ )
         {   
             // If a READ transaction, and a previously built one is cached, use it.
-            dsgTxn = lastreader.get();
-            if ( dsgTxn != null )
-                return dsgTxn ;
+            DatasetGraphTDB dsgCached = currentReaderView.get();
+            if ( dsgCached != null )
+            {
+                // No components so we don't need to notify them.
+                // We can just reuse the storage dataset.
+                return new DatasetGraphTxn(dsgCached, txn) ;
+            }
         }
         
-        dsgTxn = (DatasetGraphTxn)new DatasetBuilderTxn(this).build(txn, mode, dsg) ;
+        DatasetGraphTxn dsgTxn = new DatasetBuilderTxn(this).build(txn, mode, dsg) ;
         if ( mode == ReadWrite.READ )
-            // If a READ transaction, cached it.
+        {
+            // If a READ transaction, cache the storage view.
             // This is cleared when a WRITE commits
-            lastreader.set(dsgTxn);
+            currentReaderView.set(dsgTxn.getView());
+        }
         return dsgTxn ;
     }
 
@@ -430,7 +436,7 @@ public class TransactionManager
         {
             case READ: break ;
             case WRITE:
-                lastreader.set(null) ;      // Clear the READ transaction cache.
+                currentReaderView.set(null) ;      // Clear the READ transaction cache.
                 writersWaiting.release() ;  // Single writer: let another (waiting?) writer have a turn.
         }
     }
@@ -463,11 +469,15 @@ public class TransactionManager
         transaction.signalEnacted() ;
     }
 
+    /** Try to flush the delayed write queue - only happens if there are no active transactions */ 
+    public void flush()
+    {
+        processDelayedReplayQueue(null) ;
+    }
+    
     private void processDelayedReplayQueue(Transaction txn)
     {
-        // Sync'ed by notifyCommit.
-        // If we knew which version of the DB each was looking at, we could reduce more often here.
-        // [TxTDB:TODO]
+        // Can we do work?
         if ( activeReaders.get() != 0 || activeWriters.get() != 0 )
         {
             if ( queue.size() > 0 && log() )
@@ -481,15 +491,15 @@ public class TransactionManager
                 System.out.print("!"+queue.size()+"!") ;
         }
         
-        if ( log() )
-            log("Start flush delayed commits", txn) ;
-        
         if ( DEBUG ) checkNodesDatJrnl("1", txn) ;
         
         if ( queue.size() == 0 && txn != null )
             // Nothing to do - journal should be empty. 
             return ;
         
+        if ( log() )
+            log("Start flush delayed commits", txn) ;
+        
         while ( queue.size() > 0 )
         {
             // Currently, replay is replay everything
@@ -501,7 +511,7 @@ public class TransactionManager
                 if ( txn2.getMode() == ReadWrite.READ )
                     continue ;
                 if ( log() )
-                    log("Flush delayed commit of "+txn2.getLabel(), txn) ;
+                    log("  Flush delayed commit of "+txn2.getLabel(), txn) ;
                 if ( DEBUG ) checkNodesDatJrnl("2", txn) ;
                 checkReplaySafe() ;
                 enactTransaction(txn2) ;
@@ -526,7 +536,7 @@ public class TransactionManager
         
     }
 
-    private static void checkNodesDatJrnl(String label, Transaction txn)
+    private void checkNodesDatJrnl(String label, Transaction txn)
     {
         if (txn != null)
         {
@@ -559,7 +569,6 @@ public class TransactionManager
         noteTxnClose(txn) ;
     }
         
-    // TODO Collapse these.
     private void noteStartTxn(Transaction transaction)
     {
         switch (transaction.getMode())
@@ -624,12 +633,17 @@ public class TransactionManager
         return journal ;
     }
 
-    private static boolean log()
+    // ---- Logging
+    // Choose log output once when this object is created.
+    
+    private final boolean logstate = (syslog.isDebugEnabled() || log.isDebugEnabled()) ;
+    
+    private boolean log()
     {
-        return syslog.isDebugEnabled() || log.isDebugEnabled() ;
+        return logstate ;
     }
     
-    private static void log(String msg, Transaction txn)
+    private void log(String msg, Transaction txn)
     {
         if ( ! log() )
             return ;
@@ -644,7 +658,8 @@ public class TransactionManager
         if ( ! log() )
             return ;
         String txnStr = ( txn == null ) ? "<null>" : txn.getLabel() ;
-        System.err.printf(format("%6s %s -- %s", action, txnStr, state())) ;
+        //System.err.printf(format("%6s %s -- %s", action, txnStr, state())) ;
+        logger().debug(format("%6s %s -- %s", action, txnStr, state())) ;
     }
 
     private static Logger logger()

Modified: jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/migrate/AbstractTestTransaction.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/migrate/AbstractTestTransaction.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/migrate/AbstractTestTransaction.java (original)
+++ jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/migrate/AbstractTestTransaction.java Sat Aug 18 10:39:26 2012
@@ -101,7 +101,20 @@ public abstract class AbstractTestTransa
 
     @Test public void transaction_7()
     {
-        // .end is not necessary
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ; 
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ; 
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+    
+    @Test public void transaction_8()
+    {
         Dataset ds = create() ;
         ds.begin(ReadWrite.WRITE) ;
         assertTrue(ds.isInTransaction()) ; 
@@ -113,6 +126,32 @@ public abstract class AbstractTestTransa
         ds.commit() ;
         assertFalse(ds.isInTransaction()) ;
     }
+    
+    @Test public void transaction_9()
+    {
+        Dataset ds = create() ;
+        ds.begin(ReadWrite.WRITE) ;
+        assertTrue(ds.isInTransaction()) ; 
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ; 
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+
+        ds.begin(ReadWrite.READ) ;
+        assertTrue(ds.isInTransaction()) ; 
+        ds.commit() ;
+        assertFalse(ds.isInTransaction()) ;
+        ds.end() ;
+        assertFalse(ds.isInTransaction()) ;
+    }
+
 
 }
 

Modified: jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/transaction/AbstractTestTransSeq.java
URL: http://svn.apache.org/viewvc/jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/transaction/AbstractTestTransSeq.java?rev=1374552&r1=1374551&r2=1374552&view=diff
==============================================================================
--- jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/transaction/AbstractTestTransSeq.java (original)
+++ jena/trunk/jena-tdb/src/test/java/com/hp/hpl/jena/tdb/transaction/AbstractTestTransSeq.java Sat Aug 18 10:39:26 2012
@@ -89,6 +89,7 @@ public abstract class AbstractTestTransS
         assertTrue(dsg2.contains(q)) ;
         dsg2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q)) ;
         
@@ -109,6 +110,7 @@ public abstract class AbstractTestTransS
         assertFalse(dsg2.contains(q)) ;
         dsg2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertFalse(dsg.contains(q)) ;
     }
@@ -132,6 +134,7 @@ public abstract class AbstractTestTransS
         assertTrue(dsgR2.contains(q2)) ;
         dsgR2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q1)) ;
         assertTrue(dsg.contains(q2)) ;
@@ -184,6 +187,7 @@ public abstract class AbstractTestTransS
         assertTrue(dsgR2.contains(q)) ;
         dsgR2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q)) ;
     }
@@ -240,6 +244,7 @@ public abstract class AbstractTestTransS
         assertTrue(dsgR2.contains(q2)) ;
         dsgR2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q1)) ;
         assertTrue(dsg.contains(q2)) ;
@@ -268,6 +273,7 @@ public abstract class AbstractTestTransS
         
         dsgR1.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertFalse(dsg.contains(q2)) ;
         assertTrue(dsg.contains(q3)) ;
@@ -304,6 +310,7 @@ public abstract class AbstractTestTransS
         
         dsgR1.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q1)) ;
         assertFalse(dsg.contains(q2)) ;
@@ -328,7 +335,9 @@ public abstract class AbstractTestTransS
 
         DatasetGraphTxn dsgR2 = sConn.begin(ReadWrite.READ) ;
         assertTrue(dsgR2.contains(q)) ;
+        dsgR2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q)) ;
     }
@@ -353,6 +362,7 @@ public abstract class AbstractTestTransS
         assertTrue(dsgR2.contains(q)) ;
         dsgR2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q)) ;
     }
@@ -377,6 +387,7 @@ public abstract class AbstractTestTransS
         dsgR1.end() ;
         dsgR2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q)) ;
     }
@@ -406,6 +417,7 @@ public abstract class AbstractTestTransS
         dsgR1.end() ;
         dsgR2.end() ;
         
+        sConn.flush() ;
         DatasetGraph dsg = sConn.getBaseDataset() ;
         assertTrue(dsg.contains(q1)) ;
         assertTrue(dsg.contains(q2)) ;
@@ -459,6 +471,7 @@ public abstract class AbstractTestTransS
 
         dsgR1.end() ;
         
+        sConn.flush() ;
         DatasetGraphTDB dsg = sConn.getBaseDataset() ; 
         assertTrue(dsg.contains(q1)) ;
         assertTrue(dsg.contains(q2)) ;