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 org.junit.Rule; 9 import org.junit.Test; 10 import org.junit.rules.TemporaryFolder; 11 12 import java.util.ArrayList; 13 import java.util.Arrays; 14 import java.util.List; 15 import java.util.Random; 16 17 import static java.nio.charset.StandardCharsets.UTF_8; 18 import static org.assertj.core.api.Assertions.assertThat; 19 import static org.assertj.core.api.Assertions.fail; 20 21 /** 22 * Base class of {@link TransactionTest} and {@link OptimisticTransactionTest} 23 */ 24 public abstract class AbstractTransactionTest { 25 26 protected final static byte[] TXN_TEST_COLUMN_FAMILY = "txn_test_cf" 27 .getBytes(); 28 29 protected static final Random rand = PlatformRandomHelper. 30 getPlatformSpecificRandomFactory(); 31 32 @Rule 33 public TemporaryFolder dbFolder = new TemporaryFolder(); 34 35 public abstract DBContainer startDb() 36 throws RocksDBException; 37 38 @Test 39 public void setSnapshot() throws RocksDBException { 40 try(final DBContainer dbContainer = startDb(); 41 final Transaction txn = dbContainer.beginTransaction()) { 42 txn.setSnapshot(); 43 } 44 } 45 46 @Test 47 public void setSnapshotOnNextOperation() throws RocksDBException { 48 try(final DBContainer dbContainer = startDb(); 49 final Transaction txn = dbContainer.beginTransaction()) { 50 txn.setSnapshotOnNextOperation(); 51 txn.put("key1".getBytes(), "value1".getBytes()); 52 } 53 } 54 55 @Test 56 public void setSnapshotOnNextOperation_transactionNotifier() throws RocksDBException { 57 try(final DBContainer dbContainer = startDb(); 58 final Transaction txn = dbContainer.beginTransaction()) { 59 60 try(final TestTransactionNotifier notifier = new TestTransactionNotifier()) { 61 txn.setSnapshotOnNextOperation(notifier); 62 txn.put("key1".getBytes(), "value1".getBytes()); 63 64 txn.setSnapshotOnNextOperation(notifier); 65 txn.put("key2".getBytes(), "value2".getBytes()); 66 67 assertThat(notifier.getCreatedSnapshots().size()).isEqualTo(2); 68 } 69 } 70 } 71 72 @Test 73 public void getSnapshot() throws RocksDBException { 74 try(final DBContainer dbContainer = startDb(); 75 final Transaction txn = dbContainer.beginTransaction()) { 76 txn.setSnapshot(); 77 final Snapshot snapshot = txn.getSnapshot(); 78 assertThat(snapshot.isOwningHandle()).isFalse(); 79 } 80 } 81 82 @Test 83 public void getSnapshot_null() throws RocksDBException { 84 try(final DBContainer dbContainer = startDb(); 85 final Transaction txn = dbContainer.beginTransaction()) { 86 final Snapshot snapshot = txn.getSnapshot(); 87 assertThat(snapshot).isNull(); 88 } 89 } 90 91 @Test 92 public void clearSnapshot() throws RocksDBException { 93 try(final DBContainer dbContainer = startDb(); 94 final Transaction txn = dbContainer.beginTransaction()) { 95 txn.setSnapshot(); 96 txn.clearSnapshot(); 97 } 98 } 99 100 @Test 101 public void clearSnapshot_none() throws RocksDBException { 102 try(final DBContainer dbContainer = startDb(); 103 final Transaction txn = dbContainer.beginTransaction()) { 104 txn.clearSnapshot(); 105 } 106 } 107 108 @Test 109 public void commit() throws RocksDBException { 110 final byte k1[] = "rollback-key1".getBytes(UTF_8); 111 final byte v1[] = "rollback-value1".getBytes(UTF_8); 112 try(final DBContainer dbContainer = startDb()) { 113 try(final Transaction txn = dbContainer.beginTransaction()) { 114 txn.put(k1, v1); 115 txn.commit(); 116 } 117 118 try(final ReadOptions readOptions = new ReadOptions(); 119 final Transaction txn2 = dbContainer.beginTransaction()) { 120 assertThat(txn2.get(readOptions, k1)).isEqualTo(v1); 121 } 122 } 123 } 124 125 @Test 126 public void rollback() throws RocksDBException { 127 final byte k1[] = "rollback-key1".getBytes(UTF_8); 128 final byte v1[] = "rollback-value1".getBytes(UTF_8); 129 try(final DBContainer dbContainer = startDb()) { 130 try(final Transaction txn = dbContainer.beginTransaction()) { 131 txn.put(k1, v1); 132 txn.rollback(); 133 } 134 135 try(final ReadOptions readOptions = new ReadOptions(); 136 final Transaction txn2 = dbContainer.beginTransaction()) { 137 assertThat(txn2.get(readOptions, k1)).isNull(); 138 } 139 } 140 } 141 142 @Test 143 public void savePoint() throws RocksDBException { 144 final byte k1[] = "savePoint-key1".getBytes(UTF_8); 145 final byte v1[] = "savePoint-value1".getBytes(UTF_8); 146 final byte k2[] = "savePoint-key2".getBytes(UTF_8); 147 final byte v2[] = "savePoint-value2".getBytes(UTF_8); 148 149 try(final DBContainer dbContainer = startDb(); 150 final ReadOptions readOptions = new ReadOptions()) { 151 152 153 try(final Transaction txn = dbContainer.beginTransaction()) { 154 txn.put(k1, v1); 155 156 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 157 158 txn.setSavePoint(); 159 160 txn.put(k2, v2); 161 162 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 163 assertThat(txn.get(readOptions, k2)).isEqualTo(v2); 164 165 txn.rollbackToSavePoint(); 166 167 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 168 assertThat(txn.get(readOptions, k2)).isNull(); 169 170 txn.commit(); 171 } 172 173 try(final Transaction txn2 = dbContainer.beginTransaction()) { 174 assertThat(txn2.get(readOptions, k1)).isEqualTo(v1); 175 assertThat(txn2.get(readOptions, k2)).isNull(); 176 } 177 } 178 } 179 180 @Test 181 public void getPut_cf() throws RocksDBException { 182 final byte k1[] = "key1".getBytes(UTF_8); 183 final byte v1[] = "value1".getBytes(UTF_8); 184 try(final DBContainer dbContainer = startDb(); 185 final ReadOptions readOptions = new ReadOptions(); 186 final Transaction txn = dbContainer.beginTransaction()) { 187 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 188 assertThat(txn.get(testCf, readOptions, k1)).isNull(); 189 txn.put(testCf, k1, v1); 190 assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1); 191 } 192 } 193 194 @Test 195 public void getPut() throws RocksDBException { 196 final byte k1[] = "key1".getBytes(UTF_8); 197 final byte v1[] = "value1".getBytes(UTF_8); 198 try(final DBContainer dbContainer = startDb(); 199 final ReadOptions readOptions = new ReadOptions(); 200 final Transaction txn = dbContainer.beginTransaction()) { 201 assertThat(txn.get(readOptions, k1)).isNull(); 202 txn.put(k1, v1); 203 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 204 } 205 } 206 207 @Test 208 public void multiGetPut_cf() throws RocksDBException { 209 final byte keys[][] = new byte[][] { 210 "key1".getBytes(UTF_8), 211 "key2".getBytes(UTF_8)}; 212 final byte values[][] = new byte[][] { 213 "value1".getBytes(UTF_8), 214 "value2".getBytes(UTF_8)}; 215 216 try(final DBContainer dbContainer = startDb(); 217 final ReadOptions readOptions = new ReadOptions(); 218 final Transaction txn = dbContainer.beginTransaction()) { 219 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 220 final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf); 221 222 assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(new byte[][] { null, null }); 223 224 txn.put(testCf, keys[0], values[0]); 225 txn.put(testCf, keys[1], values[1]); 226 assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(values); 227 } 228 } 229 230 @Test 231 public void multiGetPut() throws RocksDBException { 232 final byte keys[][] = new byte[][] { 233 "key1".getBytes(UTF_8), 234 "key2".getBytes(UTF_8)}; 235 final byte values[][] = new byte[][] { 236 "value1".getBytes(UTF_8), 237 "value2".getBytes(UTF_8)}; 238 239 try(final DBContainer dbContainer = startDb(); 240 final ReadOptions readOptions = new ReadOptions(); 241 final Transaction txn = dbContainer.beginTransaction()) { 242 243 assertThat(txn.multiGet(readOptions, keys)).isEqualTo(new byte[][] { null, null }); 244 245 txn.put(keys[0], values[0]); 246 txn.put(keys[1], values[1]); 247 assertThat(txn.multiGet(readOptions, keys)).isEqualTo(values); 248 } 249 } 250 251 @Test 252 public void getForUpdate_cf() throws RocksDBException { 253 final byte k1[] = "key1".getBytes(UTF_8); 254 final byte v1[] = "value1".getBytes(UTF_8); 255 try(final DBContainer dbContainer = startDb(); 256 final ReadOptions readOptions = new ReadOptions(); 257 final Transaction txn = dbContainer.beginTransaction()) { 258 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 259 assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isNull(); 260 txn.put(testCf, k1, v1); 261 assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isEqualTo(v1); 262 } 263 } 264 265 @Test 266 public void getForUpdate() throws RocksDBException { 267 final byte k1[] = "key1".getBytes(UTF_8); 268 final byte v1[] = "value1".getBytes(UTF_8); 269 try(final DBContainer dbContainer = startDb(); 270 final ReadOptions readOptions = new ReadOptions(); 271 final Transaction txn = dbContainer.beginTransaction()) { 272 assertThat(txn.getForUpdate(readOptions, k1, true)).isNull(); 273 txn.put(k1, v1); 274 assertThat(txn.getForUpdate(readOptions, k1, true)).isEqualTo(v1); 275 } 276 } 277 278 @Test 279 public void multiGetForUpdate_cf() throws RocksDBException { 280 final byte keys[][] = new byte[][] { 281 "key1".getBytes(UTF_8), 282 "key2".getBytes(UTF_8)}; 283 final byte values[][] = new byte[][] { 284 "value1".getBytes(UTF_8), 285 "value2".getBytes(UTF_8)}; 286 287 try(final DBContainer dbContainer = startDb(); 288 final ReadOptions readOptions = new ReadOptions(); 289 final Transaction txn = dbContainer.beginTransaction()) { 290 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 291 final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf); 292 293 assertThat(txn.multiGetForUpdate(readOptions, cfList, keys)) 294 .isEqualTo(new byte[][] { null, null }); 295 296 txn.put(testCf, keys[0], values[0]); 297 txn.put(testCf, keys[1], values[1]); 298 assertThat(txn.multiGetForUpdate(readOptions, cfList, keys)) 299 .isEqualTo(values); 300 } 301 } 302 303 @Test 304 public void multiGetForUpdate() throws RocksDBException { 305 final byte keys[][] = new byte[][]{ 306 "key1".getBytes(UTF_8), 307 "key2".getBytes(UTF_8)}; 308 final byte values[][] = new byte[][]{ 309 "value1".getBytes(UTF_8), 310 "value2".getBytes(UTF_8)}; 311 312 try (final DBContainer dbContainer = startDb(); 313 final ReadOptions readOptions = new ReadOptions(); 314 final Transaction txn = dbContainer.beginTransaction()) { 315 assertThat(txn.multiGetForUpdate(readOptions, keys)).isEqualTo(new byte[][]{null, null}); 316 317 txn.put(keys[0], values[0]); 318 txn.put(keys[1], values[1]); 319 assertThat(txn.multiGetForUpdate(readOptions, keys)).isEqualTo(values); 320 } 321 } 322 323 @Test 324 public void getIterator() throws RocksDBException { 325 try(final DBContainer dbContainer = startDb(); 326 final ReadOptions readOptions = new ReadOptions(); 327 final Transaction txn = dbContainer.beginTransaction()) { 328 329 final byte[] k1 = "key1".getBytes(UTF_8); 330 final byte[] v1 = "value1".getBytes(UTF_8); 331 332 txn.put(k1, v1); 333 334 try(final RocksIterator iterator = txn.getIterator(readOptions)) { 335 iterator.seek(k1); 336 assertThat(iterator.isValid()).isTrue(); 337 assertThat(iterator.key()).isEqualTo(k1); 338 assertThat(iterator.value()).isEqualTo(v1); 339 } 340 } 341 } 342 343 @Test 344 public void getIterator_cf() throws RocksDBException { 345 try(final DBContainer dbContainer = startDb(); 346 final ReadOptions readOptions = new ReadOptions(); 347 final Transaction txn = dbContainer.beginTransaction()) { 348 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 349 350 final byte[] k1 = "key1".getBytes(UTF_8); 351 final byte[] v1 = "value1".getBytes(UTF_8); 352 353 txn.put(testCf, k1, v1); 354 355 try(final RocksIterator iterator = txn.getIterator(readOptions, testCf)) { 356 iterator.seek(k1); 357 assertThat(iterator.isValid()).isTrue(); 358 assertThat(iterator.key()).isEqualTo(k1); 359 assertThat(iterator.value()).isEqualTo(v1); 360 } 361 } 362 } 363 364 @Test 365 public void merge_cf() throws RocksDBException { 366 final byte[] k1 = "key1".getBytes(UTF_8); 367 final byte[] v1 = "value1".getBytes(UTF_8); 368 369 try(final DBContainer dbContainer = startDb(); 370 final Transaction txn = dbContainer.beginTransaction()) { 371 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 372 txn.merge(testCf, k1, v1); 373 } 374 } 375 376 @Test 377 public void merge() throws RocksDBException { 378 final byte[] k1 = "key1".getBytes(UTF_8); 379 final byte[] v1 = "value1".getBytes(UTF_8); 380 381 try(final DBContainer dbContainer = startDb(); 382 final Transaction txn = dbContainer.beginTransaction()) { 383 txn.merge(k1, v1); 384 } 385 } 386 387 388 @Test 389 public void delete_cf() throws RocksDBException { 390 final byte[] k1 = "key1".getBytes(UTF_8); 391 final byte[] v1 = "value1".getBytes(UTF_8); 392 393 try(final DBContainer dbContainer = startDb(); 394 final ReadOptions readOptions = new ReadOptions(); 395 final Transaction txn = dbContainer.beginTransaction()) { 396 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 397 txn.put(testCf, k1, v1); 398 assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1); 399 400 txn.delete(testCf, k1); 401 assertThat(txn.get(testCf, readOptions, k1)).isNull(); 402 } 403 } 404 405 @Test 406 public void delete() throws RocksDBException { 407 final byte[] k1 = "key1".getBytes(UTF_8); 408 final byte[] v1 = "value1".getBytes(UTF_8); 409 410 try(final DBContainer dbContainer = startDb(); 411 final ReadOptions readOptions = new ReadOptions(); 412 final Transaction txn = dbContainer.beginTransaction()) { 413 txn.put(k1, v1); 414 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 415 416 txn.delete(k1); 417 assertThat(txn.get(readOptions, k1)).isNull(); 418 } 419 } 420 421 @Test 422 public void delete_parts_cf() throws RocksDBException { 423 final byte keyParts[][] = new byte[][] { 424 "ke".getBytes(UTF_8), 425 "y1".getBytes(UTF_8)}; 426 final byte valueParts[][] = new byte[][] { 427 "val".getBytes(UTF_8), 428 "ue1".getBytes(UTF_8)}; 429 final byte[] key = concat(keyParts); 430 final byte[] value = concat(valueParts); 431 432 try(final DBContainer dbContainer = startDb(); 433 final ReadOptions readOptions = new ReadOptions(); 434 final Transaction txn = dbContainer.beginTransaction()) { 435 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 436 txn.put(testCf, keyParts, valueParts); 437 assertThat(txn.get(testCf, readOptions, key)).isEqualTo(value); 438 439 txn.delete(testCf, keyParts); 440 441 assertThat(txn.get(testCf, readOptions, key)) 442 .isNull(); 443 } 444 } 445 446 @Test 447 public void delete_parts() throws RocksDBException { 448 final byte keyParts[][] = new byte[][] { 449 "ke".getBytes(UTF_8), 450 "y1".getBytes(UTF_8)}; 451 final byte valueParts[][] = new byte[][] { 452 "val".getBytes(UTF_8), 453 "ue1".getBytes(UTF_8)}; 454 final byte[] key = concat(keyParts); 455 final byte[] value = concat(valueParts); 456 457 try(final DBContainer dbContainer = startDb(); 458 final ReadOptions readOptions = new ReadOptions(); 459 final Transaction txn = dbContainer.beginTransaction()) { 460 461 txn.put(keyParts, valueParts); 462 463 assertThat(txn.get(readOptions, key)).isEqualTo(value); 464 465 txn.delete(keyParts); 466 467 assertThat(txn.get(readOptions, key)).isNull(); 468 } 469 } 470 471 @Test 472 public void getPutUntracked_cf() throws RocksDBException { 473 final byte k1[] = "key1".getBytes(UTF_8); 474 final byte v1[] = "value1".getBytes(UTF_8); 475 try(final DBContainer dbContainer = startDb(); 476 final ReadOptions readOptions = new ReadOptions(); 477 final Transaction txn = dbContainer.beginTransaction()) { 478 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 479 assertThat(txn.get(testCf, readOptions, k1)).isNull(); 480 txn.putUntracked(testCf, k1, v1); 481 assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1); 482 } 483 } 484 485 @Test 486 public void getPutUntracked() throws RocksDBException { 487 final byte k1[] = "key1".getBytes(UTF_8); 488 final byte v1[] = "value1".getBytes(UTF_8); 489 try(final DBContainer dbContainer = startDb(); 490 final ReadOptions readOptions = new ReadOptions(); 491 final Transaction txn = dbContainer.beginTransaction()) { 492 assertThat(txn.get(readOptions, k1)).isNull(); 493 txn.putUntracked(k1, v1); 494 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 495 } 496 } 497 498 @Test 499 public void multiGetPutUntracked_cf() throws RocksDBException { 500 final byte keys[][] = new byte[][] { 501 "key1".getBytes(UTF_8), 502 "key2".getBytes(UTF_8)}; 503 final byte values[][] = new byte[][] { 504 "value1".getBytes(UTF_8), 505 "value2".getBytes(UTF_8)}; 506 507 try(final DBContainer dbContainer = startDb(); 508 final ReadOptions readOptions = new ReadOptions(); 509 final Transaction txn = dbContainer.beginTransaction()) { 510 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 511 512 final List<ColumnFamilyHandle> cfList = Arrays.asList(testCf, testCf); 513 514 assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(new byte[][] { null, null }); 515 txn.putUntracked(testCf, keys[0], values[0]); 516 txn.putUntracked(testCf, keys[1], values[1]); 517 assertThat(txn.multiGet(readOptions, cfList, keys)).isEqualTo(values); 518 } 519 } 520 521 @Test 522 public void multiGetPutUntracked() throws RocksDBException { 523 final byte keys[][] = new byte[][] { 524 "key1".getBytes(UTF_8), 525 "key2".getBytes(UTF_8)}; 526 final byte values[][] = new byte[][] { 527 "value1".getBytes(UTF_8), 528 "value2".getBytes(UTF_8)}; 529 530 try(final DBContainer dbContainer = startDb(); 531 final ReadOptions readOptions = new ReadOptions(); 532 final Transaction txn = dbContainer.beginTransaction()) { 533 534 assertThat(txn.multiGet(readOptions, keys)).isEqualTo(new byte[][] { null, null }); 535 txn.putUntracked(keys[0], values[0]); 536 txn.putUntracked(keys[1], values[1]); 537 assertThat(txn.multiGet(readOptions, keys)).isEqualTo(values); 538 } 539 } 540 541 @Test 542 public void mergeUntracked_cf() throws RocksDBException { 543 final byte[] k1 = "key1".getBytes(UTF_8); 544 final byte[] v1 = "value1".getBytes(UTF_8); 545 546 try(final DBContainer dbContainer = startDb(); 547 final Transaction txn = dbContainer.beginTransaction()) { 548 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 549 txn.mergeUntracked(testCf, k1, v1); 550 } 551 } 552 553 @Test 554 public void mergeUntracked() throws RocksDBException { 555 final byte[] k1 = "key1".getBytes(UTF_8); 556 final byte[] v1 = "value1".getBytes(UTF_8); 557 558 try(final DBContainer dbContainer = startDb(); 559 final Transaction txn = dbContainer.beginTransaction()) { 560 txn.mergeUntracked(k1, v1); 561 } 562 } 563 564 @Test 565 public void deleteUntracked_cf() throws RocksDBException { 566 final byte[] k1 = "key1".getBytes(UTF_8); 567 final byte[] v1 = "value1".getBytes(UTF_8); 568 569 try(final DBContainer dbContainer = startDb(); 570 final ReadOptions readOptions = new ReadOptions(); 571 final Transaction txn = dbContainer.beginTransaction()) { 572 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 573 txn.put(testCf, k1, v1); 574 assertThat(txn.get(testCf, readOptions, k1)).isEqualTo(v1); 575 576 txn.deleteUntracked(testCf, k1); 577 assertThat(txn.get(testCf, readOptions, k1)).isNull(); 578 } 579 } 580 581 @Test 582 public void deleteUntracked() throws RocksDBException { 583 final byte[] k1 = "key1".getBytes(UTF_8); 584 final byte[] v1 = "value1".getBytes(UTF_8); 585 586 try(final DBContainer dbContainer = startDb(); 587 final ReadOptions readOptions = new ReadOptions(); 588 final Transaction txn = dbContainer.beginTransaction()) { 589 txn.put(k1, v1); 590 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 591 592 txn.deleteUntracked(k1); 593 assertThat(txn.get(readOptions, k1)).isNull(); 594 } 595 } 596 597 @Test 598 public void deleteUntracked_parts_cf() throws RocksDBException { 599 final byte keyParts[][] = new byte[][] { 600 "ke".getBytes(UTF_8), 601 "y1".getBytes(UTF_8)}; 602 final byte valueParts[][] = new byte[][] { 603 "val".getBytes(UTF_8), 604 "ue1".getBytes(UTF_8)}; 605 final byte[] key = concat(keyParts); 606 final byte[] value = concat(valueParts); 607 608 try(final DBContainer dbContainer = startDb(); 609 final ReadOptions readOptions = new ReadOptions(); 610 final Transaction txn = dbContainer.beginTransaction()) { 611 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 612 txn.put(testCf, keyParts, valueParts); 613 assertThat(txn.get(testCf, readOptions, key)).isEqualTo(value); 614 615 txn.deleteUntracked(testCf, keyParts); 616 assertThat(txn.get(testCf, readOptions, key)).isNull(); 617 } 618 } 619 620 @Test 621 public void deleteUntracked_parts() throws RocksDBException { 622 final byte keyParts[][] = new byte[][] { 623 "ke".getBytes(UTF_8), 624 "y1".getBytes(UTF_8)}; 625 final byte valueParts[][] = new byte[][] { 626 "val".getBytes(UTF_8), 627 "ue1".getBytes(UTF_8)}; 628 final byte[] key = concat(keyParts); 629 final byte[] value = concat(valueParts); 630 631 try(final DBContainer dbContainer = startDb(); 632 final ReadOptions readOptions = new ReadOptions(); 633 final Transaction txn = dbContainer.beginTransaction()) { 634 txn.put(keyParts, valueParts); 635 assertThat(txn.get(readOptions, key)).isEqualTo(value); 636 637 txn.deleteUntracked(keyParts); 638 assertThat(txn.get(readOptions, key)).isNull(); 639 } 640 } 641 642 @Test 643 public void putLogData() throws RocksDBException { 644 final byte[] blob = "blobby".getBytes(UTF_8); 645 try(final DBContainer dbContainer = startDb(); 646 final Transaction txn = dbContainer.beginTransaction()) { 647 txn.putLogData(blob); 648 } 649 } 650 651 @Test 652 public void enabledDisableIndexing() throws RocksDBException { 653 try(final DBContainer dbContainer = startDb(); 654 final Transaction txn = dbContainer.beginTransaction()) { 655 txn.disableIndexing(); 656 txn.enableIndexing(); 657 txn.disableIndexing(); 658 txn.enableIndexing(); 659 } 660 } 661 662 @Test 663 public void numKeys() throws RocksDBException { 664 final byte k1[] = "key1".getBytes(UTF_8); 665 final byte v1[] = "value1".getBytes(UTF_8); 666 final byte k2[] = "key2".getBytes(UTF_8); 667 final byte v2[] = "value2".getBytes(UTF_8); 668 final byte k3[] = "key3".getBytes(UTF_8); 669 final byte v3[] = "value3".getBytes(UTF_8); 670 671 try(final DBContainer dbContainer = startDb(); 672 final Transaction txn = dbContainer.beginTransaction()) { 673 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 674 txn.put(k1, v1); 675 txn.put(testCf, k2, v2); 676 txn.merge(k3, v3); 677 txn.delete(testCf, k2); 678 679 assertThat(txn.getNumKeys()).isEqualTo(3); 680 assertThat(txn.getNumPuts()).isEqualTo(2); 681 assertThat(txn.getNumMerges()).isEqualTo(1); 682 assertThat(txn.getNumDeletes()).isEqualTo(1); 683 } 684 } 685 686 @Test 687 public void elapsedTime() throws RocksDBException, InterruptedException { 688 final long preStartTxnTime = System.currentTimeMillis(); 689 try (final DBContainer dbContainer = startDb(); 690 final Transaction txn = dbContainer.beginTransaction()) { 691 Thread.sleep(2); 692 693 final long txnElapsedTime = txn.getElapsedTime(); 694 assertThat(txnElapsedTime).isLessThan(System.currentTimeMillis() - preStartTxnTime); 695 assertThat(txnElapsedTime).isGreaterThan(0); 696 } 697 } 698 699 @Test 700 public void getWriteBatch() throws RocksDBException { 701 final byte k1[] = "key1".getBytes(UTF_8); 702 final byte v1[] = "value1".getBytes(UTF_8); 703 704 try(final DBContainer dbContainer = startDb(); 705 final Transaction txn = dbContainer.beginTransaction()) { 706 707 txn.put(k1, v1); 708 709 final WriteBatchWithIndex writeBatch = txn.getWriteBatch(); 710 assertThat(writeBatch).isNotNull(); 711 assertThat(writeBatch.isOwningHandle()).isFalse(); 712 assertThat(writeBatch.count()).isEqualTo(1); 713 } 714 } 715 716 @Test 717 public void setLockTimeout() throws RocksDBException { 718 try(final DBContainer dbContainer = startDb(); 719 final Transaction txn = dbContainer.beginTransaction()) { 720 txn.setLockTimeout(1000); 721 } 722 } 723 724 @Test 725 public void writeOptions() throws RocksDBException { 726 final byte k1[] = "key1".getBytes(UTF_8); 727 final byte v1[] = "value1".getBytes(UTF_8); 728 729 try(final DBContainer dbContainer = startDb(); 730 final WriteOptions writeOptions = new WriteOptions() 731 .setDisableWAL(true) 732 .setSync(true); 733 final Transaction txn = dbContainer.beginTransaction(writeOptions)) { 734 735 txn.put(k1, v1); 736 737 WriteOptions txnWriteOptions = txn.getWriteOptions(); 738 assertThat(txnWriteOptions).isNotNull(); 739 assertThat(txnWriteOptions.isOwningHandle()).isFalse(); 740 assertThat(txnWriteOptions).isNotSameAs(writeOptions); 741 assertThat(txnWriteOptions.disableWAL()).isTrue(); 742 assertThat(txnWriteOptions.sync()).isTrue(); 743 744 txn.setWriteOptions(txnWriteOptions.setSync(false)); 745 txnWriteOptions = txn.getWriteOptions(); 746 assertThat(txnWriteOptions).isNotNull(); 747 assertThat(txnWriteOptions.isOwningHandle()).isFalse(); 748 assertThat(txnWriteOptions).isNotSameAs(writeOptions); 749 assertThat(txnWriteOptions.disableWAL()).isTrue(); 750 assertThat(txnWriteOptions.sync()).isFalse(); 751 } 752 } 753 754 @Test 755 public void undoGetForUpdate_cf() throws RocksDBException { 756 final byte k1[] = "key1".getBytes(UTF_8); 757 final byte v1[] = "value1".getBytes(UTF_8); 758 try(final DBContainer dbContainer = startDb(); 759 final ReadOptions readOptions = new ReadOptions(); 760 final Transaction txn = dbContainer.beginTransaction()) { 761 final ColumnFamilyHandle testCf = dbContainer.getTestColumnFamily(); 762 assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isNull(); 763 txn.put(testCf, k1, v1); 764 assertThat(txn.getForUpdate(readOptions, testCf, k1, true)).isEqualTo(v1); 765 txn.undoGetForUpdate(testCf, k1); 766 } 767 } 768 769 @Test 770 public void undoGetForUpdate() throws RocksDBException { 771 final byte k1[] = "key1".getBytes(UTF_8); 772 final byte v1[] = "value1".getBytes(UTF_8); 773 try(final DBContainer dbContainer = startDb(); 774 final ReadOptions readOptions = new ReadOptions(); 775 final Transaction txn = dbContainer.beginTransaction()) { 776 assertThat(txn.getForUpdate(readOptions, k1, true)).isNull(); 777 txn.put(k1, v1); 778 assertThat(txn.getForUpdate(readOptions, k1, true)).isEqualTo(v1); 779 txn.undoGetForUpdate(k1); 780 } 781 } 782 783 @Test 784 public void rebuildFromWriteBatch() throws RocksDBException { 785 final byte k1[] = "key1".getBytes(UTF_8); 786 final byte v1[] = "value1".getBytes(UTF_8); 787 final byte k2[] = "key2".getBytes(UTF_8); 788 final byte v2[] = "value2".getBytes(UTF_8); 789 final byte k3[] = "key3".getBytes(UTF_8); 790 final byte v3[] = "value3".getBytes(UTF_8); 791 792 try(final DBContainer dbContainer = startDb(); 793 final ReadOptions readOptions = new ReadOptions(); 794 final Transaction txn = dbContainer.beginTransaction()) { 795 796 txn.put(k1, v1); 797 798 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 799 assertThat(txn.getNumKeys()).isEqualTo(1); 800 801 try(final WriteBatch writeBatch = new WriteBatch()) { 802 writeBatch.put(k2, v2); 803 writeBatch.put(k3, v3); 804 txn.rebuildFromWriteBatch(writeBatch); 805 806 assertThat(txn.get(readOptions, k1)).isEqualTo(v1); 807 assertThat(txn.get(readOptions, k2)).isEqualTo(v2); 808 assertThat(txn.get(readOptions, k3)).isEqualTo(v3); 809 assertThat(txn.getNumKeys()).isEqualTo(3); 810 } 811 } 812 } 813 814 @Test 815 public void getCommitTimeWriteBatch() throws RocksDBException { 816 final byte k1[] = "key1".getBytes(UTF_8); 817 final byte v1[] = "value1".getBytes(UTF_8); 818 819 try(final DBContainer dbContainer = startDb(); 820 final Transaction txn = dbContainer.beginTransaction()) { 821 822 txn.put(k1, v1); 823 final WriteBatch writeBatch = txn.getCommitTimeWriteBatch(); 824 825 assertThat(writeBatch).isNotNull(); 826 assertThat(writeBatch.isOwningHandle()).isFalse(); 827 assertThat(writeBatch.count()).isEqualTo(0); 828 } 829 } 830 831 @Test 832 public void logNumber() throws RocksDBException { 833 try(final DBContainer dbContainer = startDb(); 834 final Transaction txn = dbContainer.beginTransaction()) { 835 assertThat(txn.getLogNumber()).isEqualTo(0); 836 final long logNumber = rand.nextLong(); 837 txn.setLogNumber(logNumber); 838 assertThat(txn.getLogNumber()).isEqualTo(logNumber); 839 } 840 } 841 842 private static byte[] concat(final byte[][] bufs) { 843 int resultLength = 0; 844 for(final byte[] buf : bufs) { 845 resultLength += buf.length; 846 } 847 848 final byte[] result = new byte[resultLength]; 849 int resultOffset = 0; 850 for(final byte[] buf : bufs) { 851 final int srcLength = buf.length; 852 System.arraycopy(buf, 0, result, resultOffset, srcLength); 853 resultOffset += srcLength; 854 } 855 856 return result; 857 } 858 859 private static class TestTransactionNotifier 860 extends AbstractTransactionNotifier { 861 private final List<Snapshot> createdSnapshots = new ArrayList<>(); 862 863 @Override 864 public void snapshotCreated(final Snapshot newSnapshot) { 865 createdSnapshots.add(newSnapshot); 866 } 867 868 public List<Snapshot> getCreatedSnapshots() { 869 return createdSnapshots; 870 } 871 } 872 873 protected static abstract class DBContainer 874 implements AutoCloseable { 875 protected final WriteOptions writeOptions; 876 protected final List<ColumnFamilyHandle> columnFamilyHandles; 877 protected final ColumnFamilyOptions columnFamilyOptions; 878 protected final DBOptions options; 879 880 public DBContainer(final WriteOptions writeOptions, 881 final List<ColumnFamilyHandle> columnFamilyHandles, 882 final ColumnFamilyOptions columnFamilyOptions, 883 final DBOptions options) { 884 this.writeOptions = writeOptions; 885 this.columnFamilyHandles = columnFamilyHandles; 886 this.columnFamilyOptions = columnFamilyOptions; 887 this.options = options; 888 } 889 890 public abstract Transaction beginTransaction(); 891 892 public abstract Transaction beginTransaction( 893 final WriteOptions writeOptions); 894 895 public ColumnFamilyHandle getTestColumnFamily() { 896 return columnFamilyHandles.get(1); 897 } 898 899 @Override 900 public abstract void close(); 901 } 902 } 903