KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: FileManagerTest.java,v 1.65 2006/11/27 02:06:45 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.io.RandomAccessFile JavaDoc;
14 import java.util.Set JavaDoc;
15
16 import junit.framework.TestCase;
17
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.config.EnvironmentParams;
26 import com.sleepycat.je.dbi.EnvironmentImpl;
27 import com.sleepycat.je.util.TestUtils;
28 import com.sleepycat.je.utilint.DbLsn;
29
30 /**
31  * File Manager
32  */

33 public class FileManagerTest extends TestCase {
34
35     static private int FILE_SIZE = 120;
36
37     private EnvironmentImpl envImpl;
38     private FileManager fileManager;
39     private File JavaDoc envHome;
40
41     public FileManagerTest() {
42         super();
43         envHome = new File JavaDoc(System.getProperty(TestUtils.DEST_DIR));
44     }
45
46     protected void setUp()
47         throws DatabaseException, IOException JavaDoc {
48
49         /* Remove files to start with a clean slate. */
50         TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX);
51
52         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
53     DbInternal.disableParameterValidation(envConfig);
54         envConfig.setConfigParam(EnvironmentParams.LOG_FILE_MAX.getName(),
55                                  new Integer JavaDoc(FILE_SIZE).toString());
56         /* Yank the cache size way down. */
57         envConfig.setConfigParam
58         (EnvironmentParams.LOG_FILE_CACHE_SIZE.getName(), "3");
59         envConfig.setAllowCreate(true);
60         envImpl = new EnvironmentImpl(envHome, envConfig);
61
62         /* Make a standalone file manager for this test. */
63         envImpl.close();
64         envImpl.open(); /* Just sets state to OPEN. */
65         fileManager = new FileManager(envImpl, envHome, false);
66
67         /*
68          * Remove any files after the environment is created again! We want to
69          * remove the files made by recovery, so we can test the file manager
70          * in controlled cases.
71          */

72         TestUtils.removeFiles("Setup", envHome, FileManager.JE_SUFFIX);
73     }
74
75     protected void tearDown()
76         throws IOException JavaDoc, DatabaseException {
77
78         if (fileManager != null) {
79             fileManager.clear();
80             fileManager.close();
81         }
82         TestUtils.removeFiles("TearDown", envHome, FileManager.JE_SUFFIX);
83     }
84
85     /**
86      * Test LSN administration.
87      */

