KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: RecoveryCreateDupTest.java,v 1.8 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.bind.tuple.IntegerBinding;
14 import com.sleepycat.je.CheckpointConfig;
15 import com.sleepycat.je.Cursor;
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.Transaction;
21 import com.sleepycat.je.dbi.EnvironmentImpl;
22 import com.sleepycat.je.log.LogEntryType;
23 import com.sleepycat.je.log.SearchFileReader;
24 import com.sleepycat.je.utilint.CmdUtil;
25 import com.sleepycat.je.utilint.DbLsn;
26
27 /*
28  * Test the log entries that are made when a duplicate tree is
29  * created. Inspired by SR 10203.
30  */

31 public class RecoveryCreateDupTest extends RecoveryTestBase {
32
33     /*
34      * These tests insert 2 records in order to create a duplicate tree. Then
35      * they truncate the log and recover, checking that (a) the recovery was
36      * able to succeed, and (b), that the results are correct.
37      *
38      * They vary where the truncation happens and if the two records are
39      * inserted in a single or in two txns.
40      */

41
42     public void testCreateDup1()
43         throws Throwable JavaDoc {
44         errorHaltCase(false, true);
45     }
46
47     public void testCreateDup2()
48         throws Throwable JavaDoc {
49         errorHaltCase(true, true);
50     }
51
52     public void testCreateDup3()
53         throws Throwable JavaDoc {
54         errorHaltCase(false, false);
55     }
56
57     public void testCreateDup4()
58         throws Throwable JavaDoc {
59         errorHaltCase(true, false);
60     }
61
62     /**
63      * Insert 2 duplicate records, cut the log off at different places,
64      * recover.
65      *
66      * @param allValuesCreatedWithinTxn true if both records are inserted
67      * the same txn.
68      * @param truncateBeforeDIN if true, truncate just before the DIN entry.
69      * If false, truncate before the first LN
70      */

71     private void errorHaltCase(boolean allValuesCreatedWithinTxn,
72                                boolean truncateBeforeDIN)
73         throws Throwable JavaDoc {
74
75         /* test data setup. */
76         byte [] key = new byte [1];
77         key[0] = 5;
78         DatabaseEntry keyEntry1 = new DatabaseEntry(key);
79         DatabaseEntry keyEntry2 = new DatabaseEntry(key);
80         byte [] data1 = new byte [1];
81         byte [] data2 = new byte [1];
82         data1[0] = 7;
83         data2[0] = 8;
84         DatabaseEntry dataEntry1 = new DatabaseEntry(data1);
85         DatabaseEntry dataEntry2 = new DatabaseEntry(data2);
86
87         /* Create 1 database. */
88         createEnvAndDbs(1 << 20, true, 1);
89         try {
90             /*
91              * Set up an repository of expected data. We'll be inserting
92              * 2 records, varying whether they are in the same txn or not.
93              */

94             Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
95
96             Transaction txn = env.beginTransaction(null, null);
97             dbs[0].put(txn, keyEntry1, dataEntry1);
98             addExpectedData(expectedData, 0, keyEntry1, dataEntry1,
99                             !allValuesCreatedWithinTxn);
100
101             if (!allValuesCreatedWithinTxn) {
102                 txn.commit();
103                 txn = env.beginTransaction(null, null);
104             }
105
106             dbs[0].put(txn, keyEntry2, dataEntry2);
107             addExpectedData(expectedData, 0, keyEntry2, dataEntry2, false);
108
109             txn.commit();
110             closeEnv();
111
112             /*
113              * Find the location of the DIN and the location of the followon
114              * LN.
115              */

116
117             env = new Environment(envHome, null);
118             EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
119             SearchFileReader searcher =
120                 new SearchFileReader(envImpl, 1000, true, DbLsn.NULL_LSN,
121                      DbLsn.NULL_LSN, LogEntryType.LOG_DIN);
122             searcher.readNextEntry();
123             long dinLsn = searcher.getLastLsn();
124
125             searcher =
126                 new SearchFileReader(envImpl, 1000, true, dinLsn,
127                      DbLsn.NULL_LSN,
128                                      LogEntryType.LOG_LN_TRANSACTIONAL);
129             searcher.readNextEntry();
130             long lnLsn = searcher.getLastLsn();
131             
132             env.close();
133
134             /*
135              * Truncate the log, sometimes before the DIN, sometimes after.
136              */

137             EnvironmentImpl cmdEnvImpl =
138                 CmdUtil.makeUtilityEnvironment(envHome, false);
139
140             /* Go through the file manager to get the JE file. Truncate. */
141             long truncateLsn = truncateBeforeDIN ? dinLsn : lnLsn;
142             cmdEnvImpl.getFileManager().
143                 truncateLog(DbLsn.getFileNumber(truncateLsn),
144                             DbLsn.getFileOffset(truncateLsn));
145
146             cmdEnvImpl.close();
147
148             /*
149              * Recover and verify that we have the expected data.
150              */

151             recoverAndVerify(expectedData, 1);
152             
153
154     } catch (Throwable JavaDoc t) {
155             // print stacktrace before trying to clean up files
156
t.printStackTrace();
157             throw t;
158         }
159     }
160
161     /**
162      * Test when a duplicate tree reuses an entry previously populated by
163      * a deleted LN. [#SR12847]
164      * The sequence is this:
165      * create database
166      * insert k1/d1 (make BIN with a slot for k1)
167      * abort the insert, so the BIN is marked known deleted
168      * flush the BIN to the log
169      *
170      * insert k1/d100
171      * insert k1/d200 (creates a new duplicate tree)
172      *
173      * Now recover from here. The root of the duplicate tree must be put
174      * into the old known deleted slot used for k1/d1. There is some
175      * finagling to make this happen; namely the BIN must not be compressed
176      * during checkpoint.
177      */

178     public void testReuseSlot()
179         throws DatabaseException {
180
181         /* Create 1 database. */
182         createEnvAndDbs(1 << 20, false, 1);
183
184         DatabaseEntry key = new DatabaseEntry();
185         DatabaseEntry data = new DatabaseEntry();
186
187         /* Insert a record, then abort it so it's marked knownDeleted. */
188         Transaction txn = env.beginTransaction(null, null);
189         IntegerBinding.intToEntry(100, key);
190         IntegerBinding.intToEntry(1, data);
191         dbs[0].put(txn, key, data);
192         txn.abort();
193
194         /*
195          * Put a cursor on this bin to prevent lazy compression and preserve
196          * the slot created above.
197          */

198         IntegerBinding.intToEntry(200, key);
199         IntegerBinding.intToEntry(1, data);
200         txn = env.beginTransaction(null, null);
201         Cursor c = dbs[0].openCursor(txn, null);
202         c.put(key, data);
203
204         /* Flush this bin to the log. */
205         CheckpointConfig ckptConfig = new CheckpointConfig();
206         ckptConfig.setForce(true);
207         env.checkpoint(ckptConfig);
208         c.close();
209         txn.abort();
210
211         /*
212          * Now create a duplicate tree, reusing the known deleted slot
213          * in the bin.
214          */

215         Hashtable JavaDoc expectedData = new Hashtable JavaDoc();
216         IntegerBinding.intToEntry(100, key);
217         IntegerBinding.intToEntry(1, data);
218         dbs[0].put(null, key, data);
219         addExpectedData(expectedData, 0, key, data, true);
220
221         IntegerBinding.intToEntry(2, data);
222         dbs[0].put(null, key, data);
223         addExpectedData(expectedData, 0, key, data, true);
224
225         /* close the environment. */
226         closeEnv();
227
228         recoverAndVerify(expectedData, 1);
229     }
230 }
231
Popular Tags