KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > cleaner > SR12978Test


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

8
9 package com.sleepycat.je.cleaner;
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.IntegerBinding;
17 import com.sleepycat.je.CheckpointConfig;
18 import com.sleepycat.je.Database;
19 import com.sleepycat.je.DatabaseConfig;
20 import com.sleepycat.je.DatabaseEntry;
21 import com.sleepycat.je.DatabaseException;
22 import com.sleepycat.je.DbInternal;
23 import com.sleepycat.je.Environment;
24 import com.sleepycat.je.EnvironmentConfig;
25 import com.sleepycat.je.OperationStatus;
26 import com.sleepycat.je.config.EnvironmentParams;
27 import com.sleepycat.je.log.FileManager;
28 import com.sleepycat.je.util.TestUtils;
29
30 /**
31  * Tests a fix to 12978, which was a ClassCastException in the following
32  * sequence.
33  *
34  * 1) A LN's BIN entry has the MIGRATE flag set.
35  *
36  * 2) Another LN with the same key is inserted (duplicates are allowed) and the
37  * first LN is moved to a dup tree,
38  *
39  * 3) The MIGRATE flag on the BIN entry is not cleared, and this entry now
40  * contains a DIN.
41  *
42  * 4) A split of the BIN occurs, logging the BIN with DIN entry. During a
43  * split we can't do migration, so we attempt to put the DIN onto the cleaner's
44  * pending list. We cast from DIN to LN, causing the exception.
45  *
46  * The fix was to clear the MIGRATE flag on the BIN entry at the time we update
47  * it to contain the DIN.
48  *
49  * This bug also left latches unreleased if a runtime exception occurred during
50  * a split, and that problem was fixed also.
51  */

52 public class SR12978Test extends TestCase {
53
54     private static final String JavaDoc DB_NAME = "foo";
55
56     private static final CheckpointConfig forceConfig = new CheckpointConfig();
57     static {
58         forceConfig.setForce(true);
59     }
60
61     private File JavaDoc envHome;
62     private Environment env;
63     private Database db;
64
65     public SR12978Test() {
66         envHome = new File JavaDoc(System.getProperty(TestUtils.DEST_DIR));
67     }
68
69     public void setUp()
70         throws IOException JavaDoc, DatabaseException {
71
72         TestUtils.removeLogFiles("Setup", envHome, false);
73         TestUtils.removeFiles("Setup", envHome, FileManager.DEL_SUFFIX);
74     }
75
76     public void tearDown()
77         throws IOException JavaDoc, DatabaseException {
78
79         try {
80             if (env != null) {
81                 env.close();
82             }
83         } catch (Throwable JavaDoc e) {
84             System.out.println("tearDown: " + e);
85         }
86                 
87         try {
88             TestUtils.removeLogFiles("tearDown", envHome, true);
89             TestUtils.removeFiles("tearDown", envHome, FileManager.DEL_SUFFIX);
90         } catch (Throwable JavaDoc e) {
91             System.out.println("tearDown: " + e);
92         }
93
94         db = null;
95         env = null;
96         envHome = null;
97     }
98
99     /**
100      * Opens the environment and database.
101      */

102     private void open()
103         throws DatabaseException {
104
105         EnvironmentConfig config = TestUtils.initEnvConfig();
106     DbInternal.disableParameterValidation(config);
107         config.setAllowCreate(true);
108         /* Do not run the daemons. */
109         config.setConfigParam
110             (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false");
111         config.setConfigParam
112             (EnvironmentParams.ENV_RUN_EVICTOR.getName(), "false");
113         config.setConfigParam
114         (EnvironmentParams.ENV_RUN_CHECKPOINTER.getName(), "false");
115         config.setConfigParam
116             (EnvironmentParams.ENV_RUN_INCOMPRESSOR.getName(), "false");
117         /* Configure to make cleaning more frequent. */
118         config.setConfigParam
119             (EnvironmentParams.LOG_FILE_MAX.getName(), "10240");
120         config.setConfigParam
121             (EnvironmentParams.CLEANER_MIN_UTILIZATION.getName(), "90");
122         
123         env = new Environment(envHome, config);
124
125         DatabaseConfig dbConfig = new DatabaseConfig();
126         dbConfig.setAllowCreate(true);
127         dbConfig.setSortedDuplicates(true);
128         db = env.openDatabase(null, DB_NAME, dbConfig);
129     }
130
131     /**
132      * Closes the environment and database.
133      */

134     private void close()
135         throws DatabaseException {
136
137         if (db != null) {
138             db.close();
139             db = null;
140         }
141         if (env != null) {
142             env.close();
143             env = null;
144         }
145     }
146
147     /**
148      */

149     public void testSR12978()
150         throws DatabaseException {
151
152         open();
153
154         final int COUNT = 500;
155         DatabaseEntry key = new DatabaseEntry();
156         DatabaseEntry data = new DatabaseEntry();
157         OperationStatus status;
158
159         /*
160          * Insert enough non-dup records to write a few log files. Delete
161          * every other so that cleaning will occur. Leave key space so we can
162          * insert below to cause splits.
163          */

164         IntegerBinding.intToEntry(0, data);
165         for (int i = 0; i < COUNT; i += 4) {
166
167             IntegerBinding.intToEntry(i + 0, key);
168             status = db.putNoOverwrite(null, key, data);
169             assertEquals(OperationStatus.SUCCESS, status);
170
171             IntegerBinding.intToEntry(i + 1, key);
172             status = db.putNoOverwrite(null, key, data);
173             assertEquals(OperationStatus.SUCCESS, status);
174
175             status = db.delete(null, key);
176             assertEquals(OperationStatus.SUCCESS, status);
177         }
178
179         /* Clean to set the MIGRATE flag on some LN entries. */
180         env.checkpoint(forceConfig);
181         int nCleaned = env.cleanLog();
182         assertTrue(nCleaned > 0);
183
184         /* Add dups to cause the LNs to be moved to a dup tree. */
185         IntegerBinding.intToEntry(1, data);
186         for (int i = 0; i < COUNT; i += 4) {
187
188             IntegerBinding.intToEntry(i + 0, key);
189             status = db.putNoDupData(null, key, data);
190             assertEquals(OperationStatus.SUCCESS, status);
191         }
192
193         /*
194          * Insert more unique keys to cause BIN splits. Before the fix to
195          * 12978, a CastCastException would occur during a split.
196          */

197         IntegerBinding.intToEntry(0, data);
198         for (int i = 0; i < COUNT; i += 4) {
199
200             IntegerBinding.intToEntry(i + 2, key);
201             status = db.putNoOverwrite(null, key, data);
202             assertEquals(OperationStatus.SUCCESS, status);
203
204             IntegerBinding.intToEntry(i + 3, key);
205             status = db.putNoOverwrite(null, key, data);
206             assertEquals(OperationStatus.SUCCESS, status);
207         }
208
209         close();
210     }
211 }
212
Popular Tags