88     public void testLsnBumping()
89         throws Exception JavaDoc {
90
91         /*
92        We are adding these entries:
93        +----+------+---------+--------+
94        file 0: |hdr | 30 | 50 |empty |
95        +----+------+---------+--------+
96        0 hdr hdr+30 hdr+80 99
97
98        +----+--------+-------+-------+-----+-------+
99        file 1: |hdr | 40 | 20 | 10 | 5 | empty |
100        +----+--------+-------+-------+-----+-------+
101        0 hdr hdr+40 hdr+60 hdr+70 hdr+75
102
103        +-----+-----+--------+
104        file 2: | hdr | 75 | empty |
105        +-----+-----+--------+
106        0 hdr hdr+75
107
108        +-----+-------------------------------+
109        file 3: | hdr | 125 |
110        +-----+-------------------------------+
111        0 hdr
112
113        +-----+-----+------+-----+--------------+
114        file 4: | hdr | 10 | 20 | 30 | empty
115        +-----+-----+------+-----+--------------+
116        0 hdr hdr+10 hdr+30
117
118         */

119
120         try {
121             /* Should start out at LSN 0. */
122                           
123             /* "add" some entries to the log. */
124             long hdrSize = FileManager.firstLogEntryOffset();
125
126             fileManager.bumpLsn(30L);
127             /* Item placed here. */
128             assertEquals(DbLsn.makeLsn(0, hdrSize),
129                          fileManager.getLastUsedLsn());
130             /* prev entry. */
131             assertEquals(0, fileManager.getPrevEntryOffset());
132
133             fileManager.bumpLsn(50L);
134             /* Item placed here. */
135             assertEquals(DbLsn.makeLsn(0, (hdrSize + 30)),
136                          fileManager.getLastUsedLsn());
137             assertEquals(hdrSize, fileManager.getPrevEntryOffset());
138
139             /* bump over to a file 1. */
140             fileManager.bumpLsn(40L);
141             /* item placed here. */
142             assertEquals(DbLsn.makeLsn(1, hdrSize),
143                          fileManager.getLastUsedLsn());
144             assertEquals(0, fileManager.getPrevEntryOffset());
145
146             fileManager.bumpLsn(20L);
147             /* Item placed here. */
148             assertEquals(DbLsn.makeLsn(1,(hdrSize+40)),
149                          fileManager.getLastUsedLsn());
150             assertEquals(hdrSize, fileManager.getPrevEntryOffset());
151
152             fileManager.bumpLsn(10L);
153             /* Item placed here. */
154             assertEquals(DbLsn.makeLsn(1,(hdrSize+60)),
155                          fileManager.getLastUsedLsn());
156             assertEquals(hdrSize+40, fileManager.getPrevEntryOffset());
157
158             fileManager.bumpLsn(5L);
159             /* item placed here. */
160             assertEquals(DbLsn.makeLsn(1,(hdrSize+70)),
161                          fileManager.getLastUsedLsn());
162             assertEquals(hdrSize+60, fileManager.getPrevEntryOffset());
163
164             /* bump over to file 2. */
165             fileManager.bumpLsn(75L);
166             /* Item placed here. */
167             assertEquals(DbLsn.makeLsn(2, hdrSize),
168                          fileManager.getLastUsedLsn());
169             assertEquals(0, fileManager.getPrevEntryOffset());
170
171             /* Ask for something bigger than a file: bump over to file 3. */
172             fileManager.bumpLsn(125L);
173             /* item placed here. */
174             assertEquals(DbLsn.makeLsn(3, hdrSize),
175                          fileManager.getLastUsedLsn());
176             assertEquals(0, fileManager.getPrevEntryOffset());
177
178             /* bump over to file 4. */
179             fileManager.bumpLsn(10L);
180             /* Item placed here. */
181             assertEquals(DbLsn.makeLsn(4, hdrSize),
182              fileManager.getLastUsedLsn());
183             assertEquals(0, fileManager.getPrevEntryOffset());
184
185             fileManager.bumpLsn(20L);
186             /* Item placed here. */
187             assertEquals(DbLsn.makeLsn(4, (hdrSize+10)),
188              fileManager.getLastUsedLsn());
189             assertEquals(hdrSize, fileManager.getPrevEntryOffset());
190
191             fileManager.bumpLsn(30L);
192             /* Item placed here. */
193             assertEquals(DbLsn.makeLsn(4, (hdrSize+30)),
194              fileManager.getLastUsedLsn());
195             assertEquals((hdrSize+10), fileManager.getPrevEntryOffset());
196
197         } catch (Exception JavaDoc e) {
198             e.printStackTrace();
199             throw e;
200         }
201     }
202
203     /**
204      * Test initializing the last position in the logs.
205      */

206     public void testSetLastPosition()
207         throws DatabaseException {
208
209         /*
210          * Pretend that the last file is file 79.
211          */

212         fileManager.setLastPosition(// next available LSN
213
DbLsn.makeLsn(79L, 88L),
214                                     DbLsn.makeLsn(79L, 77),
215                                     66L);
216
217         /* Put an entry down, should fit within file 79. */
218         fileManager.bumpLsn(11L);
219         assertEquals(DbLsn.makeLsn(79L, 88L), fileManager.getLastUsedLsn());
220         assertEquals(77L, fileManager.getPrevEntryOffset());
221
222         /* Put another entry in, should go to the next file. */
223         fileManager.bumpLsn(22L);
224         assertEquals(DbLsn.makeLsn(80L, FileManager.firstLogEntryOffset()),
225                      fileManager.getLastUsedLsn());
226         assertEquals(0, fileManager.getPrevEntryOffset());
227     }
228
229     /**
230      * Test log file naming.
231      */

232     public void testFileNameFormat()
233         throws DatabaseException {
234
235         String JavaDoc filePrefix = envHome + File.separator;
236         assertEquals(filePrefix + "00000001.jdb",
237                      fileManager.getFullFileNames(1L)[0]);
238         assertEquals(filePrefix + "0000007b.jdb",
239                      fileManager.getFullFileNames(123L)[0]);
240     }
241
242     /**
243      * Test log file creation.
244      */

