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.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 }