You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2013/12/20 10:58:43 UTC

svn commit: r1552574 - in /directory/mavibot/trunk/mavibot/src: main/java/org/apache/directory/mavibot/btree/ test/java/org/apache/directory/mavibot/btree/

Author: elecharny
Date: Fri Dec 20 09:58:42 2013
New Revision: 1552574

URL: http://svn.apache.org/r1552574
Log:
o First drop of transaction support. It really does nothing but encapsulates the transaction mechanisms to get it working when t will be ready.

Added:
    directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeTransactionTest.java
Modified:
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
    directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java?rev=1552574&r1=1552573&r2=1552574&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java Fri Dec 20 09:58:42 2013
@@ -24,6 +24,7 @@ import java.io.Closeable;
 import java.io.IOException;
 import java.nio.ByteBuffer;
 import java.nio.channels.FileChannel;
+import java.util.Map;
 import java.util.concurrent.ConcurrentLinkedQueue;
 import java.util.concurrent.locks.ReentrantLock;
 
@@ -347,7 +348,7 @@ public class PersistedBTree<K, V> extend
                 // Write the modified page on disk
                 // Note that we don't use the holder, the new root page will
                 // remain in memory.
-                PageHolder<K, V> holder = recordManager.writePage( this, modifiedPage, revision );
+                PageHolder<K, V> holder = writePage( modifiedPage, revision );
 
                 // Store the offset on disk in the page in memory
                 ( ( AbstractPage<K, V> ) modifiedPage ).setOffset( ( ( PersistedPageHolder<K, V> ) holder )
@@ -430,7 +431,7 @@ public class PersistedBTree<K, V> extend
             // Write the modified page on disk
             // Note that we don't use the holder, the new root page will
             // remain in memory.
-            PageHolder<K, V> holder = recordManager.writePage( this, modifiedPage, revision );
+            writePage( modifiedPage, revision );
 
             // The root has just been modified, we haven't split it
             // Get it and make it the current root page
@@ -451,17 +452,16 @@ public class PersistedBTree<K, V> extend
 
             // If the BTree is managed, we have to write the two pages that were created
             // and to keep a track of the two offsets for the upper node
-            PageHolder<K, V> holderLeft = recordManager.writePage( this, leftPage, revision );
+            PageHolder<K, V> holderLeft = writePage( leftPage, revision );
 
-            PageHolder<K, V> holderRight = recordManager.writePage( this, rightPage, revision );
+            PageHolder<K, V> holderRight = writePage( rightPage, revision );
 
             // Create the new rootPage
             newRootPage = new PersistedNode<K, V>( this, revision, pivot, holderLeft, holderRight );
 
             // If the BTree is managed, we now have to write the page on disk
             // and to add this page to the list of modified pages
-            PageHolder<K, V> holder = recordManager
-                .writePage( this, newRootPage, revision );
+            PageHolder<K, V> holder = writePage( newRootPage, revision );
 
             rootPage = newRootPage;
         }
@@ -475,16 +475,19 @@ public class PersistedBTree<K, V> extend
 
         // If the BTree is managed, we have to update the rootPage on disk
         // Update the RecordManager header
-        recordManager.updateRecordManagerHeader();
+        if ( ( writeTransaction == null ) || !writeTransaction.isStarted() )
+        {
+            recordManager.updateRecordManagerHeader();
 
-        // Update the BTree header now
-        recordManager.updateBtreeHeader( this, ( ( AbstractPage<K, V> ) rootPage ).getOffset() );
+            // Update the BTree header now
+            recordManager.updateBtreeHeader( this, ( ( AbstractPage<K, V> ) rootPage ).getOffset() );
 
-        // Moved the free pages into the list of free pages
-        recordManager.addFreePages( this, result.getCopiedPages() );
+            // Moved the free pages into the list of free pages
+            recordManager.addFreePages( this, result.getCopiedPages() );
 
-        // Store the created rootPage into the revision BTree, this will be stored in RecordManager only if revisions are set to keep
-        recordManager.storeRootPage( this, rootPage );
+            // Store the created rootPage into the revision BTree, this will be stored in RecordManager only if revisions are set to keep
+            recordManager.storeRootPage( this, rootPage );
+        }
 
         // Return the value we have found if it was modified
         return result;
