KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > log > INFileReaderTest


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: INFileReaderTest.java,v 1.71 2006/11/03 03:08:05 mark Exp $
7  */

8
9 package com.sleepycat.je.log;
10
11 import java.io.File JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.util.ArrayList JavaDoc;
14 import java.util.Arrays JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.List JavaDoc;
17 import java.util.Map JavaDoc;
18
19 import junit.framework.TestCase;
20
21 import com.sleepycat.je.Database;
22 import com.sleepycat.je.DatabaseConfig;
23 import com.sleepycat.je.DatabaseException;
24 import com.sleepycat.je.DbInternal;
25 import com.sleepycat.je.Environment;
26 import com.sleepycat.je.EnvironmentConfig;
27 import com.sleepycat.je.config.EnvironmentParams;
28 import com.sleepycat.je.dbi.DbConfigManager;
29 import com.sleepycat.je.dbi.EnvironmentImpl;
30 import com.sleepycat.je.tree.BIN;
31 import com.sleepycat.je.tree.ChildReference;
32 import com.sleepycat.je.tree.IN;
33 import com.sleepycat.je.tree.INDeleteInfo;
34 import com.sleepycat.je.tree.Key;
35 import com.sleepycat.je.tree.LN;
36 import com.sleepycat.je.util.TestUtils;
37 import com.sleepycat.je.utilint.DbLsn;
38 import com.sleepycat.je.utilint.Tracer;
39
40 /**
41  *
42  */

