View Javadoc
1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.directory.mavibot.btree;
21  
22  import java.util.HashMap;
23  import java.util.Map;
24  import java.util.concurrent.locks.Lock;
25  import java.util.concurrent.locks.ReadWriteLock;
26  import java.util.concurrent.locks.ReentrantLock;
27  import java.util.concurrent.locks.ReentrantReadWriteLock;
28  
29  /**
30   * An implementation of a TransactionManager for in-memory B-trees
31   *
32   * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
33   */
34  public class InMemoryTransactionManager extends AbstractTransactionManager
35  {
36      /** A lock to protect the transaction handling */
37      private Lock transactionLock = new ReentrantLock();
38      
39      /** A ThreadLocalStorage used to store the current transaction */
40      private static final ThreadLocal<Integer> context = new ThreadLocal<Integer>();
41      
42      /** A Map keeping the latest revisions for each managed BTree */
43      private Map<String, BTreeHeader<?, ?>> currentBTreeHeaders = new HashMap<String, BTreeHeader<?, ?>>();
44  
45      /** A Map storing the new revisions when some change have been made in some BTrees */
46      private Map<String, BTreeHeader<?, ?>> newBTreeHeaders = new HashMap<String, BTreeHeader<?, ?>>();
47      
48      /** A lock to protect the BtreeHeader maps */
49      private ReadWriteLock btreeHeadersLock = new ReentrantReadWriteLock();
50  
51      /**
52       * {@inheritDoc}
53       */
54      @Override
55      public void beginTransaction()
56      {
57          // First, take the lock
58          transactionLock.lock();
59          
60          // Now, check the TLS state
61          Integer nbTxnLevel = context.get();
62          
63          if ( nbTxnLevel == null )
64          {
65              context.set( 1 );
66          }
67          else
68          {
69              // And increment the counter of inner txn.
70              context.set( nbTxnLevel + 1 );
71          }
72      }
73  
74  
75      /**
76       * {@inheritDoc}
77       */
78      @Override
79      public void commit()
80      {
81          int nbTxnStarted = context.get();
82          
83          if ( nbTxnStarted == 0 )
84          {
85              // The transaction was rollbacked, quit immediatelly
86              transactionLock.unlock();
87              
88              return;
89          }
90          else
91          {
92              
93              // And decrement the number of started transactions
94              context.set( nbTxnStarted - 1 );
95          }
96  
97          // Finally, release the global lock
98          transactionLock.unlock();
99      }
100 
101 
102     /**
103      * {@inheritDoc}
104      */
105     @Override
106     public void rollback()
107     {
108         // Reset the counter
109         context.set( 0 );
110 
111         // Finally, release the global lock
112         transactionLock.unlock();
113     }
114     
115     
116     /**
117      * Get the current BTreeHeader for a given Btree. It might not exist
118      */
119     public BTreeHeader getBTreeHeader( String name )
120     {
121         // Get a lock
122         btreeHeadersLock.readLock().lock();
123         
124         // get the current BTree Header for this BTree and revision
125         BTreeHeader<?, ?> btreeHeader = currentBTreeHeaders.get( name );
126         
127         // And unlock 
128         btreeHeadersLock.readLock().unlock();
129 
130         return btreeHeader;
131     }
132 
133 
134     
135     
136     /**
137      * {@inheritDoc}
138      */
139     public void updateNewBTreeHeaders( BTreeHeader btreeHeader )
140     {
141         newBTreeHeaders.put( btreeHeader.getBtree().getName(), btreeHeader );
142     }
143 }