KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > incomp > EmptyBINTest


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

8
9 package com.sleepycat.je.incomp;
10
11 import java.io.File JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.util.Enumeration JavaDoc;
14
15 import junit.framework.Test;
16 import junit.framework.TestCase;
17 import junit.framework.TestSuite;
18
19 import com.sleepycat.je.CheckpointConfig;
20 import com.sleepycat.je.Cursor;
21 import com.sleepycat.je.Database;
22 import com.sleepycat.je.DatabaseConfig;
23 import com.sleepycat.je.DatabaseEntry;
24 import com.sleepycat.je.DatabaseException;
25 import com.sleepycat.je.DbInternal;
26 import com.sleepycat.je.Environment;
27 import com.sleepycat.je.EnvironmentConfig;
28 import com.sleepycat.je.LockMode;
29 import com.sleepycat.je.OperationStatus;
30 import com.sleepycat.je.config.EnvironmentParams;
31 import com.sleepycat.je.dbi.CursorImpl;
32 import com.sleepycat.je.util.TestUtils;
33 import com.sleepycat.je.utilint.TestHook;
34
35 /**
36  * Test that searches and cursor traversals execute correctly in the face of
37  * a BIN with 0 entries, and with tree pruning at key points.
38  */

39 public class EmptyBINTest extends TestCase {
40     private static final boolean DEBUG = false;
41
42     private static final byte DEFAULT_VAL = 100;
43     private File JavaDoc envHome;
44     private Environment env;
45     private Database db;
46
47     private boolean useDups;
48     private boolean doPruningAtCursorLevel;
49     private boolean doPruningAtTreeLevel;
50
51     public EmptyBINTest() {
52         envHome = new File JavaDoc(System.getProperty(TestUtils.DEST_DIR));
53     }
54
55     public void setUp()
56         throws IOException JavaDoc {
57
58         TestUtils.removeLogFiles("Setup", envHome, false);
59     }
60     
61     public void tearDown()
62         throws Exception JavaDoc {
63
64         if (db != null) {
65             try {
66         db.close();
67         } catch (DatabaseException ignore) {
68         }
69         }
70
71         if (env != null) {
72             try {
73         env.close();
74         } catch (DatabaseException ignore) {
75         }
76         }
77         env = null;
78         db = null;
79         setName(getName() + "-" +
80         (useDups ? "DUPS" : "!DUPS") +
81         "/" +
82         (doPruningAtCursorLevel ? "CURSORPRUNE" : "!CURSORPRUNE") +
83         "/" +
84         (doPruningAtTreeLevel ? "TREEPRUNE" : "!TREEPRUNE"));
85     super.tearDown();
86         TestUtils.removeLogFiles("TearDown", envHome, false);
87     }
88
89     /*
90      * Run all tests in four combinations, using dups, and invoking bin
91      * pruning.
92      */

93     public static Test suite() {
94         TestSuite allTests = new TestSuite();
95         boolean[] dupCombo = new boolean[] {true, false};
96         boolean[] pruneCombo = new boolean[] {true, false};
97         for (int dup = 0; dup < dupCombo.length; dup++) {
98             for (int pruneCursor = 0;
99          pruneCursor < pruneCombo.length;
100          pruneCursor++) {
101         for (int pruneTree = 0;
102              pruneTree < pruneCombo.length;
103              pruneTree++) {
104             TestSuite suite = new TestSuite(EmptyBINTest.class);
105             Enumeration JavaDoc e = suite.tests();
106             while (e.hasMoreElements()) {
107             EmptyBINTest test = (EmptyBINTest) e.nextElement();
108             boolean pruneC = pruneCombo[pruneCursor];
109             boolean pruneT = pruneCombo[pruneTree];
110             if (pruneC && pruneT) {
111                 /* Only do one hook at a time. */
112                 break;
113             }
114             test.init(dupCombo[dup], pruneC, pruneT);
115             allTests.addTest(test);
116             }
117         }
118         }
119         }
120         return allTests;
121     }
122
123     private void init(boolean useDups,
124               boolean doPruningAtCursorLevel,
125               boolean doPruningAtTreeLevel) {
126         this.useDups = useDups;
127         this.doPruningAtCursorLevel = doPruningAtCursorLevel;
128         this.doPruningAtTreeLevel = doPruningAtTreeLevel;
129         if (DEBUG) {
130             System.out.println("useDups=" + useDups +
131                                " doPruningAtCursorLevel=" +
132                    doPruningAtCursorLevel +
133                                " doPruningAtTreeLevel=" +
134                    doPruningAtTreeLevel);
135         }
136     }
137
138     /* Non-dupes scans across an empty BIN. */
139     public void testScanFromEndOfFirstBin()
140         throws DatabaseException {
141
142     /*
143          * Tree holds <0,1> <2,3,4> <empty> <8,9,10>.
144          * |
145          * fwd scan starts --- -+
146          * Fwd scan starting at 4. Expect 4, 8, 9, 10
147          */

148         doScanAcrossEmptyBin(true, // forward
149
(byte) 4, // start
150
new byte[] {4,8,9,10}); // expected
151
}
152
153     public void testScanFromLeftSideOfEmptyBin()
154         throws DatabaseException {
155
156     /*
157          * Tree holds <0,1> <2,3,4> <empty> <8,9,10>.
158          * |
159          * scan starts -------------+
160          * Fwd scan starting at 5 (deleted). Expect 8, 9, 10
161          */

162         doScanAcrossEmptyBin(true, // forward
163
(byte) 5, // start
164
new byte[] {8,9,10}); // expected
165
}
166
167     public void testScanFromRightSideOfEmptyBin()
168         throws DatabaseException {
169
170     /*
171          * Tree holds <0,1> <2,3,4> <empty> <8,9,10>.
172          * |
173          * backwards scan starts ------+
174          * Backwards scan starting at 7 (deleted). Expect 8,4,3,2,1,0
175          */

176         doScanAcrossEmptyBin(false, // backwards
177
(byte) 7, // start
178
new byte[] {8,4,3,2,1,0}); // expected
179
}
180
181     public void testScanFromBeginningOfLastBin()
182         throws DatabaseException {
183
184     /*
185          * Tree holds <0,1> <2,3,4> <empty> <8,9,10>.
186          * |
187          * backwards scan starts -----------+
188          */

189         doScanAcrossEmptyBin(false, // backwards
190
(byte) 8, // start
191
new byte[] {8,4,3,2,1,0}); // expected vals
192
}
193
194     public void testScanForward()
195         throws DatabaseException {
196
197     /*
198          * Tree holds <0,1> <2,3,4> <empty> <8,9,10>.
199          * Fwd scan starting with first. Expect 0, 1, 2, 4, 8, 9, 10.
200          */

201         doScanAcrossEmptyBin(true, // forward
202
(byte) -1,
203                              new byte[] {0,1,2,3,4,8,9,10});
204     }
205
206     public void testScanBackwards()
207         throws DatabaseException {
208
209     /*
210          * Tree holds <0,1> <2,3,4> <empty> <8,9,10>.
211          * Bwd scan starting with last. 10 -> 0
212          */

213         doScanAcrossEmptyBin(false, // backwards
214
(byte) -1,
215                              new byte[] {10,9,8,4,3,2,1,0});
216     }
217
218     /**
219      * Scan over an empty BIN that is in the middle of the tree. [#11778]
220      * The tree holds values from 0 - 10. Values 5, 6, 7 have been deleted.
221      * @param forward indicates use getNext().
222      * @param startKey >= 0 indicates do getSearchKeyRange to init cursor.
223      * @param expectVals are the elements to expect find
224      */

225     private void doScanAcrossEmptyBin(boolean forward,
226                       byte startKey,
227                                       byte[] expectVals)
228         throws DatabaseException {
229
230         int deleteStartVal = 5;
231         int deleteEndVal = 7;
232         openAndInitEmptyMiddleBIN(deleteStartVal, deleteEndVal);
233
234         if (DEBUG) {
235         DbInternal.dbGetDatabaseImpl(db).getTree().dump();
236         }
237
238         DatabaseEntry key = new DatabaseEntry();
239         DatabaseEntry data = new DatabaseEntry();
240
241     /*
242      * Position a cursor and check that we get the expected values.
243      */

244     int cnt = 0;
245         Cursor cursor = db.openCursor(null, null);
246         CursorImpl cursorImpl = DbInternal.getCursorImpl(cursor);
247
248         if (doPruningAtCursorLevel) {
249             cursorImpl.setTestHook(new PruningHook(env));
250         }
251
252         if (doPruningAtTreeLevel) {
253             DbInternal.dbGetDatabaseImpl(db).getTree().
254         setSearchHook(new PruningHook(env));
255         }
256
257         int expectIndex = 0;
258     if (startKey < 0) {
259         if (forward) {
260         assertEquals(OperationStatus.SUCCESS,
261                              cursor.getFirst(key, data, null));
262         } else {
263         assertEquals(OperationStatus.SUCCESS,
264                              cursor.getLast(key, data, null));
265         }
266     } else {
267             if (useDups) {
268                 key.setData(new byte[] {DEFAULT_VAL});
269                 data.setData(new byte[] {startKey});
270             } else {
271                 key.setData(new byte[] { startKey });
272             }
273                 
274         if ((startKey >= deleteStartVal) &&
275         (startKey <= deleteEndVal)) {
276         /* Test range query. */
277                 if (useDups) {
278                     assertEquals(OperationStatus.SUCCESS,
279                                  cursor.getSearchBothRange(key, data, null));
280                 } else {
281                     assertEquals(OperationStatus.SUCCESS,
282                                  cursor.getSearchKeyRange(key, data, null));
283                 }
284         } else {
285         /* Test from getSearchKey(). */
286                 if (useDups) {
287                     assertEquals(OperationStatus.SUCCESS,
288                                  cursor.getSearchBoth(key, data, null));
289                 } else {
290                     assertEquals(OperationStatus.SUCCESS,
291                                  cursor.getSearchKey(key, data, null));
292                 }
293         }
294     }
295
296         OperationStatus status;
297         do {
298             cnt++;
299
300             /* check value. */
301             if (DEBUG) {
302                 System.out.println("=>key=" + key.getData()[0] +
303                                    " data=" + data.getData()[0]);
304             }
305             if (useDups) {
306                 assertEquals(expectVals[expectIndex++], data.getData()[0]);
307             } else {
308                 assertEquals(expectVals[expectIndex++], key.getData()[0]);
309             }
310
311         if (forward) {
312         status = cursor.getNext(key, data, null);
313         } else {
314         status = cursor.getPrev(key, data, null);
315             }
316         } while (status == OperationStatus.SUCCESS);
317
318     assertEquals(expectVals.length, cnt);
319     cursor.close();
320         closeEnv();
321     }
322
323     /**
324      * Create a tree with:
325      * IN
326      * / \
327      * IN IN
328      * / \ / \
329      * BIN1 BIN2 BIN3 BIN4
330      *
331      * where BIN1 has values 0,1
332      * BIN2 has valus 2,3,4
333      * BIN3 has valus 5,6,7
334      * BIN4 has valus 8,9,10
335      * Depending on configuration, the entries in BIN2 or BIN3
336      */

337     private void openAndInitEmptyMiddleBIN(int deleteStartVal,
338                                            int deleteEndVal)
339         throws DatabaseException {
340
341         openEnv(false, "4");
342         DatabaseEntry data = new DatabaseEntry();
343         data.setData(new byte[] {DEFAULT_VAL});
344         DatabaseEntry key = new DatabaseEntry();
345         key.setData(new byte[] {DEFAULT_VAL});
346
347         /* Create four BINs */
348         OperationStatus status;
349         for (int i = 0; i < 11; i++) {
350             if (useDups) {
351                 data = new DatabaseEntry(new byte[] { (byte) i });
352             } else {
353                 key = new DatabaseEntry(new byte[] { (byte) i });
354             }
355             status = db.put(null, key, data);
356             assertEquals(OperationStatus.SUCCESS, status);
357     }
358
359         /* Empty out one of the middle ones. */
360         if (useDups) {
361             Cursor cursor = db.openCursor(null, null);
362             data = new DatabaseEntry(new byte[] { (byte) deleteStartVal });
363             assertEquals(OperationStatus.SUCCESS,
364                          cursor.getSearchBoth(key, data, LockMode.DEFAULT));
365             for (int i = deleteStartVal; i <= deleteEndVal; i++) {
366                 assertEquals(OperationStatus.SUCCESS,
367                              cursor.delete());
368                 assertEquals(OperationStatus.SUCCESS,
369                              cursor.getNext(key, data, LockMode.DEFAULT));
370             }
371             cursor.close();
372         } else {
373             for (int i = deleteStartVal; i <= deleteEndVal; i++) {
374                 key = new DatabaseEntry(new byte[] { (byte) i });
375                 status = db.delete(null, key);
376                 assertEquals(OperationStatus.SUCCESS, status);
377             }
378         }
379
380         CheckpointConfig config = new CheckpointConfig();
381         config.setForce(true);
382         env.checkpoint(config);
383     }
384
385     /**
386      * Opens the environment and db.
387      */

388     private void openEnv(boolean transactional, String JavaDoc nodeMax)
389         throws DatabaseException {
390
391         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
392         envConfig.setTransactional(transactional);
393         envConfig.setConfigParam
394             (EnvironmentParams.ENV_RUN_INCOMPRESSOR.getName(), "true");
395     if (nodeMax != null) {
396         envConfig.setConfigParam
397         (EnvironmentParams.NODE_MAX.getName(), nodeMax);
398         envConfig.setConfigParam
399         (EnvironmentParams.NODE_MAX_DUPTREE.getName(), nodeMax);
400     }
401         envConfig.setAllowCreate(true);
402         env = new Environment(envHome, envConfig);
403
404         /* Make a db and open it. */
405         DatabaseConfig dbConfig = new DatabaseConfig();
406         dbConfig.setTransactional(transactional);
407         dbConfig.setSortedDuplicates(useDups);
408         dbConfig.setAllowCreate(true);
409         db = env.openDatabase(null, "testDB", dbConfig);
410     }
411
412     /**
413      * Closes the db and environment.
414      */

415     private void closeEnv()
416         throws DatabaseException {
417
418         db.close();
419         db = null;
420         env.close();
421         env = null;
422     }
423
424     private static class PruningHook implements TestHook {
425         Environment env;
426
427         PruningHook(Environment env) {
428             this.env = env;
429         }
430
431         public void doIOHook() throws IOException JavaDoc {}
432
433         public void doHook() {
434         DbInternal.envGetEnvironmentImpl(env).getINCompressor().
435         wakeup();
436         Thread.yield();
437         try {
438         Thread.sleep(100);
439         } catch (Throwable JavaDoc T) {
440         }
441         }
442
443         public Object JavaDoc getHookValue() {
444             return null;
445         }
446     }
447 }
448
Popular Tags