KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > persist > test > OperationTest


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: OperationTest.java,v 1.12 2006/11/27 22:44:24 mark Exp $
7  */

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 JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Set JavaDoc;
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 /**
41  * Tests misc store and index operations that are not tested by IndexTest.
42  *
43  * @author Mark Hayes
44  */

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     /**
84      * The store must be closed before closing the environment.
85      */

86     public void tearDown()
87         throws Exception JavaDoc {
88
89         try {
90             if (store != null) {
91                 store.close();
92             }
93         } catch (Throwable JavaDoc 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 JavaDoc,SharedSequenceEntity1> priIndex =
105             store.getPrimaryIndex(Integer JavaDoc.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         /*
114          * Check that we can open the store read-only and read the records
115          * written above.
116          */

117         openReadOnly();
118         priIndex =
119             store.getPrimaryIndex(Integer JavaDoc.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 JavaDoc<String JavaDoc> 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 JavaDoc,MyEntity> priIndex =
141             store.getPrimaryIndex(Integer JavaDoc.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 JavaDoc expected) {}
155         try {
156             entities.prevDup();
157             fail();
158         } catch (IllegalStateException JavaDoc expected) {}
159         try {
160             entities.current();
161             fail();
162         } catch (IllegalStateException JavaDoc expected) {}
163         try {
164             entities.delete();
165             fail();
166         } catch (IllegalStateException JavaDoc expected) {}
167         try {
168             entities.update(e);
169             fail();
170         } catch (IllegalStateException JavaDoc expected) {}
171         try {
172             entities.count();
173             fail();
174         } catch (IllegalStateException JavaDoc 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 JavaDoc,MyEntity> priIndex =
187             store.getPrimaryIndex(Integer JavaDoc.class, MyEntity.class);
188
189         SecondaryIndex<Integer JavaDoc,Integer JavaDoc,MyEntity> secIndex =
190             store.getSecondaryIndex(priIndex, Integer JavaDoc.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 JavaDoc,MyEntity> priIndex =
221             store.getPrimaryIndex(Integer JavaDoc.class, MyEntity.class);
222
223         SecondaryIndex<Integer JavaDoc,Integer JavaDoc,MyEntity> secIndex =
224             store.getSecondaryIndex(priIndex, Integer JavaDoc.class, "secKey");
225
226         Transaction txn = txnBeginCursor();
227
228         Integer JavaDoc k;
229         MyEntity e = new MyEntity();
230         e.priKey = 1;
231         e.secKey = 2;
232         priIndex.put(txn, e);
233
234         /* update() with primary entity cursor. */
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         /* update() with primary keys cursor. */
255         EntityCursor<Integer JavaDoc> 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 JavaDoc expected) {
263         }
264         keys.close();
265
266         /* update() with secondary entity cursor. */
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 JavaDoc expected) {
276         }
277         entities.close();
278
279         /* update() with secondary keys cursor. */
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 JavaDoc 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 JavaDoc,MyEntity> priIndex =
301             store.getPrimaryIndex(Integer JavaDoc.class, MyEntity.class);
302
303         SecondaryIndex<Integer JavaDoc,Integer JavaDoc,MyEntity> secIndex =
304             store.getSecondaryIndex(priIndex, Integer JavaDoc.class, "secKey");
305
306         Transaction txn = txnBeginCursor();
307
308         /* delete() with primary and secondary entities cursor. */
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         /* delete() with primary and secondary keys cursor. */
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 JavaDoc> cursor = index.keys(txn, null);
366
367             Integer JavaDoc 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 JavaDoc,MyEntity> priIndex =
404             store.getPrimaryIndex(Integer JavaDoc.class, MyEntity.class);
405
406         SecondaryIndex<Integer JavaDoc,Integer JavaDoc,MyEntity> secIndex =
407             store.getSecondaryIndex(priIndex, Integer JavaDoc.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 JavaDoc,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 JavaDoc secKey;
470
471         private MyEntity() {}
472     }
473     
474     public void testSharedSequence()
475         throws DatabaseException {
476
477         open();
478
479         PrimaryIndex<Integer JavaDoc,SharedSequenceEntity1> priIndex1 =
480             store.getPrimaryIndex(Integer JavaDoc.class, SharedSequenceEntity1.class);
481
482         PrimaryIndex<Integer JavaDoc,SharedSequenceEntity2> priIndex2 =
483             store.getPrimaryIndex(Integer JavaDoc.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 JavaDoc key;
515     }
516     
517     public void testSeparateSequence()
518         throws DatabaseException {
519
520         open();
521
522         PrimaryIndex<Integer JavaDoc,SeparateSequenceEntity1> priIndex1 =
523             store.getPrimaryIndex
524                 (Integer JavaDoc.class, SeparateSequenceEntity1.class);
525
526         PrimaryIndex<Integer JavaDoc,SeparateSequenceEntity2> priIndex2 =
527             store.getPrimaryIndex
528                 (Integer JavaDoc.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 JavaDoc key;
560     }
561
562     /**
563      * When opening read-only, secondaries are not opened when the primary is
564      * opened, causing a different code path to be used for opening
565      * secondaries. For a RawStore in particular, this caused an unreported
566      * NullPointerException in JE 3.0.12. No SR was created because the use
567      * case is very obscure and was discovered by code inspection.
568      */

569     public void testOpenRawStoreReadOnly()
570         throws DatabaseException {
571
572         open();
573         store.getPrimaryIndex(Integer JavaDoc.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 JavaDoc clsName = MyEntity.class.getName();
582         rawStore.getSecondaryIndex(clsName, "secKey");
583
584         rawStore.close();
585     }
586
587     /**
588      * When opening an X_TO_MANY secondary that has a persistent key class, the
589      * key class was not recognized as being persistent if it was never before
590      * referenced when getSecondaryIndex was called. This was a bug in JE
591      * 3.0.12, reported on OTN. [#15103]
592      */

593     public void testToManyKeyClass()
594         throws DatabaseException {
595
596         open();
597
598         PrimaryIndex<Integer JavaDoc,ToManyKeyEntity> priIndex =
599             store.getPrimaryIndex(Integer JavaDoc.class, ToManyKeyEntity.class);
600         SecondaryIndex<ToManyKey,Integer JavaDoc,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     /**
611      * Test a fix for a bug where opening a TO_MANY secondary index would fail
612      * fail with "IllegalArgumentException: Wrong secondary key class: ..."
613      * when the store was opened read-only. [#15156]
614      */

615     public void testToManyReadOnly()
616         throws DatabaseException {
617
618         open();
619         PrimaryIndex<Integer JavaDoc,ToManyKeyEntity> priIndex =
620             store.getPrimaryIndex(Integer JavaDoc.class, ToManyKeyEntity.class);
621         priIndex.put(new ToManyKeyEntity());
622         close();
623
624         openReadOnly();
625         priIndex = store.getPrimaryIndex(Integer JavaDoc.class, ToManyKeyEntity.class);
626         SecondaryIndex<ToManyKey,Integer JavaDoc,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 JavaDoc<ToManyKey> key2;
647
648         ToManyKeyEntity() {
649             key2 = new HashSet JavaDoc<ToManyKey>();
650             key2.add(new ToManyKey());
651         }
652     }
653     
654     public void testDeferredWrite()
655         throws DatabaseException {
656
657         if (envConfig.getTransactional()) {
658             /* Deferred write cannot be used with transactions. */
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 JavaDoc,MyEntity> priIndex =
668             store.getPrimaryIndex(Integer JavaDoc.class, MyEntity.class);
669
670         SecondaryIndex<Integer JavaDoc,Integer JavaDoc,MyEntity> secIndex =
671             store.getSecondaryIndex(priIndex, Integer JavaDoc.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 JavaDoc<Database> synced = new ArrayList JavaDoc<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