245     public void testFileCreation()
246         throws IOException JavaDoc, DatabaseException {
247
248         FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);
249         FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);
250
251         String JavaDoc [] jeFiles = fileManager.listFiles(FileManager.JE_SUFFIXES);
252
253         assertEquals("Should have two files", 2, jeFiles.length);
254
255         /* Make a fake files with confusing names. */
256         File JavaDoc fakeFile1 = new File JavaDoc(envHome, "00000abx.jdb");
257         File JavaDoc fakeFile2 = new File JavaDoc(envHome, "10.10.jdb");
258         fakeFile1.createNewFile();
259         fakeFile2.createNewFile();
260
261         jeFiles = fileManager.listFiles(FileManager.JE_SUFFIXES);
262         assertEquals("Should have two files", 2, jeFiles.length);
263
264         /* Open the two existing log files. */
265         FileHandle file0Handle = fileManager.getFileHandle(0L);
266         FileHandle file1Handle = fileManager.getFileHandle(1L);
267
268         jeFiles = fileManager.listFiles(FileManager.JE_SUFFIXES);
269         assertEquals("Should have two files", 2, jeFiles.length);
270         file0Handle.release();
271         file1Handle.release();
272
273         /* Empty the cache and get them again. */
274         fileManager.clear();
275         file0Handle = fileManager.getFileHandle(0L);
276         file1Handle = fileManager.getFileHandle(1L);
277
278         jeFiles = fileManager.listFiles(FileManager.JE_SUFFIXES);
279         assertEquals("Should have two files", 2, jeFiles.length);
280         file0Handle.close();
281         file1Handle.close();
282         file0Handle.release();
283         file1Handle.release();
284
285         fakeFile1.delete();
286         fakeFile2.delete();
287     }
288
289     /**
290      * Make sure we can find the last file.
291      */

292     public void testLastFile()
293         throws IOException JavaDoc, DatabaseException {
294
295         /* There shouldn't be any files here anymore. */
296         String JavaDoc [] jeFiles = fileManager.listFiles(FileManager.JE_SUFFIXES);
297         assertTrue(jeFiles.length == 0);
298
299         /* No files exist, should get null. */
300         assertNull("No last file", fileManager.getLastFileNum());
301
302         /* Create some files, ask for the largest. */
303         File JavaDoc fakeFile1 = new File JavaDoc(envHome, "108.cif");
304         fakeFile1.createNewFile();
305         FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);
306         FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);
307         FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);
308
309         assertEquals("Should have 2 as last file", 2L,
310                      fileManager.getLastFileNum().longValue());
311         fakeFile1.delete();
312     }
313
314     /**
315      * Make sure we can find the next file in a set of files.
316      */

317     public void testFollowingFile()
318         throws IOException JavaDoc, DatabaseException {
319
320         /* There shouldn't be any files here anymore. */
321         String JavaDoc [] jeFiles = fileManager.listFiles(FileManager.JE_SUFFIXES);
322         assertTrue(jeFiles.length == 0);
323
324         /* No files exist, should get null. */
325         assertNull("No last file", fileManager.getFollowingFileNum(0, true));
326         assertNull("No last file", fileManager.getFollowingFileNum(0, false));
327         assertNull("No last file", fileManager.getFollowingFileNum(1, true));
328         assertNull("No last file", fileManager.getFollowingFileNum(-1, false));
329
330         /* Create some files. */
331         File JavaDoc okFile1 = new File JavaDoc(envHome, "00000001.jdb");
332         okFile1.createNewFile();
333
334         File JavaDoc fakeFile3 = new File JavaDoc(envHome, "003.jdb");
335         fakeFile3.createNewFile();
336
337         File JavaDoc okFile6 = new File JavaDoc(envHome, "00000006.jdb");
338         okFile6.createNewFile();
339
340         File JavaDoc okFile9 = new File JavaDoc(envHome, "00000009.jdb");
341         okFile9.createNewFile();
342
343
344         /* Test forward */
345         assertEquals("Should get 6 next", 6L,
346                      fileManager.getFollowingFileNum(2, true).longValue());
347         assertEquals("Should get 9 next, testing non-existent file", 9L,
348                      fileManager.getFollowingFileNum(8, true).longValue());
349         assertNull("Should get null next",
350            fileManager.getFollowingFileNum(9, true));
351         assertNull("Should get null next",
352            fileManager.getFollowingFileNum(10, true));
353
354         /* Test prev */
355         assertEquals("Should get 6 next, testing non-existent file", 6L,
356                      fileManager.getFollowingFileNum(8, false).longValue());
357         assertEquals("Should get 6 next", 6L,
358                      fileManager.getFollowingFileNum(9, false).longValue());
359         assertNull("Should get null next",
360            fileManager.getFollowingFileNum(1, false));
361         assertNull("Should get null next",
362            fileManager.getFollowingFileNum(0, false));
363
364         okFile1.delete();
365         fakeFile3.delete();
366         okFile6.delete();
367         okFile9.delete();
368     }
369
370     /**
371      * See if we can catch a file with an invalid header.
372      */

