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.db; 10 11import com.sleepycat.db.internal.DbConstants; 12import com.sleepycat.db.internal.Dbc; 13 14/** 15A database cursor. Cursors are used for operating on collections of 16records, for iterating over a database, and for saving handles to 17individual records, so that they can be modified after they have been 18read. 19<p> 20Cursors may be used by multiple threads, but only serially. That is, 21the application must serialize access to the handle. 22<p> 23If the cursor is to be used to perform operations on behalf of a 24transaction, the cursor must be opened and closed within the context of 25that single transaction. 26<p> 27Once the cursor close method has been called, the handle may not be 28accessed again, regardless of the close method's success or failure. 29<p> 30To obtain a cursor with default attributes: 31<blockquote><pre> 32 Cursor cursor = myDatabase.openCursor(txn, null); 33</pre></blockquote> 34To customize the attributes of a cursor, use a CursorConfig object. 35<blockquote><pre> 36 CursorConfig config = new CursorConfig(); 37 config.setDirtyRead(true); 38 Cursor cursor = myDatabase.openCursor(txn, config); 39</pre></blockquote> 40<p> 41Modifications to the database during a sequential scan will be reflected 42in the scan; that is, records inserted behind a cursor will not be 43returned while records inserted in front of a cursor will be returned. 44In Queue and Recno databases, missing entries (that is, entries that 45were never explicitly created or that were created and then deleted) 46will be ignored during a sequential scan. 47*/ 48public class Cursor { 49 /* package */ Dbc dbc; 50 /* package */ Database database; 51 /* package */ CursorConfig config; 52 53 // Constructor needed by Java RPC server 54 protected Cursor(final Database database, final CursorConfig config) { 55 this.database = database; 56 this.config = config; 57 } 58 59 Cursor(final Database database, final Dbc dbc, final CursorConfig config) 60 throws DatabaseException { 61 62 this.database = database; 63 this.dbc = dbc; 64 this.config = config; 65 } 66 67 public synchronized void close() 68 throws DatabaseException { 69 70 if (dbc != null) { 71 try { 72 dbc.close(); 73 } finally { 74 dbc = null; 75 } 76 } 77 } 78 79 /** 80 Return a new cursor with the same transaction and locker ID as the 81 original cursor. 82 <p> 83 This is useful when an application is using locking and requires two 84 or more cursors in the same thread of control. 85 <p> 86 @param samePosition 87 If true, the newly created cursor is initialized to refer to the 88 same position in the database as the original cursor (if any) and 89 hold the same locks (if any). If false, or the original cursor does 90 not hold a database position and locks, the returned cursor is 91 uninitialized and will behave like a newly created cursor. 92 <p> 93 @return 94 A new cursor with the same transaction and locker ID as the original 95 cursor. 96 <p> 97 <p> 98@throws DatabaseException if a failure occurs. 99 */ 100 public Cursor dup(final boolean samePosition) 101 throws DatabaseException { 102 103 return new Cursor(database, 104 dbc.dup(samePosition ? DbConstants.DB_POSITION : 0), config); 105 } 106 107 /** 108 Return this cursor's configuration. 109 <p> 110 This may differ from the configuration used to open this object if 111 the cursor existed previously. 112 <p> 113 @return 114 This cursor's configuration. 115 <p> 116 <p> 117@throws DatabaseException if a failure occurs. 118 */ 119 public CursorConfig getConfig() { 120 return config; 121 } 122 123 /** 124 Return the Database handle associated with this Cursor. 125 <p> 126 @return 127 The Database handle associated with this Cursor. 128 <p> 129 */ 130 public Database getDatabase() { 131 return database; 132 } 133 134 /** 135 Return a comparison of the two cursors. 136 <p> 137 @return 138 An integer representing the result of the comparison. 0 is equal, 1 139 indicates this cursor is greater than OtherCursor, -1 indicates that 140 OtherCursor is greater than this cursor. 141 <p> 142 <p> 143@throws DeadlockException if the operation was selected to resolve a 144deadlock. 145<p> 146@throws DatabaseException if a failure occurs. 147 */ 148 public int compare(Cursor OtherCursor) 149 throws DatabaseException { 150 151 return dbc.cmp(OtherCursor.dbc, 0); 152 } 153 154 /** 155 Return a count of the number of data items for the key to which the 156 cursor refers. 157 <p> 158 @return 159 A count of the number of data items for the key to which the cursor 160 refers. 161 <p> 162 <p> 163@throws DeadlockException if the operation was selected to resolve a 164deadlock. 165<p> 166@throws DatabaseException if a failure occurs. 167 */ 168 public int count() 169 throws DatabaseException { 170 171 return dbc.count(0); 172 } 173 174 /** 175 Delete the key/data pair to which the cursor refers. 176 <p> 177 When called on a cursor opened on a database that has been made into a 178 secondary index, this method the key/data pair from the primary database 179 and all secondary indices. 180 <p> 181 The cursor position is unchanged after a delete, and subsequent calls 182to cursor functions expecting the cursor to refer to an existing key 183will fail. 184 <p> 185 <p> 186@throws DeadlockException if the operation was selected to resolve a 187deadlock. 188<p> 189@throws DatabaseException if a failure occurs. 190 */ 191 public OperationStatus delete() 192 throws DatabaseException { 193 194 return OperationStatus.fromInt(dbc.del(0)); 195 } 196 197 /** 198 Returns the key/data pair to which the cursor refers. 199<p> 200If this method fails for any reason, the position of the cursor will be 201unchanged. 202@throws NullPointerException if a DatabaseEntry parameter is null or 203does not contain a required non-null byte array. 204<p> 205@throws DeadlockException if the operation was selected to resolve a 206deadlock. 207<p> 208@throws IllegalArgumentException if an invalid parameter was specified. 209<p> 210@throws DatabaseException if a failure occurs. 211<p> 212@param key the key 213returned as output. Its byte array does not need to be initialized by the 214caller. 215@param data the data 216returned as output. Multiple results can be retrieved by passing an object 217that is a subclass of {@link com.sleepycat.db.MultipleEntry MultipleEntry}, otherwise its byte array does not 218need to be initialized by the caller. 219@param lockMode the locking attributes; if null, default attributes are used. 220@return {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the key/pair at the cursor 221position has been deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 222 */ 223 public OperationStatus getCurrent(final DatabaseEntry key, 224 final DatabaseEntry data, 225 LockMode lockMode) 226 throws DatabaseException { 227 228 return OperationStatus.fromInt( 229 dbc.get(key, data, DbConstants.DB_CURRENT | 230 LockMode.getFlag(lockMode) | 231 ((data == null) ? 0 : data.getMultiFlag()))); 232 } 233 234 /** 235 Move the cursor to the first key/data pair of the database, and return 236that pair. If the first key has duplicate values, the first data item 237in the set of duplicates is returned. 238<p> 239If this method fails for any reason, the position of the cursor will be 240unchanged. 241@throws NullPointerException if a DatabaseEntry parameter is null or 242does not contain a required non-null byte array. 243<p> 244@throws DeadlockException if the operation was selected to resolve a 245deadlock. 246<p> 247@throws IllegalArgumentException if an invalid parameter was specified. 248<p> 249@throws DatabaseException if a failure occurs. 250<p> 251@param key the key 252returned as output. Its byte array does not need to be initialized by the 253caller. 254@param data the data 255returned as output. Multiple results can be retrieved by passing an object 256that is a subclass of {@link com.sleepycat.db.MultipleEntry MultipleEntry}, otherwise its byte array does not 257need to be initialized by the caller. 258@param lockMode the locking attributes; if null, default attributes are used. 259@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 260found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 261 */ 262 public OperationStatus getFirst(final DatabaseEntry key, 263 final DatabaseEntry data, 264 LockMode lockMode) 265 throws DatabaseException { 266 267 return OperationStatus.fromInt( 268 dbc.get(key, data, DbConstants.DB_FIRST | 269 LockMode.getFlag(lockMode) | 270 ((data == null) ? 0 : data.getMultiFlag()))); 271 } 272 273 /** 274 Move the cursor to the last key/data pair of the database, and return 275that pair. If the last key has duplicate values, the last data item in 276the set of duplicates is returned. 277<p> 278If this method fails for any reason, the position of the cursor will be 279unchanged. 280@throws NullPointerException if a DatabaseEntry parameter is null or 281does not contain a required non-null byte array. 282<p> 283@throws DeadlockException if the operation was selected to resolve a 284deadlock. 285<p> 286@throws IllegalArgumentException if an invalid parameter was specified. 287<p> 288@throws DatabaseException if a failure occurs. 289<p> 290@param key the key 291returned as output. Its byte array does not need to be initialized by the 292caller. 293@param data the data 294returned as output. Its byte array does not need to be initialized by the 295caller. 296@param lockMode the locking attributes; if null, default attributes are used. 297@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 298found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 299 */ 300 public OperationStatus getLast(final DatabaseEntry key, 301 final DatabaseEntry data, 302 LockMode lockMode) 303 throws DatabaseException { 304 305 return OperationStatus.fromInt( 306 dbc.get(key, data, DbConstants.DB_LAST | 307 LockMode.getFlag(lockMode) | 308 ((data == null) ? 0 : data.getMultiFlag()))); 309 } 310 311 /** 312 Move the cursor to the next key/data pair and return that pair. If 313the matching key has duplicate values, the first data item in the set 314of duplicates is returned. 315<p> 316If the cursor is not yet initialized, move the cursor to the first 317key/data pair of the database, and return that pair. Otherwise, the 318cursor is moved to the next key/data pair of the database, and that pair 319is returned. In the presence of duplicate key values, the value of the 320key may not change. 321<p> 322If this method fails for any reason, the position of the cursor will be 323unchanged. 324@throws NullPointerException if a DatabaseEntry parameter is null or 325does not contain a required non-null byte array. 326<p> 327@throws DeadlockException if the operation was selected to resolve a 328deadlock. 329<p> 330@throws IllegalArgumentException if an invalid parameter was specified. 331<p> 332@throws DatabaseException if a failure occurs. 333<p> 334@param key the key 335returned as output. Its byte array does not need to be initialized by the 336caller. 337@param data the data 338returned as output. Multiple results can be retrieved by passing an object 339that is a subclass of {@link com.sleepycat.db.MultipleEntry MultipleEntry}, otherwise its byte array does not 340need to be initialized by the caller. 341@param lockMode the locking attributes; if null, default attributes are used. 342@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 343found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 344 */ 345 public OperationStatus getNext(final DatabaseEntry key, 346 final DatabaseEntry data, 347 LockMode lockMode) 348 throws DatabaseException { 349 350 return OperationStatus.fromInt( 351 dbc.get(key, data, DbConstants.DB_NEXT | 352 LockMode.getFlag(lockMode) | 353 ((data == null) ? 0 : data.getMultiFlag()))); 354 } 355 356 /** 357 If the next key/data pair of the database is a duplicate data record for 358the current key/data pair, move the cursor to the next key/data pair 359of the database and return that pair. 360<p> 361If this method fails for any reason, the position of the cursor will be 362unchanged. 363@throws NullPointerException if a DatabaseEntry parameter is null or 364does not contain a required non-null byte array. 365<p> 366@throws DeadlockException if the operation was selected to resolve a 367deadlock. 368<p> 369@throws IllegalArgumentException if an invalid parameter was specified. 370<p> 371@throws DatabaseException if a failure occurs. 372<p> 373@param key the key 374returned as output. Its byte array does not need to be initialized by the 375caller. 376@param data the data 377returned as output. Multiple results can be retrieved by passing an object 378that is a subclass of {@link com.sleepycat.db.MultipleEntry MultipleEntry}, otherwise its byte array does not 379need to be initialized by the caller. 380@param lockMode the locking attributes; if null, default attributes are used. 381@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 382found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 383 */ 384 public OperationStatus getNextDup(final DatabaseEntry key, 385 final DatabaseEntry data, 386 LockMode lockMode) 387 throws DatabaseException { 388 389 return OperationStatus.fromInt( 390 dbc.get(key, data, DbConstants.DB_NEXT_DUP | 391 LockMode.getFlag(lockMode) | 392 ((data == null) ? 0 : data.getMultiFlag()))); 393 } 394 395 /** 396 Move the cursor to the next non-duplicate key/data pair and return 397that pair. If the matching key has duplicate values, the first data 398item in the set of duplicates is returned. 399<p> 400If the cursor is not yet initialized, move the cursor to the first 401key/data pair of the database, and return that pair. Otherwise, the 402cursor is moved to the next non-duplicate key of the database, and that 403key/data pair is returned. 404<p> 405If this method fails for any reason, the position of the cursor will be 406unchanged. 407@throws NullPointerException if a DatabaseEntry parameter is null or 408does not contain a required non-null byte array. 409<p> 410@throws DeadlockException if the operation was selected to resolve a 411deadlock. 412<p> 413@throws IllegalArgumentException if an invalid parameter was specified. 414<p> 415@throws DatabaseException if a failure occurs. 416<p> 417@param key the key 418returned as output. Its byte array does not need to be initialized by the 419caller. 420@param data the data 421returned as output. Multiple results can be retrieved by passing an object 422that is a subclass of {@link com.sleepycat.db.MultipleEntry MultipleEntry}, otherwise its byte array does not 423need to be initialized by the caller. 424@param lockMode the locking attributes; if null, default attributes are used. 425@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 426found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 427 */ 428 public OperationStatus getNextNoDup(final DatabaseEntry key, 429 final DatabaseEntry data, 430 LockMode lockMode) 431 throws DatabaseException { 432 433 return OperationStatus.fromInt( 434 dbc.get(key, data, DbConstants.DB_NEXT_NODUP | 435 LockMode.getFlag(lockMode) | 436 ((data == null) ? 0 : data.getMultiFlag()))); 437 } 438 439 /** 440 Move the cursor to the previous key/data pair and return that pair. 441If the matching key has duplicate values, the last data item in the set 442of duplicates is returned. 443<p> 444If the cursor is not yet initialized, move the cursor to the last 445key/data pair of the database, and return that pair. Otherwise, the 446cursor is moved to the previous key/data pair of the database, and that 447pair is returned. In the presence of duplicate key values, the value of 448the key may not change. 449<p> 450If this method fails for any reason, the position of the cursor will be 451unchanged. 452@throws NullPointerException if a DatabaseEntry parameter is null or 453does not contain a required non-null byte array. 454<p> 455@throws DeadlockException if the operation was selected to resolve a 456deadlock. 457<p> 458@throws IllegalArgumentException if an invalid parameter was specified. 459<p> 460@throws DatabaseException if a failure occurs. 461<p> 462@param key the key 463returned as output. Its byte array does not need to be initialized by the 464caller. 465@param data the data 466returned as output. Its byte array does not need to be initialized by the 467caller. 468@param lockMode the locking attributes; if null, default attributes are used. 469@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 470found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 471 */ 472 public OperationStatus getPrev(final DatabaseEntry key, 473 final DatabaseEntry data, 474 LockMode lockMode) 475 throws DatabaseException { 476 477 return OperationStatus.fromInt( 478 dbc.get(key, data, DbConstants.DB_PREV | 479 LockMode.getFlag(lockMode) | 480 ((data == null) ? 0 : data.getMultiFlag()))); 481 } 482 483 /** 484 If the previous key/data pair of the database is a duplicate data record 485for the current key/data pair, move the cursor to the previous key/data 486pair of the database and return that pair. 487<p> 488If this method fails for any reason, the position of the cursor will be 489unchanged. 490@throws NullPointerException if a DatabaseEntry parameter is null or 491does not contain a required non-null byte array. 492<p> 493@throws DeadlockException if the operation was selected to resolve a 494deadlock. 495<p> 496@throws IllegalArgumentException if an invalid parameter was specified. 497<p> 498@throws DatabaseException if a failure occurs. 499<p> 500@param key the key 501returned as output. Its byte array does not need to be initialized by the 502caller. 503@param data the data 504returned as output. Its byte array does not need to be initialized by the 505caller. 506@param lockMode the locking attributes; if null, default attributes are used. 507@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 508found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 509 */ 510 public OperationStatus getPrevDup(final DatabaseEntry key, 511 final DatabaseEntry data, 512 LockMode lockMode) 513 throws DatabaseException { 514 515 return OperationStatus.fromInt( 516 dbc.get(key, data, DbConstants.DB_PREV_DUP | 517 LockMode.getFlag(lockMode) | 518 ((data == null) ? 0 : data.getMultiFlag()))); 519 } 520 521 /** 522 Move the cursor to the previous non-duplicate key/data pair and return 523that pair. If the matching key has duplicate values, the last data item 524in the set of duplicates is returned. 525<p> 526If the cursor is not yet initialized, move the cursor to the last 527key/data pair of the database, and return that pair. Otherwise, the 528cursor is moved to the previous non-duplicate key of the database, and 529that key/data pair is returned. 530<p> 531If this method fails for any reason, the position of the cursor will be 532unchanged. 533@throws NullPointerException if a DatabaseEntry parameter is null or 534does not contain a required non-null byte array. 535<p> 536@throws DeadlockException if the operation was selected to resolve a 537deadlock. 538<p> 539@throws IllegalArgumentException if an invalid parameter was specified. 540<p> 541@throws DatabaseException if a failure occurs. 542<p> 543@param key the key 544returned as output. Its byte array does not need to be initialized by the 545caller. 546@param data the data 547returned as output. Its byte array does not need to be initialized by the 548caller. 549@param lockMode the locking attributes; if null, default attributes are used. 550@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 551found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 552 */ 553 public OperationStatus getPrevNoDup(final DatabaseEntry key, 554 final DatabaseEntry data, 555 LockMode lockMode) 556 throws DatabaseException { 557 558 return OperationStatus.fromInt( 559 dbc.get(key, data, DbConstants.DB_PREV_NODUP | 560 LockMode.getFlag(lockMode) | 561 ((data == null) ? 0 : data.getMultiFlag()))); 562 } 563 564 /** 565 Return the record number associated with the cursor. The record number 566will be returned in the data parameter. 567<p> 568For this method to be called, the underlying database must be of type 569Btree, and it must have been configured to support record numbers. 570<p> 571If this method fails for any reason, the position of the cursor will be 572unchanged. 573@throws NullPointerException if a DatabaseEntry parameter is null or 574does not contain a required non-null byte array. 575<p> 576@throws DeadlockException if the operation was selected to resolve a 577deadlock. 578<p> 579@throws IllegalArgumentException if an invalid parameter was specified. 580<p> 581@throws DatabaseException if a failure occurs. 582<p> 583@param data the data 584returned as output. Its byte array does not need to be initialized by the 585caller. 586@param lockMode the locking attributes; if null, default attributes are used. 587@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 588found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 589 */ 590 public OperationStatus getRecordNumber(final DatabaseEntry data, 591 LockMode lockMode) 592 throws DatabaseException { 593 594 return OperationStatus.fromInt( 595 dbc.get(DatabaseEntry.IGNORE, data, 596 DbConstants.DB_GET_RECNO | 597 LockMode.getFlag(lockMode) | 598 ((data == null) ? 0 : data.getMultiFlag()))); 599 } 600 601 /** 602 Move the cursor to the given key of the database, and return the datum 603associated with the given key. If the matching key has duplicate 604values, the first data item in the set of duplicates is returned. 605<p> 606If this method fails for any reason, the position of the cursor will be 607unchanged. 608@throws NullPointerException if a DatabaseEntry parameter is null or 609does not contain a required non-null byte array. 610<p> 611@throws DeadlockException if the operation was selected to resolve a 612deadlock. 613<p> 614@throws IllegalArgumentException if an invalid parameter was specified. 615<p> 616@throws DatabaseException if a failure occurs. 617<p> 618@param key the key 619used as input. It must be initialized with a non-null byte array by the 620caller. 621@param data the data 622returned as output. Multiple results can be retrieved by passing an object 623that is a subclass of {@link com.sleepycat.db.MultipleEntry MultipleEntry}, otherwise its byte array does not 624need to be initialized by the caller. 625@param lockMode the locking attributes; if null, default attributes are used. 626@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 627found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 628 */ 629 public OperationStatus getSearchKey(final DatabaseEntry key, 630 final DatabaseEntry data, 631 LockMode lockMode) 632 throws DatabaseException { 633 634 return OperationStatus.fromInt( 635 dbc.get(key, data, DbConstants.DB_SET | 636 LockMode.getFlag(lockMode) | 637 ((data == null) ? 0 : data.getMultiFlag()))); 638 } 639 640 /** 641 Move the cursor to the closest matching key of the database, and return 642the data item associated with the matching key. If the matching key has 643duplicate values, the first data item in the set of duplicates is returned. 644<p> 645The returned key/data pair is for the smallest key greater than or equal 646to the specified key (as determined by the key comparison function), 647permitting partial key matches and range searches. 648<p> 649If this method fails for any reason, the position of the cursor will be 650unchanged. 651@throws NullPointerException if a DatabaseEntry parameter is null or 652does not contain a required non-null byte array. 653<p> 654@throws DeadlockException if the operation was selected to resolve a 655deadlock. 656<p> 657@throws IllegalArgumentException if an invalid parameter was specified. 658<p> 659@throws DatabaseException if a failure occurs. 660<p> 661@param key the key 662used as input and returned as output. It must be initialized with a non-null 663byte array by the caller. 664@param data the data 665returned as output. Multiple results can be retrieved by passing an object 666that is a subclass of {@link com.sleepycat.db.MultipleEntry MultipleEntry}, otherwise its byte array does not 667need to be initialized by the caller. 668@param lockMode the locking attributes; if null, default attributes are used. 669@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 670found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 671 */ 672 public OperationStatus getSearchKeyRange(final DatabaseEntry key, 673 final DatabaseEntry data, 674 LockMode lockMode) 675 throws DatabaseException { 676 677 return OperationStatus.fromInt( 678 dbc.get(key, data, DbConstants.DB_SET_RANGE | 679 LockMode.getFlag(lockMode) | 680 ((data == null) ? 0 : data.getMultiFlag()))); 681 } 682 683 /** 684 Move the cursor to the specified key/data pair, where both the key and 685data items must match. 686<p> 687If this method fails for any reason, the position of the cursor will be 688unchanged. 689@throws NullPointerException if a DatabaseEntry parameter is null or 690does not contain a required non-null byte array. 691<p> 692@throws DeadlockException if the operation was selected to resolve a 693deadlock. 694<p> 695@throws IllegalArgumentException if an invalid parameter was specified. 696<p> 697@throws DatabaseException if a failure occurs. 698<p> 699@param key the key 700used as input. It must be initialized with a non-null byte array by the 701caller. 702@param data the data 703used as input. It must be initialized with a non-null byte array by the 704caller. 705@param lockMode the locking attributes; if null, default attributes are used. 706@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 707found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 708 */ 709 public OperationStatus getSearchBoth(final DatabaseEntry key, 710 final DatabaseEntry data, 711 LockMode lockMode) 712 throws DatabaseException { 713 714 return OperationStatus.fromInt( 715 dbc.get(key, data, DbConstants.DB_GET_BOTH | 716 LockMode.getFlag(lockMode) | 717 ((data == null) ? 0 : data.getMultiFlag()))); 718 } 719 720 /** 721 Move the cursor to the specified key and closest matching data item of the 722database. 723<p> 724In the case of any database supporting sorted duplicate sets, the returned 725key/data pair is for the smallest data item greater than or equal to the 726specified data item (as determined by the duplicate comparison function), 727permitting partial matches and range searches in duplicate data sets. 728<p> 729If this method fails for any reason, the position of the cursor will be 730unchanged. 731@throws NullPointerException if a DatabaseEntry parameter is null or 732does not contain a required non-null byte array. 733<p> 734@throws DeadlockException if the operation was selected to resolve a 735deadlock. 736<p> 737@throws IllegalArgumentException if an invalid parameter was specified. 738<p> 739@throws DatabaseException if a failure occurs. 740<p> 741@param key the key 742used as input and returned as output. It must be initialized with a non-null 743byte array by the caller. 744@param data the data 745used as input and returned as output. It must be initialized with a non-null 746byte array by the caller. 747@param lockMode the locking attributes; if null, default attributes are used. 748@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 749found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 750 */ 751 public OperationStatus getSearchBothRange(final DatabaseEntry key, 752 final DatabaseEntry data, 753 LockMode lockMode) 754 throws DatabaseException { 755 756 return OperationStatus.fromInt( 757 dbc.get(key, data, DbConstants.DB_GET_BOTH_RANGE | 758 LockMode.getFlag(lockMode) | 759 ((data == null) ? 0 : data.getMultiFlag()))); 760 } 761 762 /** 763 Move the cursor to the specific numbered record of the database, and 764return the associated key/data pair. 765<p> 766The data field of the specified key must be a byte array containing a 767record number, as described in {@link com.sleepycat.db.DatabaseEntry DatabaseEntry}. This determines 768the record to be retrieved. 769<p> 770For this method to be called, the underlying database must be of type 771Btree, and it must have been configured to support record numbers. 772<p> 773If this method fails for any reason, the position of the cursor will be 774unchanged. 775@throws NullPointerException if a DatabaseEntry parameter is null or 776does not contain a required non-null byte array. 777<p> 778@throws DeadlockException if the operation was selected to resolve a 779deadlock. 780<p> 781@throws IllegalArgumentException if an invalid parameter was specified. 782<p> 783@throws DatabaseException if a failure occurs. 784<p> 785@param key the key 786returned as output. Its byte array does not need to be initialized by the 787caller. 788@param data the data 789returned as output. Multiple results can be retrieved by passing an object 790that is a subclass of {@link com.sleepycat.db.MultipleEntry MultipleEntry}, otherwise its byte array does not 791need to be initialized by the caller. 792@param lockMode the locking attributes; if null, default attributes are used. 793@return {@link com.sleepycat.db.OperationStatus#NOTFOUND OperationStatus.NOTFOUND} if no matching key/data pair is 794found; {@link com.sleepycat.db.OperationStatus#KEYEMPTY OperationStatus.KEYEMPTY} if the database is a Queue or Recno database and the specified key exists, but was never explicitly created by the application or was later deleted; otherwise, {@link com.sleepycat.db.OperationStatus#SUCCESS OperationStatus.SUCCESS}. 795 */ 796 public OperationStatus getSearchRecordNumber(final DatabaseEntry key, 797 final DatabaseEntry data, 798 LockMode lockMode) 799 throws DatabaseException { 800 801 return OperationStatus.fromInt( 802 dbc.get(key, data, DbConstants.DB_SET_RECNO | 803 LockMode.getFlag(lockMode) | 804 ((data == null) ? 0 : data.getMultiFlag()))); 805 } 806 807 /** 808 Store a key/data pair into the database. 809<p> 810If the put method succeeds, the cursor is always positioned to refer to 811the newly inserted item. If the put method fails for any reason, the 812state of the cursor will be unchanged. 813<p> 814If the key already appears in the database and duplicates are supported, 815the new data value is inserted at the correct sorted location. If the 816key already appears in the database and duplicates are not supported, 817the existing key/data pair will be replaced. 818<p> 819@param key the key {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} operated on. 820<p> 821@param data the data {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} stored. 822<p> 823<p> 824@throws DeadlockException if the operation was selected to resolve a 825deadlock. 826<p> 827@throws IllegalArgumentException if an invalid parameter was specified. 828<p> 829@throws DatabaseException if a failure occurs. 830 */ 831 public OperationStatus put(final DatabaseEntry key, 832 final DatabaseEntry data) 833 throws DatabaseException { 834 835 return OperationStatus.fromInt( 836 dbc.put(key, data, DbConstants.DB_KEYLAST)); 837 } 838 839 /** 840 Store a key/data pair into the database. 841<p> 842If the putAfter method succeeds, the cursor is always positioned to refer to 843the newly inserted item. If the putAfter method fails for any reason, the 844state of the cursor will be unchanged. 845<p> 846In the case of the Btree and Hash access methods, insert the data 847element as a duplicate element of the key to which the cursor refers. 848The new element appears immediately 849after 850the current cursor position. It is an error to call this method if the 851underlying Btree or Hash database does not support duplicate data items. 852The key parameter is ignored. 853<p> 854In the case of the Hash access method, the putAfter method will fail and 855throw an exception if the current cursor record has already been deleted. 856<p> 857In the case of the Recno access method, it is an error to call this 858method if the underlying Recno database was not configured to have 859mutable record numbers. A new key is created, all records after the 860inserted item are automatically renumbered, and the key of the new 861record is returned in the key parameter. The initial value of the key 862parameter is ignored. 863<p> 864The putAfter method may not be called for the Queue access method. 865<p> 866@param key the key {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} operated on. 867<p> 868@param data the data {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} stored. 869<p> 870<p> 871@throws DeadlockException if the operation was selected to resolve a 872deadlock. 873<p> 874@throws IllegalArgumentException if an invalid parameter was specified. 875<p> 876@throws DatabaseException if a failure occurs. 877 */ 878 public OperationStatus putAfter(final DatabaseEntry key, 879 final DatabaseEntry data) 880 throws DatabaseException { 881 882 return OperationStatus.fromInt( 883 dbc.put(key, data, DbConstants.DB_AFTER)); 884 } 885 886 /** 887 Store a key/data pair into the database. 888<p> 889If the putBefore method succeeds, the cursor is always positioned to refer to 890the newly inserted item. If the putBefore method fails for any reason, the 891state of the cursor will be unchanged. 892<p> 893In the case of the Btree and Hash access methods, insert the data 894element as a duplicate element of the key to which the cursor refers. 895The new element appears immediately 896before 897the current cursor position. It is an error to call this method if the 898underlying Btree or Hash database does not support duplicate data items. 899The key parameter is ignored. 900<p> 901In the case of the Hash access method, the putBefore method will fail and 902throw an exception if the current cursor record has already been deleted. 903<p> 904In the case of the Recno access method, it is an error to call this 905method if the underlying Recno database was not configured to have 906mutable record numbers. A new key is created, all records after the 907inserted item are automatically renumbered, and the key of the new 908record is returned in the key parameter. The initial value of the key 909parameter is ignored. 910<p> 911The putBefore method may not be called for the Queue access method. 912<p> 913@param key the key {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} operated on. 914<p> 915@param data the data {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} stored. 916<p> 917<p> 918@throws DeadlockException if the operation was selected to resolve a 919deadlock. 920<p> 921@throws IllegalArgumentException if an invalid parameter was specified. 922<p> 923@throws DatabaseException if a failure occurs. 924 */ 925 public OperationStatus putBefore(final DatabaseEntry key, 926 final DatabaseEntry data) 927 throws DatabaseException { 928 929 return OperationStatus.fromInt( 930 dbc.put(key, data, DbConstants.DB_BEFORE)); 931 } 932 933 /** 934 Store a key/data pair into the database. 935<p> 936If the putNoOverwrite method succeeds, the cursor is always positioned to refer to 937the newly inserted item. If the putNoOverwrite method fails for any reason, the 938state of the cursor will be unchanged. 939<p> 940If the key already appears in the database, putNoOverwrite will return 941{@link com.sleepycat.db.OperationStatus#KEYEXIST OperationStatus.KEYEXIST}. 942<p> 943@param key the key {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} operated on. 944<p> 945@param data the data {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} stored. 946<p> 947<p> 948@throws DeadlockException if the operation was selected to resolve a 949deadlock. 950<p> 951@throws IllegalArgumentException if an invalid parameter was specified. 952<p> 953@throws DatabaseException if a failure occurs. 954 */ 955 public OperationStatus putNoOverwrite(final DatabaseEntry key, 956 final DatabaseEntry data) 957 throws DatabaseException { 958 959 /* 960 * The tricks here are making sure the cursor doesn't move on error and 961 * noticing that if the key exists, that's an error and we don't want 962 * to return the data. 963 */ 964 Dbc tempDbc = dbc.dup(0); 965 try { 966 int errCode = tempDbc.get(key, DatabaseEntry.IGNORE, 967 DbConstants.DB_SET | database.rmwFlag); 968 if (errCode == 0) 969 return OperationStatus.KEYEXIST; 970 else if (errCode != DbConstants.DB_NOTFOUND && 971 errCode != DbConstants.DB_KEYEMPTY) 972 return OperationStatus.fromInt(errCode); 973 else { 974 Dbc tdbc = dbc; 975 dbc = tempDbc; 976 tempDbc = tdbc; 977 978 return OperationStatus.fromInt( 979 dbc.put(key, data, DbConstants.DB_KEYLAST)); 980 } 981 } finally { 982 tempDbc.close(); 983 } 984 } 985 986 /** 987 Store a key/data pair into the database. 988<p> 989If the putKeyFirst method succeeds, the cursor is always positioned to refer to 990the newly inserted item. If the putKeyFirst method fails for any reason, the 991state of the cursor will be unchanged. 992<p> 993In the case of the Btree and Hash access methods, insert the specified 994key/data pair into the database. 995<p> 996If the underlying database supports duplicate data items, and if the 997key already exists in the database and a duplicate sort function has 998been specified, the inserted data item is added in its sorted location. 999If the key already exists in the database and no duplicate sort function 1000has been specified, the inserted data item is added as the 1001first 1002of the data items for that key. 1003<p> 1004The putKeyFirst method may not be called for the Queue or Recno access methods. 1005<p> 1006@param key the key {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} operated on. 1007<p> 1008@param data the data {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} stored. 1009<p> 1010<p> 1011@throws DeadlockException if the operation was selected to resolve a 1012deadlock. 1013<p> 1014@throws IllegalArgumentException if an invalid parameter was specified. 1015<p> 1016@throws DatabaseException if a failure occurs. 1017 */ 1018 public OperationStatus putKeyFirst(final DatabaseEntry key, 1019 final DatabaseEntry data) 1020 throws DatabaseException { 1021 1022 return OperationStatus.fromInt( 1023 dbc.put(key, data, DbConstants.DB_KEYFIRST)); 1024 } 1025 1026 /** 1027 Store a key/data pair into the database. 1028<p> 1029If the putKeyLast method succeeds, the cursor is always positioned to refer to 1030the newly inserted item. If the putKeyLast method fails for any reason, the 1031state of the cursor will be unchanged. 1032<p> 1033In the case of the Btree and Hash access methods, insert the specified 1034key/data pair into the database. 1035<p> 1036If the underlying database supports duplicate data items, and if the 1037key already exists in the database and a duplicate sort function has 1038been specified, the inserted data item is added in its sorted location. 1039If the key already exists in the database and no duplicate sort function 1040has been specified, the inserted data item is added as the 1041last 1042of the data items for that key. 1043<p> 1044The putKeyLast method may not be called for the Queue or Recno access methods. 1045<p> 1046@param key the key {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} operated on. 1047<p> 1048@param data the data {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} stored. 1049<p> 1050<p> 1051@throws DeadlockException if the operation was selected to resolve a 1052deadlock. 1053<p> 1054@throws IllegalArgumentException if an invalid parameter was specified. 1055<p> 1056@throws DatabaseException if a failure occurs. 1057 */ 1058 public OperationStatus putKeyLast(final DatabaseEntry key, 1059 final DatabaseEntry data) 1060 throws DatabaseException { 1061 1062 return OperationStatus.fromInt( 1063 dbc.put(key, data, DbConstants.DB_KEYLAST)); 1064 } 1065 1066 /** 1067 Store a key/data pair into the database. 1068<p> 1069If the putNoDupData method succeeds, the cursor is always positioned to refer to 1070the newly inserted item. If the putNoDupData method fails for any reason, the 1071state of the cursor will be unchanged. 1072<p> 1073In the case of the Btree and Hash access methods, insert 1074the specified key/data pair into the database, unless a key/data pair 1075comparing equally to it already exists in the database. If a matching 1076key/data pair already exists in the database, {@link com.sleepycat.db.OperationStatus#KEYEXIST OperationStatus.KEYEXIST} is returned. 1077<p> 1078This method may only be called if the underlying database has been 1079configured to support sorted duplicate data items. 1080<p> 1081This method may not be called for the Queue or Recno access methods. 1082<p> 1083@param key the key {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} operated on. 1084<p> 1085@param data the data {@link com.sleepycat.db.DatabaseEntry DatabaseEntry} stored. 1086<p> 1087<p> 1088@throws DeadlockException if the operation was selected to resolve a 1089deadlock. 1090<p> 1091@throws IllegalArgumentException if an invalid parameter was specified. 1092<p> 1093@throws DatabaseException if a failure occurs. 1094 */ 1095 public OperationStatus putNoDupData(final DatabaseEntry key, 1096 final DatabaseEntry data) 1097 throws DatabaseException { 1098 1099 return OperationStatus.fromInt( 1100 dbc.put(key, data, DbConstants.DB_NODUPDATA)); 1101 } 1102 1103 /** 1104 Replaces the data in the key/data pair at the current cursor position. 1105 <p> 1106 Whether the putCurrent method succeeds or fails for any reason, the state 1107 of the cursor will be unchanged. 1108 <p> 1109 Overwrite the data of the key/data pair to which the cursor refers with the 1110 specified data item. This method will return OperationStatus.NOTFOUND if 1111 the cursor currently refers to an already-deleted key/data pair. 1112 <p> 1113 For a database that does not support duplicates, the data may be changed by 1114 this method. If duplicates are supported, the data may be changed only if 1115 a custom partial comparator is configured and the comparator considers the 1116 old and new data to be equal (that is, the comparator returns zero). For 1117 more information on partial comparators see {@link 1118 DatabaseConfig#setDuplicateComparator}. 1119 <p> 1120 If the old and new data are unequal according to the comparator, a {@code 1121 DatabaseException} is thrown. Changing the data in this case would change 1122 the sort order of the record, which would change the cursor position, and 1123 this is not allowed. To change the sort order of a record, delete it and 1124 then re-insert it. 1125 <p> 1126 @param data - the data DatabaseEntry stored. 1127 <br> 1128 @throws DeadlockException - if the operation was selected to resolve a 1129 deadlock. 1130 <br> 1131 @throws IllegalArgumentException - if an invalid parameter was specified. 1132 <br> 1133 @throws DatabaseException - if the old and new data are not equal according 1134 to the configured duplicate comparator or default comparator, or if a 1135 failure occurs. 1136 <br> 1137 */ 1138 public OperationStatus putCurrent(final DatabaseEntry data) 1139 throws DatabaseException { 1140 1141 return OperationStatus.fromInt( 1142 dbc.put(DatabaseEntry.UNUSED, data, DbConstants.DB_CURRENT)); 1143 } 1144 1145 /** 1146 Get the cache priority for pages referenced by the cursor. 1147 <p> 1148 This method may be called at any time during the life of the application. 1149 <p> 1150 <p> 1151@throws DatabaseException if a failure occurs. 1152 */ 1153 public CacheFilePriority getPriority() 1154 throws DatabaseException { 1155 1156 return CacheFilePriority.fromFlag(dbc.get_priority()); 1157 } 1158 1159 /** 1160 Set the cache priority for pages referenced by the DBC handle. 1161 <p> 1162 The priority of a page biases the replacement algorithm to be more or less 1163 likely to discard a page when space is needed in the buffer pool. The bias 1164 is temporary, and pages will eventually be discarded if they are not 1165 referenced again. The DBcursor->set_priority method is only advisory, and 1166 does not guarantee pages will be treated in a specific way. 1167 <p> 1168 This method may be called at any time during the life of the application. 1169 <p> 1170 <p> 1171@throws DatabaseException if a failure occurs. 1172 */ 1173 public void setPriority(final CacheFilePriority priority) 1174 throws DatabaseException { 1175 1176 dbc.set_priority(priority.getFlag()); 1177 } 1178} 1179