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