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 >= 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