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 2014/03/10 21:27:49 UTC

svn commit: r1576069 - in /directory/mavibot/branches/with-txns/mavibot/src: main/java/org/apache/directory/mavibot/btree/ test/java/org/apache/directory/mavibot/btree/

Author: elecharny
Date: Mon Mar 10 20:27:49 2014
New Revision: 1576069

URL: http://svn.apache.org/r1576069
Log:
Fixed the delete operation when used with transaction on a persisted btre.

Modified:
    directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractBTree.java
    directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java
    directory/mavibot/branches/with-txns/mavibot/src/test/java/org/apache/directory/mavibot/btree/RecordManagerTest.java

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractBTree.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractBTree.java?rev=1576069&r1=1576068&r2=1576069&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractBTree.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractBTree.java Mon Mar 10 20:27:49 2014
@@ -362,13 +362,20 @@ import org.apache.directory.mavibot.btre
     {
         ReadTransaction<K, V> transaction = beginReadTransaction( revision );
 
-        try
+        if ( transaction == null )
         {
-            return transaction.getRootPage().get( key );
+            return null;
         }
-        finally
+        else
         {
-            transaction.close();
+            try
+            {
+                return transaction.getRootPage().get( key );
+            }
+            finally
+            {
+                transaction.close();
+            }
         }
     }
 

Modified: directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java?rev=1576069&r1=1576068&r2=1576069&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/main/java/org/apache/directory/mavibot/btree/PersistedBTree.java Mon Mar 10 20:27:49 2014
@@ -273,58 +273,76 @@ public class PersistedBTree<K, V> extend
      */
     /* no qualifier */ Tuple<K, V> delete( K key, V value, long revision ) throws IOException
     {
-        recordManager.beginTransaction();
-
-        // Try to delete the entry starting from the root page. Here, the root
-        // page may be either a Node or a Leaf
-        DeleteResult<K, V> result = processDelete( key, value, revision );
-
-        // Check that we have found the element to delete
-        if ( result instanceof NotPresentResult )
+        // We have to start a new transaction, which will be committed or rollbacked
+        // locally. This will duplicate the current BtreeHeader during this phase.
+        if ( revision == -1L )
         {
-            // We haven't found the element in the B-tree, just get out
-            recordManager.commit();
-
-            return null;
+            revision = currentRevision.get() + 1;
         }
 
-        // The element was found, and removed
-        AbstractDeleteResult<K, V> deleteResult = ( AbstractDeleteResult<K, V> ) result;
-
-        Tuple<K, V> tuple = deleteResult.getRemovedElement();
-
-        // Update the B-tree header, creating a new BtreeHeader page now
-        long newBtreeHeaderOffset = recordManager.updateBtreeHeader( this, ( ( AbstractPage<K, V> ) getRootPage() ).getOffset() );
+        recordManager.beginTransaction();
 
-        // Update the B-tree of B-trees with this new offset, if we are not already doing so
-        switch ( btreeType )
+        try
         {
-            case PERSISTED :
-                // We have a new B-tree header to inject into the B-tree of btrees
-                recordManager.addInBtreeOfBtrees( getName(), revision, newBtreeHeaderOffset );
-                break;
+            // Try to delete the entry starting from the root page. Here, the root
+            // page may be either a Node or a Leaf
+            DeleteResult<K, V> result = processDelete( key, value, revision );
 
-            case BTREE_OF_BTREES :
-            case COPIED_PAGES_BTREE :
-                // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
-                getBtreeHeader().setBTreeHeaderOffset( newBtreeHeaderOffset );
+            // Check that we have found the element to delete
+            if ( result instanceof NotPresentResult )
+            {
+                // We haven't found the element in the B-tree, just get out
+                // without updating the recordManager
+                rollback();
 
-                break;
+                return null;
+            }
 
-            default:
-                // Nothing to do for sub-btrees
-                break;
-        }
+            // The element was found, and removed
+            AbstractDeleteResult<K, V> deleteResult = ( AbstractDeleteResult<K, V> ) result;
 
-        // We can safely free the copied pages
-        recordManager.freePages( this, revision, result.getCopiedPages() );
+            Tuple<K, V> tuple = deleteResult.getRemovedElement();
+//
+//            // Update the B-tree header, creating a new BtreeHeader page now
+//            long newBtreeHeaderOffset = recordManager.updateBtreeHeader( this, ( ( AbstractPage<K, V> ) getRootPage() ).getOffset() );
+//
+//            // Update the B-tree of B-trees with this new offset, if we are not already doing so
+//            switch ( btreeType )
+//            {
+//                case PERSISTED :
+//                    // We have a new B-tree header to inject into the B-tree of btrees
+//                    recordManager.addInBtreeOfBtrees( getName(), revision, newBtreeHeaderOffset );
+//                    break;
+//
+//                case BTREE_OF_BTREES :
+//                case COPIED_PAGES_BTREE :
+//                    // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
+//                    getBtreeHeader().setBTreeHeaderOffset( newBtreeHeaderOffset );
+//
+//                    break;
+//
+//                default:
+//                    // Nothing to do for sub-btrees
+//                    break;
+//            }
+//
+//            // We can safely free the copied pages
+//            recordManager.freePages( this, revision, result.getCopiedPages() );
 
-        // If the B-tree is managed, we have to update the rootPage on disk
-        // Update the RecordManager header
-        recordManager.commit();
+            // If the B-tree is managed, we have to update the rootPage on disk
+            // Update the RecordManager header
+            commit();
 
-        // Return the value we have found if it was modified
-        return tuple;
+            // Return the value we have found if it was modified
+            return tuple;
+        }
+        catch ( IOException ioe )
+        {
+            // if we've got an error, we have to rollback
+            rollback();
+
+            throw ioe;
+        }
     }
 
 
