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