001: /*-
002: * See the file LICENSE for redistribution information.
003: *
004: * Copyright (c) 2002,2008 Oracle. All rights reserved.
005: *
006: * $Id: EntityIndex.java,v 1.16.2.4 2008/01/07 15:14:18 cwl Exp $
007: */
008:
009: package com.sleepycat.persist;
010:
011: import java.util.Map;
012: import java.util.SortedMap;
013:
014: import com.sleepycat.collections.StoredMap;
015: import com.sleepycat.collections.StoredSortedMap;
016: import com.sleepycat.je.CursorConfig;
017: import com.sleepycat.je.Database;
018: import com.sleepycat.je.DatabaseEntry;
019: import com.sleepycat.je.DatabaseException;
020: import com.sleepycat.je.Environment;
021: import com.sleepycat.je.EnvironmentConfig;
022: import com.sleepycat.je.LockMode;
023: import com.sleepycat.je.SecondaryDatabase;
024: import com.sleepycat.je.Transaction;
025:
026: /**
027: * The interface for accessing keys and entities via a primary or secondary
028: * index.
029: *
030: * <p>{@code EntityIndex} objects are thread-safe. Multiple threads may safely
031: * call the methods of a shared {@code EntityIndex} object.</p>
032: *
033: * <p>An index is conceptually a <em>map</em>. {key:value} mappings are
034: * stored in the index and accessed by key. In fact, for interoperability with
035: * other libraries that use the standard Java {@link Map} or {@link SortedMap}
036: * interfaces, an {@code EntityIndex} may be accessed via these standard
037: * interfaces by calling the {@link #map} or {@link #sortedMap} methods.</p>
038: *
039: * <p>{@code EntityIndex} is an interface that is implemented by several
040: * classes in this package for different purposes. Depending on the context,
041: * the key type (K) and value type (V) of the index take on different meanings.
042: * The different classes that implement {@code EntityIndex} are:</p>
043: * <ul>
044: * <li>{@link PrimaryIndex} maps primary keys to entities.</li>
045: * <li>{@link SecondaryIndex} maps secondary keys to entities.</li>
046: * <li>{@link SecondaryIndex#keysIndex} maps secondary keys to primary
047: * keys.</li>
048: * <li>{@link SecondaryIndex#subIndex} maps primary keys to entities, for the
049: * subset of entities having a specified secondary key.</li>
050: * </ul>
051: *
052: * <p>In all cases, the index key type (K) is a primary or secondary key class.
053: * The index value type (V) is an entity class in all cases except for a {@link
054: * SecondaryIndex#keysIndex}, when it is a primary key class.</p>
055: *
056: * <p>In the following example, a {@code Employee} entity with a {@code
057: * MANY_TO_ONE} secondary key is defined.</p>
058: *
059: * <pre class="code">
060: * {@literal @Entity}
061: * class Employee {
062: *
063: * {@literal @PrimaryKey}
064: * long id;
065: *
066: * {@literal @SecondaryKey(relate=MANY_TO_ONE)}
067: * String department;
068: *
069: * String name;
070: *
071: * private Employee() {}
072: * }</pre>
073: *
074: * <p>Consider that we have stored the entities below:</p>
075: *
076: * <p><table class="code" border="1">
077: * <tr><th colspan="3">Entities</th></tr>
078: * <tr><th>ID</th><th>Department</th><th>Name</th></tr>
079: * <tr><td>1</td><td>Engineering</td><td>Jane Smith</td></tr>
080: * <tr><td>2</td><td>Sales</td><td>Joan Smith</td></tr>
081: * <tr><td>3</td><td>Engineering</td><td>John Smith</td></tr>
082: * <tr><td>4</td><td>Sales</td><td>Jim Smith</td></tr>
083: * </table></p>
084: *
085: * <p>{@link PrimaryIndex} maps primary keys to entities:</p>
086: *
087: * <pre class="code">
088: * {@code PrimaryIndex<Long,Employee>} primaryIndex =
089: * store.getPrimaryIndex(Long.class, Employee.class);</pre>
090: *
091: * <p><table class="code" border="1">
092: * <tr><th colspan="4">primaryIndex</th></tr>
093: * <tr><th>Primary Key</th><th colspan="3">Entity</th></tr>
094: * <tr><td>1</td><td>1</td><td>Engineering</td><td>Jane Smith</td></tr>
095: * <tr><td>2</td><td>2</td><td>Sales</td><td>Joan Smith</td></tr>
096: * <tr><td>3</td><td>3</td><td>Engineering</td><td>John Smith</td></tr>
097: * <tr><td>4</td><td>4</td><td>Sales</td><td>Jim Smith</td></tr>
098: * </table></p>
099: *
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} mehod 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 primay 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}/../TransactionGettingStarted/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.je 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}/../TransactionGettingStarted/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}/../TransactionGettingStarted/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}/../TransactionGettingStarted/index.html">Writing
506: * Transactional Applications</a>.</p>
507: *
508: * <p>Deadlock handling is another important topic discussed in <a
509: * href="{@docRoot}/../TransactionGettingStarted/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 >= 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.je 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 underying 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: */
567: public 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) throws DatabaseException;
580:
581: /**
582: * Checks for existence of a key in this index.
583: *
584: * @param txn the transaction used to protect this operation, or null
585: * if the operation should not be transaction protected.
586: *
587: * @param key the key to search for.
588: *
589: * @param lockMode the lock mode to use for this operation, or null to
590: * use {@link LockMode#DEFAULT}.
591: *
592: * @return whether the key exists in the index.
593: */
594: boolean contains(Transaction txn, K key, LockMode lockMode)
595: throws DatabaseException;
596:
597: /**
598: * Gets an entity via a key of this index.
599: *
600: * <p>The operation will not be transaction protected, and {@link
601: * LockMode#DEFAULT} is used implicitly.</p>
602: *
603: * @param key the key to search for.
604: *
605: * @return the value mapped to the given key, or null if the key is not
606: * present in the index.
607: */
608: V get(K key) throws DatabaseException;
609:
610: /**
611: * Gets an entity via a key of this index.
612: *
613: * @param txn the transaction used to protect this operation, or null
614: * if the operation should not be transaction protected.
615: *
616: * @param key the key to search for.
617: *
618: * @param lockMode the lock mode to use for this operation, or null to
619: * use {@link LockMode#DEFAULT}.
620: *
621: * @return the value mapped to the given key, or null if the key is not
622: * present in the index.
623: */
624: V get(Transaction txn, K key, LockMode lockMode)
625: throws DatabaseException;
626:
627: /**
628: * Returns a non-transactional count of the entities in this index.
629: *
630: * <p>This operation is faster than obtaining a count by scanning the index
631: * manually, and will not perturb the current contents of the cache.
632: * However, the count is not guaranteed to be accurate if there are
633: * concurrent updates.</p>
634: *
635: * @return the number of entities in this index.
636: */
637: long count() throws DatabaseException;
638:
639: /**
640: * Deletes all entities with a given index key.
641: *
642: * <p>Auto-commit is used implicitly if the store is transactional.</p>
643: *
644: * @param key the key to search for.
645: *
646: * @return whether any entities were deleted.
647: */
648: boolean delete(K key) throws DatabaseException;
649:
650: /**
651: * Deletes all entities with a given index key.
652: *
653: * @param txn the transaction used to protect this operation, null to use
654: * auto-commit, or null if the store is non-transactional.
655: *
656: * @param key the key to search for.
657: *
658: * @return whether any entities were deleted.
659: */
660: boolean delete(Transaction txn, K key) throws DatabaseException;
661:
662: /**
663: * Opens a cursor for traversing all keys in this index.
664: *
665: * <p>The operations performed with the cursor will not be transaction
666: * protected, and {@link CursorConfig#DEFAULT} is used implicitly. If the
667: * store is transactional, the cursor may not be used to update or delete
668: * entities.</p>
669: *
670: * @return the cursor.
671: */
672: EntityCursor<K> keys() throws DatabaseException;
673:
674: /**
675: * Opens a cursor for traversing all keys in this index.
676: *
677: * @param txn the transaction used to protect all operations performed with
678: * the cursor, or null if the operations should not be transaction
679: * protected. If null is specified and the store is transactional, the
680: * cursor may not be used to update or delete entities.
681: *
682: * @param config the cursor configuration that determines the default lock
683: * mode used for all cursor operations, or null to implicitly use {@link
684: * CursorConfig#DEFAULT}.
685: *
686: * @return the cursor.
687: */
688: EntityCursor<K> keys(Transaction txn, CursorConfig config)
689: throws DatabaseException;
690:
691: /**
692: * Opens a cursor for traversing all entities in this index.
693: *
694: * <p>The operations performed with the cursor will not be transaction
695: * protected, and {@link CursorConfig#DEFAULT} is used implicitly. If the
696: * store is transactional, the cursor may not be used to update or delete
697: * entities.</p>
698: *
699: * @return the cursor.
700: */
701: EntityCursor<V> entities() throws DatabaseException;
702:
703: /**
704: * Opens a cursor for traversing all entities in this index.
705: *
706: * @param txn the transaction used to protect all operations performed with
707: * the cursor, or null if the operations should not be transaction
708: * protected. If null is specified and the store is transactional, the
709: * cursor may not be used to update or delete entities.
710: *
711: * @param config the cursor configuration that determines the default lock
712: * mode used for all cursor operations, or null to implicitly use {@link
713: * CursorConfig#DEFAULT}.
714: *
715: * @return the cursor.
716: */
717: EntityCursor<V> entities(Transaction txn, CursorConfig config)
718: throws DatabaseException;
719:
720: /**
721: * Opens a cursor for traversing keys in a key range.
722: *
723: * <p>The operations performed with the cursor will not be transaction
724: * protected, and {@link CursorConfig#DEFAULT} is used implicitly. If the
725: * store is transactional, the cursor may not be used to update or delete
726: * entities.</p>
727: *
728: * @param fromKey is the lower bound of the key range, or null if the range
729: * has no lower bound.
730: *
731: * @param fromInclusive is true if keys greater than or equal to fromKey
732: * should be included in the key range, or false if only keys greater than
733: * fromKey should be included.
734: *
735: * @param toKey is the upper bound of the key range, or null if the range
736: * has no upper bound.
737: *
738: * @param toInclusive is true if keys less than or equal to toKey should be
739: * included in the key range, or false if only keys less than toKey should
740: * be included.
741: *
742: * @return the cursor.
743: */
744: EntityCursor<K> keys(K fromKey, boolean fromInclusive, K toKey,
745: boolean toInclusive) throws DatabaseException;
746:
747: /**
748: * Opens a cursor for traversing keys in a key range.
749: *
750: * @param txn the transaction used to protect all operations performed with
751: * the cursor, or null if the operations should not be transaction
752: * protected. If null is specified and the store is transactional, the
753: * cursor may not be used to update or delete entities.
754: *
755: * @param fromKey is the lower bound of the key range, or null if the range
756: * has no lower bound.
757: *
758: * @param fromInclusive is true if keys greater than or equal to fromKey
759: * should be included in the key range, or false if only keys greater than
760: * fromKey should be included.
761: *
762: * @param toKey is the upper bound of the key range, or null if the range
763: * has no upper bound.
764: *
765: * @param toInclusive is true if keys less than or equal to toKey should be
766: * included in the key range, or false if only keys less than toKey should
767: * be included.
768: *
769: * @param config the cursor configuration that determines the default lock
770: * mode used for all cursor operations, or null to implicitly use {@link
771: * CursorConfig#DEFAULT}.
772: *
773: * @return the cursor.
774: */
775: EntityCursor<K> keys(Transaction txn, K fromKey,
776: boolean fromInclusive, K toKey, boolean toInclusive,
777: CursorConfig config) throws DatabaseException;
778:
779: /**
780: * Opens a cursor for traversing entities in a key range.
781: *
782: * <p>The operations performed with the cursor will not be transaction
783: * protected, and {@link CursorConfig#DEFAULT} is used implicitly. If the
784: * store is transactional, the cursor may not be used to update or delete
785: * entities.</p>
786: *
787: * @param fromKey is the lower bound of the key range, or null if the range
788: * has no lower bound.
789: *
790: * @param fromInclusive is true if keys greater than or equal to fromKey
791: * should be included in the key range, or false if only keys greater than
792: * fromKey should be included.
793: *
794: * @param toKey is the upper bound of the key range, or null if the range
795: * has no upper bound.
796: *
797: * @param toInclusive is true if keys less than or equal to toKey should be
798: * included in the key range, or false if only keys less than toKey should
799: * be included.
800: *
801: * @return the cursor.
802: */
803: EntityCursor<V> entities(K fromKey, boolean fromInclusive, K toKey,
804: boolean toInclusive) throws DatabaseException;
805:
806: /**
807: * Opens a cursor for traversing entities in a key range.
808: *
809: * @param txn the transaction used to protect all operations performed with
810: * the cursor, or null if the operations should not be transaction
811: * protected. If null is specified and the store is transactional, the
812: * cursor may not be used to update or delete entities.
813: *
814: * @param fromKey is the lower bound of the key range, or null if the range
815: * has no lower bound.
816: *
817: * @param fromInclusive is true if keys greater than or equal to fromKey
818: * should be included in the key range, or false if only keys greater than
819: * fromKey should be included.
820: *
821: * @param toKey is the upper bound of the key range, or null if the range
822: * has no upper bound.
823: *
824: * @param toInclusive is true if keys less than or equal to toKey should be
825: * included in the key range, or false if only keys less than toKey should
826: * be included.
827: *
828: * @param config the cursor configuration that determines the default lock
829: * mode used for all cursor operations, or null to implicitly use {@link
830: * CursorConfig#DEFAULT}.
831: *
832: * @return the cursor.
833: */
834: EntityCursor<V> entities(Transaction txn, K fromKey,
835: boolean fromInclusive, K toKey, boolean toInclusive,
836: CursorConfig config) throws DatabaseException;
837:
838: /*
839: * Opens a cursor for traversing all keys in this index in arbitrary order.
840: *
841: * <p>Normally entities and keys are returned in key order. This method
842: * takes advantage of optimizations in the Berkeley DB engine to return
843: * entities in physical storage order, potentially decreasing the amount of
844: * physical I/O.</p>
845: *
846: * <p>The operations performed with the cursor will not be transaction
847: * protected, and {@link CursorConfig#DEFAULT} is used implicitly.</p>
848: *
849: * @param selector the filter for selecting keys to be returned, or null
850: * to select all keys.
851: *
852: * @return the cursor.
853: *
854: ForwardCursor<K> unsortedKeys(KeySelector<K> selector)
855: throws DatabaseException;
856: */
857:
858: /*
859: * Opens a cursor for traversing all keys in this index in arbitrary order.
860: *
861: * <p>Normally entities and keys are returned in key order. This method
862: * takes advantage of optimizations in the Berkeley DB engine to return
863: * entities in physical storage order, potentially decreasing the amount of
864: * physical I/O.</p>
865: *
866: * @param txn the transaction used to protect all operations performed with
867: * the cursor, or null if the operations should not be transaction
868: * protected.
869: *
870: * @param selector the filter for selecting keys to be returned, or null
871: * to select all keys.
872: *
873: * @param config the cursor configuration that determines the default lock
874: * mode used for all cursor operations, or null to implicitly use {@link
875: * CursorConfig#DEFAULT}.
876: *
877: * @return the cursor.
878: *
879: ForwardCursor<K> unsortedKeys(Transaction txn,
880: KeySelector<K> selector,
881: CursorConfig config)
882: throws DatabaseException;
883: */
884:
885: /*
886: * Opens a cursor for traversing all entities in this index in arbitrary
887: * order.
888: *
889: * <p>Normally entities and keys are returned in key order. This method
890: * takes advantage of optimizations in the Berkeley DB engine to return
891: * entities in physical storage order, potentially decreasing the amount of
892: * physical I/O.</p>
893: *
894: * <p>The operations performed with the cursor will not be transaction
895: * protected, and {@link CursorConfig#DEFAULT} is used implicitly.</p>
896:
897: * @param selector the filter for selecting keys to be returned, or null
898: * to select all keys.
899: *
900: * @return the cursor.
901: *
902: ForwardCursor<V> unsortedEntities(KeySelector<K> selector)
903: throws DatabaseException;
904: */
905:
906: /*
907: * Opens a cursor for traversing all entities in this index in arbitrary
908: * order.
909: *
910: * <p>Normally entities and keys are returned in key order. This method
911: * takes advantage of optimizations in the Berkeley DB engine to return
912: * entities in physical storage order, potentially decreasing the amount of
913: * physical I/O.</p>
914: *
915: * @param txn the transaction used to protect all operations performed with
916: * the cursor, or null if the operations should not be transaction
917: * protected.
918: *
919: * @param selector the filter for selecting keys to be returned, or null
920: * to select all keys.
921: *
922: * @param config the cursor configuration that determines the default lock
923: * mode used for all cursor operations, or null to implicitly use {@link
924: * CursorConfig#DEFAULT}.
925: *
926: * @return the cursor.
927: *
928: ForwardCursor<V> unsortedEntities(Transaction txn,
929: KeySelector<K> selector,
930: CursorConfig config)
931: throws DatabaseException;
932: */
933:
934: /**
935: * Returns a standard Java map based on this entity index. The {@link
936: * StoredMap} returned is defined by the {@linkplain
937: * com.sleepycat.collections Collections API}. Stored collections conform
938: * to the standard Java collections framework interface.
939: *
940: * @return the map.
941: */
942: Map<K, V> map();
943:
944: /**
945: * Returns a standard Java sorted map based on this entity index. The
946: * {@link StoredSortedMap} returned is defined by the {@linkplain
947: * com.sleepycat.collections Collections API}. Stored collections conform
948: * to the standard Java collections framework interface.
949: *
950: * @return the map.
951: */
952: SortedMap<K, V> sortedMap();
953: }
|