KickJava   Java API By Example, From Geeks To Geeks.

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


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

8 package com.sleepycat.je.recovery;
9
10 import com.sleepycat.bind.tuple.IntegerBinding;
11 import com.sleepycat.je.CheckpointConfig;
12 import com.sleepycat.je.Database;
13 import com.sleepycat.je.DatabaseConfig;
14 import com.sleepycat.je.DatabaseEntry;
15 import com.sleepycat.je.DatabaseException;
16 import com.sleepycat.je.DbInternal;
17 import com.sleepycat.je.EnvironmentConfig;
18 import com.sleepycat.je.OperationStatus;
19 import com.sleepycat.je.config.EnvironmentParams;
20 import com.sleepycat.je.dbi.EnvironmentImpl;
21 import com.sleepycat.je.tree.BIN;
22 import com.sleepycat.je.tree.Tree;
23 import com.sleepycat.je.util.TestUtils;
24
25 public class CheckBINDeltaTest extends CheckBase {
26
27     private static final String JavaDoc DB_NAME = "simpleDB";
28     private static final boolean DEBUG = false;
29
30     /**
31      * SR #11123
32      * Make sure that BINDeltas are applied only to non-deleted nodes.
33      */

34     public void testBINDelta()
35         throws Throwable JavaDoc {
36
37         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
38         turnOffEnvDaemons(envConfig);
39         envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(),
40                                  "4");
41         envConfig.setConfigParam(EnvironmentParams.BIN_DELTA_PERCENT.getName(),
42                                  "75");
43         envConfig.setAllowCreate(true);
44                                  
45         DatabaseConfig dbConfig = new DatabaseConfig();
46         dbConfig.setAllowCreate(true);
47
48         EnvironmentConfig restartConfig = TestUtils.initEnvConfig();
49         turnOffEnvDaemons(restartConfig);
50         envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(),
51                                  "4");
52
53         testOneCase(DB_NAME,
54                     envConfig,
55                     dbConfig,
56                     new TestGenerator(){
57                         void generateData(Database db)
58                             throws DatabaseException {
59                             addData(db);
60                         }
61                     },
62                     restartConfig,
63                     new DatabaseConfig());
64     }
65
66     /**
67      * This test checks for the bug described in SR11123. If an IN and its
68      * child-subtree is deleted, an INDeleteInfo is written to the
69      * log. If there is a BINDelta in the log for a BIN-child of the
70      * removed subtree (i.e. compressed), then recovery will apply it to the
71      * compressed IN. Since the IN has no data in * it, that is not
72      * necessarily a problem. However, reinstantiating the obsolete IN
73      * may cause a parent IN to split which is not allowed during IN
74      * recovery.
75      *
76      * Here's the case:
77      *
78      * |
79      * IN1
80      * +---------------------------------+
81      * | |
82      * IN2 IN6
83      * / | / | \
84      * BIN3 BIN4 BIN7 BIN8 BIN9
85      *
86      * IN2 and the subtree below are compressed away. During recovery
87      * replay, after the pass where INs and INDeleteINfos are
88      * processed, the in-memory tree looks like this:
89      *
90      * IN1
91      * |
92      * IN6
93      * / | \
94      * BIN7 BIN8 BIN9
95      *
96      * However, let's assume that BINDeltas were written for
97      * BIN3, BIN4, BIN5 within the recovery part of the log, before the
98      * subtree was compressed. We'll replay those BINDeltas in the
99      * following pass, and in the faulty implementation, they cause
100      * the ghosts of BIN3, BIN4 to be resurrected and applied to
101      * IN6. Let's assume that the max node size is 4 -- we won't be
102      * able to connect BIN3, BIN4 because IN6 doesn't have the
103      * capacity, and we don't expect to have to do splits.
104      */

105     private void addData(Database db)
106         throws DatabaseException {
107
108         DatabaseEntry key = new DatabaseEntry();
109         DatabaseEntry data = new DatabaseEntry();
110
111         /* Populate a tree so there are 3 levels. */
112         for (int i = 0; i < 140; i += 10) {
113             IntegerBinding.intToEntry(i, key);
114             IntegerBinding.intToEntry(i, data);
115             assertEquals(OperationStatus.SUCCESS, db.put(null, key, data));
116         }
117
118         CheckpointConfig ckptConfig = new CheckpointConfig();
119         ckptConfig.setForce(true);
120         env.checkpoint(ckptConfig);
121
122         Tree tree = DbInternal.dbGetDatabaseImpl(db).getTree();
123         com.sleepycat.je.tree.Key.DUMP_INT_BINDING = true;
124         if (DEBUG) {
125             tree.dump();
126         }
127
128         /*
129          * Update a key on the BIN3 and a key on BIN4, to create reason for
130          * a BINDelta. Force a BINDelta for BIN3 and BIN4 out to the log.
131          */

132         IntegerBinding.intToEntry(0, key);
133         IntegerBinding.intToEntry(100, data);
134         assertEquals(OperationStatus.SUCCESS, db.put(null, key, data));
135         IntegerBinding.intToEntry(20, key);
136         assertEquals(OperationStatus.SUCCESS, db.put(null, key, data));
137         
138         EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
139         BIN bin = (BIN)tree.getFirstNode();
140         bin.log(envImpl.getLogManager(), true, false, false, false, null);
141         bin = tree.getNextBin(bin, false /* traverseWithinDupTree */);
142         bin.log(envImpl.getLogManager(), true, false, false, false, null);
143         bin.releaseLatch();
144
145         /*
146          * Delete all of left hand side of the tree, so that the subtree root
147          * headed by IN2 is compressed.
148          */

149         for (int i = 0; i < 50; i+=10) {
150             IntegerBinding.intToEntry(i, key);
151             assertEquals(OperationStatus.SUCCESS, db.delete(null, key));
152         }
153
154         /* force a compression */
155         env.compress();
156         if (DEBUG) {
157             tree.dump();
158         }
159     }
160 }
161
Popular Tags