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 ) );
+ }
+}