001/*
002 *  Licensed to the Apache Software Foundation (ASF) under one
003 *  or more contributor license agreements.  See the NOTICE file
004 *  distributed with this work for additional information
005 *  regarding copyright ownership.  The ASF licenses this file
006 *  to you under the Apache License, Version 2.0 (the
007 *  "License"); you may not use this file except in compliance
008 *  with the License.  You may obtain a copy of the License at
009 *
010 *    http://www.apache.org/licenses/LICENSE-2.0
011 *
012 *  Unless required by applicable law or agreed to in writing,
013 *  software distributed under the License is distributed on an
014 *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 *  KIND, either express or implied.  See the License for the
016 *  specific language governing permissions and limitations
017 *  under the License.
018 *
019 */
020package org.apache.directory.mavibot.btree;
021
022
023import java.util.Date;
024import java.util.concurrent.ConcurrentLinkedQueue;
025
026
027/**
028 * The Transaction is used to protect the BTree against concurrent modification,
029 * and insure that a read is always done against one single revision. It's also
030 * used to gather many modifications under one single revision, if needed.
031 * <p/>
032 * A Transaction should be closed when the user is done with it, otherwise the
033 * pages associated with the given revision, and all the referenced pages, will
034 * remain on the storage.
035 * <p/>
036 * A Transaction can be hold for quite a long time, for instance while doing
037 * a browse against a big BTree. At some point, transactions which are pending
038 * for too long will be closed by the transaction manager.
039 *
040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
041 *
042 * @param <K> The type for the Key
043 * @param <V> The type for the stored value
044 */
045public class ReadTransaction<K, V>
046{
047    /** The associated revision */
048    private long revision;
049
050    /** The date of creation */
051    private long creationDate;
052
053    /** The associated B-tree header */
054    private BTreeHeader<K, V> btreeHeader;
055
056    /** A flag used to tell if a transaction is closed or not */
057    private volatile boolean closed;
058    
059    /** The list of read transactions being executed */
060    private ConcurrentLinkedQueue<ReadTransaction<K, V>> readTransactions;
061
062    /** The reference to the recordManager, if any */
063    private RecordManager recordManager;
064    
065    /**
066     * Creates a new transaction instance
067     *
068     * @param btreeHeader The BtreeHeader we will use for this read transaction
069     */
070    public ReadTransaction( RecordManager recordManager, BTreeHeader<K, V> btreeHeader, ConcurrentLinkedQueue<ReadTransaction<K, V>> readTransactions )
071    {
072        if ( btreeHeader != null )
073        {
074            this.revision = btreeHeader.getRevision();
075            this.creationDate = System.currentTimeMillis();
076            this.btreeHeader = btreeHeader;
077            this.recordManager = recordManager;
078            closed = false;
079        }
080        
081        this.readTransactions = readTransactions;
082    }
083    
084    
085    /**
086     * Creates a new transaction instance
087     *
088     * @param btreeHeader The BtreeHeader we will use for this read transaction
089     */
090    public ReadTransaction( BTreeHeader<K, V> btreeHeader, ConcurrentLinkedQueue<ReadTransaction<K, V>> readTransactions )
091    {
092        if ( btreeHeader != null )
093        {
094            this.revision = btreeHeader.getRevision();
095            this.creationDate = System.currentTimeMillis();
096            this.btreeHeader = btreeHeader;
097            closed = false;
098        }
099        
100        this.readTransactions = readTransactions;
101    }
102
103
104    /**
105     * @return the associated revision
106     */
107    public long getRevision()
108    {
109        return revision;
110    }
111
112
113    /**
114     * @return the creationDate
115     */
116    public long getCreationDate()
117    {
118        return creationDate;
119    }
120
121
122    /**
123     * @return the btreeHeader
124     */
125    public BTreeHeader<K, V> getBtreeHeader()
126    {
127        return btreeHeader;
128    }
129
130
131    /**
132     * Close the transaction, releasing the revision it was using.
133     */
134    public void close()
135    {
136        closed = true;
137        
138        // Remove the transaction from the list of opened transactions
139        readTransactions.remove( this );
140        
141        // and push the 
142        if ( recordManager != null )
143        {
144            recordManager.releaseTransaction( this );
145        }
146        
147        // Now, get back the copied pages
148    }
149
150
151    /**
152     * @return true if this transaction has been closed
153     */
154    public boolean isClosed()
155    {
156        return closed;
157    }
158
159
160    /**
161     * @see Object#toString()
162     */
163    public String toString()
164    {
165        return "Transaction[" + revision + ":" + new Date( creationDate ) + ", closed :" + closed + "]";
166    }
167}