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}