43 public class INFileReaderTest extends TestCase {
44
45     static private final boolean DEBUG = false;
46
47     private File JavaDoc envHome;
48     private Environment env;
49     /*
50      * Need a handle onto the true environment in order to create
51      * a reader
52      */

53     private EnvironmentImpl envImpl;
54     private Database db;
55     private long maxNodeId;
56     private List JavaDoc checkList;
57
58     public INFileReaderTest() {
59         super();
60         envHome = new File JavaDoc(System.getProperty(TestUtils.DEST_DIR));
61         Key.DUMP_BINARY = true;
62     }
63
64     public void setUp()
65     throws IOException JavaDoc, DatabaseException {
66
67         /*
68          * Note that we use the official Environment class to make the
69          * environment, so that everything is set up, but we then go a
70          * backdoor route to get to the underlying EnvironmentImpl class
71          * so that we don't require that the Environment.getDbEnvironment
72          * method be unnecessarily public.
73          */

74         TestUtils.removeLogFiles("Setup", envHome, false);
75
76         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
77         envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(), "6");
78         envConfig.setConfigParam
79         (EnvironmentParams.BIN_DELTA_PERCENT.getName(), "75");
80         envConfig.setAllowCreate(true);
81
82         /* Disable noisy UtilizationProfile database creation. */
83         DbInternal.setCreateUP(envConfig, false);
84         /* Don't checkpoint utilization info for this test. */
85         DbInternal.setCheckpointUP(envConfig, false);
86         /* Don't run the cleaner without a UtilizationProfile. */
87         envConfig.setConfigParam
88         (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false");
89
90         env = new Environment(envHome, envConfig);
91
92         envImpl =DbInternal.envGetEnvironmentImpl(env);
93
94     }
95
96     public void tearDown()
97     throws IOException JavaDoc, DatabaseException {
98
99         envImpl = null;
100         env.close();
101         TestUtils.removeFiles("TearDown", envHome, FileManager.JE_SUFFIX);
102     }
103
104     /**
105      * Test no log file
106      */

107     public void testNoFile()
108     throws IOException JavaDoc, DatabaseException {
109
110         /* Make a log file with a valid header, but no data. */
111         INFileReader reader =
112         new INFileReader(envImpl, 1000, DbLsn.NULL_LSN, DbLsn.NULL_LSN, false, false,
113                  DbLsn.NULL_LSN, null);
114         reader.addTargetType(LogEntryType.LOG_IN);
115         reader.addTargetType(LogEntryType.LOG_BIN);
116         reader.addTargetType(LogEntryType.LOG_IN_DELETE_INFO);
117
118         int count = 0;
119         while (reader.readNextEntry()) {
120             count += 1;
121         }
122         assertEquals("Empty file should not have entries", 0, count);
123     }
124
125     /**
126      * Run with an empty file
127      */

128     public void testEmpty()
129     throws IOException JavaDoc, DatabaseException {
130
131         /* Make a log file with a valid header, but no data. */
132         FileManager fileManager = envImpl.getFileManager();
133         fileManager.bumpLsn(1000000);
134         FileManagerTestUtils.createLogFile(fileManager, envImpl, 10000);
135         fileManager.clear();
136
137         INFileReader reader =
138         new INFileReader(envImpl, 1000, DbLsn.NULL_LSN, DbLsn.NULL_LSN, false, false,
139                  DbLsn.NULL_LSN, null);
140         reader.addTargetType(LogEntryType.LOG_IN);
141         reader.addTargetType(LogEntryType.LOG_BIN);
142         reader.addTargetType(LogEntryType.LOG_IN_DELETE_INFO);
143
144         int count = 0;
145         while (reader.readNextEntry()) {
146             count += 1;
147         }
148         assertEquals("Empty file should not have entries", 0, count);
149     }
150
151     /**
152      * Run with defaults, read whole log
153      */

154     public void testBasic()
155     throws IOException JavaDoc, DatabaseException {
156
157         DbConfigManager cm = envImpl.getConfigManager();
158         doTest(50,
159                cm.getInt(EnvironmentParams.LOG_ITERATOR_READ_SIZE),
160                0,
161                false);
162     }
163
164     /**
165      * Run with very small buffers and track node ids
166      */

167     public void testTracking()
168     throws IOException JavaDoc, DatabaseException {
169
170         doTest(50, // num iterations
171
10, // tiny buffer
172
0, // start lsn index
173
true); // track node ids
174
}
175
176     /**
177      * Start in the middle of the file
178      */

179     public void testMiddleStart()
180     throws IOException JavaDoc, DatabaseException {
181
182         doTest(50, 100, 40, true);
183     }
184
185     private void doTest(int numIters,
186                         int bufferSize,
187                         int startLsnIndex,
188                         boolean trackNodeIds)
189         throws IOException JavaDoc, DatabaseException {
190
191         /* Fill up a fake log file. */
192         createLogFile(numIters);
193
194         /* Decide where to start. */
195         long startLsn = DbLsn.NULL_LSN;
196         int checkIndex = 0;
197         if (startLsnIndex >= 0) {
198             startLsn = ((CheckInfo) checkList.get(startLsnIndex)).lsn;
199             checkIndex = startLsnIndex;
200         }
201
202         /* Use an empty utilization map for testing tracking. */
203         Map JavaDoc fileSummaryLsns = trackNodeIds ? (new HashMap JavaDoc()) : null;
204
205         INFileReader reader = new INFileReader(envImpl,
206                                                bufferSize,
207                                                startLsn,
208                            DbLsn.NULL_LSN,
209                                                trackNodeIds,
210                            false,
211                                                DbLsn.NULL_LSN,
212                                                fileSummaryLsns);
213         reader.addTargetType(LogEntryType.LOG_IN);
214         reader.addTargetType(LogEntryType.LOG_BIN);
215         reader.addTargetType(LogEntryType.LOG_BIN_DELTA);
216         reader.addTargetType(LogEntryType.LOG_IN_DELETE_INFO);
217
218         /* Read. */
219         checkLogFile(reader, checkIndex, trackNodeIds);
220     }
221
222     /**
223      * Write a logfile of entries, then read the end
224      */

225     private void createLogFile(int numIters)
226     throws IOException JavaDoc, DatabaseException {
227
228         /*
229          * Create a log file full of INs, INDeleteInfo, BINDeltas and
230          * Debug Records
231          */

232         DatabaseConfig dbConfig = new DatabaseConfig();
233         dbConfig.setAllowCreate(true);
234         db = env.openDatabase(null, "foo", dbConfig);
235         LogManager logManager = envImpl.getLogManager();
236         maxNodeId = 0;
237
238         checkList = new ArrayList JavaDoc();
239
240         for (int i = 0; i < numIters; i++) {
241             /* Add a debug record. */
242             Tracer rec = new Tracer("Hello there, rec " + (i + 1));
243             logManager.log(rec);
244
245             /* Create, log, and save an IN. */
246             byte[] data = new byte[i + 1];
247             Arrays.fill(data, (byte) (i + 1));
248
249             byte[] key = new byte[i + 1];
250             Arrays.fill(key, (byte) (i + 1));
251
252             IN in = new IN(DbInternal.dbGetDatabaseImpl(db), key, 5, 10);
253         in.latch(false);
254             long lsn = in.log(logManager);
255         in.releaseLatch();
256             checkList.add(new CheckInfo(lsn, in));
257
258             if (DEBUG) {
259                 System.out.println("LSN " + i + " = " + lsn);
260                 System.out.println("IN " + i + " = " + in.getNodeId());
261             }
262
263             /* Add other types of INs. */
264             BIN bin = new BIN(DbInternal.dbGetDatabaseImpl(db), key, 2, 1);
265         bin.latch(false);
266             lsn = bin.log(logManager);
267             checkList.add(new CheckInfo(lsn, bin));
268
269             /* Add provisional entries, which should get ignored. */
270             lsn = bin.log(logManager,
271                       false, // allowDeltas,
272
true, // isProvisional,
273
false, // proactiveMigration,
274
false, // backgroundIO
275
in);
276
277         bin.releaseLatch();
278
279             /* Add a LN, to stress the node tracking. */
280             LN ln = new LN(data);
281             lsn = ln.log(envImpl,
282                          DbInternal.dbGetDatabaseImpl(db).getId(),
283                          key, DbLsn.NULL_LSN, 0, null, false);
284
285             /*
286          * Add an IN delete entry, it should get picked up by the reader.
287          */

288             INDeleteInfo info =
289                 new INDeleteInfo(i, key, DbInternal.
290                  dbGetDatabaseImpl(db).getId());
291             lsn = logManager.log(info);
292             checkList.add(new CheckInfo(lsn, info));
293
294             /*
295              * Add an BINDelta. Generate it by making the first, full version
296              * provisional so the test doesn't pick it up, and then log a
297              * delta.
298              */

299             BIN binDeltaBin =
300         new BIN(DbInternal.dbGetDatabaseImpl(db), key, 10, 1);
301             maxNodeId = binDeltaBin.getNodeId();
302             binDeltaBin.latch();
303             ChildReference newEntry =
304                 new ChildReference(null, key, DbLsn.makeLsn(0, 0));
305             assertTrue(binDeltaBin.insertEntry(newEntry));
306
307             lsn = binDeltaBin.log(logManager,
308                               false, // allowDeltas,
309
true, // isProvisional,
310
false, // proactiveMigration,
311
false, // backgroundIO
312
in); // parent
313

314             /* Modify the bin with one entry so there can be a delta. */
315
316             byte[] keyBuf2 = new byte[2];
317             Arrays.fill(keyBuf2, (byte) (i + 2));
318             ChildReference newEntry2 =
319                 new ChildReference(null, keyBuf2,
320                                    DbLsn.makeLsn(100, 101));
321             assertTrue(binDeltaBin.insertEntry(newEntry2));
322
323             assertTrue(binDeltaBin.log(logManager,
324                                    true, // allowDeltas
325
false, // isProvisional
326
false, // proactiveMigration,
327
false, // backgroundIO
328
in) ==
329                DbLsn.NULL_LSN);
330             lsn = binDeltaBin.getLastDeltaVersion();
331             if (DEBUG) {
332                 System.out.println("delta =" + binDeltaBin.getNodeId() +
333                                    " at LSN " + lsn);
334             }
335             checkList.add(new CheckInfo(lsn, binDeltaBin));
336
337             /*
338              * Reset the generation to 0 so this version of the BIN, which gets
339              * saved for unit test comparison, will compare to the version read
340              * from the log, which is initialized to 0.
341              */

342             binDeltaBin.setGeneration(0);
343             binDeltaBin.releaseLatch();
344         }
345
346         /* Flush the log, files. */
347         logManager.flush();
348         envImpl.getFileManager().clear();
349     }
350
351     private void checkLogFile(INFileReader reader,
352                               int checkIndex,
353                               boolean checkMaxNodeId)
354         throws IOException JavaDoc, DatabaseException {
355
356         try {
357             /* Read all the INs. */
358             int i = checkIndex;
359
360             while (reader.readNextEntry()) {
361                 if (DEBUG) {
362                     System.out.println("i = "
363                                        + i
364                                        + " reader.isDeleteInfo="
365                                        + reader.isDeleteInfo()
366                                        + " LSN = "
367                                        + reader.getLastLsn());
368                 }
369
370                 CheckInfo check = (CheckInfo) checkList.get(i);
371
372                 if (reader.isDeleteInfo()) {
373                     assertEquals(check.info.getDeletedNodeId(),
374                                  reader.getDeletedNodeId());
375                     assertTrue(Arrays.equals(check.info.getDeletedIdKey(),
376                                              reader.getDeletedIdKey()));
377                     assertTrue(check.info.getDatabaseId().equals
378                                (reader.getDatabaseId()));
379
380                 } else {
381
382                     /*
383              * When comparing the check data against the data from the
384              * log, make the dirty bits match so that they compare
385              * equal.
386                      */

387                     IN inFromLog = reader.getIN();
388             inFromLog.latch(false);
389                     inFromLog.setDirty(true);
390             inFromLog.releaseLatch();
391                     IN testIN = check.in;
392             testIN.latch(false);
393                     testIN.setDirty(true);
394             testIN.releaseLatch();
395
396                     /*
397                      * Only check the INs we created in the test. (The others
398                      * are from the map db.
399                      */

400                     if (reader.getDatabaseId().
401             equals(DbInternal.dbGetDatabaseImpl(db).getId())) {
402                         // The IN should match
403
String JavaDoc inFromLogString = inFromLog.toString();
404                         String JavaDoc testINString = testIN.toString();
405                         if (DEBUG) {
406                             System.out.println("testIN=" + testINString);
407                             System.out.println("inFromLog=" + inFromLogString);
408                         }
409
410                         assertEquals("IN "
411                                      + inFromLog.getNodeId()
412                                      + " at index "
413                                      + i
414                                      + " should match.\nTestIN=" +
415                                      testIN +
416                                      "\nLogIN=" +
417                                      inFromLog,
418                                      testINString,
419                                      inFromLogString);
420                     }
421                 }
422                 /* The LSN should match. */
423                 assertEquals
424             ("LSN " + i + " should match",
425              check.lsn,
426              reader.getLastLsn());
427
428                 i++;
429             }
430             assertEquals(i, checkList.size());
431             if (checkMaxNodeId) {
432                 assertEquals(maxNodeId, reader.getMaxNodeId());
433             }
434         } finally {
435             db.close();
436         }
437     }
438
439     private class CheckInfo {
440         long lsn;
441         IN in;
442         INDeleteInfo info;
443
444         CheckInfo(long lsn, IN in) {
445             this.lsn = lsn;
446             this.in = in;
447             this.info = null;
448         }
449
450         CheckInfo(long lsn, INDeleteInfo info) {
451             this.lsn = lsn;
452             this.in = null;
453             this.info = info;
454         }
455     }
456 }
457
Popular Tags