@@ -533,6 +536,29 @@ public class PersistedBTree<K, V> extend
 
 
     /**
+     * Write a page either in the pending pages if the transaction is started,
+     * or directly on disk.
+     */
+    private PageHolder<K, V> writePage( Page<K, V> modifiedPage, long revision ) throws IOException
+    {
+        if ( ( writeTransaction != null ) && writeTransaction.isStarted() )
+        {
+            Map<Page<?, ?>, BTree<?, ?>> pendingPages = recordManager.getPendingPages();
+            pendingPages.put( modifiedPage, this );
+
+            PageHolder<K, V> pageHolder = new PageHolder<K, V>( this, modifiedPage );
+
+            return pageHolder;
+        }
+        else
+        {
+            PageHolder<K, V> pageHolder = recordManager.writePage( this, modifiedPage, revision );
+
+            return pageHolder;
+        }
+    }
+
+    /**
      * Get the rootPzge associated to a give revision.
      *
      * @param revision The revision we are looking for

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java?rev=1552574&r1=1552573&r2=1552574&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedNode.java Fri Dec 20 09:58:42 2013
@@ -104,7 +104,7 @@ import java.util.List;
         super( btree, revision, 1 );
 
         // Create the children array, and store the left and right children
-        children = ( PersistedPageHolder<K, V>[] ) Array.newInstance( PersistedPageHolder.class,
+        children = ( PageHolder<K, V>[] ) Array.newInstance( PageHolder.class,
             btree.getPageSize() + 1 );
 
         children[0] = leftPage;

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java?rev=1552574&r1=1552573&r2=1552574&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/RecordManager.java Fri Dec 20 09:58:42 2013
@@ -170,6 +170,8 @@ public class RecordManager
     /** A flag used by internal btrees */
     public static final boolean NORMAL_BTREE = false;
 
+    /** A map of pending pages */
+    private Map<Page<?, ?>, BTree<?, ?>> pendingPages = new LinkedHashMap<Page<?, ?>, BTree<?, ?>>();
 
     /**
      * Create a Record manager which will either create the underlying file
@@ -3032,6 +3034,15 @@ public class RecordManager
 
 
     /**
+     * @return the pendingPages
+     */
+    /* no qualifier*/ <K, V> Map<Page<?, ?>, BTree<?, ?>> getPendingPages()
+    {
+        return pendingPages;
+    }
+
+
+    /**
      * @see Object#toString()
      */
     public String toString()

Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java?rev=1552574&r1=1552573&r2=1552574&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/WriteTransaction.java Fri Dec 20 09:58:42 2013
@@ -19,6 +19,8 @@
  */
 package org.apache.directory.mavibot.btree;
 
+import java.io.IOException;
+import java.util.Map;
 import java.util.concurrent.locks.ReentrantLock;
 
 import org.apache.directory.mavibot.btree.exception.BadTransactionStateException;
@@ -62,6 +64,38 @@ import org.apache.directory.mavibot.btre
             throw new BadTransactionStateException( "Cannot commit a write transaction when it's not started" );
         }
 
+        Map<?, ?> pendingPages = recordManager.getPendingPages();
+
+        for ( Object object : pendingPages.keySet() )
+        {
+            BTree btree = (BTree)pendingPages.get( object );
+
+            try
+            {
+                recordManager.writePage( btree, (Page)object, ((Page)object).getRevision() );
+            }
+            catch ( IOException e )
+            {
+                // TODO Auto-generated catch block
+                e.printStackTrace();
+            }
+        }
+
+        /*
+        recordManager.updateRecordManagerHeader();
+
+        // Update the BTree header now
+        recordManager.updateBtreeHeader( btree, ( ( AbstractPage<K, V> ) rootPage ).getOffset() );
+
+        // Moved the free pages into the list of free pages
+        recordManager.addFreePages( this, result.getCopiedPages() );
+
+        // Store the created rootPage into the revision BTree, this will be stored in RecordManager only if revisions are set to keep
+        recordManager.storeRootPage( this, rootPage );
+        */
+
+        pendingPages.clear();
+
         writeLock.unlock();
     }
 
