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.managed; 21 22 23 import java.io.IOException; 24 import java.util.LinkedList; 25 26 import org.apache.directory.mavibot.btree.Tuple; 27 import org.apache.directory.mavibot.btree.ValueCursor; 28 import org.apache.directory.mavibot.btree.exception.EndOfFileExceededException; 29 import org.apache.directory.mavibot.btree.exception.KeyNotFoundException; 30 31 32 /** 33 * A MVCC Page interface. A Page can be either a Leaf (containing keys and values) or a Node 34 * (containing keys and references to child pages).<br/> 35 * A Page can be stored on disk. If so, we store the serialized value of this Page into 36 * one or more {@link PageIO} (they will be linked) 37 * 38 * @param <K> The type for the Key 39 * @param <V> The type for the stored value 40 * 41 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 42 */ 43 /* No qualifier */interface Page<K, V> 44 { 45 /** 46 * @return The number of keys present in this page 47 */ 48 int getNbElems(); 49 50 51 /** 52 * Inserts the given key and value into this page. We first find the place were to 53 * inject the <K,V> into the tree, by recursively browsing the pages :<br/> 54 * <ul> 55 * <li>If the index is below zero, the key is present in the Page : we modify the 56 * value and return</li> 57 * <li>If the page is a node, we have to go down to the right child page</li> 58 * <li>If the page is a leaf, we insert the new <K,V> element into the page, and if 59 * the Page is full, we split it and propagate the new pivot up into the tree</li> 60 * </ul> 61 * <p> 62 * 63 * @param revision The new revision for the modified pages 64 * @param key Inserted key 65 * @param value Inserted value 66 * @return Either a modified Page or an Overflow element if the Page was full 67 * @throws IOException If we have an error while trying to access the page 68 */ 69 InsertResult<K, V> insert( long revision, K key, V value ) throws IOException; 70 71 72 /** 73 * Deletes the value from an entry associated with the given key in this page. We first find 74 * the place were to remove the <K,V> into the tree, by recursively browsing the pages. 75 * If the value is present, it will be deleted first, later if there are no other values associated with 76 * this key(which can happen when duplicates are enabled), we will remove the key from the tree. 77 * 78 * @param revision The new revision for the modified pages 79 * @param key The key to delete 80 * @param value The value to delete (can be null) 81 * @param parent The parent page 82 * @param parentPos The position of the current page in it's parent 83 * @return Either a modified Page if the key has been removed from the page, or a NotPresentResult. 84 * @throws IOException If we have an error while trying to access the page 85 */ 86 DeleteResult<K, V> delete( long revision, K key, V value, Page<K, V> parent, int parentPos ) throws IOException; 87 88 89 /** 90 * Gets the value associated with the given key, if any. If we don't have 91 * one, this method will throw a KeyNotFoundException.<br/> 92 * Note that we may get back null if a null value has been associated 93 * with the key. 94 * 95 * @param key The key we are looking for 96 * @return The associated value, which can be null 97 * @throws KeyNotFoundException If no entry with the given key can be found 98 * @throws IOException If we have an error while trying to access the page 99 */ 100 V get( K key ) throws KeyNotFoundException, IOException; 101 102 103 /** 104 * Gets the values associated with the given key, if any. If we don't have 105 * the key, this method will throw a KeyNotFoundException.<br/> 106 * Note that we may get back null if a null value has been associated 107 * with the key. 108 * 109 * @param key The key we are looking for 110 * @return The associated value, which can be null 111 * @throws KeyNotFoundException If no entry with the given key can be found 112 * @throws IOException If we have an error while trying to access the page 113 * @throws IllegalArgumentException If duplicates are not enabled 114 */ 115 ValueCursor<V> getValues( K key ) throws KeyNotFoundException, IOException, IllegalArgumentException; 116 117 118 /** 119 * Checks if the page contains the given key with the given value. 120 * 121 * @param key The key we are looking for 122 * @param value The value associated with the given key 123 * @return true if the key and value are associated with each other, false otherwise 124 */ 125 boolean contains( K key, V value ) throws IOException; 126 127 128 /** 129 * Browses the tree, looking for the given key, and creates a Cursor on top 130 * of the found result. 131 * 132 * @param key The key we are looking for. 133 * @param transaction The started transaction for this operation 134 * @param stack The stack of parents we go through to get to this page 135 * @return A Cursor to browse the next elements 136 * @throws IOException If we have an error while trying to access the page 137 */ 138 CursorImpl<K, V> browse( K key, Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack ) 139 throws IOException; 140 141 142 /** 143 * Browses the whole tree, and creates a Cursor on top of it. 144 * 145 * @param transaction The started transaction for this operation 146 * @param stack The stack of parents we go through to get to this page 147 * @return A Cursor to browse the next elements 148 * @throws IOException If we have an error while trying to access the page 149 */ 150 CursorImpl<K, V> browse( Transaction<K, V> transaction, LinkedList<ParentPos<K, V>> stack ) 151 throws EndOfFileExceededException, IOException; 152 153 154 /** 155 * @return the revision 156 */ 157 long getRevision(); 158 159 160 /** 161 * Returns the key at a given position 162 * 163 * @param pos The position of the key we want to retrieve 164 * @return The key found at the given position 165 */ 166 K getKey( int pos ); 167 168 169 /** 170 * Finds the leftmost key in this page. If the page is a node, it will go 171 * down in the leftmost children to recursively find the leftmost key. 172 * 173 * @return The leftmost key in the tree 174 * @throws IOException If we have an error while trying to access the page 175 */ 176 K getLeftMostKey() throws IOException; 177 178 179 /** 180 * Finds the rightmost key in this page. If the page is a node, it will go 181 * down in the rightmost children to recursively find the rightmost key. 182 * 183 * @return The rightmost key in the tree 184 * @throws IOException If we have an error while trying to access the page 185 */ 186 K getRightMostKey() throws IOException; 187 188 189 /** 190 * Finds the leftmost element in this page. If the page is a node, it will go 191 * down in the leftmost children to recursively find the leftmost element. 192 * 193 * @return The leftmost element in the tree 194 * @throws IOException If we have an error while trying to access the page 195 */ 196 Tuple<K, V> findLeftMost() throws IOException; 197 198 199 /** 200 * Finds the rightmost element in this page. If the page is a node, it will go 201 * down in the rightmost children to recursively find the rightmost element. 202 * 203 * @return The rightmost element in the tree 204 * @throws IOException If we have an error while trying to access the page 205 */ 206 Tuple<K, V> findRightMost() throws EndOfFileExceededException, IOException; 207 208 209 /** 210 * Pretty-prints the tree with tabs 211 * @param tabs The tabs to add in front of each node 212 * @return A pretty-print dump of the tree 213 */ 214 String dumpPage( String tabs ); 215 216 217 /** 218 * Find the position of the given key in the page. If we have found the key, 219 * we will return its position as a negative value. 220 * <p/> 221 * Assuming that the array is zero-indexed, the returned value will be : <br/> 222 * position = - ( position + 1) 223 * <br/> 224 * So for the following table of keys : <br/> 225 * <pre> 226 * +---+---+---+---+ 227 * | b | d | f | h | 228 * +---+---+---+---+ 229 * 0 1 2 3 230 * </pre> 231 * looking for 'b' will return -1 (-(0+1)) and looking for 'f' will return -3 (-(2+1)).<br/> 232 * Computing the real position is just a matter to get -(position++). 233 * <p/> 234 * If we don't find the key in the table, we will return the position of the key 235 * immediately above the key we are looking for. <br/> 236 * For instance, looking for : 237 * <ul> 238 * <li>'a' will return 0</li> 239 * <li>'b' will return -1</li> 240 * <li>'c' will return 1</li> 241 * <li>'d' will return -2</li> 242 * <li>'e' will return 2</li> 243 * <li>'f' will return -3</li> 244 * <li>'g' will return 3</li> 245 * <li>'h' will return -4</li> 246 * <li>'i' will return 4</li> 247 * </ul> 248 * 249 * 250 * @param key The key to find 251 * @return The position in the page. 252 */ 253 int findPos( K key ); 254 255 256 /** 257 * Checks if the given key exists. 258 * 259 * @param key The key we are looking at 260 * @return true if the key is present, false otherwise 261 * @throws IOException If we have an error while trying to access the page 262 */ 263 boolean hasKey( K key ) throws IOException; 264 265 266 /** 267 * @return the offset of the first {@link PageIO} which stores the Page on disk. 268 */ 269 long getOffset(); 270 271 272 /** 273 * @return the offset of the last {@link PageIO} which stores the Page on disk. 274 */ 275 long getLastOffset(); 276 }