KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > recovery > RecoveryAbortTest


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: RecoveryAbortTest.java,v 1.54 2006/10/30 21:14:48 bostic Exp $
7  */

8
9 package com.sleepycat.je.recovery;
10
11 import java.util.Hashtable JavaDoc;
12
13 import com.sleepycat.je.Cursor;
14 import com.sleepycat.je.Database;
15 import com.sleepycat.je.DatabaseConfig;
16 import com.sleepycat.je.DatabaseEntry;
17 import com.sleepycat.je.DatabaseException;
18 import com.sleepycat.je.DbInternal;
19 import com.sleepycat.je.Environment;
20 import com.sleepycat.je.EnvironmentConfig;
21 import com.sleepycat.je.OperationStatus;
22 import com.sleepycat.je.Transaction;
23 import com.sleepycat.je.config.EnvironmentParams;
24 import com.sleepycat.je.dbi.EnvironmentImpl;
25 import com.sleepycat.je.util.TestUtils;
26
27 public class RecoveryAbortTest extends RecoveryTestBase {
28     private static final boolean DEBUG = false;
29
30     public RecoveryAbortTest() {
31     super(true);
32     }
33
34     /**
35      * Insert data into several dbs, then abort.
36      */

37     public void testBasic()
38     throws Throwable JavaDoc {
39
40     createEnvAndDbs(1 << 20, true, NUM_DBS);
41         int numRecs = NUM_RECS * 3;
42
43         try {
44             /* Set up an repository of expected data. */
45             Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
46             
47             /* Insert all the data. */
48             Transaction txn = env.beginTransaction(null, null);
49             insertData(txn, 0, numRecs - 1, expectedData, 1, false, NUM_DBS);
50             txn.abort();
51             closeEnv();
52             recoverAndVerify(expectedData, NUM_DBS);
53         } catch (Throwable JavaDoc t) {
54             /* Print stacktrace before trying to clean up files. */
55             t.printStackTrace();
56             throw t;
57         }
58     }
59
60     /**
61      * Test insert/abort with no duplicates.
62      */

63     public void testInserts()
64     throws Throwable JavaDoc {
65
66     createEnvAndDbs(1 << 20, true, NUM_DBS);
67         EnvironmentImpl realEnv = DbInternal.envGetEnvironmentImpl(env);
68         
69         int N = NUM_RECS;
70         
71         if (DEBUG) {
72             System.out.println("<dump>");
73         }
74         try {
75             /* Set up an repository of expected data. */
76             Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
77             
78             /* Insert 0 - N and commit. */
79             Transaction txn = env.beginTransaction(null, null);
80             insertData(txn, 0, N - 1, expectedData, 1, true, NUM_DBS);
81             txn.commit();
82             verifyData(expectedData, false, NUM_DBS);
83             
84             /* Insert N - 3N and abort. */
85             txn = env.beginTransaction(null, null);
86             insertData(txn, N, (3 * N) - 1, expectedData, 1, false, NUM_DBS);
87             txn.abort();
88             verifyData(expectedData, false, NUM_DBS);
89
90             /*
91          * Wait for the incompressor queue to be processed, so we force the
92          * recovery to run w/IN delete replays.
93          */

94             while (realEnv.getINCompressorQueueSize() > 0) {
95                 Thread.sleep(10000);
96             }
97
98             /* Insert 2N - 4N and commit. */
99             txn = env.beginTransaction(null, null);
100             insertData(txn, (2 * N), (4 * N) - 1, expectedData, 1, true,
101                NUM_DBS);
102             txn.commit();
103             verifyData(expectedData, false, NUM_DBS);
104
105             closeEnv();
106             recoverAndVerify(expectedData, NUM_DBS);
107
108         } catch (Throwable JavaDoc t) {
109             /* Print stacktrace before trying to clean up files. */
110             t.printStackTrace();
111             throw t;
112         } finally {
113             if (DEBUG) {
114                 System.out.println("</dump>");
115             }
116         }
117     }
118
119     public void testMix()
120     throws Throwable JavaDoc {
121
122     createEnvAndDbs(1 << 20, true, NUM_DBS);
123
124         int numRecs = NUM_RECS;
125         int numDups = 10;
126                 
127         try {
128             /* Set up an repository of expected data. */
129             Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
130             
131             /* Insert data without duplicates. */
132             Transaction txn = env.beginTransaction(null, null);
133             insertData(txn, 0, numRecs, expectedData, 1, true, NUM_DBS);
134
135             /* Insert more with duplicates, commit. */
136             insertData(txn, numRecs+1, (2*numRecs), expectedData,
137                        numDups, true, NUM_DBS);
138             txn.commit();
139
140             /* Delete all and abort. */
141             txn = env.beginTransaction(null, null);
142             deleteData(txn, expectedData, true, false, NUM_DBS);
143             txn.abort();
144
145             /* Delete every other and commit. */
146             txn = env.beginTransaction(null, null);
147             deleteData(txn, expectedData, false, true, NUM_DBS);
148             txn.commit();
149             
150             /* Modify some and abort. */
151             txn = env.beginTransaction(null, null);
152             modifyData(txn, numRecs, expectedData, 3, false, NUM_DBS);
153             txn.abort();
154
155             /* Modify some and commit. */
156             txn = env.beginTransaction(null, null);
157             modifyData(txn, numRecs/2, expectedData, 2, true, NUM_DBS);
158             txn.commit();
159
160             if (DEBUG) {
161                 dumpData(NUM_DBS);
162                 dumpExpected(expectedData);
163                 com.sleepycat.je.tree.Key.DUMP_BINARY = true;
164                 DbInternal.dbGetDatabaseImpl(dbs[0]).getTree().dump();
165             }
166             TestUtils.validateNodeMemUsage
167                            (DbInternal.envGetEnvironmentImpl(env),
168                             false);
169             closeEnv();
170             recoverAndVerify(expectedData, NUM_DBS);
171         } catch (Throwable JavaDoc t) {
172             // print stacktrace before trying to clean up files
173
t.printStackTrace();
174             throw t;
175         }
176     }
177
178     public void testSR13726()
179     throws Throwable JavaDoc {
180
181     int numDbs = 1;
182
183     createEnvAndDbs(1 << 20, true, numDbs);
184
185         try {
186             /*
187          * Insert data without duplicates, commit. This gets us a
188          * DupCountLN.
189          */

190             Transaction txn = env.beginTransaction(null, null);
191         Cursor c = dbs[0].openCursor(txn, null);
192         DatabaseEntry key = new DatabaseEntry();
193         DatabaseEntry data = new DatabaseEntry();
194             byte[] keyData = TestUtils.getTestArray(0);
195             byte[] dataData = TestUtils.byteArrayCopy(keyData);
196             key.setData(keyData);
197         data.setData(dataData);
198         for (int i = 0; i < 3; i++) {
199         data.setData(TestUtils.getTestArray(i));
200         assertEquals("insert some dups",
201                  c.put(key, data),
202                  OperationStatus.SUCCESS);
203         }
204         c.close();
205         txn.commit();
206
207         /* This gets us a DelDupLN in the slot in the BIN. */
208         txn = env.beginTransaction(null, null);
209         assertEquals("delete initial dups",
210              dbs[0].delete(txn, key),
211              OperationStatus.SUCCESS);
212             txn.commit();
213
214         /* This gets the dup tree cleaned up. */
215         env.compress();
216
217         /* Gets the BIN written out with knownDeleted=true. */
218         closeEnv();
219         recoverOnly(numDbs);
220         createDbs(null, numDbs);
221
222         /*
223          * Tree now has a BIN referring to a DelDupLN. Add duplicates,
224          * and abort.
225          */

226         txn = env.beginTransaction(null, null);
227         c = dbs[0].openCursor(txn, null);
228         for (int i = 0; i < 3; i++) {
229         data.setData(TestUtils.getTestArray(i));
230         assertEquals("insert later dups",
231                  c.put(key, data),
232                  OperationStatus.SUCCESS);
233         }
234         c.close();
235             txn.abort();
236
237         /*
238          * Now add duplicates again and commit.
239          */

240         txn = env.beginTransaction(null, null);
241         c = dbs[0].openCursor(txn, null);
242         for (int i = 0; i < 3; i++) {
243         data.setData(TestUtils.getTestArray(i));
244         assertEquals("insert later dups",
245                  c.put(key, data),
246                  OperationStatus.SUCCESS);
247         }
248         c.close();
249             txn.commit();
250
251         txn = env.beginTransaction(null, null);
252         c = dbs[0].openCursor(txn, null);
253         int count = 0;
254         while (c.getNext(key, data, null) == OperationStatus.SUCCESS) {
255         count++;
256         }
257         c.getSearchKey(key, data, null);
258         assertEquals("scanned count == count()", count, c.count());
259         c.close();
260         txn.commit();
261         closeEnv();
262         } catch (Throwable JavaDoc t) {
263             // print stacktrace before trying to clean up files
264
t.printStackTrace();
265             throw t;
266         }
267     }
268
269     /*
270      * Test the sequence where we have an existing record in the
271      * database; then in a separate transaction we delete that data
272      * and reinsert it and then abort that transaction. During the
273      * undo, the insert will be undone first (by deleting the record
274      * and setting knownDeleted true in the ChildReference); the
275      * deletion will be undone second by adding the record back into
276      * the database. The entry needs to be present in the BIN when we
277      * add it back in. But the compressor may be running at the same
278      * time and compress the entry out between the deletion and
279      * re-insertion making the entry disappear from the BIN. This is
280      * prevented by a lock being taken by the compressor on the LN,
281      * even if the LN is "knownDeleted". [#9465]
282      */

283     public void testSR9465Part1()
284     throws Throwable JavaDoc {
285
286     createEnvAndDbs(1 << 20, true, NUM_DBS);
287         int numRecs = NUM_RECS;
288         
289         try {
290             /* Set up an repository of expected data. */
291             Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
292             
293             /* Insert data without duplicates. */
294             Transaction txn = env.beginTransaction(null, null);
295             insertData(txn, 0, numRecs, expectedData, 1, true, NUM_DBS);
296             txn.commit();
297
298             /* Delete all and abort. */
299             txn = env.beginTransaction(null, null);
300             deleteData(txn, expectedData, true, false, NUM_DBS);
301             insertData(txn, 0, numRecs, expectedData, 1, false, NUM_DBS);
302             txn.abort();
303
304             txn = env.beginTransaction(null, null);
305         verifyData(expectedData, NUM_DBS);
306             txn.commit();
307
308             if (DEBUG) {
309                 dumpData(NUM_DBS);
310                 dumpExpected(expectedData);
311                 com.sleepycat.je.tree.Key.DUMP_BINARY = true;
312                 DbInternal.dbGetDatabaseImpl(dbs[0]).getTree().dump();
313             }
314
315             closeEnv();
316             recoverAndVerify(expectedData, NUM_DBS);
317         } catch (Throwable JavaDoc t) {
318             /* Print stacktrace before trying to clean up files. */
319             t.printStackTrace();
320             throw t;
321         }
322     }
323
324     public void testSR9465Part2()
325     throws Throwable JavaDoc {
326
327     createEnvAndDbs(1 << 20, true, NUM_DBS);
328         int numRecs = NUM_RECS;
329         
330         try {
331             /* Set up an repository of expected data. */
332             Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
333             
334             /* Insert data without duplicates. */
335             Transaction txn = env.beginTransaction(null, null);
336             insertData(txn, 0, numRecs, expectedData, 1, true, NUM_DBS);
337             txn.commit();
338
339             /* Delete all and abort. */
340             txn = env.beginTransaction(null, null);
341             deleteData(txn, expectedData, true, false, NUM_DBS);
342             insertData(txn, 0, numRecs, expectedData, 1, false, NUM_DBS);
343             deleteData(txn, expectedData, true, false, NUM_DBS);
344             txn.abort();
345
346             if (DEBUG) {
347                 dumpData(NUM_DBS);
348                 dumpExpected(expectedData);
349                 com.sleepycat.je.tree.Key.DUMP_BINARY = true;
350                 DbInternal.dbGetDatabaseImpl(dbs[0]).getTree().dump();
351             }
352
353             txn = env.beginTransaction(null, null);
354         verifyData(expectedData, NUM_DBS);
355             txn.commit();
356
357             if (DEBUG) {
358                 dumpData(NUM_DBS);
359                 dumpExpected(expectedData);
360                 com.sleepycat.je.tree.Key.DUMP_BINARY = true;
361                 DbInternal.dbGetDatabaseImpl(dbs[0]).getTree().dump();
362             }
363
364             closeEnv();
365             recoverAndVerify(expectedData, NUM_DBS);
366         } catch (Throwable JavaDoc t) {
367             /* Print stacktrace before trying to clean up files. */
368             t.printStackTrace();
369             throw t;
370         }
371     }
372
373     public void testSR9752Part1()
374     throws Throwable JavaDoc {
375
376     createEnvAndDbs(1 << 20, false, NUM_DBS);
377         int numRecs = NUM_RECS;
378         
379         try {
380             /* Set up an repository of expected data. */
381             Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
382             
383             /* Insert data without duplicates. */
384             Transaction txn = env.beginTransaction(null, null);
385             insertData(txn, 0, numRecs, expectedData, 1, true, NUM_DBS);
386             txn.commit();
387
388         /*
389          * txn1 just puts a piece of data out to a database that won't
390          * be seen by deleteData or insertData. The idea is to hold
391          * the transaction open across the env.sync() so that firstActive
392          * comes before ckptStart.
393          */

394             Transaction txn1 = env.beginTransaction(null, null);
395         DatabaseEntry key = new DatabaseEntry(new byte[] { 1, 2, 3, 4 });
396         DatabaseEntry data = new DatabaseEntry(new byte[] { 4, 3, 2, 1 });
397         DatabaseConfig dbConfig = new DatabaseConfig();
398         dbConfig.setAllowCreate(true);
399         dbConfig.setSortedDuplicates(false);
400         dbConfig.setTransactional(true);
401             Database otherDb = env.openDatabase(txn1, "extradb", dbConfig);
402         otherDb.put(txn1, key, data);
403
404             /* Delete all and abort. */
405             txn = env.beginTransaction(null, null);
406             deleteData(txn, expectedData, false, false, NUM_DBS);
407             txn.abort();
408
409             /* Delete all and commit. */
410             txn = env.beginTransaction(null, null);
411             deleteData(txn, expectedData, false, true, NUM_DBS);
412             txn.commit();
413
414         env.sync(); /* env.checkpoint does not seem to be sufficient. */
415             txn1.commit();
416         otherDb.close();
417
418         closeEnv();
419
420             if (DEBUG) {
421                 dumpData(NUM_DBS);
422                 dumpExpected(expectedData);
423                 com.sleepycat.je.tree.Key.DUMP_BINARY = true;
424                 DbInternal.dbGetDatabaseImpl(dbs[0]).getTree().dump();
425             }
426
427             recoverAndVerify(expectedData, NUM_DBS);
428         } catch (Throwable JavaDoc t) {
429             /* Print stacktrace before trying to clean up files. */
430             t.printStackTrace();
431             throw t;
432         }
433     }
434
435     public void testSR9752Part2()
436     throws Throwable JavaDoc {
437
438     createEnvAndDbs(1 << 20, false, NUM_DBS);
439     DbInternal.envGetEnvironmentImpl(env).shutdownCleaner();
440         int numRecs = NUM_RECS;
441         
442         try {
443             /* Set up an repository of expected data. */
444             Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
445             
446             /* Insert data without duplicates. */
447             Transaction txn = env.beginTransaction(null, null);
448             insertData(txn, 0, numRecs, expectedData, 1, true, NUM_DBS);
449             txn.commit();
450
451         /*
452          * txn1 just puts a piece of data out to a database that won't
453          * be seen by deleteData or insertData. The idea is to hold
454          * the transaction open across the env.sync() so that firstActive
455          * comes before ckptStart.
456          */

457             Transaction txn1 = env.beginTransaction(null, null);
458         DatabaseEntry key = new DatabaseEntry(new byte[] { 1, 2, 3, 4 });
459         DatabaseEntry data = new DatabaseEntry(new byte[] { 4, 3, 2, 1 });
460         DatabaseConfig dbConfig = new DatabaseConfig();
461         dbConfig.setAllowCreate(true);
462         dbConfig.setSortedDuplicates(false);
463         dbConfig.setTransactional(true);
464             Database otherDb = env.openDatabase(txn1, "extradb", dbConfig);
465         otherDb.put(txn1, key, data);
466
467             /* Delete all and abort. */
468             txn = env.beginTransaction(null, null);
469             deleteData(txn, expectedData, false, false, NUM_DBS);
470             txn.abort();
471
472             /* Delete all and commit. */
473             txn = env.beginTransaction(null, null);
474             deleteData(txn, expectedData, false, true, NUM_DBS);
475             txn.commit();
476
477         env.sync(); /* env.checkpoint does not seem to be sufficient. */
478             txn1.commit();
479         otherDb.close();
480
481         closeEnv();
482
483             if (DEBUG) {
484                 dumpData(NUM_DBS);
485                 dumpExpected(expectedData);
486                 com.sleepycat.je.tree.Key.DUMP_BINARY = true;
487                 DbInternal.dbGetDatabaseImpl(dbs[0]).getTree().dump();
488             }
489
490             recoverAndVerify(expectedData, NUM_DBS);
491         } catch (Throwable JavaDoc t) {
492             /* Print stacktrace before trying to clean up files. */
493             t.printStackTrace();
494             throw t;
495         }
496     }
497
498     /**
499      * Insert dbs, commit some, abort some. To do: add db remove, rename.
500      */

501     public void testDbCreateRemove()
502     throws Throwable JavaDoc {
503
504         createEnv(1 << 20, true);
505         int N1 = 10;
506         int N2 = 50;
507         int N3 = 60;
508         int N4 = 70;
509         int N5 = 100;
510
511         String JavaDoc dbName1 = "foo";
512         String JavaDoc dbName2 = "bar";
513
514         try {
515             /* Make Dbs, abort */
516             Transaction txn = env.beginTransaction(null, null);
517
518             DatabaseConfig dbConfig = new DatabaseConfig();
519             dbConfig.setTransactional(true);
520             dbConfig.setAllowCreate(true);
521             for (int i = 0; i < N2; i++) {
522                 env.openDatabase(txn, dbName1 + i, dbConfig);
523             }
524             txn.abort();
525             
526             /* All dbs should not exist */
527             checkForNoDb(dbName1, 0, N2);
528
529             /* Make more dbs, overlapping with some of the aborted set. */
530             txn = env.beginTransaction(null, null);
531             for (int i = N1; i < N5; i++) {
532                 Database db = env.openDatabase(txn, dbName1 + i, dbConfig);
533                 db.close();
534             }
535             txn.commit();
536
537             /*
538              * Dbs 0 - N1-1 shouldn't exist
539              * Dbs N1 - N5 should exist
540              */

541             checkForNoDb(dbName1, 0, N1);
542             checkForDb(dbName1, N1, N5);
543
544             /* Close and recover */
545             env.close();
546
547             EnvironmentConfig envConfig = TestUtils.initEnvConfig();
548         envConfig.setConfigParam
549         (EnvironmentParams.NODE_MAX.getName(), "6");
550         envConfig.setConfigParam(EnvironmentParams.MAX_MEMORY.getName(),
551                      new Long JavaDoc(1 << 24).toString());
552             envConfig.setTransactional(true);
553             envConfig.setTxnNoSync(Boolean.getBoolean(TestUtils.NO_SYNC));
554             env = new Environment(envHome, envConfig);
555
556             /*
557              * Dbs 0 - N1-1 shouldn't exist
558              * Dbs N1 - N5 should exist
559              */

560             checkForNoDb(dbName1, 0, N1);
561             checkForDb(dbName1, N1, N5);
562
563             /* Remove some dbs, abort */
564             txn = env.beginTransaction(null, null);
565             for (int i = N2; i < N4; i++) {
566                 env.removeDatabase(txn, dbName1+i);
567             }
568             txn.abort();
569
570             /* Remove some dbs, commit */
571             txn = env.beginTransaction(null, null);
572             for (int i = N3; i < N4; i++) {
573                 env.removeDatabase(txn, dbName1+i);
574             }
575             txn.commit();
576
577             /*
578              * Dbs 0 - N1-1 should not exist
579              * Dbs N1 - N3-1 should exist
580              * Dbs N3 - N4-1 should not exist
581              * Dbs N4 - N5-1 should exist
582              */

583             checkForNoDb(dbName1, 0, N1);
584             checkForDb(dbName1, N1, N3);
585             checkForNoDb(dbName1, N3, N4);
586             checkForDb(dbName1, N4, N5);
587
588             /* Close and recover */
589             env.close();
590             env = new Environment(envHome, envConfig);
591
592             /*
593              * Dbs 0 - N1-1 should not exist
594              * Dbs N1 - N3-1 should exist
595              * Dbs N3 - N4-1 should not exist
596              * Dbs N4 - N5-1 should exist
597              */

598             checkForNoDb(dbName1, 0, N1);
599             checkForDb(dbName1, N1, N3);
600             checkForNoDb(dbName1, N3, N4);
601             checkForDb(dbName1, N4, N5);
602             
603             /* Rename some dbs, abort */
604             txn = env.beginTransaction(null, null);
605             for (int i = N1; i < N3; i++) {
606                 env.renameDatabase
607             (txn, dbName1+i, dbName2+i);
608             }
609             txn.abort();
610
611             /* Remove some dbs, commit */
612             txn = env.beginTransaction(null, null);
613             for (int i = N2; i < N3; i++) {
614                 env.renameDatabase
615             (txn, dbName1+i, dbName2+i);
616             }
617             txn.commit();
618
619             /*
620              * Dbs 0 - N1-1 should not exist
621              * Dbs N1 - N2-1 should exist with old name
622              * Dbs N2 - N3-1 should exist with new name
623              * Dbs N3 - N4 should not exist
624              * Dbs N4 - N5-1 should exist with old name
625              */

626             checkForNoDb(dbName1, 0, N1);
627             checkForDb(dbName1, N1, N2);
628             checkForDb(dbName2, N2, N3);
629             checkForNoDb(dbName1, N3, N4);
630             checkForDb(dbName1, N4, N5);
631         } catch (Throwable JavaDoc t) {
632             /* print stacktrace before trying to clean up files. */
633             t.printStackTrace();
634             throw t;
635         }
636     }
637
638     /**
639      * Fail if any db from start - (end -1) exists
640      */

641     private void checkForNoDb(String JavaDoc dbName, int start, int end)
642         throws DatabaseException {
643             
644         /* Dbs start - end -1 shouldn't exist */
645         for (int i = start; i < end; i++) {
646             try {
647                 env.openDatabase(null, dbName + i, null);
648                 fail(DB_NAME + i + " shouldn't exist");
649             } catch (DatabaseException e) {
650             }
651         }
652     }
653
654     /**
655      * Fail if any db from start - (end -1) doesn't exist
656      */

657     private void checkForDb(String JavaDoc dbName, int start, int end)
658         throws DatabaseException {
659         /* Dbs start - end -1 should exist. */
660         for (int i = start; i < end; i++) {
661             try {
662                 Database checkDb = env.openDatabase(null, dbName + i, null);
663                 checkDb.close();
664             } catch (DatabaseException e) {
665                 fail(e.getMessage());
666             }
667         }
668     }
669 }
670
Popular Tags