373     public void testBadHeader()
374         throws IOException JavaDoc, DatabaseException {
375
376         /* First try a bad environment r/w. */
377         try {
378             FileManager test =
379                 new FileManager(envImpl, new File JavaDoc("xxyy"), true);
380             fail("expect creation of " + test + "to fail.");
381         } catch (LogException e) {
382             /* should throw */
383         }
384         
385         /* Next try a bad environment r/o. */
386         try {
387             FileManager test =
388                 new FileManager(envImpl, new File JavaDoc("xxyy"), false);
389             fail("expect creation of " + test + "to fail.");
390         } catch (DatabaseException e) {
391             /* should throw */
392         }
393         
394         /* Now create a file, but mess up the header. */
395         FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);
396
397         byte [] badData = new byte[]{1,1};
398         int headerSize = FileManager.firstLogEntryOffset();
399         RandomAccessFile JavaDoc file0 =
400             new RandomAccessFile JavaDoc
401         (fileManager.getFullFileName(0, FileManager.JE_SUFFIX),
402          FileManager.FileMode.READWRITE_MODE.getModeValue());
403         file0.write(badData);
404         file0.close();
405         fileManager.clear();
406
407         try {
408             FileHandle file0Handle = fileManager.getFileHandle(0L);
409             fail("expect to catch a checksum error");
410         } catch (DbChecksumException e) {
411         }
412     }
413
414     public void testTruncatedHeader()
415         throws IOException JavaDoc, DatabaseException {
416
417         /* Create a log file */
418         FileManagerTestUtils.createLogFile(fileManager, envImpl, FILE_SIZE);
419
420         /* Truncate the header */
421         RandomAccessFile JavaDoc file0 =
422             new RandomAccessFile JavaDoc
423         (fileManager.getFullFileName(0, FileManager.JE_SUFFIX),
424          FileManager.FileMode.READWRITE_MODE.getModeValue());
425         file0.getChannel().truncate(FileManager.firstLogEntryOffset()/2);
426         file0.close();
427
428         try {
429             fileManager.getFileHandle(0);
430             fail("Should see assertion");
431         } catch (DatabaseException e) {
432         }
433     }
434
435     /**
436      * Test the file cache.
437      */

