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 2015/03/08 18:24:55 UTC
svn commit: r1665059 - in
/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree:
AbstractTransactionManager.java RecordManager.java TransactionManager.java
Author: elecharny
Date: Sun Mar 8 17:24:55 2015
New Revision: 1665059
URL: http://svn.apache.org/r1665059
Log:
o Added a dedicated logger for the transaction : TXN_LOG
o Removed the lock from the AbstractTransactionManager
o Added a map to keep a track of the number of times a page is written
o Fixes in the way we handle transactions in the RM
o Added some explicit generics
Modified:
directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractTransactionManager.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/TransactionManager.java
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractTransactionManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractTransactionManager.java?rev=1665059&r1=1665058&r2=1665059&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractTransactionManager.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/AbstractTransactionManager.java Sun Mar 8 17:24:55 2015
@@ -19,16 +19,12 @@
*/
package org.apache.directory.mavibot.btree;
-import java.util.concurrent.locks.ReadWriteLock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* An abstract class implementing the TransactionManager interface.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public abstract class AbstractTransactionManager implements TransactionManager
+public abstract class AbstractTransactionManager<K, V> implements TransactionManager<K, V>
{
- /** A lock to protect the transaction handling */
- private ReadWriteLock transactionLock = new ReentrantReadWriteLock();
}
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=1665059&r1=1665058&r2=1665059&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 Sun Mar 8 17:24:55 2015
@@ -35,7 +35,6 @@ import java.util.Queue;
import java.util.Set;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -69,6 +68,9 @@ public class RecordManager extends Abstr
/** The LoggerFactory used by this class */
protected static final Logger LOG = LoggerFactory.getLogger( RecordManager.class );
+ /** The LoggerFactory used to trace TXN operations */
+ protected static final Logger TXN_LOG = LoggerFactory.getLogger( "TXN_LOG" );
+
/** The LoggerFactory used by this class */
protected static final Logger LOG_PAGES = LoggerFactory.getLogger( "org.apache.directory.mavibot.LOG_PAGES" );
@@ -177,7 +179,7 @@ public class RecordManager extends Abstr
private long previousBtreeOfBtreesOffset = NO_PAGE;
/** A lock to protect the transaction handling */
- private Lock transactionLock = new ReentrantLock();
+ private ReentrantLock transactionLock = new ReentrantLock();
/** A ThreadLocalStorage used to store the current transaction */
private static final ThreadLocal<Integer> context = new ThreadLocal<Integer>();
@@ -212,6 +214,8 @@ public class RecordManager extends Abstr
/** the threshold at which the SpaceReclaimer will be run to free the copied pages */
private int spaceReclaimerThreshold = 200;
+ public Map<Long, Integer> writeCounter = new HashMap<Long, Integer>();
+
/**
* Create a Record manager which will either create the underlying file
@@ -556,9 +560,22 @@ public class RecordManager extends Abstr
*/
public void beginTransaction()
{
+ if ( TXN_LOG.isDebugEnabled() )
+ {
+ TXN_LOG.debug( "Begining a new transaction on thread {}, TxnLevel {}",
+ Thread.currentThread().getName(), getTxnLevel() );
+ }
+
// First, take the lock if it's not already taken
- //( ( ReadWriteLock ) transactionLock ).writeLock();
- transactionLock.lock();
+ if ( !( ( ReentrantLock ) transactionLock ).isHeldByCurrentThread() )
+ {
+ TXN_LOG.debug( "--> Lock taken" );
+ transactionLock.lock();
+ }
+ else
+ {
+ TXN_LOG.debug( "..o The current thread already holds the lock" );
+ }
// Now, check the TLS state
incrementTxnLevel();
@@ -570,13 +587,30 @@ public class RecordManager extends Abstr
*/
public void commit()
{
- if ( !fileChannel.isOpen() )
+ // We *must* own the transactionLock
+ if ( !transactionLock.isHeldByCurrentThread() )
+ {
+ TXN_LOG.error( "This thread does not hold the transactionLock" );
+ throw new RecordManagerException( "This thread does not hold the transactionLock" );
+ }
+
+ if ( TXN_LOG.isDebugEnabled() )
{
- // The file has been closed, nothing remains to commit, let's get out
- transactionLock.unlock();
+ TXN_LOG.debug( "Committing a transaction on thread {}, TxnLevel {}",
+ Thread.currentThread().getName(), getTxnLevel() );
+ }
+ if ( !fileChannel.isOpen() )
+ {
// Still we have to decrement the TransactionLevel
- decrementTxnLevel();
+ int txnLevel = decrementTxnLevel();
+
+ if ( txnLevel == 0 )
+ {
+ // We can safely release the lock
+ // The file has been closed, nothing remains to commit, let's get out
+ transactionLock.unlock();
+ }
return;
}
@@ -620,9 +654,6 @@ public class RecordManager extends Abstr
// here, we have to erase the old references to keep only the new ones.
updateRecordManagerHeader();
- // And decrement the number of started transactions
- decrementTxnLevel();
-
commitCount++;
if ( commitCount >= spaceReclaimerThreshold )
@@ -630,8 +661,14 @@ public class RecordManager extends Abstr
runReclaimer();
}
- // Finally, release the global lock
- transactionLock.unlock();
+ // Finally, decrement the number of started transactions
+ // and release the global lock if possible
+ int txnLevel = decrementTxnLevel();
+
+ if ( txnLevel == 0 )
+ {
+ transactionLock.unlock();
+ }
return;
@@ -664,9 +701,6 @@ public class RecordManager extends Abstr
// here, we have to erase the old references to keep only the new ones.
updateRecordManagerHeader();
- // And decrement the number of started transactions
- decrementTxnLevel();
-
commitCount++;
if ( commitCount >= spaceReclaimerThreshold )
@@ -674,8 +708,14 @@ public class RecordManager extends Abstr
runReclaimer();
}
- // Finally, release the global lock
- transactionLock.unlock();
+ // Finally, decrement the number of started transactions
+ // and release the global lock
+ txnLevel = decrementTxnLevel();
+
+ if ( txnLevel == 0 )
+ {
+ transactionLock.unlock();
+ }
return;
}
@@ -689,6 +729,22 @@ public class RecordManager extends Abstr
/**
+ * Get the transactionLevel, ie the number of encapsulated update ops
+ */
+ private int getTxnLevel()
+ {
+ Integer nbTxnLevel = context.get();
+
+ if ( nbTxnLevel == null )
+ {
+ return -1;
+ }
+
+ return nbTxnLevel;
+ }
+
+
+ /**
* Increment the transactionLevel
*/
private void incrementTxnLevel()
@@ -705,27 +761,28 @@ public class RecordManager extends Abstr
context.set( nbTxnLevel + 1 );
}
- /*
- System.out.println( "Incrementing : " + context.get() );
-
- if ( context.get() == 0 )
+ if ( TXN_LOG.isDebugEnabled() )
{
- System.out.println( "-------------" );
+ TXN_LOG.debug( "Incrementing the TxnLevel : {}", context.get() );
}
- */
}
/**
* Decrement the transactionLevel
*/
- private void decrementTxnLevel()
+ private int decrementTxnLevel()
{
- int nbTxnStarted = context.get();
+ int nbTxnStarted = context.get() - 1;
- context.set( nbTxnStarted - 1 );
+ context.set( nbTxnStarted );
- //System.out.println( "Incrementing : " + context.get() );
+ if ( TXN_LOG.isDebugEnabled() )
+ {
+ TXN_LOG.debug( "Decrementing the TxnLevel : {}", context.get() );
+ }
+
+ return nbTxnStarted;
}
@@ -734,6 +791,19 @@ public class RecordManager extends Abstr
*/
public void rollback()
{
+ // We *must* own the transactionLock
+ if ( !transactionLock.isHeldByCurrentThread() )
+ {
+ TXN_LOG.error( "This thread does not hold the transactionLock" );
+ throw new RecordManagerException( "This thread does not hold the transactionLock" );
+ }
+
+ if ( TXN_LOG.isDebugEnabled() )
+ {
+ TXN_LOG.debug( "Rollbacking a new transaction on thread {}, TxnLevel {}",
+ Thread.currentThread().getName(), getTxnLevel() );
+ }
+
// Reset the counter
context.set( ROLLBACKED_TXN );
@@ -760,6 +830,8 @@ public class RecordManager extends Abstr
// And restore the BTreeHeaders new Map to the current state
revertBtreeHeaders();
+ // This is an all-of-nothing operation : we can't have a transaction within
+ // a transaction that would survive an inner transaction rollback.
transactionLock.unlock();
}
@@ -1948,6 +2020,7 @@ public class RecordManager extends Abstr
try
{
+ writeCounter.put( 0L, writeCounter.containsKey( 0L ) ? writeCounter.get( 0L ) + 1 : 1 );
fileChannel.write( RECORD_MANAGER_HEADER_BUFFER, 0 );
}
catch ( IOException ioe )
@@ -2433,12 +2506,14 @@ public class RecordManager extends Abstr
for ( PageIO pageIo : pageIos )
{
pageIo.getData().rewind();
+ long pos = pageIo.getOffset();
if ( fileChannel.size() < ( pageIo.getOffset() + pageSize ) )
{
LOG.debug( "Adding a page at the end of the file" );
// This is a page we have to add to the file
- fileChannel.write( pageIo.getData(), fileChannel.size() );
+ pos = fileChannel.size();
+ fileChannel.write( pageIo.getData(), pos );
//fileChannel.force( false );
}
else
@@ -2448,6 +2523,8 @@ public class RecordManager extends Abstr
//fileChannel.force( false );
}
+ writeCounter.put( pos, writeCounter.containsKey( pos ) ? writeCounter.get( pos ) + 1 : 1 );
+
nbUpdatePageIOs.incrementAndGet();
pageIo.getData().rewind();
@@ -3873,8 +3950,6 @@ public class RecordManager extends Abstr
private void checkFreePages() throws EndOfFileExceededException, IOException
{
- System.out.println( "Checking the free pages, starting from " + Long.toHexString( firstFreePage ) );
-
// read all the free pages, add them into a set, to be sure we don't have a cycle
Set<Long> freePageOffsets = new HashSet<Long>();
@@ -3882,8 +3957,6 @@ public class RecordManager extends Abstr
while ( currentFreePageOffset != NO_PAGE )
{
- System.out.println( "Next page offset :" + Long.toHexString( currentFreePageOffset ) );
-
if ( ( currentFreePageOffset % pageSize ) != 0 )
{
throw new InvalidOffsetException( "Wrong offset : " + Long.toHexString( currentFreePageOffset ) );
Modified: directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/TransactionManager.java
URL: http://svn.apache.org/viewvc/directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/TransactionManager.java?rev=1665059&r1=1665058&r2=1665059&view=diff
==============================================================================
--- directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/TransactionManager.java (original)
+++ directory/mavibot/trunk/mavibot/src/main/java/org/apache/directory/mavibot/btree/TransactionManager.java Sun Mar 8 17:24:55 2015
@@ -19,13 +19,14 @@
*/
package org.apache.directory.mavibot.btree;
+
/**
* An interface used to manage the transactions mechanism in B-trees. Transactions are cross
* B-trees.
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
-public interface TransactionManager
+public interface TransactionManager<K, V>
{
/**
* Starts a transaction
@@ -43,21 +44,21 @@ public interface TransactionManager
* Rollback a transaction
*/
void rollback();
-
-
+
+
/**
* Gets the current BtreeHeader for a given BTree.
*
* @param btreeName The Btree name we are looking the BtreeHeader for
* @return the current BTreeHeader
*/
- BTreeHeader<?, ?> getBTreeHeader( String btreeName );
-
-
+ BTreeHeader<K, V> getBTreeHeader( String btreeName );
+
+
/**
* Updates the map of new BTreeHeaders
*
* @param btreeHeader The new BtreeHeader
*/
- void updateNewBTreeHeaders( BTreeHeader<?, ?> btreeHeader );
+ void updateNewBTreeHeaders( BTreeHeader<K, V> btreeHeader );
}