KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > tree > SR13034Test


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

8
9 package com.sleepycat.je.tree;
10
11 import java.io.File JavaDoc;
12 import java.io.IOException JavaDoc;
13
14 import junit.framework.TestCase;
15
16 import com.sleepycat.bind.tuple.StringBinding;
17 import com.sleepycat.je.Database;
18 import com.sleepycat.je.DatabaseConfig;
19 import com.sleepycat.je.DatabaseEntry;
20 import com.sleepycat.je.DatabaseException;
21 import com.sleepycat.je.DbInternal;
22 import com.sleepycat.je.Environment;
23 import com.sleepycat.je.EnvironmentConfig;
24 import com.sleepycat.je.OperationStatus;
25 import com.sleepycat.je.Transaction;
26 import com.sleepycat.je.config.EnvironmentParams;
27 import com.sleepycat.je.util.TestUtils;
28
29 /**
30  * Reproduce a bug where fetchEntry rather than fetchEntryIgnoreKnownDeleted
31  * was being called when searching the duplicate tree by LN node ID during
32  * recovery.
33  *
34  * The trick is to create a DBIN with a KnownDeleted flag set on an entry. And
35  * to cause recovery to search that DBIN by node ID during redo of a deleted
36  * LN. This deleted LN log entry must not have any data -- it must have been
37  * deleted before creation of the dup tree as in SR 8984.
38  *
39  * In addition, the deleted LN must appear after the entries with KnownDeleted
40  * set in the BIN, otherwise the search by node ID will find the LN before
41  * it encounters a KnownDeleted entry.
42
43  * The sequence in the test is as follows. I'm not positive this was the same
44  * sequence as seen by the user, since the user did not send their logs, but
45  * I believe the bug fix is general enough to cover similar cases.
46  *
47  * 1) Insert {A, C} (LN with key A, data C) in T1.
48  * 2) Delete {A, C} in T1. The LN log entry will not have any data.
49  * 3) Commit T1 so these log entries will be replayed during recovery redo.
50  * 4) Insert {A, A} and {A, B} in T2.
51  * 5) Abort T2 so that the KnownDeleted flag will be set on these DBIN entries
52  * during recovery.
53  * 6) Close without a checkpoint and recover. When replaying the deleted LN
54  * {A, C}, we don't have a dup key because it was deleted before the dup tree
55  * was created. So we search the dup tree by LN node ID. Calling fetchEntry
56  * on {A, A} (or {A, B}) throws an exception because KnownDeleted is set. We
57  * neglected to check KnownDeleted.
58  */

59 public class SR13034Test extends TestCase {
60
61     private File JavaDoc envHome;
62     private Environment env;
63     private Database db;
64
65     public SR13034Test() {
66         envHome = new File JavaDoc(System.getProperty(TestUtils.DEST_DIR));
67     }
68
69     public void setUp()
70         throws IOException JavaDoc {
71
72         TestUtils.removeLogFiles("Setup", envHome, false);
73     }
74     
75     public void tearDown()
76         throws Exception JavaDoc {
77
78         try {
79             if (env != null) {
80         env.close();
81             }
82         } catch (Exception JavaDoc e) {
83             System.out.println("During tearDown: " + e);
84         }
85
86         env = null;
87         db = null;
88
89         TestUtils.removeLogFiles("TearDown", envHome, false);
90     }
91
92     private void open()
93     throws DatabaseException {
94
95         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
96         envConfig.setAllowCreate(true);
97         envConfig.setTransactional(true);
98         /* Do not run the daemons to avoid timing considerations. */
99         envConfig.setConfigParam
100             (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false");
101         envConfig.setConfigParam
102             (EnvironmentParams.ENV_RUN_EVICTOR.getName(), "false");
103         envConfig.setConfigParam
104         (EnvironmentParams.ENV_RUN_CHECKPOINTER.getName(), "false");
105         envConfig.setConfigParam
106             (EnvironmentParams.ENV_RUN_INCOMPRESSOR.getName(), "false");
107         env = new Environment(envHome, envConfig);
108
109         DatabaseConfig dbConfig = new DatabaseConfig();
110         dbConfig.setAllowCreate(true);
111         dbConfig.setTransactional(true);
112         dbConfig.setSortedDuplicates(true);
113         db = env.openDatabase(null, "foo", dbConfig);
114     }
115
116     private void close()
117     throws DatabaseException {
118
119         db.close();
120         db = null;
121
122         env.close();
123         env = null;
124     }
125
126     public void testSR13034()
127     throws DatabaseException {
128
129         open();
130
131         DatabaseEntry key = new DatabaseEntry();
132         DatabaseEntry data = new DatabaseEntry();
133         OperationStatus status;
134         Transaction txn;
135
136         /*
137          * Insert {A, C}, then delete it. No dup tree has been created, so
138          * this logs a deleted LN with no data.
139          */

140         txn = env.beginTransaction(null, null);
141         StringBinding.stringToEntry("A", key);
142         StringBinding.stringToEntry("C", data);
143         status = db.putNoOverwrite(txn, key, data);
144         assertEquals(OperationStatus.SUCCESS, status);
145         status = db.delete(txn, key);
146         assertEquals(OperationStatus.SUCCESS, status);
147         txn.commit();
148
149         /*
150          * Insert {A, A}, {A, B}, which creates a dup tree. Then abort to set
151          * KnownDeleted on these entries.
152          */

153         txn = env.beginTransaction(null, null);
154         StringBinding.stringToEntry("A", key);
155         StringBinding.stringToEntry("A", data);
156         status = db.putNoDupData(txn, key, data);
157         StringBinding.stringToEntry("A", key);
158         StringBinding.stringToEntry("B", data);
159         status = db.putNoDupData(txn, key, data);
160         assertEquals(OperationStatus.SUCCESS, status);
161         txn.abort();
162
163         /*
164          * Close without a checkpoint and recover. Before the bug fix, the
165          * recovery would throw DatabaseException "attempt to fetch a deleted
166          * entry".
167          */

168         db.close();
169         DbInternal.envGetEnvironmentImpl(env).close(false);
170         open();
171
172         close();
173     }
174 }
175
Popular Tags