1/*-
2 * See the file LICENSE for redistribution information.
3 *
4 * Copyright (c) 2002,2008 Oracle.  All rights reserved.
5 *
6 * $Id: EntityIndex.java,v 1.2 2008/04/28 23:11:22 sarette Exp $
7 */
8
9package com.sleepycat.persist;
10
11import java.util.Map;
12import java.util.SortedMap;
13
14import com.sleepycat.collections.StoredMap;
15import com.sleepycat.collections.StoredSortedMap;
16import com.sleepycat.db.CursorConfig;
17import com.sleepycat.db.Database;
18import com.sleepycat.db.DatabaseEntry;
19import com.sleepycat.db.DatabaseException;
20import com.sleepycat.db.Environment;
21import com.sleepycat.db.EnvironmentConfig;
22import com.sleepycat.db.LockMode;
23import com.sleepycat.db.SecondaryDatabase;
24import com.sleepycat.db.Transaction;
25
26/**
27 * The interface for accessing keys and entities via a primary or secondary
28 * index.
29 *
30 * <p>{@code EntityIndex} objects are thread-safe.  Multiple threads may safely
31 * call the methods of a shared {@code EntityIndex} object.</p>
32 *
33 * <p>An index is conceptually a <em>map</em>. {key:value} mappings are
34 * stored in the index and accessed by key.  In fact, for interoperability with
35 * other libraries that use the standard Java {@link Map} or {@link SortedMap}
36 * interfaces, an {@code EntityIndex} may be accessed via these standard
37 * interfaces by calling the {@link #map} or {@link #sortedMap} methods.</p>
38 *
39 * <p>{@code EntityIndex} is an interface that is implemented by several
40 * classes in this package for different purposes.  Depending on the context,
41 * the key type (K) and value type (V) of the index take on different meanings.
42 * The different classes that implement {@code EntityIndex} are:</p>
43 * <ul>
44 * <li>{@link PrimaryIndex} maps primary keys to entities.</li>
45 * <li>{@link SecondaryIndex} maps secondary keys to entities.</li>
46 * <li>{@link SecondaryIndex#keysIndex} maps secondary keys to primary
47 * keys.</li>
48 * <li>{@link SecondaryIndex#subIndex} maps primary keys to entities, for the
49 * subset of entities having a specified secondary key.</li>
50 * </ul>
51 *
52 * <p>In all cases, the index key type (K) is a primary or secondary key class.
53 * The index value type (V) is an entity class in all cases except for a {@link
54 * SecondaryIndex#keysIndex}, when it is a primary key class.</p>
55 *
56 * <p>In the following example, a {@code Employee} entity with a {@code
57 * MANY_TO_ONE} secondary key is defined.</p>
58 *
59 * <pre class="code">
60 * {@literal @Entity}
61 * class Employee {
62 *
63 *     {@literal @PrimaryKey}
64 *     long id;
65 *
66 *     {@literal @SecondaryKey(relate=MANY_TO_ONE)}
67 *     String department;
68 *
69 *     String name;
70 *
71 *     private Employee() {}
72 * }</pre>
73 *
74 * <p>Consider that we have stored the entities below:</p>
75 *
76 * <p><table class="code" border="1">
77 *   <tr><th colspan="3">Entities</th></tr>
78 *   <tr><th>ID</th><th>Department</th><th>Name</th></tr>
79 *   <tr><td>1</td><td>Engineering</td><td>Jane Smith</td></tr>
80 *   <tr><td>2</td><td>Sales</td><td>Joan Smith</td></tr>
81 *   <tr><td>3</td><td>Engineering</td><td>John Smith</td></tr>
82 *   <tr><td>4</td><td>Sales</td><td>Jim Smith</td></tr>
83 * </table></p>
84*
85 * <p>{@link PrimaryIndex} maps primary keys to entities:</p>
86 *
87 * <pre class="code">
88 * {@code PrimaryIndex<Long,Employee>} primaryIndex =
89 *     store.getPrimaryIndex(Long.class, Employee.class);</pre>
90 *
91 * <p><table class="code" border="1">
92 *   <tr><th colspan="4">primaryIndex</th></tr>
93 *   <tr><th>Primary Key</th><th colspan="3">Entity</th></tr>
94 *   <tr><td>1</td><td>1</td><td>Engineering</td><td>Jane Smith</td></tr>
95 *   <tr><td>2</td><td>2</td><td>Sales</td><td>Joan Smith</td></tr>
96 *   <tr><td>3</td><td>3</td><td>Engineering</td><td>John Smith</td></tr>
97 *   <tr><td>4</td><td>4</td><td>Sales</td><td>Jim Smith</td></tr>
98 * </table></p>
99 *
100 * <p>{@link SecondaryIndex} maps secondary keys to entities:</p>
101 *
102 * <pre class="code">
103 * {@code SecondaryIndex<String,Long,Employee>} secondaryIndex =
104 *     store.getSecondaryIndex(primaryIndex, String.class, "department");</pre>
105 *
106 * <p><table class="code" border="1">
107 *   <tr><th colspan="4">secondaryIndex</th></tr>
108 *   <tr><th>Secondary Key</th><th colspan="3">Entity</th></tr>
109 *   <tr><td>Engineering</td><td>1</td><td>Engineering</td><td>Jane Smith</td></tr>
110 *   <tr><td>Engineering</td><td>3</td><td>Engineering</td><td>John Smith</td></tr>
111 *   <tr><td>Sales</td><td>2</td><td>Sales</td><td>Joan Smith</td></tr>
112 *   <tr><td>Sales</td><td>4</td><td>Sales</td><td>Jim Smith</td></tr>
113 * </table></p>
114 *
115 * <p>{@link SecondaryIndex#keysIndex} maps secondary keys to primary
116 * keys:</p>
117 *
118 * <pre class="code">
119 * {@code EntityIndex<String,Long>} keysIndex = secondaryIndex.keysIndex();</pre>
120 *
121 * <p><table class="code" border="1">
122 *   <tr><th colspan="4">keysIndex</th></tr>
123 *   <tr><th>Secondary Key</th><th colspan="3">Primary Key</th></tr>
124 *   <tr><td>Engineering</td><td>1</td></tr>
125 *   <tr><td>Engineering</td><td>3</td></tr>
126 *   <tr><td>Sales</td><td>2</td></tr>
127 *   <tr><td>Sales</td><td>4</td></tr>
128 * </table></p>
129 *
130 * <p>{@link SecondaryIndex#subIndex} maps primary keys to entities, for the
131 * subset of entities having a specified secondary key:</p>
132 *
133 * <pre class="code">
134 * {@code EntityIndex<Long,Entity>} subIndex = secondaryIndex.subIndex("Engineering");</pre>
135 *
136 * <p><table class="code" border="1">
137 *   <tr><th colspan="4">subIndex</th></tr>
138 *   <tr><th>Primary Key</th><th colspan="3">Entity</th></tr>
139 *   <tr><td>1</td><td>1</td><td>Engineering</td><td>Jane Smith</td></tr>
140 *   <tr><td>3</td><td>3</td><td>Engineering</td><td>John Smith</td></tr>
141 * </table></p>
142 *
143 * <h3>Accessing the Index</h3>
144 *
145 * <p>An {@code EntityIndex} provides a variety of methods for retrieving
146 * entities from an index.  It also provides methods for deleting entities.
147 * However, it does not provide methods for inserting and updating.  To insert
148 * and update entities, use the {@link PrimaryIndex#put} family of methods in
149 * the {@link PrimaryIndex} class.</p>
150 *
151 * <p>An {@code EntityIndex} supports two mechanisms for retrieving
152 * entities:</p>
153 * <ol>
154 * <li>The {@link #get} method returns a single value for a given key.  If there
155 * are multiple values with the same secondary key (duplicates), it returns the
156 * first entity in the duplicate set.</li>
157 * <li>An {@link EntityCursor} can be obtained using the {@link #keys} and
158 * {@link #entities} family of methods.  A cursor can be used to return all
159 * values in the index, including duplicates.  A cursor can also be used to
160 * return values within a specified range of keys.</li>
161 * </ol>
162 *
163 * <p>Using the example entities above, calling {@link #get} on the primary
164 * index will always return the employee with the given ID, or null if no such
165 * ID exists.  But calling {@link #get} on the secondary index will retrieve
166 * the first employee in the given department, which may not be very
167 * useful:</p>
168 *
169 * <pre class="code">
170 * Employee emp = primaryIndex.get(1);      // Returns by unique ID
171 * emp = secondaryIndex.get("Engineering"); // Returns first in department</pre>
172 *
173 * <p>Using a cursor, you can iterate through all duplicates in the secondary
174 * index:</p>
175 *
176 * <pre class="code">
177 * {@code EntityCursor<Employee>} cursor = secondaryIndex.entities();
178 * try {
179 *     for (Employee entity : cursor) {
180 *         if (entity.department.equals("Engineering")) {
181 *             // Do something with the entity...
182 *         }
183 *     }
184 * } finally {
185 *     cursor.close();
186 * }</pre>
187 *
188 * <p>But for a large database it is much more efficient to iterate over only
189 * those entities with the secondary key you're searching for.  This could be
190 * done by restricting a cursor to a range of keys:</p>
191 *
192 * <pre class="code">
193 * {@code EntityCursor<Employee>} cursor =
194 *     secondaryIndex.entities("Engineering", true, "Engineering", true);
195 * try {
196 *     for (Employee entity : cursor) {
197 *         // Do something with the entity...
198 *     }
199 * } finally {
200 *     cursor.close();
201 * }</pre>
202 *
203 * <p>However, when you are interested only in the entities with a particular
204 * secondary key value, it is more convenient to use a sub-index:</p>
205 *
206 * <pre class="code">
207 * {@code EntityIndex<Long,Entity>} subIndex = secondaryIndex.subIndex("Engineering");
208 * {@code EntityCursor<Employee>} cursor = subIndex.entities();
209 * try {
210 *     for (Employee entity : cursor) {
211 *         // Do something with the entity...
212 *     }
213 * } finally {
214 *     cursor.close();
215 * }</pre>
216 *
217 * <p>In addition to being more convenient than a cursor range, a sub-index
218 * allows retrieving by primary key:</p>
219 *
220 * <pre class="code">
221 * Employee emp = subIndex.get(1);</pre>
222 *
223 * <p>When using a sub-index, all operations performed on the sub-index are
224 * restricted to the single key that was specified when the sub-index was
225 * created.  For example, the following returns null because employee 2 is not
226 * in the Engineering department and therefore is not part of the
227 * sub-index:</p>
228 *
229 * <pre class="code">
230 * Employee emp = subIndex.get(2);</pre>
231 *
232 * <p>For more information on using cursors and cursor ranges, see {@link
233 * EntityCursor}.</p>
234 *
235 * <p>Note that when using an index, keys and values are stored and retrieved
236 * by value not by reference.  In other words, if an entity object is stored
237 * and then retrieved, or retrieved twice, each object will be a separate
238 * instance.  For example, in the code below the assertion will always
239 * fail.</p>
240 * <pre class="code">
241 * MyKey key = ...;
242 * MyEntity entity1 = index.get(key);
243 * MyEntity entity2 = index.get(key);
244 * assert entity1 == entity2; // always fails!
245 * </pre>
246 *
247 * <h3>Deleting from the Index</h3>
248 *
249 * <p>Any type of index may be used to delete entities with a specified key by
250 * calling {@link #delete}.  The important thing to keep in mind is that
251 * <em>all entities</em> with the specified key are deleted.  In a primary index,
252 * at most a single entity is deleted:</p>
253 *
254 * <pre class="code">
255 * primaryIndex.delete(1); // Deletes a single employee by unique ID</pre>
256 *
257 * <p>But in a secondary index, multiple entities may be deleted:</p>
258 *
259 * <pre class="code">
260 * secondaryIndex.delete("Engineering"); // Deletes all Engineering employees</pre>
261 *
262 * <p>This begs this question: How can a single entity be deleted without
263 * knowing its primary key?  The answer is to use cursors.  After locating an
264 * entity using a cursor, the entity can be deleted by calling {@link
265 * EntityCursor#delete}.</p>
266 *
267 * <h3>Transactions</h3>
268 *
269 * <p>Transactions can be used to provide standard ACID (Atomicity,
270 * Consistency, Integrity and Durability) guarantees when retrieving, storing
271 * and deleting entities.  This section provides a brief overview of how to use
272 * transactions with the Direct Persistence Layer.  For more information on
273 * using transactions, see <a
274 * href="{@docRoot}/../gsg_txn/JAVA/index.html">Writing
275 * Transactional Applications</a>.</p>
276 *
277 * <p>Transactions may be used only with a transactional {@link EntityStore},
278 * which is one for which {@link StoreConfig#setTransactional
279 * StoreConfig.setTransactional(true)} has been called.  Likewise, a
280 * transactional store may only be used with a transactional {@link
281 * Environment}, which is one for which {@link
282 * EnvironmentConfig#setTransactional EnvironmentConfig.setTransactional(true)}
283 * has been called.  For example:</p>
284 *
285 * <pre class="code">
286 * EnvironmentConfig envConfig = new EnvironmentConfig();
287 * envConfig.setTransactional(true);
288 * envConfig.setAllowCreate(true);
289 * Environment env = new Environment(new File("/my/data"), envConfig);
290 *
291 * StoreConfig storeConfig = new StoreConfig();
292 * storeConfig.setTransactional(true);
293 * storeConfig.setAllowCreate(true);
294 * EntityStore store = new EntityStore(env, "myStore", storeConfig);</pre>
295 *
296 * <p>Transactions are represented by {@link Transaction} objects, which are
297 * part of the {@link com.sleepycat.db Base API}.  Transactions are created
298 * using the {@link Environment#beginTransaction Environment.beginTransaction}
299 * method.</p>
300 *
301 * <p>A transaction will include all operations for which the transaction
302 * object is passed as a method argument.  All retrieval, storage and deletion
303 * methods have an optional {@link Transaction} parameter for this purpose.
304 * When a transaction is passed to a method that opens a cursor, all retrieval,
305 * storage and deletion operations performed using that cursor will be included
306 * in the transaction.</p>
307 *
308 * <p>A transaction may be committed by calling {@link Transaction#commit} or
309 * aborted by calling {@link Transaction#abort}.  For example, two employees
310 * may be deleted atomically with a transaction; other words, either both are
311 * deleted or neither is deleted:</p>
312 *
313 * <pre class="code">
314 * Transaction txn = env.beginTransaction(null, null);
315 * try {
316 *     primaryIndex.delete(txn, 1);
317 *     primaryIndex.delete(txn, 2);
318 *     txn.commit();
319 *     txn = null;
320 * } finally {
321 *     if (txn != null) {
322 *         txn.abort();
323 *     }
324 * }</pre>
325 *
326 * <p><em>WARNING:</em> Transactions must always be committed or aborted to
327 * prevent resource leaks which could lead to the index becoming unusable or
328 * cause an <code>OutOfMemoryError</code>.  To ensure that a transaction is
329 * aborted in the face of exceptions, call {@link Transaction#abort} in a
330 * finally block.</p>
331 *
332 * <p>For a transactional store, storage and deletion operations are always
333 * transaction protected, whether or not a transaction is explicitly used.  A
334 * null transaction argument means to perform the operation using auto-commit,
335 * or the implied thread transaction if an XAEnvironment is being used.  A
336 * transaction is automatically started as part of the operation and is
337 * automatically committed if the operation completes successfully.  The
338 * transaction is automatically aborted if an exception occurs during the
339 * operation, and the exception is re-thrown to the caller.  For example, each
340 * employee is deleted using a an auto-commit transaction below, but it is
341 * possible that employee 1 will be deleted and employee 2 will not be deleted,
342 * if an error or crash occurs while deleting employee 2:</p>
343 *
344 * <pre class="code">
345 * primaryIndex.delete(null, 1);
346 * primaryIndex.delete(null, 2);</pre>
347 *
348 * <p>When retrieving entities, a null transaction argument means to perform
349 * the operation non-transactionally.  The operation is performed outside the
350 * scope of any transaction, without providing transactional ACID guarantees.
351 * If an implied thread transaction is present (i.e. if an XAEnvironment is
352 * being used), that transaction is used.  When a non-transactional store is
353 * used, transactional ACID guarantees are also not provided.</p>
354 *
355 * <p>For non-transactional and auto-commit usage, overloaded signatures for
356 * retrieval, storage and deletion methods are provided to avoid having to pass
357 * a null transaction argument.  For example, {@link #delete} may be called
358 * instead of {@link #delete(Transaction,Object)}.  For example, the following
359 * code is equivalent to the code above where null was passed for the
360 * transaction:</p>
361 *
362 * <pre class="code">
363 * primaryIndex.delete(1);
364 * primaryIndex.delete(2);</pre>
365 *
366 * <p>For retrieval methods the overloaded signatures also include an optional
367 * {@link LockMode} parameter, and overloaded signatures for opening cursors
368 * include an optional {@link CursorConfig} parameter.  These parameters are
369 * described further below in the Locking and Lock Modes section.</p>
370 *
371 * <h3>Transactions and Cursors</h3>
372 *
373 * <p>There are two special consideration when using cursors with transactions.
374 * First, for a transactional store, a non-null transaction must be passed to
375 * methods that open a cursor if that cursor will be used to delete or update
376 * entities.  Cursors do not perform auto-commit when a null transaction is
377 * explicitly passed or implied by the method signature.  For example, the
378 * following code will throw {@link DatabaseException} when the {@link
379 * EntityCursor#delete} method is called:</p>
380 *
381 * <pre class="code">
382 * // <strong>Does not work with a transactional store!</strong>
383 * {@code EntityCursor<Employee>} cursor = primaryIndex.entities();
384 * try {
385 *     for (Employee entity : cursor) {
386 *         cursor.delete(); // <strong>Will throw DatabaseException.</strong>
387 *     }
388 * } finally {
389 *     cursor.close();
390 * }</pre>
391 *
392 * <p>Instead, the {@link #entities(Transaction,CursorConfig)} signature must
393 * be used and a non-null transaction must be passed:</p>
394 *
395 * <pre class="code">
396 * {@code EntityCursor<Employee>} cursor = primaryIndex.entities(txn, null);
397 * try {
398 *     for (Employee entity : cursor) {
399 *         cursor.delete();
400 *     }
401 * } finally {
402 *     cursor.close();
403 * }</pre>
404 *
405 * <p>The second consideration is that error handling is more complex when
406 * using both transactions and cursors, for the following reasons:</p>
407 * <ol>
408 * <li>When an exception occurs, the transaction should be aborted.</li>
409 * <li>Cursors must be closed whether or not an exception occurs.</li>
410 * <li>Cursors must be closed before committing or aborting the
411 * transaction.</li>
412 * </ol>
413 *
414 * <p>For example:</p>
415 *
416 * <pre class="code">
417 * Transaction txn = env.beginTransaction(null, null);
418 * {@code EntityCursor<Employee>} cursor = null;
419 * try {
420 *     cursor = primaryIndex.entities(txn, null);
421 *     for (Employee entity : cursor) {
422 *         cursor.delete();
423 *     }
424 *     cursor.close();
425 *     cursor = null;
426 *     txn.commit();
427 *     txn = null;
428 * } finally {
429 *     if (cursor != null) {
430 *         cursor.close();
431 *     }
432 *     if (txn != null) {
433 *         txn.abort();
434 *     }
435 * }</pre>
436 *
437 * <h3>Locking and Lock Modes</h3>
438 *
439 * <p>This section provides a brief overview of locking and describes how lock
440 * modes are used with the Direct Persistence Layer.  For more information on
441 * locking, see <a
442 * href="{@docRoot}/../gsg_txn/JAVA/index.html">Writing
443 * Transactional Applications</a>.</p>
444 *
445 * <p>When using transactions, locks are normally acquired on each entity that
446 * is retrieved or stored.  The locks are used to isolate one transaction from
447 * another.  Locks are normally released only when the transaction is committed
448 * or aborted.</p>
449 *
450 * <p>When not using transactions, locks are also normally acquired on each
451 * entity that is retrieved or stored.  However, these locks are released when
452 * the operation is complete.  When using cursors, in order to provide
453 * <em>cursor stability</em> locks are held until the cursor is moved to a
454 * different entity or closed.</p>
455 *
456 * <p>This default locking behavior provides full transactional ACID guarantees
457 * and cursor stability.  However, application performance can sometimes be
458 * improved by compromising these guarantees.  As described in <a
459 * href="{@docRoot}/../gsg_txn/JAVA/index.html">Writing
460 * Transactional Applications</a>, the {@link LockMode} and {@link
461 * CursorConfig} parameters are two of the mechanisms that can be used to make
462 * compromises.</p>
463 *
464 * <p>For example, imagine that you need an approximate count of all entities
465 * matching certain criterion, and it is acceptable for entities to be changed
466 * by other threads or other transactions while performing this query.  {@link
467 * LockMode#READ_UNCOMMITTED} can be used to perform the retrievals without
468 * acquiring any locks.  This reduces memory consumption, does less processing,
469 * and can improve concurrency.</p>
470 *
471 * <pre class="code">
472 * {@code EntityCursor<Employee>} cursor = primaryIndex.entities(txn, null);
473 * try {
474 *     Employee entity;
475 *     while ((entity = cursor.next(LockMode.READ_UNCOMMITTED)) != null) {
476 *         // Examine the entity and accumulate totals...
477 *     }
478 * } finally {
479 *     cursor.close();
480 * }</pre>
481 *
482 * <p>The {@link LockMode} parameter specifies locking behavior on a
483 * per-operation basis.  If null or {@link LockMode#DEFAULT} is specified, the
484 * default lock mode is used.</p>
485 *
486 * <p>It is also possible to specify the default locking behavior for a cursor
487 * using {@link CursorConfig}.  The example below is equivalent to the example
488 * above:</p>
489 *
490 * <pre class="code">
491 * CursorConfig config = new CursorConfig();
492 * config.setReadUncommitted(true);
493 * {@code EntityCursor<Employee>} cursor = primaryIndex.entities(txn, config);
494 * try {
495 *     Employee entity;
496 *     while ((entity = cursor.next()) != null) {
497 *         // Examine the entity and accumulate totals...
498 *     }
499 * } finally {
500 *     cursor.close();
501 * }</pre>
502 *
503 * <p>The use of other lock modes, cursor configuration, and transaction
504 * configuration are discussed in <a
505 * href="{@docRoot}/../gsg_txn/JAVA/index.html">Writing
506 * Transactional Applications</a>.</p>
507 *
508 * <p>Deadlock handling is another important topic discussed in <a
509 * href="{@docRoot}/../gsg_txn/JAVA/index.html">Writing
510 * Transactional Applications</a>.  To go along with that material, here we
511 * show a deadlock handling loop in the context of the Direct Persistence
512 * Layer.  The example below shows deleting all entities in a primary index in
513 * a single transaction.  If a deadlock occurs, the transaction is aborted and
514 * the operation is retried.</p>
515 *
516 * <pre class="code">
517 * int retryCount = 0;
518 * boolean retry = true;
519 * while (retry) {
520 *     Transaction txn = env.beginTransaction(null, null);
521 *     {@code EntityCursor<Employee>} cursor = null;
522 *     try {
523 *         cursor = primaryIndex.entities(txn, null);
524 *         for (Employee entity : cursor) {
525 *             cursor.delete();
526 *         }
527 *         cursor.close();
528 *         cursor = null;
529 *         txn.commit();
530 *         txn = null;
531 *         retry = false;
532 *     } catch (DeadlockException e) {
533 *         retryCount += 1;
534 *         if (retryCount &gt;= MAX_DEADLOCK_RETRIES) {
535 *             throw e;
536 *         }
537 *     } finally {
538 *         if (cursor != null) {
539 *             cursor.close();
540 *         }
541 *         if (txn != null) {
542 *             txn.abort();
543 *         }
544 *     }
545 *  }</pre>
546 *
547 * <h3>Low Level Access</h3>
548 *
549 * <p>Each Direct Persistence Layer index is associated with an underlying
550 * {@link Database} or {@link SecondaryDatabase} defined in the {@link
551 * com.sleepycat.db Base API}.  At this level, an index is a Btree managed by
552 * the Berkeley DB Java Edition transactional storage engine.  Although you may
553 * never need to work at the {@code Base API} level, keep in mind that some
554 * types of performance tuning can be done by configuring the underlying
555 * databases.  See the {@link EntityStore} class for more information on
556 * database and sequence configuration.</p>
557 *
558 * <p>If you wish to access an index using the {@code Base API}, you may call
559 * the {@link PrimaryIndex#getDatabase} or {@link SecondaryIndex#getDatabase}
560 * method to get the underlying database.  To translate between entity or key
561 * objects and {@link DatabaseEntry} objects at this level, use the bindings
562 * returned by {@link PrimaryIndex#getEntityBinding}, {@link
563 * PrimaryIndex#getKeyBinding}, and {@link SecondaryIndex#getKeyBinding}.</p>
564 *
565 * @author Mark Hayes
566 */
567public interface EntityIndex<K,V> {
568
569    /**
570     * Checks for existence of a key in this index.
571     *
572     * <p>The operation will not be transaction protected, and {@link
573     * LockMode#DEFAULT} is used implicitly.</p>
574     *
575     * @param key the key to search for.
576     *
577     * @return whether the key exists in the index.
578     */
579    boolean contains(K key)
580        throws DatabaseException;
581
582    /**
583     * Checks for existence of a key in this index.
584     *
585     * @param txn the transaction used to protect this operation, or null
586     * if the operation should not be transaction protected.
587     *
588     * @param key the key to search for.
589     *
590     * @param lockMode the lock mode to use for this operation, or null to
591     * use {@link LockMode#DEFAULT}.
592     *
593     * @return whether the key exists in the index.
594     */
595    boolean contains(Transaction txn, K key, LockMode lockMode)
596        throws DatabaseException;
597
598    /**
599     * Gets an entity via a key of this index.
600     *
601     * <p>The operation will not be transaction protected, and {@link
602     * LockMode#DEFAULT} is used implicitly.</p>
603     *
604     * @param key the key to search for.
605     *
606     * @return the value mapped to the given key, or null if the key is not
607     * present in the index.
608     */
609    V get(K key)
610        throws DatabaseException;
611
612    /**
613     * Gets an entity via a key of this index.
614     *
615     * @param txn the transaction used to protect this operation, or null
616     * if the operation should not be transaction protected.
617     *
618     * @param key the key to search for.
619     *
620     * @param lockMode the lock mode to use for this operation, or null to
621     * use {@link LockMode#DEFAULT}.
622     *
623     * @return the value mapped to the given key, or null if the key is not
624     * present in the index.
625     */
626    V get(Transaction txn, K key, LockMode lockMode)
627        throws DatabaseException;
628
629    /**
630     * Returns a non-transactional count of the entities in this index.
631     *
632     * <p>This operation is faster than obtaining a count by scanning the index
633     * manually, and will not perturb the current contents of the cache.
634     * However, the count is not guaranteed to be accurate if there are
635     * concurrent updates.</p>
636     *
637     * @return the number of entities in this index.
638     */
639    long count()
640        throws DatabaseException;
641
642    /**
643     * Deletes all entities with a given index key.
644     *
645     * <p>Auto-commit is used implicitly if the store is transactional.</p>
646     *
647     * @param key the key to search for.
648     *
649     * @return whether any entities were deleted.
650     */
651    boolean delete(K key)
652        throws DatabaseException;
653
654    /**
655     * Deletes all entities with a given index key.
656     *
657     * @param txn the transaction used to protect this operation, null to use
658     * auto-commit, or null if the store is non-transactional.
659     *
660     * @param key the key to search for.
661     *
662     * @return whether any entities were deleted.
663     */
664    boolean delete(Transaction txn, K key)
665        throws DatabaseException;
666
667    /**
668     * Opens a cursor for traversing all keys in this index.
669     *
670     * <p>The operations performed with the cursor will not be transaction
671     * protected, and {@link CursorConfig#DEFAULT} is used implicitly.  If the
672     * store is transactional, the cursor may not be used to update or delete
673     * entities.</p>
674     *
675     * @return the cursor.
676     */
677    EntityCursor<K> keys()
678        throws DatabaseException;
679
680    /**
681     * Opens a cursor for traversing all keys in this index.
682     *
683     * @param txn the transaction used to protect all operations performed with
684     * the cursor, or null if the operations should not be transaction
685     * protected.  If null is specified and the store is transactional, the
686     * cursor may not be used to update or delete entities.
687     *
688     * @param config the cursor configuration that determines the default lock
689     * mode used for all cursor operations, or null to implicitly use {@link
690     * CursorConfig#DEFAULT}.
691     *
692     * @return the cursor.
693     */
694    EntityCursor<K> keys(Transaction txn, CursorConfig config)
695        throws DatabaseException;
696
697    /**
698     * Opens a cursor for traversing all entities in this index.
699     *
700     * <p>The operations performed with the cursor will not be transaction
701     * protected, and {@link CursorConfig#DEFAULT} is used implicitly.  If the
702     * store is transactional, the cursor may not be used to update or delete
703     * entities.</p>
704     *
705     * @return the cursor.
706     */
707    EntityCursor<V> entities()
708        throws DatabaseException;
709
710    /**
711     * Opens a cursor for traversing all entities in this index.
712     *
713     * @param txn the transaction used to protect all operations performed with
714     * the cursor, or null if the operations should not be transaction
715     * protected.  If null is specified and the store is transactional, the
716     * cursor may not be used to update or delete entities.
717     *
718     * @param config the cursor configuration that determines the default lock
719     * mode used for all cursor operations, or null to implicitly use {@link
720     * CursorConfig#DEFAULT}.
721     *
722     * @return the cursor.
723     */
724    EntityCursor<V> entities(Transaction txn,
725                             CursorConfig config)
726        throws DatabaseException;
727
728    /**
729     * Opens a cursor for traversing keys in a key range.
730     *
731     * <p>The operations performed with the cursor will not be transaction
732     * protected, and {@link CursorConfig#DEFAULT} is used implicitly.  If the
733     * store is transactional, the cursor may not be used to update or delete
734     * entities.</p>
735     *
736     * @param fromKey is the lower bound of the key range, or null if the range
737     * has no lower bound.
738     *
739     * @param fromInclusive is true if keys greater than or equal to fromKey
740     * should be included in the key range, or false if only keys greater than
741     * fromKey should be included.
742     *
743     * @param toKey is the upper bound of the key range, or null if the range
744     * has no upper bound.
745     *
746     * @param toInclusive is true if keys less than or equal to toKey should be
747     * included in the key range, or false if only keys less than toKey should
748     * be included.
749     *
750     * @return the cursor.
751     */
752    EntityCursor<K> keys(K fromKey,
753                         boolean fromInclusive,
754                         K toKey,
755                         boolean toInclusive)
756        throws DatabaseException;
757
758    /**
759     * Opens a cursor for traversing keys in a key range.
760     *
761     * @param txn the transaction used to protect all operations performed with
762     * the cursor, or null if the operations should not be transaction
763     * protected.  If null is specified and the store is transactional, the
764     * cursor may not be used to update or delete entities.
765     *
766     * @param fromKey is the lower bound of the key range, or null if the range
767     * has no lower bound.
768     *
769     * @param fromInclusive is true if keys greater than or equal to fromKey
770     * should be included in the key range, or false if only keys greater than
771     * fromKey should be included.
772     *
773     * @param toKey is the upper bound of the key range, or null if the range
774     * has no upper bound.
775     *
776     * @param toInclusive is true if keys less than or equal to toKey should be
777     * included in the key range, or false if only keys less than toKey should
778     * be included.
779     *
780     * @param config the cursor configuration that determines the default lock
781     * mode used for all cursor operations, or null to implicitly use {@link
782     * CursorConfig#DEFAULT}.
783     *
784     * @return the cursor.
785     */
786    EntityCursor<K> keys(Transaction txn,
787                         K fromKey,
788                         boolean fromInclusive,
789                         K toKey,
790                         boolean toInclusive,
791                         CursorConfig config)
792        throws DatabaseException;
793
794    /**
795     * Opens a cursor for traversing entities in a key range.
796     *
797     * <p>The operations performed with the cursor will not be transaction
798     * protected, and {@link CursorConfig#DEFAULT} is used implicitly.  If the
799     * store is transactional, the cursor may not be used to update or delete
800     * entities.</p>
801     *
802     * @param fromKey is the lower bound of the key range, or null if the range
803     * has no lower bound.
804     *
805     * @param fromInclusive is true if keys greater than or equal to fromKey
806     * should be included in the key range, or false if only keys greater than
807     * fromKey should be included.
808     *
809     * @param toKey is the upper bound of the key range, or null if the range
810     * has no upper bound.
811     *
812     * @param toInclusive is true if keys less than or equal to toKey should be
813     * included in the key range, or false if only keys less than toKey should
814     * be included.
815     *
816     * @return the cursor.
817     */
818    EntityCursor<V> entities(K fromKey,
819                             boolean fromInclusive,
820                             K toKey,
821                             boolean toInclusive)
822        throws DatabaseException;
823
824    /**
825     * Opens a cursor for traversing entities in a key range.
826     *
827     * @param txn the transaction used to protect all operations performed with
828     * the cursor, or null if the operations should not be transaction
829     * protected.  If null is specified and the store is transactional, the
830     * cursor may not be used to update or delete entities.
831     *
832     * @param fromKey is the lower bound of the key range, or null if the range
833     * has no lower bound.
834     *
835     * @param fromInclusive is true if keys greater than or equal to fromKey
836     * should be included in the key range, or false if only keys greater than
837     * fromKey should be included.
838     *
839     * @param toKey is the upper bound of the key range, or null if the range
840     * has no upper bound.
841     *
842     * @param toInclusive is true if keys less than or equal to toKey should be
843     * included in the key range, or false if only keys less than toKey should
844     * be included.
845     *
846     * @param config the cursor configuration that determines the default lock
847     * mode used for all cursor operations, or null to implicitly use {@link
848     * CursorConfig#DEFAULT}.
849     *
850     * @return the cursor.
851     */
852    EntityCursor<V> entities(Transaction txn,
853                             K fromKey,
854                             boolean fromInclusive,
855                             K toKey,
856                             boolean toInclusive,
857                             CursorConfig config)
858        throws DatabaseException;
859
860    /*
861     * Opens a cursor for traversing all keys in this index in arbitrary order.
862     *
863     * <p>Normally entities and keys are returned in key order.  This method
864     * takes advantage of optimizations in the Berkeley DB engine to return
865     * entities in physical storage order, potentially decreasing the amount of
866     * physical I/O.</p>
867     *
868     * <p>The operations performed with the cursor will not be transaction
869     * protected, and {@link CursorConfig#DEFAULT} is used implicitly.</p>
870     *
871     * @param selector the filter for selecting keys to be returned, or null
872     * to select all keys.
873     *
874     * @return the cursor.
875     *
876    ForwardCursor<K> unsortedKeys(KeySelector<K> selector)
877        throws DatabaseException;
878     */
879
880    /*
881     * Opens a cursor for traversing all keys in this index in arbitrary order.
882     *
883     * <p>Normally entities and keys are returned in key order.  This method
884     * takes advantage of optimizations in the Berkeley DB engine to return
885     * entities in physical storage order, potentially decreasing the amount of
886     * physical I/O.</p>
887     *
888     * @param txn the transaction used to protect all operations performed with
889     * the cursor, or null if the operations should not be transaction
890     * protected.
891     *
892     * @param selector the filter for selecting keys to be returned, or null
893     * to select all keys.
894     *
895     * @param config the cursor configuration that determines the default lock
896     * mode used for all cursor operations, or null to implicitly use {@link
897     * CursorConfig#DEFAULT}.
898     *
899     * @return the cursor.
900     *
901    ForwardCursor<K> unsortedKeys(Transaction txn,
902                                  KeySelector<K> selector,
903                                  CursorConfig config)
904        throws DatabaseException;
905     */
906
907    /*
908     * Opens a cursor for traversing all entities in this index in arbitrary
909     * order.
910     *
911     * <p>Normally entities and keys are returned in key order.  This method
912     * takes advantage of optimizations in the Berkeley DB engine to return
913     * entities in physical storage order, potentially decreasing the amount of
914     * physical I/O.</p>
915     *
916     * <p>The operations performed with the cursor will not be transaction
917     * protected, and {@link CursorConfig#DEFAULT} is used implicitly.</p>
918
919     * @param selector the filter for selecting keys to be returned, or null
920     * to select all keys.
921     *
922     * @return the cursor.
923     *
924    ForwardCursor<V> unsortedEntities(KeySelector<K> selector)
925        throws DatabaseException;
926     */
927
928    /*
929     * Opens a cursor for traversing all entities in this index in arbitrary
930     * order.
931     *
932     * <p>Normally entities and keys are returned in key order.  This method
933     * takes advantage of optimizations in the Berkeley DB engine to return
934     * entities in physical storage order, potentially decreasing the amount of
935     * physical I/O.</p>
936     *
937     * @param txn the transaction used to protect all operations performed with
938     * the cursor, or null if the operations should not be transaction
939     * protected.
940     *
941     * @param selector the filter for selecting keys to be returned, or null
942     * to select all keys.
943     *
944     * @param config the cursor configuration that determines the default lock
945     * mode used for all cursor operations, or null to implicitly use {@link
946     * CursorConfig#DEFAULT}.
947     *
948     * @return the cursor.
949     *
950    ForwardCursor<V> unsortedEntities(Transaction txn,
951                                      KeySelector<K> selector,
952                                      CursorConfig config)
953        throws DatabaseException;
954     */
955
956    /**
957     * Returns a standard Java map based on this entity index.  The {@link
958     * StoredMap} returned is defined by the {@linkplain
959     * com.sleepycat.collections Collections API}.  Stored collections conform
960     * to the standard Java collections framework interface.
961     *
962     * @return the map.
963     */
964    Map<K,V> map();
965
966    /**
967     * Returns a standard Java sorted map based on this entity index.  The
968     * {@link StoredSortedMap} returned is defined by the {@linkplain
969     * com.sleepycat.collections Collections API}.  Stored collections conform
970     * to the standard Java collections framework interface.
971     *
972     * @return the map.
973     */
974    SortedMap<K,V> sortedMap();
975}
976