438     public void testCache()
439         throws Throwable JavaDoc {
440
441         try {
442
443             /*
444              * Make five log files. The file descriptor cache should be empty.
445              */

446             FileManagerTestUtils.createLogFile
447         (fileManager, envImpl, FILE_SIZE);
448             FileManagerTestUtils.createLogFile
449         (fileManager, envImpl, FILE_SIZE);
450             FileManagerTestUtils.createLogFile
451         (fileManager, envImpl, FILE_SIZE);
452             FileManagerTestUtils.createLogFile
453         (fileManager, envImpl, FILE_SIZE);
454             FileManagerTestUtils.createLogFile
455         (fileManager, envImpl, FILE_SIZE);
456             
457             Long JavaDoc f0 = new Long JavaDoc(0L);
458             Long JavaDoc f1 = new Long JavaDoc(1L);
459             Long JavaDoc f2 = new Long JavaDoc(2L);
460             Long JavaDoc f3 = new Long JavaDoc(3L);
461             Long JavaDoc f4 = new Long JavaDoc(4L);
462
463             Set JavaDoc keySet = fileManager.getCacheKeys();
464             assertEquals("should have 0 keys", 0, keySet.size());
465
466             /*
467              * Get file descriptors for three files, expect 3 handles in the
468              * cache.
469              */

470             FileHandle f0Handle = fileManager.getFileHandle(0);
471             FileHandle f1Handle = fileManager.getFileHandle(1);
472             FileHandle f2Handle = fileManager.getFileHandle(2);
473             keySet = fileManager.getCacheKeys();
474             assertEquals("should have 3 keys", 3, keySet.size());
475             assertTrue(keySet.contains(f0));
476             assertTrue(keySet.contains(f1));
477             assertTrue(keySet.contains(f2));
478
479             /*
480              * Ask for a fourth handle, the cache should grow even though it
481              * was set to 3 as a starting size, because all handles are
482              * locked. Do it within another thread, otherwise we'll get a
483              * latch-already-held exception when we test the other handles in
484              * the cache. The other thread will get the handle and then release
485              * it.
486              */

487             CachingThread otherThread = new CachingThread(fileManager, 3);
488             otherThread.start();
489             otherThread.join();
490
491             keySet = fileManager.getCacheKeys();
492             assertEquals("should have 4 keys", 4, keySet.size());
493             assertTrue(keySet.contains(f0));
494             assertTrue(keySet.contains(f1));
495             assertTrue(keySet.contains(f2));
496             assertTrue(keySet.contains(f3));
497
498             /*
499              * Now ask for another file. The cache should not grow, because no
500              * handles are locked and there's room to evict one.
501              */

502             f0Handle.release();
503             f1Handle.release();
504             f2Handle.release();
505             FileHandle f4Handle = fileManager.getFileHandle(4);
506             keySet = fileManager.getCacheKeys();
507             assertEquals("should have 4 keys", 4, keySet.size());
508             assertTrue(keySet.contains(f4));
509
510             f4Handle.release();
511
512             /* Clearing should release all file descriptors. */
513             fileManager.clear();
514             assertEquals("should have 0 keys", 0,
515                          fileManager.getCacheKeys().size());
516         } catch (Throwable JavaDoc t) {
517             t.printStackTrace();
518             throw t;
519         }
520     }
521
522     public void testFlipFile()
523     throws Throwable JavaDoc {
524
525         /*
526          * The setUp() method opens a standalone FileManager, but in this test
527          * case we need a regular Environment. On Windows, we can't lock the
528          * file range twice in FileManager.lockEnvironment, so we must close
529          * the standalone FileManager here before opening a regular
530          * environment.
531          */

532         fileManager.clear();
533         fileManager.close();
534         fileManager = null;
535
536         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
537         envConfig.setAllowCreate(true);
538         envConfig.setTransactional(true);
539         Environment env = new Environment(envHome, envConfig);
540     EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
541     FileManager fileManager = envImpl.getFileManager();
542
543         DatabaseConfig dbConfig = new DatabaseConfig();
544         dbConfig.setAllowCreate(true);
545         Database exampleDb =
546         env.openDatabase(null, "simpleDb", dbConfig);
547
548         assertEquals("Should have 0 as current file", 0L,
549                      fileManager.getCurrentFileNum());
550     long flipLsn = envImpl.forceLogFileFlip();
551     assertEquals("LSN should be 1 post-flip", 1L,
552              DbLsn.getFileNumber(flipLsn));
553     DatabaseEntry key = new DatabaseEntry();
554     DatabaseEntry data = new DatabaseEntry();
555     key.setData("key".getBytes());
556     data.setData("data".getBytes());
557     exampleDb.put(null, key, data);
558         assertEquals("Should have 1 as last file", 1L,
559                      fileManager.getCurrentFileNum());
560     exampleDb.close();
561     env.close();
562     }
563
564     class CachingThread extends Thread JavaDoc {
565         private FileManager fileManager;
566         private long fileNum;
567  
568         private FileHandle handle;
569
570         CachingThread(FileManager fileManager, long fileNum) {
571             this.fileManager = fileManager;
572             this.fileNum = fileNum;
573         }
574
575         public void run() {
576             try {
577                 handle = fileManager.getFileHandle(fileNum);
578                 handle.release();
579             } catch (Exception JavaDoc e) {
580                 fail(e.getMessage());
581             }
582         }
583
584         FileHandle getHandle() {
585             return handle;
586         }
587     }
588 }
589
Popular Tags