1 8 9 package com.sleepycat.persist.test; 10 11 import static com.sleepycat.persist.model.Relationship.MANY_TO_ONE; 12 import static com.sleepycat.persist.model.Relationship.ONE_TO_MANY; 13 14 import java.util.ArrayList ; 15 import java.util.HashSet ; 16 import java.util.List ; 17 import java.util.Set ; 18 19 import junit.framework.Test; 20 21 import com.sleepycat.je.Database; 22 import com.sleepycat.je.DatabaseConfig; 23 import com.sleepycat.je.DatabaseException; 24 import com.sleepycat.je.Transaction; 25 import com.sleepycat.je.test.TxnTestCase; 26 import com.sleepycat.persist.EntityCursor; 27 import com.sleepycat.persist.EntityIndex; 28 import com.sleepycat.persist.EntityStore; 29 import com.sleepycat.persist.PrimaryIndex; 30 import com.sleepycat.persist.SecondaryIndex; 31 import com.sleepycat.persist.StoreConfig; 32 import com.sleepycat.persist.impl.Store; 33 import com.sleepycat.persist.model.Entity; 34 import com.sleepycat.persist.model.KeyField; 35 import com.sleepycat.persist.model.Persistent; 36 import com.sleepycat.persist.model.PrimaryKey; 37 import com.sleepycat.persist.model.SecondaryKey; 38 import com.sleepycat.persist.raw.RawStore; 39 40 45 public class OperationTest extends TxnTestCase { 46 47 public static Test suite() { 48 return txnTestSuite(OperationTest.class, null, null); 49 } 50 51 private EntityStore store; 52 53 private void openReadOnly() 54 throws DatabaseException { 55 56 StoreConfig config = new StoreConfig(); 57 config.setReadOnly(true); 58 open(config); 59 } 60 61 private void open() 62 throws DatabaseException { 63 64 StoreConfig config = new StoreConfig(); 65 config.setAllowCreate(envConfig.getAllowCreate()); 66 open(config); 67 } 68 69 private void open(StoreConfig config) 70 throws DatabaseException { 71 72 config.setTransactional(envConfig.getTransactional()); 73 store = new EntityStore(env, "test", config); 74 } 75 76 private void close() 77 throws DatabaseException { 78 79 store.close(); 80 store = null; 81 } 82 83 86 public void tearDown() 87 throws Exception { 88 89 try { 90 if (store != null) { 91 store.close(); 92 } 93 } catch (Throwable e) { 94 System.out.println("During tearDown: " + e); 95 } 96 store = null; 97 super.tearDown(); 98 } 99 100 public void testReadOnly() 101 throws DatabaseException { 102 103 open(); 104 PrimaryIndex<Integer ,SharedSequenceEntity1> priIndex = 105 store.getPrimaryIndex(Integer .class, SharedSequenceEntity1.class); 106 Transaction txn = txnBegin(); 107 SharedSequenceEntity1 e = new SharedSequenceEntity1(); 108 priIndex.put(txn, e); 109 assertEquals(1, e.key); 110 txnCommit(txn); 111 close(); 112 113 117 openReadOnly(); 118 priIndex = 119 store.getPrimaryIndex(Integer .class, SharedSequenceEntity1.class); 120 e = priIndex.get(1); 121 assertNotNull(e); 122 close(); 123 } 124 125 public void testGetStoreNames() 126 throws DatabaseException { 127 128 open(); 129 close(); 130 Set <String > names = EntityStore.getStoreNames(env); 131 assertEquals(1, names.size()); 132 assertEquals("test", names.iterator().next()); 133 } 134 135 public void testUninitializedCursor() 136 throws DatabaseException { 137 138 open(); 139 140 PrimaryIndex<Integer ,MyEntity> priIndex = 141 store.getPrimaryIndex(Integer .class, MyEntity.class); 142 143 Transaction txn = txnBeginCursor(); 144 145 MyEntity e = new MyEntity(); 146 e.priKey = 1; 147 e.secKey = 1; 148 priIndex.put(txn, e); 149 150 EntityCursor<MyEntity> entities = priIndex.entities(txn, null); 151 try { 152 entities.nextDup(); 153 fail(); 154 } catch (IllegalStateException expected) {} 155 try { 156 entities.prevDup(); 157 fail(); 158 } catch (IllegalStateException expected) {} 159 try { 160 entities.current(); 161 fail(); 162 } catch (IllegalStateException expected) {} 163 try { 164 entities.delete(); 165 fail(); 166 } catch (IllegalStateException expected) {} 167 try { 168 entities.update(e); 169 fail(); 170 } catch (IllegalStateException expected) {} 171 try { 172 entities.count(); 173 fail(); 174 } catch (IllegalStateException expected) {} 175 176 entities.close(); 177 txnCommit(txn); 178 close(); 179 } 180 181 public void testCursorCount() 182 throws DatabaseException { 183 184 open(); 185 186 PrimaryIndex<Integer ,MyEntity> priIndex = 187 store.getPrimaryIndex(Integer .class, MyEntity.class); 188 189 SecondaryIndex<Integer ,Integer ,MyEntity> secIndex = 190 store.getSecondaryIndex(priIndex, Integer .class, "secKey"); 191 192 Transaction txn = txnBeginCursor(); 193 194 MyEntity e = new MyEntity(); 195 e.priKey = 1; 196 e.secKey = 1; 197 priIndex.put(txn, e); 198 199 EntityCursor<MyEntity> cursor = secIndex.entities(txn, null); 200 cursor.next(); 201 assertEquals(1, cursor.count()); 202 cursor.close(); 203 204 e.priKey = 2; 205 priIndex.put(txn, e); 206 cursor = secIndex.entities(txn, null); 207 cursor.next(); 208 assertEquals(2, cursor.count()); 209 cursor.close(); 210 211 txnCommit(txn); 212 close(); 213 } 214 215 public void testCursorUpdate() 216 throws DatabaseException { 217 218 open(); 219 220 PrimaryIndex<Integer ,MyEntity> priIndex = 221 store.getPrimaryIndex(Integer .class, MyEntity.class); 222 223 SecondaryIndex<Integer ,Integer ,MyEntity> secIndex = 224 store.getSecondaryIndex(priIndex, Integer .class, "secKey"); 225 226 Transaction txn = txnBeginCursor(); 227 228 Integer k; 229 MyEntity e = new MyEntity(); 230 e.priKey = 1; 231 e.secKey = 2; 232 priIndex.put(txn, e); 233 234 235 EntityCursor<MyEntity> entities = priIndex.entities(txn, null); 236 e = entities.next(); 237 assertNotNull(e); 238 assertEquals(1, e.priKey); 239 assertEquals(Integer.valueOf(2), e.secKey); 240 e.secKey = null; 241 assertTrue(entities.update(e)); 242 e = entities.current(); 243 assertNotNull(e); 244 assertEquals(1, e.priKey); 245 assertEquals(null, e.secKey); 246 e.secKey = 3; 247 assertTrue(entities.update(e)); 248 e = entities.current(); 249 assertNotNull(e); 250 assertEquals(1, e.priKey); 251 assertEquals(Integer.valueOf(3), e.secKey); 252 entities.close(); 253 254 255 EntityCursor<Integer > keys = priIndex.keys(txn, null); 256 k = keys.next(); 257 assertNotNull(k); 258 assertEquals(Integer.valueOf(1), k); 259 try { 260 keys.update(2); 261 fail(); 262 } catch (UnsupportedOperationException expected) { 263 } 264 keys.close(); 265 266 267 entities = secIndex.entities(txn, null); 268 e = entities.next(); 269 assertNotNull(e); 270 assertEquals(1, e.priKey); 271 assertEquals(Integer.valueOf(3), e.secKey); 272 try { 273 entities.update(e); 274 fail(); 275 } catch (UnsupportedOperationException expected) { 276 } 277 entities.close(); 278 279 280 keys = secIndex.keys(txn, null); 281 k = keys.next(); 282 assertNotNull(k); 283 assertEquals(Integer.valueOf(3), k); 284 try { 285 keys.update(k); 286 fail(); 287 } catch (UnsupportedOperationException expected) { 288 } 289 keys.close(); 290 291 txnCommit(txn); 292 close(); 293 } 294 295 public void testCursorDelete() 296 throws DatabaseException { 297 298 open(); 299 300 PrimaryIndex<Integer ,MyEntity> priIndex = 301 store.getPrimaryIndex(Integer .class, MyEntity.class); 302 303 SecondaryIndex<Integer ,Integer ,MyEntity> secIndex = 304 store.getSecondaryIndex(priIndex, Integer .class, "secKey"); 305 306 Transaction txn = txnBeginCursor(); 307 308 309 310 for (EntityIndex index : new EntityIndex[] { priIndex, secIndex }) { 311 312 MyEntity e = new MyEntity(); 313 e.priKey = 1; 314 e.secKey = 1; 315 priIndex.put(txn, e); 316 e.priKey = 2; 317 priIndex.put(txn, e); 318 319 EntityCursor<MyEntity> cursor = index.entities(txn, null); 320 321 e = cursor.next(); 322 assertNotNull(e); 323 assertEquals(1, e.priKey); 324 e = cursor.current(); 325 assertNotNull(e); 326 assertEquals(1, e.priKey); 327 assertTrue(cursor.delete()); 328 assertTrue(!cursor.delete()); 329 assertNull(cursor.current()); 330 331 e = cursor.next(); 332 assertNotNull(e); 333 assertEquals(2, e.priKey); 334 e = cursor.current(); 335 assertNotNull(e); 336 assertEquals(2, e.priKey); 337 assertTrue(cursor.delete()); 338 assertTrue(!cursor.delete()); 339 assertNull(cursor.current()); 340 341 e = cursor.next(); 342 assertNull(e); 343 344 if (index == priIndex) { 345 e = new MyEntity(); 346 e.priKey = 2; 347 e.secKey = 1; 348 assertTrue(!cursor.update(e)); 349 } 350 351 cursor.close(); 352 } 353 354 355 356 for (EntityIndex index : new EntityIndex[] { priIndex, secIndex }) { 357 358 MyEntity e = new MyEntity(); 359 e.priKey = 1; 360 e.secKey = 1; 361 priIndex.put(txn, e); 362 e.priKey = 2; 363 priIndex.put(txn, e); 364 365 EntityCursor<Integer > cursor = index.keys(txn, null); 366 367 Integer k = cursor.next(); 368 assertNotNull(k); 369 assertEquals(1, k.intValue()); 370 k = cursor.current(); 371 assertNotNull(k); 372 assertEquals(1, k.intValue()); 373 assertTrue(cursor.delete()); 374 assertTrue(!cursor.delete()); 375 assertNull(cursor.current()); 376 377 int expectKey = (index == priIndex) ? 2 : 1; 378 k = cursor.next(); 379 assertNotNull(k); 380 assertEquals(expectKey, k.intValue()); 381 k = cursor.current(); 382 assertNotNull(k); 383 assertEquals(expectKey, k.intValue()); 384 assertTrue(cursor.delete()); 385 assertTrue(!cursor.delete()); 386 assertNull(cursor.current()); 387 388 k = cursor.next(); 389 assertNull(k); 390 391 cursor.close(); 392 } 393 394 txnCommit(txn); 395 close(); 396 } 397 398 public void testDeleteFromSubIndex() 399 throws DatabaseException { 400 401 open(); 402 403 PrimaryIndex<Integer ,MyEntity> priIndex = 404 store.getPrimaryIndex(Integer .class, MyEntity.class); 405 406 SecondaryIndex<Integer ,Integer ,MyEntity> secIndex = 407 store.getSecondaryIndex(priIndex, Integer .class, "secKey"); 408 409 Transaction txn = txnBegin(); 410 MyEntity e = new MyEntity(); 411 e.secKey = 1; 412 e.priKey = 1; 413 priIndex.put(txn, e); 414 e.priKey = 2; 415 priIndex.put(txn, e); 416 e.priKey = 3; 417 priIndex.put(txn, e); 418 e.priKey = 4; 419 priIndex.put(txn, e); 420 txnCommit(txn); 421 422 EntityIndex<Integer ,MyEntity> subIndex = secIndex.subIndex(1); 423 txn = txnBeginCursor(); 424 e = subIndex.get(txn, 1, null); 425 assertEquals(1, e.priKey); 426 assertEquals(Integer.valueOf(1), e.secKey); 427 e = subIndex.get(txn, 2, null); 428 assertEquals(2, e.priKey); 429 assertEquals(Integer.valueOf(1), e.secKey); 430 e = subIndex.get(txn, 3, null); 431 assertEquals(3, e.priKey); 432 assertEquals(Integer.valueOf(1), e.secKey); 433 e = subIndex.get(txn, 5, null); 434 assertNull(e); 435 436 boolean deleted = subIndex.delete(txn, 1); 437 assertTrue(deleted); 438 assertNull(subIndex.get(txn, 1, null)); 439 assertNotNull(subIndex.get(txn, 2, null)); 440 441 EntityCursor<MyEntity> cursor = subIndex.entities(txn, null); 442 boolean saw4 = false; 443 for (MyEntity e2 = cursor.first(); e2 != null; e2 = cursor.next()) { 444 if (e2.priKey == 3) { 445 cursor.delete(); 446 } 447 if (e2.priKey == 4) { 448 saw4 = true; 449 } 450 } 451 cursor.close(); 452 assertTrue(saw4); 453 assertNull(subIndex.get(txn, 1, null)); 454 assertNull(subIndex.get(txn, 3, null)); 455 assertNotNull(subIndex.get(txn, 2, null)); 456 assertNotNull(subIndex.get(txn, 4, null)); 457 458 txnCommit(txn); 459 close(); 460 } 461 462 @Entity 463 static class MyEntity { 464 465 @PrimaryKey 466 private int priKey; 467 468 @SecondaryKey(relate=MANY_TO_ONE) 469 private Integer secKey; 470 471 private MyEntity() {} 472 } 473 474 public void testSharedSequence() 475 throws DatabaseException { 476 477 open(); 478 479 PrimaryIndex<Integer ,SharedSequenceEntity1> priIndex1 = 480 store.getPrimaryIndex(Integer .class, SharedSequenceEntity1.class); 481 482 PrimaryIndex<Integer ,SharedSequenceEntity2> priIndex2 = 483 store.getPrimaryIndex(Integer .class, SharedSequenceEntity2.class); 484 485 Transaction txn = txnBegin(); 486 SharedSequenceEntity1 e1 = new SharedSequenceEntity1(); 487 SharedSequenceEntity2 e2 = new SharedSequenceEntity2(); 488 priIndex1.put(txn, e1); 489 assertEquals(1, e1.key); 490 priIndex2.putNoOverwrite(txn, e2); 491 assertEquals(Integer.valueOf(2), e2.key); 492 e1.key = 0; 493 priIndex1.putNoOverwrite(txn, e1); 494 assertEquals(3, e1.key); 495 e2.key = null; 496 priIndex2.put(txn, e2); 497 assertEquals(Integer.valueOf(4), e2.key); 498 txnCommit(txn); 499 500 close(); 501 } 502 503 @Entity 504 static class SharedSequenceEntity1 { 505 506 @PrimaryKey(sequence="shared") 507 private int key; 508 } 509 510 @Entity 511 static class SharedSequenceEntity2 { 512 513 @PrimaryKey(sequence="shared") 514 private Integer key; 515 } 516 517 public void testSeparateSequence() 518 throws DatabaseException { 519 520 open(); 521 522 PrimaryIndex<Integer ,SeparateSequenceEntity1> priIndex1 = 523 store.getPrimaryIndex 524 (Integer .class, SeparateSequenceEntity1.class); 525 526 PrimaryIndex<Integer ,SeparateSequenceEntity2> priIndex2 = 527 store.getPrimaryIndex 528 (Integer .class, SeparateSequenceEntity2.class); 529 530 Transaction txn = txnBegin(); 531 SeparateSequenceEntity1 e1 = new SeparateSequenceEntity1(); 532 SeparateSequenceEntity2 e2 = new SeparateSequenceEntity2(); 533 priIndex1.put(txn, e1); 534 assertEquals(1, e1.key); 535 priIndex2.putNoOverwrite(txn, e2); 536 assertEquals(Integer.valueOf(1), e2.key); 537 e1.key = 0; 538 priIndex1.putNoOverwrite(txn, e1); 539 assertEquals(2, e1.key); 540 e2.key = null; 541 priIndex2.put(txn, e2); 542 assertEquals(Integer.valueOf(2), e2.key); 543 txnCommit(txn); 544 545 close(); 546 } 547 548 @Entity 549 static class SeparateSequenceEntity1 { 550 551 @PrimaryKey(sequence="seq1") 552 private int key; 553 } 554 555 @Entity 556 static class SeparateSequenceEntity2 { 557 558 @PrimaryKey(sequence="seq2") 559 private Integer key; 560 } 561 562 569 public void testOpenRawStoreReadOnly() 570 throws DatabaseException { 571 572 open(); 573 store.getPrimaryIndex(Integer .class, MyEntity.class); 574 close(); 575 576 StoreConfig config = new StoreConfig(); 577 config.setReadOnly(true); 578 config.setTransactional(envConfig.getTransactional()); 579 RawStore rawStore = new RawStore(env, "test", config); 580 581 String clsName = MyEntity.class.getName(); 582 rawStore.getSecondaryIndex(clsName, "secKey"); 583 584 rawStore.close(); 585 } 586 587 593 public void testToManyKeyClass() 594 throws DatabaseException { 595 596 open(); 597 598 PrimaryIndex<Integer ,ToManyKeyEntity> priIndex = 599 store.getPrimaryIndex(Integer .class, ToManyKeyEntity.class); 600 SecondaryIndex<ToManyKey,Integer ,ToManyKeyEntity> secIndex = 601 store.getSecondaryIndex(priIndex, ToManyKey.class, "key2"); 602 603 priIndex.put(new ToManyKeyEntity()); 604 secIndex.get(new ToManyKey()); 605 606 close(); 607 } 608 609 610 615 public void testToManyReadOnly() 616 throws DatabaseException { 617 618 open(); 619 PrimaryIndex<Integer ,ToManyKeyEntity> priIndex = 620 store.getPrimaryIndex(Integer .class, ToManyKeyEntity.class); 621 priIndex.put(new ToManyKeyEntity()); 622 close(); 623 624 openReadOnly(); 625 priIndex = store.getPrimaryIndex(Integer .class, ToManyKeyEntity.class); 626 SecondaryIndex<ToManyKey,Integer ,ToManyKeyEntity> secIndex = 627 store.getSecondaryIndex(priIndex, ToManyKey.class, "key2"); 628 secIndex.get(new ToManyKey()); 629 close(); 630 } 631 632 @Persistent 633 static class ToManyKey { 634 635 @KeyField(1) 636 int value = 99; 637 } 638 639 @Entity 640 static class ToManyKeyEntity { 641 642 @PrimaryKey 643 int key = 88; 644 645 @SecondaryKey(relate=ONE_TO_MANY) 646 Set <ToManyKey> key2; 647 648 ToManyKeyEntity() { 649 key2 = new HashSet <ToManyKey>(); 650 key2.add(new ToManyKey()); 651 } 652 } 653 654 public void testDeferredWrite() 655 throws DatabaseException { 656 657 if (envConfig.getTransactional()) { 658 659 return; 660 } 661 StoreConfig storeConfig = new StoreConfig(); 662 storeConfig.setDeferredWrite(true); 663 storeConfig.setAllowCreate(true); 664 open(storeConfig); 665 assertTrue(store.getConfig().getDeferredWrite()); 666 667 PrimaryIndex<Integer ,MyEntity> priIndex = 668 store.getPrimaryIndex(Integer .class, MyEntity.class); 669 670 SecondaryIndex<Integer ,Integer ,MyEntity> secIndex = 671 store.getSecondaryIndex(priIndex, Integer .class, "secKey"); 672 673 DatabaseConfig dbConfig = priIndex.getDatabase().getConfig(); 674 assertTrue(dbConfig.getDeferredWrite()); 675 dbConfig = secIndex.getDatabase().getConfig(); 676 assertTrue(dbConfig.getDeferredWrite()); 677 678 MyEntity e = new MyEntity(); 679 e.priKey = 1; 680 e.secKey = 1; 681 priIndex.put(e); 682 683 EntityCursor<MyEntity> cursor = secIndex.entities(); 684 cursor.next(); 685 assertEquals(1, cursor.count()); 686 cursor.close(); 687 688 e.priKey = 2; 689 priIndex.put(e); 690 cursor = secIndex.entities(); 691 cursor.next(); 692 assertEquals(2, cursor.count()); 693 cursor.close(); 694 695 class MySyncHook implements Store.SyncHook { 696 697 boolean gotFlush; 698 List <Database> synced = new ArrayList <Database>(); 699 700 public void onSync(Database db, boolean flushLog) { 701 synced.add(db); 702 if (flushLog) { 703 assertTrue(!gotFlush); 704 gotFlush = true; 705 } 706 } 707 } 708 709 MySyncHook hook = new MySyncHook(); 710 Store.setSyncHook(hook); 711 store.sync(); 712 assertTrue(hook.gotFlush); 713 assertEquals(2, hook.synced.size()); 714 assertTrue(hook.synced.contains(priIndex.getDatabase())); 715 assertTrue(hook.synced.contains(secIndex.getDatabase())); 716 717 close(); 718 } 719 } 720 | Popular Tags |