1 // Copyright (c) 2011-present, Facebook, Inc. All rights reserved. 2 // This source code is licensed under both the GPLv2 (found in the 3 // COPYING file in the root directory) and Apache 2.0 License 4 // (found in the LICENSE.Apache file in the root directory). 5 6 package org.rocksdb; 7 8 import java.util.List; 9 10 /** 11 * Provides BEGIN/COMMIT/ROLLBACK transactions. 12 * 13 * To use transactions, you must first create either an 14 * {@link OptimisticTransactionDB} or a {@link TransactionDB} 15 * 16 * To create a transaction, use 17 * {@link OptimisticTransactionDB#beginTransaction(org.rocksdb.WriteOptions)} or 18 * {@link TransactionDB#beginTransaction(org.rocksdb.WriteOptions)} 19 * 20 * It is up to the caller to synchronize access to this object. 21 * 22 * See samples/src/main/java/OptimisticTransactionSample.java and 23 * samples/src/main/java/TransactionSample.java for some simple 24 * examples. 25 */ 26 public class Transaction extends RocksObject { 27 28 private final RocksDB parent; 29 30 /** 31 * Intentionally package private 32 * as this is called from 33 * {@link OptimisticTransactionDB#beginTransaction(org.rocksdb.WriteOptions)} 34 * or {@link TransactionDB#beginTransaction(org.rocksdb.WriteOptions)} 35 * 36 * @param parent This must be either {@link TransactionDB} or 37 * {@link OptimisticTransactionDB} 38 * @param transactionHandle The native handle to the underlying C++ 39 * transaction object 40 */ Transaction(final RocksDB parent, final long transactionHandle)41 Transaction(final RocksDB parent, final long transactionHandle) { 42 super(transactionHandle); 43 this.parent = parent; 44 } 45 46 /** 47 * If a transaction has a snapshot set, the transaction will ensure that 48 * any keys successfully written(or fetched via {@link #getForUpdate}) have 49 * not been modified outside of this transaction since the time the snapshot 50 * was set. 51 * 52 * If a snapshot has not been set, the transaction guarantees that keys have 53 * not been modified since the time each key was first written (or fetched via 54 * {@link #getForUpdate}). 55 * 56 * Using {@link #setSnapshot()} will provide stricter isolation guarantees 57 * at the expense of potentially more transaction failures due to conflicts 58 * with other writes. 59 * 60 * Calling {@link #setSnapshot()} has no effect on keys written before this 61 * function has been called. 62 * 63 * {@link #setSnapshot()} may be called multiple times if you would like to 64 * change the snapshot used for different operations in this transaction. 65 * 66 * Calling {@link #setSnapshot()} will not affect the version of Data returned 67 * by get(...) methods. See {@link #get} for more details. 68 */ setSnapshot()69 public void setSnapshot() { 70 assert(isOwningHandle()); 71 setSnapshot(nativeHandle_); 72 } 73 74 /** 75 * Similar to {@link #setSnapshot()}, but will not change the current snapshot 76 * until put/merge/delete/getForUpdate/multiGetForUpdate is called. 77 * By calling this function, the transaction will essentially call 78 * {@link #setSnapshot()} for you right before performing the next 79 * write/getForUpdate. 80 * 81 * Calling {@link #setSnapshotOnNextOperation()} will not affect what 82 * snapshot is returned by {@link #getSnapshot} until the next 83 * write/getForUpdate is executed. 84 * 85 * When the snapshot is created the notifier's snapshotCreated method will 86 * be called so that the caller can get access to the snapshot. 87 * 88 * This is an optimization to reduce the likelihood of conflicts that 89 * could occur in between the time {@link #setSnapshot()} is called and the 90 * first write/getForUpdate operation. i.e. this prevents the following 91 * race-condition: 92 * 93 * txn1->setSnapshot(); 94 * txn2->put("A", ...); 95 * txn2->commit(); 96 * txn1->getForUpdate(opts, "A", ...); * FAIL! 97 */ setSnapshotOnNextOperation()98 public void setSnapshotOnNextOperation() { 99 assert(isOwningHandle()); 100 setSnapshotOnNextOperation(nativeHandle_); 101 } 102 103 /** 104 * Similar to {@link #setSnapshot()}, but will not change the current snapshot 105 * until put/merge/delete/getForUpdate/multiGetForUpdate is called. 106 * By calling this function, the transaction will essentially call 107 * {@link #setSnapshot()} for you right before performing the next 108 * write/getForUpdate. 109 * 110 * Calling {@link #setSnapshotOnNextOperation()} will not affect what 111 * snapshot is returned by {@link #getSnapshot} until the next 112 * write/getForUpdate is executed. 113 * 114 * When the snapshot is created the 115 * {@link AbstractTransactionNotifier#snapshotCreated(Snapshot)} method will 116 * be called so that the caller can get access to the snapshot. 117 * 118 * This is an optimization to reduce the likelihood of conflicts that 119 * could occur in between the time {@link #setSnapshot()} is called and the 120 * first write/getForUpdate operation. i.e. this prevents the following 121 * race-condition: 122 * 123 * txn1->setSnapshot(); 124 * txn2->put("A", ...); 125 * txn2->commit(); 126 * txn1->getForUpdate(opts, "A", ...); * FAIL! 127 * 128 * @param transactionNotifier A handler for receiving snapshot notifications 129 * for the transaction 130 * 131 */ setSnapshotOnNextOperation( final AbstractTransactionNotifier transactionNotifier)132 public void setSnapshotOnNextOperation( 133 final AbstractTransactionNotifier transactionNotifier) { 134 assert(isOwningHandle()); 135 setSnapshotOnNextOperation(nativeHandle_, transactionNotifier.nativeHandle_); 136 } 137 138 /** 139 * Returns the Snapshot created by the last call to {@link #setSnapshot()}. 140 * 141 * REQUIRED: The returned Snapshot is only valid up until the next time 142 * {@link #setSnapshot()}/{@link #setSnapshotOnNextOperation()} is called, 143 * {@link #clearSnapshot()} is called, or the Transaction is deleted. 144 * 145 * @return The snapshot or null if there is no snapshot 146 */ getSnapshot()147 public Snapshot getSnapshot() { 148 assert(isOwningHandle()); 149 final long snapshotNativeHandle = getSnapshot(nativeHandle_); 150 if(snapshotNativeHandle == 0) { 151 return null; 152 } else { 153 final Snapshot snapshot = new Snapshot(snapshotNativeHandle); 154 return snapshot; 155 } 156 } 157 158 /** 159 * Clears the current snapshot (i.e. no snapshot will be 'set') 160 * 161 * This removes any snapshot that currently exists or is set to be created 162 * on the next update operation ({@link #setSnapshotOnNextOperation()}). 163 * 164 * Calling {@link #clearSnapshot()} has no effect on keys written before this 165 * function has been called. 166 * 167 * If a reference to a snapshot was retrieved via {@link #getSnapshot()}, it 168 * will no longer be valid and should be discarded after a call to 169 * {@link #clearSnapshot()}. 170 */ clearSnapshot()171 public void clearSnapshot() { 172 assert(isOwningHandle()); 173 clearSnapshot(nativeHandle_); 174 } 175 176 /** 177 * Prepare the current transaction for 2PC 178 */ prepare()179 void prepare() throws RocksDBException { 180 //TODO(AR) consider a Java'ish version of this function, which returns an AutoCloseable (commit) 181 assert(isOwningHandle()); 182 prepare(nativeHandle_); 183 } 184 185 /** 186 * Write all batched keys to the db atomically. 187 * 188 * Returns OK on success. 189 * 190 * May return any error status that could be returned by DB:Write(). 191 * 192 * If this transaction was created by an {@link OptimisticTransactionDB} 193 * Status::Busy() may be returned if the transaction could not guarantee 194 * that there are no write conflicts. Status::TryAgain() may be returned 195 * if the memtable history size is not large enough 196 * (See max_write_buffer_number_to_maintain). 197 * 198 * If this transaction was created by a {@link TransactionDB}, 199 * Status::Expired() may be returned if this transaction has lived for 200 * longer than {@link TransactionOptions#getExpiration()}. 201 * 202 * @throws RocksDBException if an error occurs when committing the transaction 203 */ commit()204 public void commit() throws RocksDBException { 205 assert(isOwningHandle()); 206 commit(nativeHandle_); 207 } 208 209 /** 210 * Discard all batched writes in this transaction. 211 * 212 * @throws RocksDBException if an error occurs when rolling back the transaction 213 */ rollback()214 public void rollback() throws RocksDBException { 215 assert(isOwningHandle()); 216 rollback(nativeHandle_); 217 } 218 219 /** 220 * Records the state of the transaction for future calls to 221 * {@link #rollbackToSavePoint()}. 222 * 223 * May be called multiple times to set multiple save points. 224 * 225 * @throws RocksDBException if an error occurs whilst setting a save point 226 */ setSavePoint()227 public void setSavePoint() throws RocksDBException { 228 assert(isOwningHandle()); 229 setSavePoint(nativeHandle_); 230 } 231 232 /** 233 * Undo all operations in this transaction (put, merge, delete, putLogData) 234 * since the most recent call to {@link #setSavePoint()} and removes the most 235 * recent {@link #setSavePoint()}. 236 * 237 * If there is no previous call to {@link #setSavePoint()}, 238 * returns Status::NotFound() 239 * 240 * @throws RocksDBException if an error occurs when rolling back to a save point 241 */ rollbackToSavePoint()242 public void rollbackToSavePoint() throws RocksDBException { 243 assert(isOwningHandle()); 244 rollbackToSavePoint(nativeHandle_); 245 } 246 247 /** 248 * This function is similar to 249 * {@link RocksDB#get(ColumnFamilyHandle, ReadOptions, byte[])} except it will 250 * also read pending changes in this transaction. 251 * Currently, this function will return Status::MergeInProgress if the most 252 * recent write to the queried key in this batch is a Merge. 253 * 254 * If {@link ReadOptions#snapshot()} is not set, the current version of the 255 * key will be read. Calling {@link #setSnapshot()} does not affect the 256 * version of the data returned. 257 * 258 * Note that setting {@link ReadOptions#setSnapshot(Snapshot)} will affect 259 * what is read from the DB but will NOT change which keys are read from this 260 * transaction (the keys in this transaction do not yet belong to any snapshot 261 * and will be fetched regardless). 262 * 263 * @param columnFamilyHandle {@link org.rocksdb.ColumnFamilyHandle} instance 264 * @param readOptions Read options. 265 * @param key the key to retrieve the value for. 266 * 267 * @return a byte array storing the value associated with the input key if 268 * any. null if it does not find the specified key. 269 * 270 * @throws RocksDBException thrown if error happens in underlying native 271 * library. 272 */ get(final ColumnFamilyHandle columnFamilyHandle, final ReadOptions readOptions, final byte[] key)273 public byte[] get(final ColumnFamilyHandle columnFamilyHandle, 274 final ReadOptions readOptions, final byte[] key) throws RocksDBException { 275 assert(isOwningHandle()); 276 return get(nativeHandle_, readOptions.nativeHandle_, key, key.length, 277 columnFamilyHandle.nativeHandle_); 278 } 279 280 /** 281 * This function is similar to 282 * {@link RocksDB#get(ReadOptions, byte[])} except it will 283 * also read pending changes in this transaction. 284 * Currently, this function will return Status::MergeInProgress if the most 285 * recent write to the queried key in this batch is a Merge. 286 * 287 * If {@link ReadOptions#snapshot()} is not set, the current version of the 288 * key will be read. Calling {@link #setSnapshot()} does not affect the 289 * version of the data returned. 290 * 291 * Note that setting {@link ReadOptions#setSnapshot(Snapshot)} will affect 292 * what is read from the DB but will NOT change which keys are read from this 293 * transaction (the keys in this transaction do not yet belong to any snapshot 294 * and will be fetched regardless). 295 * 296 * @param readOptions Read options. 297 * @param key the key to retrieve the value for. 298 * 299 * @return a byte array storing the value associated with the input key if 300 * any. null if it does not find the specified key. 301 * 302 * @throws RocksDBException thrown if error happens in underlying native 303 * library. 304 */ get(final ReadOptions readOptions, final byte[] key)305 public byte[] get(final ReadOptions readOptions, final byte[] key) 306 throws RocksDBException { 307 assert(isOwningHandle()); 308 return get(nativeHandle_, readOptions.nativeHandle_, key, key.length); 309 } 310 311 /** 312 * This function is similar to 313 * {@link RocksDB#multiGet(ReadOptions, List, List)} except it will 314 * also read pending changes in this transaction. 315 * Currently, this function will return Status::MergeInProgress if the most 316 * recent write to the queried key in this batch is a Merge. 317 * 318 * If {@link ReadOptions#snapshot()} is not set, the current version of the 319 * key will be read. Calling {@link #setSnapshot()} does not affect the 320 * version of the data returned. 321 * 322 * Note that setting {@link ReadOptions#setSnapshot(Snapshot)} will affect 323 * what is read from the DB but will NOT change which keys are read from this 324 * transaction (the keys in this transaction do not yet belong to any snapshot 325 * and will be fetched regardless). 326 * 327 * @param readOptions Read options. 328 * @param columnFamilyHandles {@link java.util.List} containing 329 * {@link org.rocksdb.ColumnFamilyHandle} instances. 330 * @param keys of keys for which values need to be retrieved. 331 * 332 * @return Array of values, one for each key 333 * 334 * @throws RocksDBException thrown if error happens in underlying 335 * native library. 336 * @throws IllegalArgumentException thrown if the size of passed keys is not 337 * equal to the amount of passed column family handles. 338 */ multiGet(final ReadOptions readOptions, final List<ColumnFamilyHandle> columnFamilyHandles, final byte[][] keys)339 public byte[][] multiGet(final ReadOptions readOptions, 340 final List<ColumnFamilyHandle> columnFamilyHandles, 341 final byte[][] keys) throws RocksDBException { 342 assert(isOwningHandle()); 343 // Check if key size equals cfList size. If not a exception must be 344 // thrown. If not a Segmentation fault happens. 345 if (keys.length != columnFamilyHandles.size()) { 346 throw new IllegalArgumentException( 347 "For each key there must be a ColumnFamilyHandle."); 348 } 349 if(keys.length == 0) { 350 return new byte[0][0]; 351 } 352 final long[] cfHandles = new long[columnFamilyHandles.size()]; 353 for (int i = 0; i < columnFamilyHandles.size(); i++) { 354 cfHandles[i] = columnFamilyHandles.get(i).nativeHandle_; 355 } 356 357 return multiGet(nativeHandle_, readOptions.nativeHandle_, 358 keys, cfHandles); 359 } 360 361 /** 362 * This function is similar to 363 * {@link RocksDB#multiGet(ReadOptions, List)} except it will 364 * also read pending changes in this transaction. 365 * Currently, this function will return Status::MergeInProgress if the most 366 * recent write to the queried key in this batch is a Merge. 367 * 368 * If {@link ReadOptions#snapshot()} is not set, the current version of the 369 * key will be read. Calling {@link #setSnapshot()} does not affect the 370 * version of the data returned. 371 * 372 * Note that setting {@link ReadOptions#setSnapshot(Snapshot)} will affect 373 * what is read from the DB but will NOT change which keys are read from this 374 * transaction (the keys in this transaction do not yet belong to any snapshot 375 * and will be fetched regardless). 376 * 377 * @param readOptions Read options.= 378 * {@link org.rocksdb.ColumnFamilyHandle} instances. 379 * @param keys of keys for which values need to be retrieved. 380 * 381 * @return Array of values, one for each key 382 * 383 * @throws RocksDBException thrown if error happens in underlying 384 * native library. 385 */ multiGet(final ReadOptions readOptions, final byte[][] keys)386 public byte[][] multiGet(final ReadOptions readOptions, 387 final byte[][] keys) throws RocksDBException { 388 assert(isOwningHandle()); 389 if(keys.length == 0) { 390 return new byte[0][0]; 391 } 392 393 return multiGet(nativeHandle_, readOptions.nativeHandle_, 394 keys); 395 } 396 397 /** 398 * Read this key and ensure that this transaction will only 399 * be able to be committed if this key is not written outside this 400 * transaction after it has first been read (or after the snapshot if a 401 * snapshot is set in this transaction). The transaction behavior is the 402 * same regardless of whether the key exists or not. 403 * 404 * Note: Currently, this function will return Status::MergeInProgress 405 * if the most recent write to the queried key in this batch is a Merge. 406 * 407 * The values returned by this function are similar to 408 * {@link RocksDB#get(ColumnFamilyHandle, ReadOptions, byte[])}. 409 * If value==nullptr, then this function will not read any data, but will 410 * still ensure that this key cannot be written to by outside of this 411 * transaction. 412 * 413 * If this transaction was created by an {@link OptimisticTransactionDB}, 414 * {@link #getForUpdate(ReadOptions, ColumnFamilyHandle, byte[], boolean)} 415 * could cause {@link #commit()} to fail. Otherwise, it could return any error 416 * that could be returned by 417 * {@link RocksDB#get(ColumnFamilyHandle, ReadOptions, byte[])}. 418 * 419 * If this transaction was created on a {@link TransactionDB}, an 420 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 421 * when: 422 * {@link Status.Code#Busy} if there is a write conflict, 423 * {@link Status.Code#TimedOut} if a lock could not be acquired, 424 * {@link Status.Code#TryAgain} if the memtable history size is not large 425 * enough. See 426 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 427 * {@link Status.Code#MergeInProgress} if merge operations cannot be 428 * resolved. 429 * 430 * @param readOptions Read options. 431 * @param columnFamilyHandle {@link org.rocksdb.ColumnFamilyHandle} 432 * instance 433 * @param key the key to retrieve the value for. 434 * @param exclusive true if the transaction should have exclusive access to 435 * the key, otherwise false for shared access. 436 * @param doValidate true if it should validate the snapshot before doing the read 437 * 438 * @return a byte array storing the value associated with the input key if 439 * any. null if it does not find the specified key. 440 * 441 * @throws RocksDBException thrown if error happens in underlying 442 * native library. 443 */ getForUpdate(final ReadOptions readOptions, final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final boolean exclusive, final boolean doValidate)444 public byte[] getForUpdate(final ReadOptions readOptions, 445 final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final boolean exclusive, 446 final boolean doValidate) throws RocksDBException { 447 assert (isOwningHandle()); 448 return getForUpdate(nativeHandle_, readOptions.nativeHandle_, key, key.length, 449 columnFamilyHandle.nativeHandle_, exclusive, doValidate); 450 } 451 452 /** 453 * Same as 454 * {@link #getForUpdate(ReadOptions, ColumnFamilyHandle, byte[], boolean, boolean)} 455 * with doValidate=true. 456 * 457 * @param readOptions Read options. 458 * @param columnFamilyHandle {@link org.rocksdb.ColumnFamilyHandle} 459 * instance 460 * @param key the key to retrieve the value for. 461 * @param exclusive true if the transaction should have exclusive access to 462 * the key, otherwise false for shared access. 463 * 464 * @return a byte array storing the value associated with the input key if 465 * any. null if it does not find the specified key. 466 * 467 * @throws RocksDBException thrown if error happens in underlying 468 * native library. 469 */ getForUpdate(final ReadOptions readOptions, final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final boolean exclusive)470 public byte[] getForUpdate(final ReadOptions readOptions, 471 final ColumnFamilyHandle columnFamilyHandle, final byte[] key, 472 final boolean exclusive) throws RocksDBException { 473 assert(isOwningHandle()); 474 return getForUpdate(nativeHandle_, readOptions.nativeHandle_, key, key.length, 475 columnFamilyHandle.nativeHandle_, exclusive, true /*doValidate*/); 476 } 477 478 /** 479 * Read this key and ensure that this transaction will only 480 * be able to be committed if this key is not written outside this 481 * transaction after it has first been read (or after the snapshot if a 482 * snapshot is set in this transaction). The transaction behavior is the 483 * same regardless of whether the key exists or not. 484 * 485 * Note: Currently, this function will return Status::MergeInProgress 486 * if the most recent write to the queried key in this batch is a Merge. 487 * 488 * The values returned by this function are similar to 489 * {@link RocksDB#get(ReadOptions, byte[])}. 490 * If value==nullptr, then this function will not read any data, but will 491 * still ensure that this key cannot be written to by outside of this 492 * transaction. 493 * 494 * If this transaction was created on an {@link OptimisticTransactionDB}, 495 * {@link #getForUpdate(ReadOptions, ColumnFamilyHandle, byte[], boolean)} 496 * could cause {@link #commit()} to fail. Otherwise, it could return any error 497 * that could be returned by 498 * {@link RocksDB#get(ReadOptions, byte[])}. 499 * 500 * If this transaction was created on a {@link TransactionDB}, an 501 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 502 * when: 503 * {@link Status.Code#Busy} if there is a write conflict, 504 * {@link Status.Code#TimedOut} if a lock could not be acquired, 505 * {@link Status.Code#TryAgain} if the memtable history size is not large 506 * enough. See 507 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 508 * {@link Status.Code#MergeInProgress} if merge operations cannot be 509 * resolved. 510 * 511 * @param readOptions Read options. 512 * @param key the key to retrieve the value for. 513 * @param exclusive true if the transaction should have exclusive access to 514 * the key, otherwise false for shared access. 515 * 516 * @return a byte array storing the value associated with the input key if 517 * any. null if it does not find the specified key. 518 * 519 * @throws RocksDBException thrown if error happens in underlying 520 * native library. 521 */ getForUpdate(final ReadOptions readOptions, final byte[] key, final boolean exclusive)522 public byte[] getForUpdate(final ReadOptions readOptions, final byte[] key, 523 final boolean exclusive) throws RocksDBException { 524 assert(isOwningHandle()); 525 return getForUpdate( 526 nativeHandle_, readOptions.nativeHandle_, key, key.length, exclusive, true /*doValidate*/); 527 } 528 529 /** 530 * A multi-key version of 531 * {@link #getForUpdate(ReadOptions, ColumnFamilyHandle, byte[], boolean)}. 532 * 533 * 534 * @param readOptions Read options. 535 * @param columnFamilyHandles {@link org.rocksdb.ColumnFamilyHandle} 536 * instances 537 * @param keys the keys to retrieve the values for. 538 * 539 * @return Array of values, one for each key 540 * 541 * @throws RocksDBException thrown if error happens in underlying 542 * native library. 543 */ multiGetForUpdate(final ReadOptions readOptions, final List<ColumnFamilyHandle> columnFamilyHandles, final byte[][] keys)544 public byte[][] multiGetForUpdate(final ReadOptions readOptions, 545 final List<ColumnFamilyHandle> columnFamilyHandles, 546 final byte[][] keys) throws RocksDBException { 547 assert(isOwningHandle()); 548 // Check if key size equals cfList size. If not a exception must be 549 // thrown. If not a Segmentation fault happens. 550 if (keys.length != columnFamilyHandles.size()){ 551 throw new IllegalArgumentException( 552 "For each key there must be a ColumnFamilyHandle."); 553 } 554 if(keys.length == 0) { 555 return new byte[0][0]; 556 } 557 final long[] cfHandles = new long[columnFamilyHandles.size()]; 558 for (int i = 0; i < columnFamilyHandles.size(); i++) { 559 cfHandles[i] = columnFamilyHandles.get(i).nativeHandle_; 560 } 561 return multiGetForUpdate(nativeHandle_, readOptions.nativeHandle_, 562 keys, cfHandles); 563 } 564 565 /** 566 * A multi-key version of {@link #getForUpdate(ReadOptions, byte[], boolean)}. 567 * 568 * 569 * @param readOptions Read options. 570 * @param keys the keys to retrieve the values for. 571 * 572 * @return Array of values, one for each key 573 * 574 * @throws RocksDBException thrown if error happens in underlying 575 * native library. 576 */ multiGetForUpdate(final ReadOptions readOptions, final byte[][] keys)577 public byte[][] multiGetForUpdate(final ReadOptions readOptions, 578 final byte[][] keys) throws RocksDBException { 579 assert(isOwningHandle()); 580 if(keys.length == 0) { 581 return new byte[0][0]; 582 } 583 584 return multiGetForUpdate(nativeHandle_, 585 readOptions.nativeHandle_, keys); 586 } 587 588 /** 589 * Returns an iterator that will iterate on all keys in the default 590 * column family including both keys in the DB and uncommitted keys in this 591 * transaction. 592 * 593 * Setting {@link ReadOptions#setSnapshot(Snapshot)} will affect what is read 594 * from the DB but will NOT change which keys are read from this transaction 595 * (the keys in this transaction do not yet belong to any snapshot and will be 596 * fetched regardless). 597 * 598 * Caller is responsible for deleting the returned Iterator. 599 * 600 * The returned iterator is only valid until {@link #commit()}, 601 * {@link #rollback()}, or {@link #rollbackToSavePoint()} is called. 602 * 603 * @param readOptions Read options. 604 * 605 * @return instance of iterator object. 606 */ getIterator(final ReadOptions readOptions)607 public RocksIterator getIterator(final ReadOptions readOptions) { 608 assert(isOwningHandle()); 609 return new RocksIterator(parent, getIterator(nativeHandle_, 610 readOptions.nativeHandle_)); 611 } 612 613 /** 614 * Returns an iterator that will iterate on all keys in the default 615 * column family including both keys in the DB and uncommitted keys in this 616 * transaction. 617 * 618 * Setting {@link ReadOptions#setSnapshot(Snapshot)} will affect what is read 619 * from the DB but will NOT change which keys are read from this transaction 620 * (the keys in this transaction do not yet belong to any snapshot and will be 621 * fetched regardless). 622 * 623 * Caller is responsible for calling {@link RocksIterator#close()} on 624 * the returned Iterator. 625 * 626 * The returned iterator is only valid until {@link #commit()}, 627 * {@link #rollback()}, or {@link #rollbackToSavePoint()} is called. 628 * 629 * @param readOptions Read options. 630 * @param columnFamilyHandle {@link org.rocksdb.ColumnFamilyHandle} 631 * instance 632 * 633 * @return instance of iterator object. 634 */ getIterator(final ReadOptions readOptions, final ColumnFamilyHandle columnFamilyHandle)635 public RocksIterator getIterator(final ReadOptions readOptions, 636 final ColumnFamilyHandle columnFamilyHandle) { 637 assert(isOwningHandle()); 638 return new RocksIterator(parent, getIterator(nativeHandle_, 639 readOptions.nativeHandle_, columnFamilyHandle.nativeHandle_)); 640 } 641 642 /** 643 * Similar to {@link RocksDB#put(ColumnFamilyHandle, byte[], byte[])}, but 644 * will also perform conflict checking on the keys be written. 645 * 646 * If this Transaction was created on an {@link OptimisticTransactionDB}, 647 * these functions should always succeed. 648 * 649 * If this Transaction was created on a {@link TransactionDB}, an 650 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 651 * when: 652 * {@link Status.Code#Busy} if there is a write conflict, 653 * {@link Status.Code#TimedOut} if a lock could not be acquired, 654 * {@link Status.Code#TryAgain} if the memtable history size is not large 655 * enough. See 656 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 657 * 658 * @param columnFamilyHandle The column family to put the key/value into 659 * @param key the specified key to be inserted. 660 * @param value the value associated with the specified key. 661 * @param assumeTracked true when it is expected that the key is already 662 * tracked. More specifically, it means the the key was previous tracked 663 * in the same savepoint, with the same exclusive flag, and at a lower 664 * sequence number. If valid then it skips ValidateSnapshot, 665 * throws an error otherwise. 666 * 667 * @throws RocksDBException when one of the TransactionalDB conditions 668 * described above occurs, or in the case of an unexpected error 669 */ put(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value, final boolean assumeTracked)670 public void put(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, 671 final byte[] value, final boolean assumeTracked) throws RocksDBException { 672 assert (isOwningHandle()); 673 put(nativeHandle_, key, key.length, value, value.length, 674 columnFamilyHandle.nativeHandle_, assumeTracked); 675 } 676 677 /** 678 * Similar to {@link #put(ColumnFamilyHandle, byte[], byte[], boolean)} 679 * but with {@code assumeTracked = false}. 680 * 681 * Will also perform conflict checking on the keys be written. 682 * 683 * If this Transaction was created on an {@link OptimisticTransactionDB}, 684 * these functions should always succeed. 685 * 686 * If this Transaction was created on a {@link TransactionDB}, an 687 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 688 * when: 689 * {@link Status.Code#Busy} if there is a write conflict, 690 * {@link Status.Code#TimedOut} if a lock could not be acquired, 691 * {@link Status.Code#TryAgain} if the memtable history size is not large 692 * enough. See 693 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 694 * 695 * @param columnFamilyHandle The column family to put the key/value into 696 * @param key the specified key to be inserted. 697 * @param value the value associated with the specified key. 698 * 699 * @throws RocksDBException when one of the TransactionalDB conditions 700 * described above occurs, or in the case of an unexpected error 701 */ put(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value)702 public void put(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, 703 final byte[] value) throws RocksDBException { 704 assert(isOwningHandle()); 705 put(nativeHandle_, key, key.length, value, value.length, 706 columnFamilyHandle.nativeHandle_, false); 707 } 708 709 /** 710 * Similar to {@link RocksDB#put(byte[], byte[])}, but 711 * will also perform conflict checking on the keys be written. 712 * 713 * If this Transaction was created on an {@link OptimisticTransactionDB}, 714 * these functions should always succeed. 715 * 716 * If this Transaction was created on a {@link TransactionDB}, an 717 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 718 * when: 719 * {@link Status.Code#Busy} if there is a write conflict, 720 * {@link Status.Code#TimedOut} if a lock could not be acquired, 721 * {@link Status.Code#TryAgain} if the memtable history size is not large 722 * enough. See 723 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 724 * 725 * @param key the specified key to be inserted. 726 * @param value the value associated with the specified key. 727 * 728 * @throws RocksDBException when one of the TransactionalDB conditions 729 * described above occurs, or in the case of an unexpected error 730 */ put(final byte[] key, final byte[] value)731 public void put(final byte[] key, final byte[] value) 732 throws RocksDBException { 733 assert(isOwningHandle()); 734 put(nativeHandle_, key, key.length, value, value.length); 735 } 736 737 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 738 /** 739 * Similar to {@link #put(ColumnFamilyHandle, byte[], byte[])} but allows 740 * you to specify the key and value in several parts that will be 741 * concatenated together. 742 * 743 * @param columnFamilyHandle The column family to put the key/value into 744 * @param keyParts the specified key to be inserted. 745 * @param valueParts the value associated with the specified key. 746 * @param assumeTracked true when it is expected that the key is already 747 * tracked. More specifically, it means the the key was previous tracked 748 * in the same savepoint, with the same exclusive flag, and at a lower 749 * sequence number. If valid then it skips ValidateSnapshot, 750 * throws an error otherwise. 751 * 752 * @throws RocksDBException when one of the TransactionalDB conditions 753 * described above occurs, or in the case of an unexpected error 754 */ put(final ColumnFamilyHandle columnFamilyHandle, final byte[][] keyParts, final byte[][] valueParts, final boolean assumeTracked)755 public void put(final ColumnFamilyHandle columnFamilyHandle, 756 final byte[][] keyParts, final byte[][] valueParts, 757 final boolean assumeTracked) throws RocksDBException { 758 assert (isOwningHandle()); 759 put(nativeHandle_, keyParts, keyParts.length, valueParts, valueParts.length, 760 columnFamilyHandle.nativeHandle_, assumeTracked); 761 } 762 763 /** 764 * Similar to {@link #put(ColumnFamilyHandle, byte[][], byte[][], boolean)} 765 * but with with {@code assumeTracked = false}. 766 * 767 * Allows you to specify the key and value in several parts that will be 768 * concatenated together. 769 * 770 * @param columnFamilyHandle The column family to put the key/value into 771 * @param keyParts the specified key to be inserted. 772 * @param valueParts the value associated with the specified key. 773 * 774 * @throws RocksDBException when one of the TransactionalDB conditions 775 * described above occurs, or in the case of an unexpected error 776 */ put(final ColumnFamilyHandle columnFamilyHandle, final byte[][] keyParts, final byte[][] valueParts)777 public void put(final ColumnFamilyHandle columnFamilyHandle, 778 final byte[][] keyParts, final byte[][] valueParts) 779 throws RocksDBException { 780 assert(isOwningHandle()); 781 put(nativeHandle_, keyParts, keyParts.length, valueParts, valueParts.length, 782 columnFamilyHandle.nativeHandle_, false); 783 } 784 785 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 786 /** 787 * Similar to {@link #put(byte[], byte[])} but allows 788 * you to specify the key and value in several parts that will be 789 * concatenated together 790 * 791 * @param keyParts the specified key to be inserted. 792 * @param valueParts the value associated with the specified key. 793 * 794 * @throws RocksDBException when one of the TransactionalDB conditions 795 * described above occurs, or in the case of an unexpected error 796 */ put(final byte[][] keyParts, final byte[][] valueParts)797 public void put(final byte[][] keyParts, final byte[][] valueParts) 798 throws RocksDBException { 799 assert(isOwningHandle()); 800 put(nativeHandle_, keyParts, keyParts.length, valueParts, 801 valueParts.length); 802 } 803 804 /** 805 * Similar to {@link RocksDB#merge(ColumnFamilyHandle, byte[], byte[])}, but 806 * will also perform conflict checking on the keys be written. 807 * 808 * If this Transaction was created on an {@link OptimisticTransactionDB}, 809 * these functions should always succeed. 810 * 811 * If this Transaction was created on a {@link TransactionDB}, an 812 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 813 * when: 814 * {@link Status.Code#Busy} if there is a write conflict, 815 * {@link Status.Code#TimedOut} if a lock could not be acquired, 816 * {@link Status.Code#TryAgain} if the memtable history size is not large 817 * enough. See 818 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 819 * 820 * @param columnFamilyHandle The column family to merge the key/value into 821 * @param key the specified key to be merged. 822 * @param value the value associated with the specified key. 823 * @param assumeTracked true when it is expected that the key is already 824 * tracked. More specifically, it means the the key was previous tracked 825 * in the same savepoint, with the same exclusive flag, and at a lower 826 * sequence number. If valid then it skips ValidateSnapshot, 827 * throws an error otherwise. 828 * 829 * @throws RocksDBException when one of the TransactionalDB conditions 830 * described above occurs, or in the case of an unexpected error 831 */ merge(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value, final boolean assumeTracked)832 public void merge(final ColumnFamilyHandle columnFamilyHandle, 833 final byte[] key, final byte[] value, final boolean assumeTracked) 834 throws RocksDBException { 835 assert (isOwningHandle()); 836 merge(nativeHandle_, key, key.length, value, value.length, 837 columnFamilyHandle.nativeHandle_, assumeTracked); 838 } 839 840 /** 841 * Similar to {@link #merge(ColumnFamilyHandle, byte[], byte[], boolean)} 842 * but with {@code assumeTracked = false}. 843 * 844 * Will also perform conflict checking on the keys be written. 845 * 846 * If this Transaction was created on an {@link OptimisticTransactionDB}, 847 * these functions should always succeed. 848 * 849 * If this Transaction was created on a {@link TransactionDB}, an 850 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 851 * when: 852 * {@link Status.Code#Busy} if there is a write conflict, 853 * {@link Status.Code#TimedOut} if a lock could not be acquired, 854 * {@link Status.Code#TryAgain} if the memtable history size is not large 855 * enough. See 856 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 857 * 858 * @param columnFamilyHandle The column family to merge the key/value into 859 * @param key the specified key to be merged. 860 * @param value the value associated with the specified key. 861 * 862 * @throws RocksDBException when one of the TransactionalDB conditions 863 * described above occurs, or in the case of an unexpected error 864 */ merge(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value)865 public void merge(final ColumnFamilyHandle columnFamilyHandle, 866 final byte[] key, final byte[] value) throws RocksDBException { 867 assert(isOwningHandle()); 868 merge(nativeHandle_, key, key.length, value, value.length, 869 columnFamilyHandle.nativeHandle_, false); 870 } 871 872 /** 873 * Similar to {@link RocksDB#merge(byte[], byte[])}, but 874 * will also perform conflict checking on the keys be written. 875 * 876 * If this Transaction was created on an {@link OptimisticTransactionDB}, 877 * these functions should always succeed. 878 * 879 * If this Transaction was created on a {@link TransactionDB}, an 880 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 881 * when: 882 * {@link Status.Code#Busy} if there is a write conflict, 883 * {@link Status.Code#TimedOut} if a lock could not be acquired, 884 * {@link Status.Code#TryAgain} if the memtable history size is not large 885 * enough. See 886 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 887 * 888 * @param key the specified key to be merged. 889 * @param value the value associated with the specified key. 890 * 891 * @throws RocksDBException when one of the TransactionalDB conditions 892 * described above occurs, or in the case of an unexpected error 893 */ merge(final byte[] key, final byte[] value)894 public void merge(final byte[] key, final byte[] value) 895 throws RocksDBException { 896 assert(isOwningHandle()); 897 merge(nativeHandle_, key, key.length, value, value.length); 898 } 899 900 /** 901 * Similar to {@link RocksDB#delete(ColumnFamilyHandle, byte[])}, but 902 * will also perform conflict checking on the keys be written. 903 * 904 * If this Transaction was created on an {@link OptimisticTransactionDB}, 905 * these functions should always succeed. 906 * 907 * If this Transaction was created on a {@link TransactionDB}, an 908 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 909 * when: 910 * {@link Status.Code#Busy} if there is a write conflict, 911 * {@link Status.Code#TimedOut} if a lock could not be acquired, 912 * {@link Status.Code#TryAgain} if the memtable history size is not large 913 * enough. See 914 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 915 * 916 * @param columnFamilyHandle The column family to delete the key/value from 917 * @param key the specified key to be deleted. 918 * @param assumeTracked true when it is expected that the key is already 919 * tracked. More specifically, it means the the key was previous tracked 920 * in the same savepoint, with the same exclusive flag, and at a lower 921 * sequence number. If valid then it skips ValidateSnapshot, 922 * throws an error otherwise. 923 * 924 * @throws RocksDBException when one of the TransactionalDB conditions 925 * described above occurs, or in the case of an unexpected error 926 */ delete(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final boolean assumeTracked)927 public void delete(final ColumnFamilyHandle columnFamilyHandle, 928 final byte[] key, final boolean assumeTracked) throws RocksDBException { 929 assert (isOwningHandle()); 930 delete(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_, 931 assumeTracked); 932 } 933 934 /** 935 * Similar to {@link #delete(ColumnFamilyHandle, byte[], boolean)} 936 * but with {@code assumeTracked = false}. 937 * 938 * Will also perform conflict checking on the keys be written. 939 * 940 * If this Transaction was created on an {@link OptimisticTransactionDB}, 941 * these functions should always succeed. 942 * 943 * If this Transaction was created on a {@link TransactionDB}, an 944 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 945 * when: 946 * {@link Status.Code#Busy} if there is a write conflict, 947 * {@link Status.Code#TimedOut} if a lock could not be acquired, 948 * {@link Status.Code#TryAgain} if the memtable history size is not large 949 * enough. See 950 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 951 * 952 * @param columnFamilyHandle The column family to delete the key/value from 953 * @param key the specified key to be deleted. 954 * 955 * @throws RocksDBException when one of the TransactionalDB conditions 956 * described above occurs, or in the case of an unexpected error 957 */ delete(final ColumnFamilyHandle columnFamilyHandle, final byte[] key)958 public void delete(final ColumnFamilyHandle columnFamilyHandle, 959 final byte[] key) throws RocksDBException { 960 assert(isOwningHandle()); 961 delete(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_, 962 /*assumeTracked*/ false); 963 } 964 965 /** 966 * Similar to {@link RocksDB#delete(byte[])}, but 967 * will also perform conflict checking on the keys be written. 968 * 969 * If this Transaction was created on an {@link OptimisticTransactionDB}, 970 * these functions should always succeed. 971 * 972 * If this Transaction was created on a {@link TransactionDB}, an 973 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 974 * when: 975 * {@link Status.Code#Busy} if there is a write conflict, 976 * {@link Status.Code#TimedOut} if a lock could not be acquired, 977 * {@link Status.Code#TryAgain} if the memtable history size is not large 978 * enough. See 979 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 980 * 981 * @param key the specified key to be deleted. 982 * 983 * @throws RocksDBException when one of the TransactionalDB conditions 984 * described above occurs, or in the case of an unexpected error 985 */ delete(final byte[] key)986 public void delete(final byte[] key) throws RocksDBException { 987 assert(isOwningHandle()); 988 delete(nativeHandle_, key, key.length); 989 } 990 991 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 992 /** 993 * Similar to {@link #delete(ColumnFamilyHandle, byte[])} but allows 994 * you to specify the key in several parts that will be 995 * concatenated together. 996 * 997 * @param columnFamilyHandle The column family to delete the key/value from 998 * @param keyParts the specified key to be deleted. 999 * @param assumeTracked true when it is expected that the key is already 1000 * tracked. More specifically, it means the the key was previous tracked 1001 * in the same savepoint, with the same exclusive flag, and at a lower 1002 * sequence number. If valid then it skips ValidateSnapshot, 1003 * throws an error otherwise. 1004 * 1005 * @throws RocksDBException when one of the TransactionalDB conditions 1006 * described above occurs, or in the case of an unexpected error 1007 */ delete(final ColumnFamilyHandle columnFamilyHandle, final byte[][] keyParts, final boolean assumeTracked)1008 public void delete(final ColumnFamilyHandle columnFamilyHandle, 1009 final byte[][] keyParts, final boolean assumeTracked) 1010 throws RocksDBException { 1011 assert (isOwningHandle()); 1012 delete(nativeHandle_, keyParts, keyParts.length, 1013 columnFamilyHandle.nativeHandle_, assumeTracked); 1014 } 1015 1016 /** 1017 * Similar to{@link #delete(ColumnFamilyHandle, byte[][], boolean)} 1018 * but with {@code assumeTracked = false}. 1019 * 1020 * Allows you to specify the key in several parts that will be 1021 * concatenated together. 1022 * 1023 * @param columnFamilyHandle The column family to delete the key/value from 1024 * @param keyParts the specified key to be deleted. 1025 * 1026 * @throws RocksDBException when one of the TransactionalDB conditions 1027 * described above occurs, or in the case of an unexpected error 1028 */ delete(final ColumnFamilyHandle columnFamilyHandle, final byte[][] keyParts)1029 public void delete(final ColumnFamilyHandle columnFamilyHandle, 1030 final byte[][] keyParts) throws RocksDBException { 1031 assert(isOwningHandle()); 1032 delete(nativeHandle_, keyParts, keyParts.length, 1033 columnFamilyHandle.nativeHandle_, false); 1034 } 1035 1036 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 1037 /** 1038 * Similar to {@link #delete(byte[])} but allows 1039 * you to specify key the in several parts that will be 1040 * concatenated together. 1041 * 1042 * @param keyParts the specified key to be deleted 1043 * 1044 * @throws RocksDBException when one of the TransactionalDB conditions 1045 * described above occurs, or in the case of an unexpected error 1046 */ delete(final byte[][] keyParts)1047 public void delete(final byte[][] keyParts) throws RocksDBException { 1048 assert(isOwningHandle()); 1049 delete(nativeHandle_, keyParts, keyParts.length); 1050 } 1051 1052 /** 1053 * Similar to {@link RocksDB#singleDelete(ColumnFamilyHandle, byte[])}, but 1054 * will also perform conflict checking on the keys be written. 1055 * 1056 * If this Transaction was created on an {@link OptimisticTransactionDB}, 1057 * these functions should always succeed. 1058 * 1059 * If this Transaction was created on a {@link TransactionDB}, an 1060 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 1061 * when: 1062 * {@link Status.Code#Busy} if there is a write conflict, 1063 * {@link Status.Code#TimedOut} if a lock could not be acquired, 1064 * {@link Status.Code#TryAgain} if the memtable history size is not large 1065 * enough. See 1066 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 1067 * 1068 * @param columnFamilyHandle The column family to delete the key/value from 1069 * @param key the specified key to be deleted. 1070 * @param assumeTracked true when it is expected that the key is already 1071 * tracked. More specifically, it means the the key was previous tracked 1072 * in the same savepoint, with the same exclusive flag, and at a lower 1073 * sequence number. If valid then it skips ValidateSnapshot, 1074 * throws an error otherwise. 1075 * 1076 * @throws RocksDBException when one of the TransactionalDB conditions 1077 * described above occurs, or in the case of an unexpected error 1078 */ 1079 @Experimental("Performance optimization for a very specific workload") singleDelete(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final boolean assumeTracked)1080 public void singleDelete(final ColumnFamilyHandle columnFamilyHandle, 1081 final byte[] key, final boolean assumeTracked) throws RocksDBException { 1082 assert (isOwningHandle()); 1083 singleDelete(nativeHandle_, key, key.length, 1084 columnFamilyHandle.nativeHandle_, assumeTracked); 1085 } 1086 1087 /** 1088 * Similar to {@link #singleDelete(ColumnFamilyHandle, byte[], boolean)} 1089 * but with {@code assumeTracked = false}. 1090 * 1091 * will also perform conflict checking on the keys be written. 1092 * 1093 * If this Transaction was created on an {@link OptimisticTransactionDB}, 1094 * these functions should always succeed. 1095 * 1096 * If this Transaction was created on a {@link TransactionDB}, an 1097 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 1098 * when: 1099 * {@link Status.Code#Busy} if there is a write conflict, 1100 * {@link Status.Code#TimedOut} if a lock could not be acquired, 1101 * {@link Status.Code#TryAgain} if the memtable history size is not large 1102 * enough. See 1103 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 1104 * 1105 * @param columnFamilyHandle The column family to delete the key/value from 1106 * @param key the specified key to be deleted. 1107 * 1108 * @throws RocksDBException when one of the TransactionalDB conditions 1109 * described above occurs, or in the case of an unexpected error 1110 */ 1111 @Experimental("Performance optimization for a very specific workload") singleDelete(final ColumnFamilyHandle columnFamilyHandle, final byte[] key)1112 public void singleDelete(final ColumnFamilyHandle columnFamilyHandle, 1113 final byte[] key) throws RocksDBException { 1114 assert(isOwningHandle()); 1115 singleDelete(nativeHandle_, key, key.length, 1116 columnFamilyHandle.nativeHandle_, false); 1117 } 1118 1119 /** 1120 * Similar to {@link RocksDB#singleDelete(byte[])}, but 1121 * will also perform conflict checking on the keys be written. 1122 * 1123 * If this Transaction was created on an {@link OptimisticTransactionDB}, 1124 * these functions should always succeed. 1125 * 1126 * If this Transaction was created on a {@link TransactionDB}, an 1127 * {@link RocksDBException} may be thrown with an accompanying {@link Status} 1128 * when: 1129 * {@link Status.Code#Busy} if there is a write conflict, 1130 * {@link Status.Code#TimedOut} if a lock could not be acquired, 1131 * {@link Status.Code#TryAgain} if the memtable history size is not large 1132 * enough. See 1133 * {@link ColumnFamilyOptions#maxWriteBufferNumberToMaintain()} 1134 * 1135 * @param key the specified key to be deleted. 1136 * 1137 * @throws RocksDBException when one of the TransactionalDB conditions 1138 * described above occurs, or in the case of an unexpected error 1139 */ 1140 @Experimental("Performance optimization for a very specific workload") singleDelete(final byte[] key)1141 public void singleDelete(final byte[] key) throws RocksDBException { 1142 assert(isOwningHandle()); 1143 singleDelete(nativeHandle_, key, key.length); 1144 } 1145 1146 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 1147 /** 1148 * Similar to {@link #singleDelete(ColumnFamilyHandle, byte[])} but allows 1149 * you to specify the key in several parts that will be 1150 * concatenated together. 1151 * 1152 * @param columnFamilyHandle The column family to delete the key/value from 1153 * @param keyParts the specified key to be deleted. 1154 * @param assumeTracked true when it is expected that the key is already 1155 * tracked. More specifically, it means the the key was previous tracked 1156 * in the same savepoint, with the same exclusive flag, and at a lower 1157 * sequence number. If valid then it skips ValidateSnapshot, 1158 * throws an error otherwise. 1159 * 1160 * @throws RocksDBException when one of the TransactionalDB conditions 1161 * described above occurs, or in the case of an unexpected error 1162 */ 1163 @Experimental("Performance optimization for a very specific workload") singleDelete(final ColumnFamilyHandle columnFamilyHandle, final byte[][] keyParts, final boolean assumeTracked)1164 public void singleDelete(final ColumnFamilyHandle columnFamilyHandle, 1165 final byte[][] keyParts, final boolean assumeTracked) 1166 throws RocksDBException { 1167 assert (isOwningHandle()); 1168 singleDelete(nativeHandle_, keyParts, keyParts.length, 1169 columnFamilyHandle.nativeHandle_, assumeTracked); 1170 } 1171 1172 /** 1173 * Similar to{@link #singleDelete(ColumnFamilyHandle, byte[][], boolean)} 1174 * but with {@code assumeTracked = false}. 1175 * 1176 * Allows you to specify the key in several parts that will be 1177 * concatenated together. 1178 * 1179 * @param columnFamilyHandle The column family to delete the key/value from 1180 * @param keyParts the specified key to be deleted. 1181 * 1182 * @throws RocksDBException when one of the TransactionalDB conditions 1183 * described above occurs, or in the case of an unexpected error 1184 */ 1185 @Experimental("Performance optimization for a very specific workload") singleDelete(final ColumnFamilyHandle columnFamilyHandle, final byte[][] keyParts)1186 public void singleDelete(final ColumnFamilyHandle columnFamilyHandle, 1187 final byte[][] keyParts) throws RocksDBException { 1188 assert(isOwningHandle()); 1189 singleDelete(nativeHandle_, keyParts, keyParts.length, 1190 columnFamilyHandle.nativeHandle_, false); 1191 } 1192 1193 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 1194 /** 1195 * Similar to {@link #singleDelete(byte[])} but allows 1196 * you to specify the key in several parts that will be 1197 * concatenated together. 1198 * 1199 * @param keyParts the specified key to be deleted. 1200 * 1201 * @throws RocksDBException when one of the TransactionalDB conditions 1202 * described above occurs, or in the case of an unexpected error 1203 */ 1204 @Experimental("Performance optimization for a very specific workload") singleDelete(final byte[][] keyParts)1205 public void singleDelete(final byte[][] keyParts) throws RocksDBException { 1206 assert(isOwningHandle()); 1207 singleDelete(nativeHandle_, keyParts, keyParts.length); 1208 } 1209 1210 /** 1211 * Similar to {@link RocksDB#put(ColumnFamilyHandle, byte[], byte[])}, 1212 * but operates on the transactions write batch. This write will only happen 1213 * if this transaction gets committed successfully. 1214 * 1215 * Unlike {@link #put(ColumnFamilyHandle, byte[], byte[])} no conflict 1216 * checking will be performed for this key. 1217 * 1218 * If this Transaction was created on a {@link TransactionDB}, this function 1219 * will still acquire locks necessary to make sure this write doesn't cause 1220 * conflicts in other transactions; This may cause a {@link RocksDBException} 1221 * with associated {@link Status.Code#Busy}. 1222 * 1223 * @param columnFamilyHandle The column family to put the key/value into 1224 * @param key the specified key to be inserted. 1225 * @param value the value associated with the specified key. 1226 * 1227 * @throws RocksDBException when one of the TransactionalDB conditions 1228 * described above occurs, or in the case of an unexpected error 1229 */ putUntracked(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value)1230 public void putUntracked(final ColumnFamilyHandle columnFamilyHandle, 1231 final byte[] key, final byte[] value) throws RocksDBException { 1232 assert(isOwningHandle()); 1233 putUntracked(nativeHandle_, key, key.length, value, value.length, 1234 columnFamilyHandle.nativeHandle_); 1235 } 1236 1237 /** 1238 * Similar to {@link RocksDB#put(byte[], byte[])}, 1239 * but operates on the transactions write batch. This write will only happen 1240 * if this transaction gets committed successfully. 1241 * 1242 * Unlike {@link #put(byte[], byte[])} no conflict 1243 * checking will be performed for this key. 1244 * 1245 * If this Transaction was created on a {@link TransactionDB}, this function 1246 * will still acquire locks necessary to make sure this write doesn't cause 1247 * conflicts in other transactions; This may cause a {@link RocksDBException} 1248 * with associated {@link Status.Code#Busy}. 1249 * 1250 * @param key the specified key to be inserted. 1251 * @param value the value associated with the specified key. 1252 * 1253 * @throws RocksDBException when one of the TransactionalDB conditions 1254 * described above occurs, or in the case of an unexpected error 1255 */ putUntracked(final byte[] key, final byte[] value)1256 public void putUntracked(final byte[] key, final byte[] value) 1257 throws RocksDBException { 1258 assert(isOwningHandle()); 1259 putUntracked(nativeHandle_, key, key.length, value, value.length); 1260 } 1261 1262 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 1263 /** 1264 * Similar to {@link #putUntracked(ColumnFamilyHandle, byte[], byte[])} but 1265 * allows you to specify the key and value in several parts that will be 1266 * concatenated together. 1267 * 1268 * @param columnFamilyHandle The column family to put the key/value into 1269 * @param keyParts the specified key to be inserted. 1270 * @param valueParts the value associated with the specified key. 1271 * 1272 * @throws RocksDBException when one of the TransactionalDB conditions 1273 * described above occurs, or in the case of an unexpected error 1274 */ putUntracked(final ColumnFamilyHandle columnFamilyHandle, final byte[][] keyParts, final byte[][] valueParts)1275 public void putUntracked(final ColumnFamilyHandle columnFamilyHandle, 1276 final byte[][] keyParts, final byte[][] valueParts) 1277 throws RocksDBException { 1278 assert(isOwningHandle()); 1279 putUntracked(nativeHandle_, keyParts, keyParts.length, valueParts, 1280 valueParts.length, columnFamilyHandle.nativeHandle_); 1281 } 1282 1283 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 1284 /** 1285 * Similar to {@link #putUntracked(byte[], byte[])} but 1286 * allows you to specify the key and value in several parts that will be 1287 * concatenated together. 1288 * 1289 * @param keyParts the specified key to be inserted. 1290 * @param valueParts the value associated with the specified key. 1291 * 1292 * @throws RocksDBException when one of the TransactionalDB conditions 1293 * described above occurs, or in the case of an unexpected error 1294 */ putUntracked(final byte[][] keyParts, final byte[][] valueParts)1295 public void putUntracked(final byte[][] keyParts, final byte[][] valueParts) 1296 throws RocksDBException { 1297 assert(isOwningHandle()); 1298 putUntracked(nativeHandle_, keyParts, keyParts.length, valueParts, 1299 valueParts.length); 1300 } 1301 1302 /** 1303 * Similar to {@link RocksDB#merge(ColumnFamilyHandle, byte[], byte[])}, 1304 * but operates on the transactions write batch. This write will only happen 1305 * if this transaction gets committed successfully. 1306 * 1307 * Unlike {@link #merge(ColumnFamilyHandle, byte[], byte[])} no conflict 1308 * checking will be performed for this key. 1309 * 1310 * If this Transaction was created on a {@link TransactionDB}, this function 1311 * will still acquire locks necessary to make sure this write doesn't cause 1312 * conflicts in other transactions; This may cause a {@link RocksDBException} 1313 * with associated {@link Status.Code#Busy}. 1314 * 1315 * @param columnFamilyHandle The column family to merge the key/value into 1316 * @param key the specified key to be merged. 1317 * @param value the value associated with the specified key. 1318 * 1319 * @throws RocksDBException when one of the TransactionalDB conditions 1320 * described above occurs, or in the case of an unexpected error 1321 */ mergeUntracked(final ColumnFamilyHandle columnFamilyHandle, final byte[] key, final byte[] value)1322 public void mergeUntracked(final ColumnFamilyHandle columnFamilyHandle, 1323 final byte[] key, final byte[] value) throws RocksDBException { 1324 mergeUntracked(nativeHandle_, key, key.length, value, value.length, 1325 columnFamilyHandle.nativeHandle_); 1326 } 1327 1328 /** 1329 * Similar to {@link RocksDB#merge(byte[], byte[])}, 1330 * but operates on the transactions write batch. This write will only happen 1331 * if this transaction gets committed successfully. 1332 * 1333 * Unlike {@link #merge(byte[], byte[])} no conflict 1334 * checking will be performed for this key. 1335 * 1336 * If this Transaction was created on a {@link TransactionDB}, this function 1337 * will still acquire locks necessary to make sure this write doesn't cause 1338 * conflicts in other transactions; This may cause a {@link RocksDBException} 1339 * with associated {@link Status.Code#Busy}. 1340 * 1341 * @param key the specified key to be merged. 1342 * @param value the value associated with the specified key. 1343 * 1344 * @throws RocksDBException when one of the TransactionalDB conditions 1345 * described above occurs, or in the case of an unexpected error 1346 */ mergeUntracked(final byte[] key, final byte[] value)1347 public void mergeUntracked(final byte[] key, final byte[] value) 1348 throws RocksDBException { 1349 assert(isOwningHandle()); 1350 mergeUntracked(nativeHandle_, key, key.length, value, value.length); 1351 } 1352 1353 /** 1354 * Similar to {@link RocksDB#delete(ColumnFamilyHandle, byte[])}, 1355 * but operates on the transactions write batch. This write will only happen 1356 * if this transaction gets committed successfully. 1357 * 1358 * Unlike {@link #delete(ColumnFamilyHandle, byte[])} no conflict 1359 * checking will be performed for this key. 1360 * 1361 * If this Transaction was created on a {@link TransactionDB}, this function 1362 * will still acquire locks necessary to make sure this write doesn't cause 1363 * conflicts in other transactions; This may cause a {@link RocksDBException} 1364 * with associated {@link Status.Code#Busy}. 1365 * 1366 * @param columnFamilyHandle The column family to delete the key/value from 1367 * @param key the specified key to be deleted. 1368 * 1369 * @throws RocksDBException when one of the TransactionalDB conditions 1370 * described above occurs, or in the case of an unexpected error 1371 */ deleteUntracked(final ColumnFamilyHandle columnFamilyHandle, final byte[] key)1372 public void deleteUntracked(final ColumnFamilyHandle columnFamilyHandle, 1373 final byte[] key) throws RocksDBException { 1374 assert(isOwningHandle()); 1375 deleteUntracked(nativeHandle_, key, key.length, 1376 columnFamilyHandle.nativeHandle_); 1377 } 1378 1379 /** 1380 * Similar to {@link RocksDB#delete(byte[])}, 1381 * but operates on the transactions write batch. This write will only happen 1382 * if this transaction gets committed successfully. 1383 * 1384 * Unlike {@link #delete(byte[])} no conflict 1385 * checking will be performed for this key. 1386 * 1387 * If this Transaction was created on a {@link TransactionDB}, this function 1388 * will still acquire locks necessary to make sure this write doesn't cause 1389 * conflicts in other transactions; This may cause a {@link RocksDBException} 1390 * with associated {@link Status.Code#Busy}. 1391 * 1392 * @param key the specified key to be deleted. 1393 * 1394 * @throws RocksDBException when one of the TransactionalDB conditions 1395 * described above occurs, or in the case of an unexpected error 1396 */ deleteUntracked(final byte[] key)1397 public void deleteUntracked(final byte[] key) throws RocksDBException { 1398 assert(isOwningHandle()); 1399 deleteUntracked(nativeHandle_, key, key.length); 1400 } 1401 1402 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 1403 /** 1404 * Similar to {@link #deleteUntracked(ColumnFamilyHandle, byte[])} but allows 1405 * you to specify the key in several parts that will be 1406 * concatenated together. 1407 * 1408 * @param columnFamilyHandle The column family to delete the key/value from 1409 * @param keyParts the specified key to be deleted. 1410 * 1411 * @throws RocksDBException when one of the TransactionalDB conditions 1412 * described above occurs, or in the case of an unexpected error 1413 */ deleteUntracked(final ColumnFamilyHandle columnFamilyHandle, final byte[][] keyParts)1414 public void deleteUntracked(final ColumnFamilyHandle columnFamilyHandle, 1415 final byte[][] keyParts) throws RocksDBException { 1416 assert(isOwningHandle()); 1417 deleteUntracked(nativeHandle_, keyParts, keyParts.length, 1418 columnFamilyHandle.nativeHandle_); 1419 } 1420 1421 //TODO(AR) refactor if we implement org.rocksdb.SliceParts in future 1422 /** 1423 * Similar to {@link #deleteUntracked(byte[])} but allows 1424 * you to specify the key in several parts that will be 1425 * concatenated together. 1426 * 1427 * @param keyParts the specified key to be deleted. 1428 * 1429 * @throws RocksDBException when one of the TransactionalDB conditions 1430 * described above occurs, or in the case of an unexpected error 1431 */ deleteUntracked(final byte[][] keyParts)1432 public void deleteUntracked(final byte[][] keyParts) throws RocksDBException { 1433 assert(isOwningHandle()); 1434 deleteUntracked(nativeHandle_, keyParts, keyParts.length); 1435 } 1436 1437 /** 1438 * Similar to {@link WriteBatch#putLogData(byte[])} 1439 * 1440 * @param blob binary object to be inserted 1441 */ putLogData(final byte[] blob)1442 public void putLogData(final byte[] blob) { 1443 assert(isOwningHandle()); 1444 putLogData(nativeHandle_, blob, blob.length); 1445 } 1446 1447 /** 1448 * By default, all put/merge/delete operations will be indexed in the 1449 * transaction so that get/getForUpdate/getIterator can search for these 1450 * keys. 1451 * 1452 * If the caller does not want to fetch the keys about to be written, 1453 * they may want to avoid indexing as a performance optimization. 1454 * Calling {@link #disableIndexing()} will turn off indexing for all future 1455 * put/merge/delete operations until {@link #enableIndexing()} is called. 1456 * 1457 * If a key is put/merge/deleted after {@link #disableIndexing()} is called 1458 * and then is fetched via get/getForUpdate/getIterator, the result of the 1459 * fetch is undefined. 1460 */ disableIndexing()1461 public void disableIndexing() { 1462 assert(isOwningHandle()); 1463 disableIndexing(nativeHandle_); 1464 } 1465 1466 /** 1467 * Re-enables indexing after a previous call to {@link #disableIndexing()} 1468 */ enableIndexing()1469 public void enableIndexing() { 1470 assert(isOwningHandle()); 1471 enableIndexing(nativeHandle_); 1472 } 1473 1474 /** 1475 * Returns the number of distinct Keys being tracked by this transaction. 1476 * If this transaction was created by a {@link TransactionDB}, this is the 1477 * number of keys that are currently locked by this transaction. 1478 * If this transaction was created by an {@link OptimisticTransactionDB}, 1479 * this is the number of keys that need to be checked for conflicts at commit 1480 * time. 1481 * 1482 * @return the number of distinct Keys being tracked by this transaction 1483 */ getNumKeys()1484 public long getNumKeys() { 1485 assert(isOwningHandle()); 1486 return getNumKeys(nativeHandle_); 1487 } 1488 1489 /** 1490 * Returns the number of puts that have been applied to this 1491 * transaction so far. 1492 * 1493 * @return the number of puts that have been applied to this transaction 1494 */ getNumPuts()1495 public long getNumPuts() { 1496 assert(isOwningHandle()); 1497 return getNumPuts(nativeHandle_); 1498 } 1499 1500 /** 1501 * Returns the number of deletes that have been applied to this 1502 * transaction so far. 1503 * 1504 * @return the number of deletes that have been applied to this transaction 1505 */ getNumDeletes()1506 public long getNumDeletes() { 1507 assert(isOwningHandle()); 1508 return getNumDeletes(nativeHandle_); 1509 } 1510 1511 /** 1512 * Returns the number of merges that have been applied to this 1513 * transaction so far. 1514 * 1515 * @return the number of merges that have been applied to this transaction 1516 */ getNumMerges()1517 public long getNumMerges() { 1518 assert(isOwningHandle()); 1519 return getNumMerges(nativeHandle_); 1520 } 1521 1522 /** 1523 * Returns the elapsed time in milliseconds since this Transaction began. 1524 * 1525 * @return the elapsed time in milliseconds since this transaction began. 1526 */ getElapsedTime()1527 public long getElapsedTime() { 1528 assert(isOwningHandle()); 1529 return getElapsedTime(nativeHandle_); 1530 } 1531 1532 /** 1533 * Fetch the underlying write batch that contains all pending changes to be 1534 * committed. 1535 * 1536 * Note: You should not write or delete anything from the batch directly and 1537 * should only use the functions in the {@link Transaction} class to 1538 * write to this transaction. 1539 * 1540 * @return The write batch 1541 */ getWriteBatch()1542 public WriteBatchWithIndex getWriteBatch() { 1543 assert(isOwningHandle()); 1544 final WriteBatchWithIndex writeBatchWithIndex = 1545 new WriteBatchWithIndex(getWriteBatch(nativeHandle_)); 1546 return writeBatchWithIndex; 1547 } 1548 1549 /** 1550 * Change the value of {@link TransactionOptions#getLockTimeout()} 1551 * (in milliseconds) for this transaction. 1552 * 1553 * Has no effect on OptimisticTransactions. 1554 * 1555 * @param lockTimeout the timeout (in milliseconds) for locks used by this 1556 * transaction. 1557 */ setLockTimeout(final long lockTimeout)1558 public void setLockTimeout(final long lockTimeout) { 1559 assert(isOwningHandle()); 1560 setLockTimeout(nativeHandle_, lockTimeout); 1561 } 1562 1563 /** 1564 * Return the WriteOptions that will be used during {@link #commit()}. 1565 * 1566 * @return the WriteOptions that will be used 1567 */ getWriteOptions()1568 public WriteOptions getWriteOptions() { 1569 assert(isOwningHandle()); 1570 final WriteOptions writeOptions = 1571 new WriteOptions(getWriteOptions(nativeHandle_)); 1572 return writeOptions; 1573 } 1574 1575 /** 1576 * Reset the WriteOptions that will be used during {@link #commit()}. 1577 * 1578 * @param writeOptions The new WriteOptions 1579 */ setWriteOptions(final WriteOptions writeOptions)1580 public void setWriteOptions(final WriteOptions writeOptions) { 1581 assert(isOwningHandle()); 1582 setWriteOptions(nativeHandle_, writeOptions.nativeHandle_); 1583 } 1584 1585 /** 1586 * If this key was previously fetched in this transaction using 1587 * {@link #getForUpdate(ReadOptions, ColumnFamilyHandle, byte[], boolean)}/ 1588 * {@link #multiGetForUpdate(ReadOptions, List, byte[][])}, calling 1589 * {@link #undoGetForUpdate(ColumnFamilyHandle, byte[])} will tell 1590 * the transaction that it no longer needs to do any conflict checking 1591 * for this key. 1592 * 1593 * If a key has been fetched N times via 1594 * {@link #getForUpdate(ReadOptions, ColumnFamilyHandle, byte[], boolean)}/ 1595 * {@link #multiGetForUpdate(ReadOptions, List, byte[][])}, then 1596 * {@link #undoGetForUpdate(ColumnFamilyHandle, byte[])} will only have an 1597 * effect if it is also called N times. If this key has been written to in 1598 * this transaction, {@link #undoGetForUpdate(ColumnFamilyHandle, byte[])} 1599 * will have no effect. 1600 * 1601 * If {@link #setSavePoint()} has been called after the 1602 * {@link #getForUpdate(ReadOptions, ColumnFamilyHandle, byte[], boolean)}, 1603 * {@link #undoGetForUpdate(ColumnFamilyHandle, byte[])} will not have any 1604 * effect. 1605 * 1606 * If this Transaction was created by an {@link OptimisticTransactionDB}, 1607 * calling {@link #undoGetForUpdate(ColumnFamilyHandle, byte[])} can affect 1608 * whether this key is conflict checked at commit time. 1609 * If this Transaction was created by a {@link TransactionDB}, 1610 * calling {@link #undoGetForUpdate(ColumnFamilyHandle, byte[])} may release 1611 * any held locks for this key. 1612 * 1613 * @param columnFamilyHandle {@link org.rocksdb.ColumnFamilyHandle} 1614 * instance 1615 * @param key the key to retrieve the value for. 1616 */ undoGetForUpdate(final ColumnFamilyHandle columnFamilyHandle, final byte[] key)1617 public void undoGetForUpdate(final ColumnFamilyHandle columnFamilyHandle, 1618 final byte[] key) { 1619 assert(isOwningHandle()); 1620 undoGetForUpdate(nativeHandle_, key, key.length, columnFamilyHandle.nativeHandle_); 1621 } 1622 1623 /** 1624 * If this key was previously fetched in this transaction using 1625 * {@link #getForUpdate(ReadOptions, byte[], boolean)}/ 1626 * {@link #multiGetForUpdate(ReadOptions, List, byte[][])}, calling 1627 * {@link #undoGetForUpdate(byte[])} will tell 1628 * the transaction that it no longer needs to do any conflict checking 1629 * for this key. 1630 * 1631 * If a key has been fetched N times via 1632 * {@link #getForUpdate(ReadOptions, byte[], boolean)}/ 1633 * {@link #multiGetForUpdate(ReadOptions, List, byte[][])}, then 1634 * {@link #undoGetForUpdate(byte[])} will only have an 1635 * effect if it is also called N times. If this key has been written to in 1636 * this transaction, {@link #undoGetForUpdate(byte[])} 1637 * will have no effect. 1638 * 1639 * If {@link #setSavePoint()} has been called after the 1640 * {@link #getForUpdate(ReadOptions, byte[], boolean)}, 1641 * {@link #undoGetForUpdate(byte[])} will not have any 1642 * effect. 1643 * 1644 * If this Transaction was created by an {@link OptimisticTransactionDB}, 1645 * calling {@link #undoGetForUpdate(byte[])} can affect 1646 * whether this key is conflict checked at commit time. 1647 * If this Transaction was created by a {@link TransactionDB}, 1648 * calling {@link #undoGetForUpdate(byte[])} may release 1649 * any held locks for this key. 1650 * 1651 * @param key the key to retrieve the value for. 1652 */ undoGetForUpdate(final byte[] key)1653 public void undoGetForUpdate(final byte[] key) { 1654 assert(isOwningHandle()); 1655 undoGetForUpdate(nativeHandle_, key, key.length); 1656 } 1657 1658 /** 1659 * Adds the keys from the WriteBatch to the transaction 1660 * 1661 * @param writeBatch The write batch to read from 1662 * 1663 * @throws RocksDBException if an error occurs whilst rebuilding from the 1664 * write batch. 1665 */ rebuildFromWriteBatch(final WriteBatch writeBatch)1666 public void rebuildFromWriteBatch(final WriteBatch writeBatch) 1667 throws RocksDBException { 1668 assert(isOwningHandle()); 1669 rebuildFromWriteBatch(nativeHandle_, writeBatch.nativeHandle_); 1670 } 1671 1672 /** 1673 * Get the Commit time Write Batch. 1674 * 1675 * @return the commit time write batch. 1676 */ getCommitTimeWriteBatch()1677 public WriteBatch getCommitTimeWriteBatch() { 1678 assert(isOwningHandle()); 1679 final WriteBatch writeBatch = 1680 new WriteBatch(getCommitTimeWriteBatch(nativeHandle_)); 1681 return writeBatch; 1682 } 1683 1684 /** 1685 * Set the log number. 1686 * 1687 * @param logNumber the log number 1688 */ setLogNumber(final long logNumber)1689 public void setLogNumber(final long logNumber) { 1690 assert(isOwningHandle()); 1691 setLogNumber(nativeHandle_, logNumber); 1692 } 1693 1694 /** 1695 * Get the log number. 1696 * 1697 * @return the log number 1698 */ getLogNumber()1699 public long getLogNumber() { 1700 assert(isOwningHandle()); 1701 return getLogNumber(nativeHandle_); 1702 } 1703 1704 /** 1705 * Set the name of the transaction. 1706 * 1707 * @param transactionName the name of the transaction 1708 * 1709 * @throws RocksDBException if an error occurs when setting the transaction 1710 * name. 1711 */ setName(final String transactionName)1712 public void setName(final String transactionName) throws RocksDBException { 1713 assert(isOwningHandle()); 1714 setName(nativeHandle_, transactionName); 1715 } 1716 1717 /** 1718 * Get the name of the transaction. 1719 * 1720 * @return the name of the transaction 1721 */ getName()1722 public String getName() { 1723 assert(isOwningHandle()); 1724 return getName(nativeHandle_); 1725 } 1726 1727 /** 1728 * Get the ID of the transaction. 1729 * 1730 * @return the ID of the transaction. 1731 */ getID()1732 public long getID() { 1733 assert(isOwningHandle()); 1734 return getID(nativeHandle_); 1735 } 1736 1737 /** 1738 * Determine if a deadlock has been detected. 1739 * 1740 * @return true if a deadlock has been detected. 1741 */ isDeadlockDetect()1742 public boolean isDeadlockDetect() { 1743 assert(isOwningHandle()); 1744 return isDeadlockDetect(nativeHandle_); 1745 } 1746 1747 /** 1748 * Get the list of waiting transactions. 1749 * 1750 * @return The list of waiting transactions. 1751 */ getWaitingTxns()1752 public WaitingTransactions getWaitingTxns() { 1753 assert(isOwningHandle()); 1754 return getWaitingTxns(nativeHandle_); 1755 } 1756 1757 /** 1758 * Get the execution status of the transaction. 1759 * 1760 * NOTE: The execution status of an Optimistic Transaction 1761 * never changes. This is only useful for non-optimistic transactions! 1762 * 1763 * @return The execution status of the transaction 1764 */ getState()1765 public TransactionState getState() { 1766 assert(isOwningHandle()); 1767 return TransactionState.getTransactionState( 1768 getState(nativeHandle_)); 1769 } 1770 1771 /** 1772 * The globally unique id with which the transaction is identified. This id 1773 * might or might not be set depending on the implementation. Similarly the 1774 * implementation decides the point in lifetime of a transaction at which it 1775 * assigns the id. Although currently it is the case, the id is not guaranteed 1776 * to remain the same across restarts. 1777 * 1778 * @return the transaction id. 1779 */ 1780 @Experimental("NOTE: Experimental feature") getId()1781 public long getId() { 1782 assert(isOwningHandle()); 1783 return getId(nativeHandle_); 1784 } 1785 1786 public enum TransactionState { 1787 STARTED((byte)0), 1788 AWAITING_PREPARE((byte)1), 1789 PREPARED((byte)2), 1790 AWAITING_COMMIT((byte)3), 1791 COMMITED((byte)4), 1792 AWAITING_ROLLBACK((byte)5), 1793 ROLLEDBACK((byte)6), 1794 LOCKS_STOLEN((byte)7); 1795 1796 private final byte value; 1797 TransactionState(final byte value)1798 TransactionState(final byte value) { 1799 this.value = value; 1800 } 1801 1802 /** 1803 * Get TransactionState by byte value. 1804 * 1805 * @param value byte representation of TransactionState. 1806 * 1807 * @return {@link org.rocksdb.Transaction.TransactionState} instance or null. 1808 * @throws java.lang.IllegalArgumentException if an invalid 1809 * value is provided. 1810 */ getTransactionState(final byte value)1811 public static TransactionState getTransactionState(final byte value) { 1812 for (final TransactionState transactionState : TransactionState.values()) { 1813 if (transactionState.value == value){ 1814 return transactionState; 1815 } 1816 } 1817 throw new IllegalArgumentException( 1818 "Illegal value provided for TransactionState."); 1819 } 1820 } 1821 1822 /** 1823 * Called from C++ native method {@link #getWaitingTxns(long)} 1824 * to construct a WaitingTransactions object. 1825 * 1826 * @param columnFamilyId The id of the {@link ColumnFamilyHandle} 1827 * @param key The key 1828 * @param transactionIds The transaction ids 1829 * 1830 * @return The waiting transactions 1831 */ newWaitingTransactions( final long columnFamilyId, final String key, final long[] transactionIds)1832 private WaitingTransactions newWaitingTransactions( 1833 final long columnFamilyId, final String key, 1834 final long[] transactionIds) { 1835 return new WaitingTransactions(columnFamilyId, key, transactionIds); 1836 } 1837 1838 public static class WaitingTransactions { 1839 private final long columnFamilyId; 1840 private final String key; 1841 private final long[] transactionIds; 1842 WaitingTransactions(final long columnFamilyId, final String key, final long[] transactionIds)1843 private WaitingTransactions(final long columnFamilyId, final String key, 1844 final long[] transactionIds) { 1845 this.columnFamilyId = columnFamilyId; 1846 this.key = key; 1847 this.transactionIds = transactionIds; 1848 } 1849 1850 /** 1851 * Get the Column Family ID. 1852 * 1853 * @return The column family ID 1854 */ getColumnFamilyId()1855 public long getColumnFamilyId() { 1856 return columnFamilyId; 1857 } 1858 1859 /** 1860 * Get the key on which the transactions are waiting. 1861 * 1862 * @return The key 1863 */ getKey()1864 public String getKey() { 1865 return key; 1866 } 1867 1868 /** 1869 * Get the IDs of the waiting transactions. 1870 * 1871 * @return The IDs of the waiting transactions 1872 */ getTransactionIds()1873 public long[] getTransactionIds() { 1874 return transactionIds; 1875 } 1876 } 1877 setSnapshot(final long handle)1878 private native void setSnapshot(final long handle); setSnapshotOnNextOperation(final long handle)1879 private native void setSnapshotOnNextOperation(final long handle); setSnapshotOnNextOperation(final long handle, final long transactionNotifierHandle)1880 private native void setSnapshotOnNextOperation(final long handle, 1881 final long transactionNotifierHandle); getSnapshot(final long handle)1882 private native long getSnapshot(final long handle); clearSnapshot(final long handle)1883 private native void clearSnapshot(final long handle); prepare(final long handle)1884 private native void prepare(final long handle) throws RocksDBException; commit(final long handle)1885 private native void commit(final long handle) throws RocksDBException; rollback(final long handle)1886 private native void rollback(final long handle) throws RocksDBException; setSavePoint(final long handle)1887 private native void setSavePoint(final long handle) throws RocksDBException; rollbackToSavePoint(final long handle)1888 private native void rollbackToSavePoint(final long handle) 1889 throws RocksDBException; get(final long handle, final long readOptionsHandle, final byte key[], final int keyLength, final long columnFamilyHandle)1890 private native byte[] get(final long handle, final long readOptionsHandle, 1891 final byte key[], final int keyLength, final long columnFamilyHandle) 1892 throws RocksDBException; get(final long handle, final long readOptionsHandle, final byte key[], final int keyLen)1893 private native byte[] get(final long handle, final long readOptionsHandle, 1894 final byte key[], final int keyLen) throws RocksDBException; multiGet(final long handle, final long readOptionsHandle, final byte[][] keys, final long[] columnFamilyHandles)1895 private native byte[][] multiGet(final long handle, 1896 final long readOptionsHandle, final byte[][] keys, 1897 final long[] columnFamilyHandles) throws RocksDBException; multiGet(final long handle, final long readOptionsHandle, final byte[][] keys)1898 private native byte[][] multiGet(final long handle, 1899 final long readOptionsHandle, final byte[][] keys) 1900 throws RocksDBException; getForUpdate(final long handle, final long readOptionsHandle, final byte key[], final int keyLength, final long columnFamilyHandle, final boolean exclusive, final boolean doValidate)1901 private native byte[] getForUpdate(final long handle, final long readOptionsHandle, 1902 final byte key[], final int keyLength, final long columnFamilyHandle, final boolean exclusive, 1903 final boolean doValidate) throws RocksDBException; getForUpdate(final long handle, final long readOptionsHandle, final byte key[], final int keyLen, final boolean exclusive, final boolean doValidate)1904 private native byte[] getForUpdate(final long handle, final long readOptionsHandle, 1905 final byte key[], final int keyLen, final boolean exclusive, final boolean doValidate) 1906 throws RocksDBException; multiGetForUpdate(final long handle, final long readOptionsHandle, final byte[][] keys, final long[] columnFamilyHandles)1907 private native byte[][] multiGetForUpdate(final long handle, 1908 final long readOptionsHandle, final byte[][] keys, 1909 final long[] columnFamilyHandles) throws RocksDBException; multiGetForUpdate(final long handle, final long readOptionsHandle, final byte[][] keys)1910 private native byte[][] multiGetForUpdate(final long handle, 1911 final long readOptionsHandle, final byte[][] keys) 1912 throws RocksDBException; getIterator(final long handle, final long readOptionsHandle)1913 private native long getIterator(final long handle, 1914 final long readOptionsHandle); getIterator(final long handle, final long readOptionsHandle, final long columnFamilyHandle)1915 private native long getIterator(final long handle, 1916 final long readOptionsHandle, final long columnFamilyHandle); put(final long handle, final byte[] key, final int keyLength, final byte[] value, final int valueLength, final long columnFamilyHandle, final boolean assumeTracked)1917 private native void put(final long handle, final byte[] key, final int keyLength, 1918 final byte[] value, final int valueLength, final long columnFamilyHandle, 1919 final boolean assumeTracked) throws RocksDBException; put(final long handle, final byte[] key, final int keyLength, final byte[] value, final int valueLength)1920 private native void put(final long handle, final byte[] key, 1921 final int keyLength, final byte[] value, final int valueLength) 1922 throws RocksDBException; put(final long handle, final byte[][] keys, final int keysLength, final byte[][] values, final int valuesLength, final long columnFamilyHandle, final boolean assumeTracked)1923 private native void put(final long handle, final byte[][] keys, final int keysLength, 1924 final byte[][] values, final int valuesLength, final long columnFamilyHandle, 1925 final boolean assumeTracked) throws RocksDBException; put(final long handle, final byte[][] keys, final int keysLength, final byte[][] values, final int valuesLength)1926 private native void put(final long handle, final byte[][] keys, 1927 final int keysLength, final byte[][] values, final int valuesLength) 1928 throws RocksDBException; merge(final long handle, final byte[] key, final int keyLength, final byte[] value, final int valueLength, final long columnFamilyHandle, final boolean assumeTracked)1929 private native void merge(final long handle, final byte[] key, final int keyLength, 1930 final byte[] value, final int valueLength, final long columnFamilyHandle, 1931 final boolean assumeTracked) throws RocksDBException; merge(final long handle, final byte[] key, final int keyLength, final byte[] value, final int valueLength)1932 private native void merge(final long handle, final byte[] key, 1933 final int keyLength, final byte[] value, final int valueLength) 1934 throws RocksDBException; delete(final long handle, final byte[] key, final int keyLength, final long columnFamilyHandle, final boolean assumeTracked)1935 private native void delete(final long handle, final byte[] key, final int keyLength, 1936 final long columnFamilyHandle, final boolean assumeTracked) throws RocksDBException; delete(final long handle, final byte[] key, final int keyLength)1937 private native void delete(final long handle, final byte[] key, 1938 final int keyLength) throws RocksDBException; delete(final long handle, final byte[][] keys, final int keysLength, final long columnFamilyHandle, final boolean assumeTracked)1939 private native void delete(final long handle, final byte[][] keys, final int keysLength, 1940 final long columnFamilyHandle, final boolean assumeTracked) throws RocksDBException; delete(final long handle, final byte[][] keys, final int keysLength)1941 private native void delete(final long handle, final byte[][] keys, 1942 final int keysLength) throws RocksDBException; singleDelete(final long handle, final byte[] key, final int keyLength, final long columnFamilyHandle, final boolean assumeTracked)1943 private native void singleDelete(final long handle, final byte[] key, final int keyLength, 1944 final long columnFamilyHandle, final boolean assumeTracked) throws RocksDBException; singleDelete(final long handle, final byte[] key, final int keyLength)1945 private native void singleDelete(final long handle, final byte[] key, 1946 final int keyLength) throws RocksDBException; singleDelete(final long handle, final byte[][] keys, final int keysLength, final long columnFamilyHandle, final boolean assumeTracked)1947 private native void singleDelete(final long handle, final byte[][] keys, final int keysLength, 1948 final long columnFamilyHandle, final boolean assumeTracked) throws RocksDBException; singleDelete(final long handle, final byte[][] keys, final int keysLength)1949 private native void singleDelete(final long handle, final byte[][] keys, 1950 final int keysLength) throws RocksDBException; putUntracked(final long handle, final byte[] key, final int keyLength, final byte[] value, final int valueLength, final long columnFamilyHandle)1951 private native void putUntracked(final long handle, final byte[] key, 1952 final int keyLength, final byte[] value, final int valueLength, 1953 final long columnFamilyHandle) throws RocksDBException; putUntracked(final long handle, final byte[] key, final int keyLength, final byte[] value, final int valueLength)1954 private native void putUntracked(final long handle, final byte[] key, 1955 final int keyLength, final byte[] value, final int valueLength) 1956 throws RocksDBException; putUntracked(final long handle, final byte[][] keys, final int keysLength, final byte[][] values, final int valuesLength, final long columnFamilyHandle)1957 private native void putUntracked(final long handle, final byte[][] keys, 1958 final int keysLength, final byte[][] values, final int valuesLength, 1959 final long columnFamilyHandle) throws RocksDBException; putUntracked(final long handle, final byte[][] keys, final int keysLength, final byte[][] values, final int valuesLength)1960 private native void putUntracked(final long handle, final byte[][] keys, 1961 final int keysLength, final byte[][] values, final int valuesLength) 1962 throws RocksDBException; mergeUntracked(final long handle, final byte[] key, final int keyLength, final byte[] value, final int valueLength, final long columnFamilyHandle)1963 private native void mergeUntracked(final long handle, final byte[] key, 1964 final int keyLength, final byte[] value, final int valueLength, 1965 final long columnFamilyHandle) throws RocksDBException; mergeUntracked(final long handle, final byte[] key, final int keyLength, final byte[] value, final int valueLength)1966 private native void mergeUntracked(final long handle, final byte[] key, 1967 final int keyLength, final byte[] value, final int valueLength) 1968 throws RocksDBException; deleteUntracked(final long handle, final byte[] key, final int keyLength, final long columnFamilyHandle)1969 private native void deleteUntracked(final long handle, final byte[] key, 1970 final int keyLength, final long columnFamilyHandle) 1971 throws RocksDBException; deleteUntracked(final long handle, final byte[] key, final int keyLength)1972 private native void deleteUntracked(final long handle, final byte[] key, 1973 final int keyLength) throws RocksDBException; deleteUntracked(final long handle, final byte[][] keys, final int keysLength, final long columnFamilyHandle)1974 private native void deleteUntracked(final long handle, final byte[][] keys, 1975 final int keysLength, final long columnFamilyHandle) 1976 throws RocksDBException; deleteUntracked(final long handle, final byte[][] keys, final int keysLength)1977 private native void deleteUntracked(final long handle, final byte[][] keys, 1978 final int keysLength) throws RocksDBException; putLogData(final long handle, final byte[] blob, final int blobLength)1979 private native void putLogData(final long handle, final byte[] blob, 1980 final int blobLength); disableIndexing(final long handle)1981 private native void disableIndexing(final long handle); enableIndexing(final long handle)1982 private native void enableIndexing(final long handle); getNumKeys(final long handle)1983 private native long getNumKeys(final long handle); getNumPuts(final long handle)1984 private native long getNumPuts(final long handle); getNumDeletes(final long handle)1985 private native long getNumDeletes(final long handle); getNumMerges(final long handle)1986 private native long getNumMerges(final long handle); getElapsedTime(final long handle)1987 private native long getElapsedTime(final long handle); getWriteBatch(final long handle)1988 private native long getWriteBatch(final long handle); setLockTimeout(final long handle, final long lockTimeout)1989 private native void setLockTimeout(final long handle, final long lockTimeout); getWriteOptions(final long handle)1990 private native long getWriteOptions(final long handle); setWriteOptions(final long handle, final long writeOptionsHandle)1991 private native void setWriteOptions(final long handle, 1992 final long writeOptionsHandle); undoGetForUpdate(final long handle, final byte[] key, final int keyLength, final long columnFamilyHandle)1993 private native void undoGetForUpdate(final long handle, final byte[] key, 1994 final int keyLength, final long columnFamilyHandle); undoGetForUpdate(final long handle, final byte[] key, final int keyLength)1995 private native void undoGetForUpdate(final long handle, final byte[] key, 1996 final int keyLength); rebuildFromWriteBatch(final long handle, final long writeBatchHandle)1997 private native void rebuildFromWriteBatch(final long handle, 1998 final long writeBatchHandle) throws RocksDBException; getCommitTimeWriteBatch(final long handle)1999 private native long getCommitTimeWriteBatch(final long handle); setLogNumber(final long handle, final long logNumber)2000 private native void setLogNumber(final long handle, final long logNumber); getLogNumber(final long handle)2001 private native long getLogNumber(final long handle); setName(final long handle, final String name)2002 private native void setName(final long handle, final String name) 2003 throws RocksDBException; getName(final long handle)2004 private native String getName(final long handle); getID(final long handle)2005 private native long getID(final long handle); isDeadlockDetect(final long handle)2006 private native boolean isDeadlockDetect(final long handle); getWaitingTxns(final long handle)2007 private native WaitingTransactions getWaitingTxns(final long handle); getState(final long handle)2008 private native byte getState(final long handle); getId(final long handle)2009 private native long getId(final long handle); 2010 disposeInternal(final long handle)2011 @Override protected final native void disposeInternal(final long handle); 2012 } 2013