@@ -333,9 +351,12 @@ public class PersistedBTree<K, V> extend
      */
     private DeleteResult<K, V> processDelete( K key, V value, long revision ) throws IOException
     {
+        // Get the current B-tree header, and delete the value from it
+        BTreeHeader<K, V> btreeHeader = getBtreeHeader();
+
         // Try to delete the entry starting from the root page. Here, the root
         // page may be either a Node or a Leaf
-        DeleteResult<K, V> result = getRootPage().delete( key, value, revision);
+        DeleteResult<K, V> result = btreeHeader.getRootPage().delete( key, value, revision);
 
         if ( result instanceof NotPresentResult )
         {
@@ -343,34 +364,92 @@ public class PersistedBTree<K, V> extend
             return result;
         }
 
+        // Create a new BTreeHeader
+        BTreeHeader<K, V> newBtreeHeader = btreeHeader.copy();
+
+        // Inject the old B-tree header into the pages to be freed
+        // if we are deleting an element from a management BTree
+        if ( ( btreeType == BTreeTypeEnum.BTREE_OF_BTREES ) || ( btreeType == BTreeTypeEnum.COPIED_PAGES_BTREE ) )
+        {
+            PageIO[] pageIos = recordManager.readPageIOs( btreeHeader.getBTreeHeaderOffset(), -1L );
+
+            for ( PageIO pageIo : pageIos )
+            {
+                recordManager.freedPages.add( pageIo );
+            }
+        }
+
         // The element was found, and removed
         AbstractDeleteResult<K, V> removeResult = ( AbstractDeleteResult<K, V> ) result;
 
-        Page<K, V> modifiedPage = removeResult.getModifiedPage();
+        // This is a new root
+        Page<K, V> newRootPage = removeResult.getModifiedPage();
 
         // 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 = writePage( modifiedPage, revision );
+        PageHolder<K, V> holder = writePage( newRootPage, revision );
 
         // Store the offset on disk in the page in memory
-        ( ( AbstractPage<K, V> ) modifiedPage ).setOffset( ( ( PersistedPageHolder<K, V> ) holder )
-            .getOffset() );
+//        ( ( AbstractPage<K, V> ) modifiedPage ).setOffset( ( ( PersistedPageHolder<K, V> ) holder )
+//            .getOffset() );
+//
+//        // Store the last offset on disk in the page in memory
+//        ( ( AbstractPage<K, V> ) modifiedPage )
+//            .setLastOffset( ( ( PersistedPageHolder<K, V> ) holder )
+//                .getLastOffset() );
+
+        // Decrease the number of elements in the current tree
+        newBtreeHeader.decrementNbElems();
+        newBtreeHeader.setRootPage( newRootPage );
+        newBtreeHeader.setRevision( revision );
 
-        // Store the last offset on disk in the page in memory
-        ( ( AbstractPage<K, V> ) modifiedPage )
-            .setLastOffset( ( ( PersistedPageHolder<K, V> ) holder )
-                .getLastOffset() );
+        // Write down the data on disk
+        long newBtreeHeaderOffset = recordManager.writeBtreeHeader( this, newBtreeHeader );
 
-        // This is a new root
-        //rootPage = modifiedPage;
 
-        // Decrease the number of elements in the current tree
-        getBtreeHeader().decrementNbElems();
+        // Update the B-tree of B-trees with this new offset, if we are not already doing so
+        switch ( btreeType )
+        {
+            case PERSISTED :
+                // We have a new B-tree header to inject into the B-tree of btrees
+                recordManager.addInBtreeOfBtrees( getName(), revision, newBtreeHeaderOffset );
+
+                recordManager.addInCopiedPagesBtree( getName(), revision, result.getCopiedPages() );
+
+                // Store the new revision
+                storeRevision( newBtreeHeader );
 
-        // We have to update the rootPage on disk
-        // Update the B-tree header now
-        recordManager.updateBtreeHeader( this, ( ( AbstractPage<K, V> ) getBtreeHeader().getRootPage() ).getOffset() );
+                break;
+
+            case BTREE_OF_BTREES :
+                // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
+                recordManager.updateRecordManagerHeader( newBtreeHeaderOffset, -1L );
+
+                // We can free the copied pages
+                recordManager.freePages( this, revision, result.getCopiedPages() );
+
+                // Store the new revision
+                storeRevision( newBtreeHeader );
+
+                break;
+
+            case COPIED_PAGES_BTREE :
+                // The B-tree of B-trees or the copiedPages B-tree has been updated, update the RMheader parameters
+                recordManager.updateRecordManagerHeader( -1L, newBtreeHeaderOffset );
+
+                // We can free the copied pages
+                recordManager.freePages( this, revision, result.getCopiedPages() );
+
+                // Store the new revision
+                storeRevision( newBtreeHeader );
+
+                break;
+
+            default:
+                // Nothing to do for sub-btrees
+                break;
+        }
 
         // Return the value we have found if it was modified
         return result;

Modified: directory/mavibot/branches/with-txns/mavibot/src/test/java/org/apache/directory/mavibot/btree/RecordManagerTest.java
URL: http://svn.apache.org/viewvc/directory/mavibot/branches/with-txns/mavibot/src/test/java/org/apache/directory/mavibot/btree/RecordManagerTest.java?rev=1576069&r1=1576068&r2=1576069&view=diff
==============================================================================
--- directory/mavibot/branches/with-txns/mavibot/src/test/java/org/apache/directory/mavibot/btree/RecordManagerTest.java (original)
+++ directory/mavibot/branches/with-txns/mavibot/src/test/java/org/apache/directory/mavibot/btree/RecordManagerTest.java Mon Mar 10 20:27:49 2014
@@ -615,20 +615,16 @@ public class RecordManagerTest
 
         // Check that we can get a value from each revision
         // revision 1
-        assertEquals( "V3", btree.get( rev1, 3L ) );
+        checkBTreeRevisionBrowse( btree, rev1 );
 
         // revision 2
-        assertEquals( "V1", btree.get( rev2, 1L ) );
-        assertEquals( "V3", btree.get( rev2, 3L ) );
+        checkBTreeRevisionBrowse( btree, rev2 );
 
         // revision 3
-        assertEquals( "V1", btree.get( rev3, 1L ) );
-        assertEquals( "V3", btree.get( rev3, 3L ) );
-        assertEquals( "V5", btree.get( rev3, 5L ) );
+        checkBTreeRevisionBrowse( btree, rev3 );
 
         // revision 4
-        assertEquals( "V1", btree.get( rev4, 1L ) );
-        assertEquals( "V5", btree.get( rev4, 5L ) );
+        checkBTreeRevisionBrowse( btree, rev4, 1L, 5L );
 
         try
         {