@@ -75,4 +109,14 @@ import org.apache.directory.mavibot.btre
 
         writeLock.unlock();
     }
+
+
+    /**
+     * Tells if the transaction has started
+     * @return true if the transaction has started
+     */
+    /* no qualifier */ boolean isStarted()
+    {
+        return writeLock.isLocked();
+    }
 }

Added: directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeTransactionTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeTransactionTest.java?rev=1552574&view=auto
==============================================================================
--- directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeTransactionTest.java (added)
+++ directory/mavibot/trunk/mavibot/src/test/java/org/apache/directory/mavibot/btree/PersistedBTreeTransactionTest.java Fri Dec 20 09:58:42 2013
@@ -0,0 +1,142 @@
+/*
+ *   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.directory.mavibot.btree;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.UUID;
+
+import org.apache.directory.mavibot.btree.serializer.LongSerializer;
+import org.apache.directory.mavibot.btree.serializer.StringSerializer;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+/**
+ * Test the PersistedBTree with transaction
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class PersistedBTreeTransactionTest
+{
+    @Rule
+    public TemporaryFolder tempFolder = new TemporaryFolder();
+    private File dataDirWithTxn = null;
+    private File dataDirNoTxn = null;
+    private BTree<Long, String> btreeWithTransactions = null;
+    private BTree<Long, String> btreeNoTransactions = null;
+    private RecordManager recordManagerTxn = null;
+    private RecordManager recordManagerNoTxn = null;
+
+
+    @Before
+    public void createBTree()
+    {
+        dataDirWithTxn = tempFolder.newFolder( UUID.randomUUID().toString() );
+        dataDirNoTxn = tempFolder.newFolder( UUID.randomUUID().toString() );
+
+        openRecordManagerAndBtrees();
+
+        try
+        {
+            // Create a new BTree with transaction and another one without
+            btreeWithTransactions = recordManagerTxn.addBTree( "testWithTxn", new LongSerializer(), new StringSerializer(), false );
+            btreeNoTransactions = recordManagerNoTxn.addBTree( "testNoTxn", new LongSerializer(), new StringSerializer(), false );
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    private void openRecordManagerAndBtrees()
+    {
+        try
+        {
+            if ( recordManagerTxn != null )
+            {
+                recordManagerTxn.close();
+            }
+
+            if ( recordManagerNoTxn != null )
+            {
+                recordManagerNoTxn.close();
+            }
+
+            // Now, try to reload the file back
+            recordManagerTxn = new RecordManager( dataDirWithTxn.getAbsolutePath() );
+            recordManagerNoTxn = new RecordManager( dataDirNoTxn.getAbsolutePath() );
+
+            // load the last created btree
+            if ( btreeWithTransactions != null )
+            {
+                btreeWithTransactions = recordManagerTxn.getManagedTree( btreeWithTransactions.getName() );
+            }
+
+            if ( btreeNoTransactions != null )
+            {
+                btreeNoTransactions = recordManagerNoTxn.getManagedTree( btreeNoTransactions.getName() );
+            }
+        }
+        catch ( Exception e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
+
+
+    @Test
+    public void testWithoutTransaction() throws IOException
+    {
+        long t0 = System.currentTimeMillis();
+
+        for ( long i = 0L; i < 1000L; i++ )
+        {
+            btreeNoTransactions.insert( i, Long.toString( i ) );
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta without transaction for 100K elements = " + ( t1 - t0 ) );
+    }
+
+
+    @Test
+    @Ignore("Fails atm")
+    public void testWithTransaction() throws IOException
+    {
+        long t0 = System.currentTimeMillis();
+
+        for ( long i = 0L; i < 1000L; i++ )
+        {
+            System.out.println( i );
+            btreeWithTransactions.beginTransaction();
+            btreeWithTransactions.insert( i, Long.toString( i ) );
+            btreeWithTransactions.commit();
+        }
+
+        long t1 = System.currentTimeMillis();
+
+        System.out.println( "Delta with transaction for 100K elements = " + ( t1 - t0 ) );
+    }
+}