KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sleepycat > je > cleaner > CleanerTest


1 /*-
2  * See the file LICENSE for redistribution information.
3  *
4  * Copyright (c) 2002,2006 Oracle. All rights reserved.
5  *
6  * $Id: CleanerTest.java,v 1.87 2006/12/05 21:34:20 mark Exp $
7  */

8
9 package com.sleepycat.je.cleaner;
10
11 import java.io.File JavaDoc;
12 import java.io.IOException JavaDoc;
13 import java.util.HashMap JavaDoc;
14 import java.util.HashSet JavaDoc;
15 import java.util.Iterator JavaDoc;
16 import java.util.Map JavaDoc;
17 import java.util.Set JavaDoc;
18
19 import junit.framework.TestCase;
20
21 import com.sleepycat.bind.tuple.IntegerBinding;
22 import com.sleepycat.je.CheckpointConfig;
23 import com.sleepycat.je.Cursor;
24 import com.sleepycat.je.Database;
25 import com.sleepycat.je.DatabaseConfig;
26 import com.sleepycat.je.DatabaseEntry;
27 import com.sleepycat.je.DatabaseException;
28 import com.sleepycat.je.DbInternal;
29 import com.sleepycat.je.Environment;
30 import com.sleepycat.je.EnvironmentConfig;
31 import com.sleepycat.je.EnvironmentMutableConfig;
32 import com.sleepycat.je.EnvironmentStats;
33 import com.sleepycat.je.LockMode;
34 import com.sleepycat.je.OperationStatus;
35 import com.sleepycat.je.Transaction;
36 import com.sleepycat.je.cleaner.Cleaner;
37 import com.sleepycat.je.cleaner.UtilizationProfile;
38 import com.sleepycat.je.config.EnvironmentParams;
39 import com.sleepycat.je.dbi.EnvironmentImpl;
40 import com.sleepycat.je.dbi.MemoryBudget;
41 import com.sleepycat.je.log.FileManager;
42 import com.sleepycat.je.util.StringDbt;
43 import com.sleepycat.je.util.TestUtils;
44
45 public class CleanerTest extends TestCase {
46
47     private static final int N_KEYS = 300;
48     private static final int N_KEY_BYTES = 10;
49
50     /*
51      * Make the log file size small enough to allow cleaning, but large enough
52      * not to generate a lot of fsyncing at the log file boundaries.
53      */

54     private static final int FILE_SIZE = 10000;
55     protected File JavaDoc envHome = null;
56     protected Database db = null;
57     private Environment exampleEnv;
58     private Database exampleDb;
59     private CheckpointConfig forceConfig;
60
61     public CleanerTest() {
62         envHome = new File JavaDoc(System.getProperty(TestUtils.DEST_DIR));
63         forceConfig = new CheckpointConfig();
64         forceConfig.setForce(true);
65     }
66
67     public void setUp()
68         throws IOException JavaDoc, DatabaseException {
69
70         TestUtils.removeLogFiles("Setup", envHome, false);
71         TestUtils.removeFiles("Setup", envHome, FileManager.DEL_SUFFIX);
72     }
73
74     private void initEnv(boolean createDb, boolean allowDups)
75         throws DatabaseException {
76
77         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
78     DbInternal.disableParameterValidation(envConfig);
79         envConfig.setTransactional(true);
80         envConfig.setAllowCreate(true);
81         envConfig.setTxnNoSync(Boolean.getBoolean(TestUtils.NO_SYNC));
82         envConfig.setConfigParam(EnvironmentParams.LOG_FILE_MAX.getName(),
83                                  Integer.toString(FILE_SIZE));
84         envConfig.setConfigParam(EnvironmentParams.ENV_CHECK_LEAKS.getName(),
85                                  "false");
86         envConfig.setConfigParam(EnvironmentParams.ENV_RUN_CLEANER.getName(),
87                                  "false");
88         envConfig.setConfigParam(EnvironmentParams.CLEANER_REMOVE.getName(),
89                                  "false");
90         envConfig.setConfigParam
91         (EnvironmentParams.CLEANER_MIN_UTILIZATION.getName(), "80");
92         envConfig.setConfigParam
93         (EnvironmentParams.ENV_RUN_CHECKPOINTER.getName(), "false");
94         envConfig.setConfigParam(EnvironmentParams.NODE_MAX.getName(), "6");
95         envConfig.setConfigParam(EnvironmentParams.BIN_DELTA_PERCENT.getName(),
96                                  "75");
97
98         /* Don't use detail tracking in this test. */
99         envConfig.setConfigParam
100             (EnvironmentParams.CLEANER_TRACK_DETAIL.getName(), "false");
101
102         exampleEnv = new Environment(envHome, envConfig);
103
104         String JavaDoc databaseName = "cleanerDb";
105         DatabaseConfig dbConfig = new DatabaseConfig();
106         dbConfig.setTransactional(true);
107         dbConfig.setAllowCreate(createDb);
108         dbConfig.setSortedDuplicates(allowDups);
109         exampleDb = exampleEnv.openDatabase(null, databaseName, dbConfig);
110     }
111
112     public void tearDown()
113         throws IOException JavaDoc, DatabaseException {
114
115         if (exampleEnv != null) {
116             try {
117                 exampleEnv.close();
118             } catch (DatabaseException e) {
119                 System.out.println("tearDown: " + e);
120             }
121         }
122         exampleDb = null;
123         exampleEnv = null;
124                 
125         //*
126
TestUtils.removeLogFiles("TearDown", envHome, true);
127         TestUtils.removeFiles("TearDown", envHome, FileManager.DEL_SUFFIX);
128         //*/
129
}
130
131     private void closeEnv()
132         throws DatabaseException {
133
134         if (exampleDb != null) {
135             exampleDb.close();
136             exampleDb = null;
137         }
138
139         if (exampleEnv != null) {
140             exampleEnv.close();
141             exampleEnv = null;
142         }
143     }
144
145     public void testCleanerNoDupes()
146         throws Throwable JavaDoc {
147
148         initEnv(true, false);
149         try {
150             doCleanerTest(N_KEYS, 1);
151         } catch (Throwable JavaDoc t) {
152             t.printStackTrace();
153             throw t;
154         }
155     }
156
157     public void testCleanerWithDupes()
158         throws Throwable JavaDoc {
159
160         initEnv(true, true);
161         try {
162             doCleanerTest(2, 500);
163         } catch (Throwable JavaDoc t) {
164             t.printStackTrace();
165             throw t;
166         }
167     }
168
169     private void doCleanerTest(int nKeys, int nDupsPerKey)
170         throws DatabaseException {
171
172         EnvironmentImpl environment =
173             DbInternal.envGetEnvironmentImpl(exampleEnv);
174         FileManager fileManager = environment.getFileManager();
175         Map JavaDoc expectedMap = new HashMap JavaDoc();
176         doLargePut(expectedMap, nKeys, nDupsPerKey, true);
177         Long JavaDoc lastNum = fileManager.getLastFileNum();
178
179         /* Read the data back. */
180         StringDbt foundKey = new StringDbt();
181         StringDbt foundData = new StringDbt();
182
183         Cursor cursor = exampleDb.openCursor(null, null);
184
185         while (cursor.getNext(foundKey, foundData, LockMode.DEFAULT) ==
186                OperationStatus.SUCCESS) {
187         }
188
189     exampleEnv.checkpoint(forceConfig);
190
191         for (int i = 0; i < (int) lastNum.longValue(); i++) {
192
193             /*
194              * Force clean one file. Utilization-based cleaning won't
195              * work here, since utilization is over 90%.
196              */

197             DbInternal.envGetEnvironmentImpl(exampleEnv).
198         getCleaner().
199         doClean(false, // cleanMultipleFiles
200
true); // forceCleaning
201
}
202
203         EnvironmentStats stats = exampleEnv.getStats(TestUtils.FAST_STATS);
204         assertTrue(stats.getNINsCleaned() > 0);
205                 
206     cursor.close();
207         closeEnv();
208
209         initEnv(false, (nDupsPerKey > 1));
210
211         checkData(expectedMap);
212         assertTrue(fileManager.getLastFileNum().longValue() >
213                    lastNum.longValue());
214
215         closeEnv();
216     }
217
218     /**
219      * Ensure that INs are cleaned.
220      */

221     public void testCleanInternalNodes()
222         throws DatabaseException {
223
224         initEnv(true, true);
225         int nKeys = 200;
226         
227         EnvironmentImpl environment =
228             DbInternal.envGetEnvironmentImpl(exampleEnv);
229         FileManager fileManager = environment.getFileManager();
230         /* Insert a lot of keys. ExpectedMap holds the expected data */
231         Map JavaDoc expectedMap = new HashMap JavaDoc();
232         doLargePut(expectedMap, nKeys, 1, true);
233
234         /* Modify every other piece of data. */
235         modifyData(expectedMap, 10, true);
236         checkData(expectedMap);
237
238         /* Checkpoint */
239         exampleEnv.checkpoint(forceConfig);
240         checkData(expectedMap);
241
242         /* Modify every other piece of data. */
243         modifyData(expectedMap, 10, true);
244         checkData(expectedMap);
245
246         /* Checkpoint -- this should obsolete INs. */
247         exampleEnv.checkpoint(forceConfig);
248         checkData(expectedMap);
249
250         /* Clean */
251         Long JavaDoc lastNum = fileManager.getLastFileNum();
252         exampleEnv.cleanLog();
253
254         /* Validate after cleaning. */
255         checkData(expectedMap);
256         EnvironmentStats stats = exampleEnv.getStats(TestUtils.FAST_STATS);
257
258         /* Make sure we really cleaned something.*/
259         assertTrue(stats.getNINsCleaned() > 0);
260         assertTrue(stats.getNLNsCleaned() > 0);
261                 
262         closeEnv();
263         initEnv(false, true);
264         checkData(expectedMap);
265         assertTrue(fileManager.getLastFileNum().longValue() >
266                    lastNum.longValue());
267
268         closeEnv();
269     }
270
271     /**
272      * See if we can clean in the middle of the file set.
273      */

274     public void testCleanFileHole()
275         throws Throwable JavaDoc {
276
277         initEnv(true, true);
278
279         int nKeys = 20; // test ends up inserting 2*nKeys
280
int nDupsPerKey = 30;
281
282         EnvironmentImpl environment =
283             DbInternal.envGetEnvironmentImpl(exampleEnv);
284         FileManager fileManager = environment.getFileManager();
285
286         /* Insert some non dup data, modify, insert dup data. */
287         Map JavaDoc expectedMap = new HashMap JavaDoc();
288         doLargePut(expectedMap, nKeys, 1, true);
289         modifyData(expectedMap, 10, true);
290         doLargePut(expectedMap, nKeys, nDupsPerKey, true);
291         checkData(expectedMap);
292
293         /*
294          * Delete all the data, but abort. (Try to fill up the log
295          * with entries we don't need.
296          */

297         deleteData(expectedMap, false, false);
298         checkData(expectedMap);
299
300         /* Do some more insertions, but abort them. */
301         doLargePut(expectedMap, nKeys, nDupsPerKey, false);
302         checkData(expectedMap);
303
304         /* Do some more insertions and commit them. */
305         doLargePut(expectedMap, nKeys, nDupsPerKey, true);
306         checkData(expectedMap);
307
308         /* Checkpoint */
309         exampleEnv.checkpoint(forceConfig);
310         checkData(expectedMap);
311
312         /* Clean */
313         Long JavaDoc lastNum = fileManager.getLastFileNum();
314         exampleEnv.cleanLog();
315             
316         /* Validate after cleaning. */
317         checkData(expectedMap);
318         EnvironmentStats stats = exampleEnv.getStats(TestUtils.FAST_STATS);
319
320         /* Make sure we really cleaned something.*/
321         assertTrue(stats.getNINsCleaned() > 0);
322         assertTrue(stats.getNLNsCleaned() > 0);
323
324         closeEnv();
325         initEnv(false, true);
326         checkData(expectedMap);
327         assertTrue(fileManager.getLastFileNum().longValue() >
328                    lastNum.longValue());
329
330         closeEnv();
331     }
332
333     /**
334      * Test for SR13191. This SR shows a problem where a MapLN is initialized
335      * with a DatabaseImpl that has a null EnvironmentImpl. When the Database
336      * gets used, a NullPointerException occurs in the Cursor code which
337      * expects there to be an EnvironmentImpl present. The MapLN gets init'd
338      * by the Cleaner reading through a log file and encountering a MapLN which
339      * is not presently in the DbTree. As an efficiency, the Cleaner calls
340      * updateEntry on the BIN to try to insert the MapLN into the BIN so that
341      * it won't have to fetch it when it migrates the BIN. But this is bad
342      * since the MapLN has not been init'd properly. The fix was to ensure
343      * that the MapLN is init'd correctly by calling postFetchInit on it just
344      * prior to inserting it into the BIN.
345      *
346      * This test first creates an environment and two databases. The first
347      * database it just adds to the tree with no data. This will be the MapLN
348      * that eventually gets instantiated by the cleaner. The second database
349      * is used just to create a bunch of data that will get deleted so as to
350      * create a low utilization for one of the log files. Once the data for
351      * db2 is created, the log is flipped (so file 0 is the one with the MapLN
352      * for db1 in it), and the environment is closed and reopened. We insert
353      * more data into db2 until we have enough .jdb files that file 0 is
354      * attractive to the cleaner. Call the cleaner to have it instantiate the
355      * MapLN and then use the MapLN in a Database.get() call.
356      */

357     public void testSR13191()
358     throws Throwable JavaDoc {
359
360         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
361         envConfig.setAllowCreate(true);
362         envConfig.setConfigParam
363         (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false");
364         Environment env = new Environment(envHome, envConfig);
365     EnvironmentImpl envImpl = DbInternal.envGetEnvironmentImpl(env);
366     FileManager fileManager =
367         DbInternal.envGetEnvironmentImpl(env).getFileManager();
368
369         DatabaseConfig dbConfig = new DatabaseConfig();
370         dbConfig.setAllowCreate(true);
371         Database db1 =
372         env.openDatabase(null, "db1", dbConfig);
373
374         Database db2 =
375         env.openDatabase(null, "db2", dbConfig);
376
377     DatabaseEntry key = new DatabaseEntry();
378     DatabaseEntry data = new DatabaseEntry();
379     IntegerBinding.intToEntry(1, key);
380     data.setData(new byte[100000]);
381         for (int i = 0; i < 50; i++) {
382             assertEquals(OperationStatus.SUCCESS, db2.put(null, key, data));
383     }
384     db1.close();
385     db2.close();
386         assertEquals("Should have 0 as current file", 0L,
387                      fileManager.getCurrentFileNum());
388     envImpl.forceLogFileFlip();
389     env.close();
390
391         env = new Environment(envHome, envConfig);
392     fileManager = DbInternal.envGetEnvironmentImpl(env).getFileManager();
393         assertEquals("Should have 1 as current file", 1L,
394                      fileManager.getCurrentFileNum());
395
396     db2 = env.openDatabase(null, "db2", dbConfig);
397
398         for (int i = 0; i < 250; i++) {
399             assertEquals(OperationStatus.SUCCESS, db2.put(null, key, data));
400     }
401
402     db2.close();
403     env.cleanLog();
404     db1 = env.openDatabase(null, "db1", dbConfig);
405     db1.get(null, key, data, null);
406     db1.close();
407     env.close();
408     }
409
410     /**
411      * Tests that setting je.env.runCleaner=false stops the cleaner from
412      * processing more files even if the target minUtilization is not met
413      * [#15158].
414      */

415     public void testCleanerStop()
416     throws Throwable JavaDoc {
417
418         final int fileSize = 1000000;
419         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
420         envConfig.setAllowCreate(true);
421         envConfig.setConfigParam
422         (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false");
423         envConfig.setConfigParam
424             (EnvironmentParams.LOG_FILE_MAX.getName(),
425              Integer.toString(fileSize));
426         envConfig.setConfigParam
427         (EnvironmentParams.CLEANER_MIN_UTILIZATION.getName(), "80");
428         Environment env = new Environment(envHome, envConfig);
429
430         DatabaseConfig dbConfig = new DatabaseConfig();
431         dbConfig.setAllowCreate(true);
432         Database db = env.openDatabase(null, "CleanerStop", dbConfig);
433
434         DatabaseEntry key = new DatabaseEntry(new byte[1]);
435         DatabaseEntry data = new DatabaseEntry(new byte[fileSize]);
436         for (int i = 0; i <= 10; i += 1) {
437             db.put(null, key, data);
438         }
439         env.checkpoint(forceConfig);
440
441         EnvironmentStats stats = env.getStats(null);
442         assertEquals(0, stats.getNCleanerRuns());
443
444         envConfig = env.getConfig();
445         envConfig.setConfigParam
446         (EnvironmentParams.ENV_RUN_CLEANER.getName(), "true");
447         env.setMutableConfig(envConfig);
448
449         int iter = 0;
450         while (stats.getNCleanerRuns() == 0) {
451             iter += 1;
452             if (iter == 20) {
453                 fail("Cleaner did not run after " + iter + " tries");
454             }
455             Thread.yield();
456             Thread.sleep(1);
457             stats = env.getStats(null);
458         }
459
460         envConfig.setConfigParam
461         (EnvironmentParams.ENV_RUN_CLEANER.getName(), "false");
462         env.setMutableConfig(envConfig);
463
464         int prevNFiles = stats.getNCleanerRuns();
465         stats = env.getStats(null);
466         int currNFiles = stats.getNCleanerRuns();
467         if (currNFiles - prevNFiles > 5) {
468             fail("Expected less than 5 files cleaned," +
469                  " prevNFiles=" + prevNFiles +
470                  " currNFiles=" + currNFiles);
471         }
472
473         //System.out.println("Num runs: " + stats.getNCleanerRuns());
474

475     db.close();
476     env.close();
477     }
478
479     /**
480      * Helper routine. Generates keys with random alpha values while data
481      * is numbered numerically.
482      */

483     private void doLargePut(Map JavaDoc expectedMap,
484                             int nKeys,
485                             int nDupsPerKey,
486                             boolean commit)
487         throws DatabaseException {
488
489         Transaction txn = exampleEnv.beginTransaction(null, null);
490         for (int i = 0; i < nKeys; i++) {
491             byte[] key = new byte[N_KEY_BYTES];
492             TestUtils.generateRandomAlphaBytes(key);
493             String JavaDoc keyString = new String JavaDoc(key);
494
495             /*
496          * The data map is keyed by key value, and holds a hash
497          * map of all data values.
498              */

499             Set JavaDoc dataVals = new HashSet JavaDoc();
500             if (commit) {
501                 expectedMap.put(keyString, dataVals);
502             }
503             for (int j = 0; j < nDupsPerKey; j++) {
504                 String JavaDoc dataString = Integer.toString(j);
505                 exampleDb.put(txn,
506                               new StringDbt(keyString),
507                               new StringDbt(dataString));
508                 dataVals.add(dataString);
509             }
510         }
511         if (commit) {
512             txn.commit();
513         } else {
514             txn.abort();
515         }
516     }
517
518     /**
519      * Increment each data value.
520      */

521     private void modifyData(Map JavaDoc expectedMap,
522                             int increment,
523                             boolean commit)
524         throws DatabaseException {
525
526         Transaction txn = exampleEnv.beginTransaction(null, null);
527
528         StringDbt foundKey = new StringDbt();
529         StringDbt foundData = new StringDbt();
530
531         Cursor cursor = exampleDb.openCursor(txn, null);
532         OperationStatus status = cursor.getFirst(foundKey, foundData,
533                                                  LockMode.DEFAULT);
534
535         boolean toggle = true;
536         while (status == OperationStatus.SUCCESS) {
537             if (toggle) {
538
539                 String JavaDoc foundKeyString = foundKey.getString();
540                 String JavaDoc foundDataString = foundData.getString();
541                 int newValue = Integer.parseInt(foundDataString) + increment;
542                 String JavaDoc newDataString = Integer.toString(newValue);
543
544                 /* If committing, adjust the expected map. */
545                 if (commit) {
546                 
547                     Set JavaDoc dataVals = (Set JavaDoc) expectedMap.get(foundKeyString);
548                     if (dataVals == null) {
549                         fail("Couldn't find " +
550                              foundKeyString + "/" + foundDataString);
551                     } else if (dataVals.contains(foundDataString)) {
552                         dataVals.remove(foundDataString);
553                         dataVals.add(newDataString);
554                     } else {
555                         fail("Couldn't find " +
556                              foundKeyString + "/" + foundDataString);
557                     }
558                 }
559  
560                 assertEquals(OperationStatus.SUCCESS,
561                              cursor.delete());
562                 assertEquals(OperationStatus.SUCCESS,
563                              cursor.put(foundKey,
564                     new StringDbt(newDataString)));
565                 toggle = false;
566             } else {
567                 toggle = true;
568             }
569
570             status = cursor.getNext(foundKey, foundData, LockMode.DEFAULT);
571         }
572
573         cursor.close();
574         if (commit) {
575             txn.commit();
576         } else {
577             txn.abort();
578         }
579     }
580     /**
581      * Delete data.
582      */

583     private void deleteData(Map JavaDoc expectedMap,
584                             boolean everyOther,
585                             boolean commit)
586         throws DatabaseException {
587
588         Transaction txn = exampleEnv.beginTransaction(null, null);
589
590         StringDbt foundKey = new StringDbt();
591         StringDbt foundData = new StringDbt();
592
593         Cursor cursor = exampleDb.openCursor(txn, null);
594         OperationStatus status = cursor.getFirst(foundKey, foundData,
595                                                  LockMode.DEFAULT);
596
597         boolean toggle = true;
598         while (status == OperationStatus.SUCCESS) {
599             if (toggle) {
600
601                 String JavaDoc foundKeyString = foundKey.getString();
602                 String JavaDoc foundDataString = foundData.getString();
603
604                 /* If committing, adjust the expected map */
605                 if (commit) {
606                 
607                     Set JavaDoc dataVals = (Set JavaDoc) expectedMap.get(foundKeyString);
608                     if (dataVals == null) {
609                         fail("Couldn't find " +
610                              foundKeyString + "/" + foundDataString);
611                     } else if (dataVals.contains(foundDataString)) {
612                         dataVals.remove(foundDataString);
613                         if (dataVals.size() == 0) {
614                 expectedMap.remove(foundKeyString);
615                         }
616                     } else {
617                         fail("Couldn't find " +
618                              foundKeyString + "/" + foundDataString);
619                     }
620                 }
621  
622                 assertEquals(OperationStatus.SUCCESS, cursor.delete());
623             }
624
625             if (everyOther) {
626                 toggle = toggle? false: true;
627             }
628
629             status = cursor.getNext(foundKey, foundData, LockMode.DEFAULT);
630         }
631
632         cursor.close();
633         if (commit) {
634             txn.commit();
635         } else {
636             txn.abort();
637         }
638     }
639
640     /**
641      * Check what's in the database against what's in the expected map.
642      */

643     private void checkData(Map JavaDoc expectedMap)
644         throws DatabaseException {
645
646         StringDbt foundKey = new StringDbt();
647         StringDbt foundData = new StringDbt();
648         Cursor cursor = exampleDb.openCursor(null, null);
649         OperationStatus status = cursor.getFirst(foundKey, foundData,
650                                                  LockMode.DEFAULT);
651
652         /*
653          * Make a copy of expectedMap so that we're free to delete out
654          * of the set of expected results when we verify.
655          * Also make a set of counts for each key value, to test count.
656          */

657
658         Map JavaDoc checkMap = new HashMap JavaDoc();
659         Map JavaDoc countMap = new HashMap JavaDoc();
660         Iterator JavaDoc iter = expectedMap.entrySet().iterator();
661         while (iter.hasNext()) {
662             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iter.next();
663             Set JavaDoc copySet = new HashSet JavaDoc();
664             copySet.addAll((Set JavaDoc) entry.getValue());
665             checkMap.put(entry.getKey(), copySet);
666             countMap.put(entry.getKey(), new Integer JavaDoc(copySet.size()));
667         }
668
669         while (status == OperationStatus.SUCCESS) {
670             String JavaDoc foundKeyString = foundKey.getString();
671             String JavaDoc foundDataString = foundData.getString();
672
673             /* Check that the current value is in the check values map */
674             Set JavaDoc dataVals = (Set JavaDoc) checkMap.get(foundKeyString);
675             if (dataVals == null) {
676                 fail("Couldn't find " +
677                      foundKeyString + "/" + foundDataString);
678             } else if (dataVals.contains(foundDataString)) {
679                 dataVals.remove(foundDataString);
680                 if (dataVals.size() == 0) {
681                     checkMap.remove(foundKeyString);
682                 }
683             } else {
684                 fail("Couldn't find " +
685                      foundKeyString + "/" +
686                      foundDataString +
687                      " in data vals");
688             }
689
690             /* Check that the count is right. */
691             int count = cursor.count();
692             assertEquals(((Integer JavaDoc)countMap.get(foundKeyString)).intValue(),
693                          count);
694
695             status = cursor.getNext(foundKey, foundData, LockMode.DEFAULT);
696         }
697
698     cursor.close();
699
700     if (checkMap.size() != 0) {
701         dumpExpected(checkMap);
702         fail("checkMapSize = " + checkMap.size());
703                 
704     }
705         assertEquals(0, checkMap.size());
706     }
707
708     private void dumpExpected(Map JavaDoc expectedMap) {
709         Iterator JavaDoc iter = expectedMap.entrySet().iterator();
710         while (iter.hasNext()) {
711             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iter.next();
712             String JavaDoc key = (String JavaDoc) entry.getKey();
713             Iterator JavaDoc dataIter = ((Set JavaDoc) entry.getValue()).iterator();
714             while (dataIter.hasNext()) {
715                 System.out.println("key=" + key +
716                                    " data=" + (String JavaDoc) dataIter.next());
717             }
718         }
719     }
720
721     /**
722      * Tests that cleaner mutable configuration parameters can be changed and
723      * that the changes actually take effect.
724      */

725     public void testMutableConfig()
726         throws DatabaseException {
727
728         EnvironmentConfig envConfig = TestUtils.initEnvConfig();
729         envConfig.setAllowCreate(true);
730         exampleEnv = new Environment(envHome, envConfig);
731         envConfig = exampleEnv.getConfig();
732         EnvironmentImpl envImpl =
733             DbInternal.envGetEnvironmentImpl(exampleEnv);
734         Cleaner cleaner = envImpl.getCleaner();
735         UtilizationProfile profile = envImpl.getUtilizationProfile();
736         MemoryBudget budget = envImpl.getMemoryBudget();
737         String JavaDoc name;
738         String JavaDoc val;
739
740         /* je.cleaner.minUtilization */
741         name = EnvironmentParams.CLEANER_MIN_UTILIZATION.getName();
742         setParam(name, "33");
743         assertEquals(33, profile.minUtilization);
744
745         /* je.cleaner.minFileUtilization */
746         name = EnvironmentParams.CLEANER_MIN_FILE_UTILIZATION.getName();
747         setParam(name, "7");
748         assertEquals(7, profile.minFileUtilization);
749
750         /* je.cleaner.bytesInterval */
751         name = EnvironmentParams.CLEANER_BYTES_INTERVAL.getName();
752         setParam(name, "1000");
753         assertEquals(1000, cleaner.cleanerBytesInterval);
754
755         /* je.cleaner.deadlockRetry */
756         name = EnvironmentParams.CLEANER_DEADLOCK_RETRY.getName();
757         setParam(name, "7");
758         assertEquals(7, cleaner.nDeadlockRetries);
759
760         /* je.cleaner.lockTimeout */
761         name = EnvironmentParams.CLEANER_LOCK_TIMEOUT.getName();
762         setParam(name, "7000");
763         assertEquals(7, cleaner.lockTimeout);
764
765         /* je.cleaner.expunge */
766         name = EnvironmentParams.CLEANER_REMOVE.getName();
767         val = "false".equals(envConfig.getConfigParam(name)) ?
768             "true" : "false";
769         setParam(name, val);
770         assertEquals(val.equals("true"), cleaner.expunge);
771
772         /* je.cleaner.minAge */
773         name = EnvironmentParams.CLEANER_MIN_AGE.getName();
774         setParam(name, "7");
775         assertEquals(7, profile.minAge);
776
777         /* je.cleaner.cluster */
778         name = EnvironmentParams.CLEANER_CLUSTER.getName();
779         val = "false".equals(envConfig.getConfigParam(name)) ?
780             "true" : "false";
781         setParam(name, val);
782         assertEquals(val.equals("true"), cleaner.clusterResident);
783         /* Cannot set both cluster and clusterAll to true. */
784         setParam(name, "false");
785
786         /* je.cleaner.clusterAll */
787         name = EnvironmentParams.CLEANER_CLUSTER_ALL.getName();
788         val = "false".equals(envConfig.getConfigParam(name)) ?
789             "true" : "false";
790         setParam(name, val);
791         assertEquals(val.equals("true"), cleaner.clusterAll);
792
793         /* je.cleaner.maxBatchFiles */
794         name = EnvironmentParams.CLEANER_MAX_BATCH_FILES.getName();
795         setParam(name, "7");
796         assertEquals(7, cleaner.maxBatchFiles);
797
798         /* je.cleaner.readSize */
799         name = EnvironmentParams.CLEANER_READ_SIZE.getName();
800         setParam(name, "7777");
801         assertEquals(7777, cleaner.readBufferSize);
802
803         /* je.cleaner.detailMaxMemoryPercentage */
804         name = EnvironmentParams.CLEANER_DETAIL_MAX_MEMORY_PERCENTAGE.
805             getName();
806         setParam(name, "7");
807         assertEquals((budget.getMaxMemory() * 7) / 100,
808                      budget.getTrackerBudget());
809
810         /* je.cleaner.threads */
811         name = EnvironmentParams.CLEANER_THREADS.getName();
812         setParam(name, "7");
813         assertEquals((envImpl.isNoLocking() ? 0 : 7),
814              countCleanerThreads());
815
816         exampleEnv.close();
817         exampleEnv = null;
818     }
819
820     /**
821      * Sets a mutable config param, checking that the given value is not
822      * already set and that it actually changes.
823      */

824     private void setParam(String JavaDoc name, String JavaDoc val)
825         throws DatabaseException {
826
827         EnvironmentMutableConfig config = exampleEnv.getMutableConfig();
828         String JavaDoc myVal = config.getConfigParam(name);
829         assertTrue(!val.equals(myVal));
830
831         config.setConfigParam(name, val);
832         exampleEnv.setMutableConfig(config);
833
834         config = exampleEnv.getMutableConfig();
835         myVal = config.getConfigParam(name);
836         assertTrue(val.equals(myVal));
837     }
838
839     /**
840      * Count the number of threads with the name "Cleaner#".
841      */

842     private int countCleanerThreads() {
843
844         Thread JavaDoc[] threads = new Thread JavaDoc[Thread.activeCount()];
845         Thread.enumerate(threads);
846
847         int count = 0;
848         for (int i = 0; i < threads.length; i += 1) {
849             if (threads[i] != null &&
850         threads[i].getName().startsWith("Cleaner")) {
851                 count += 1;
852             }
853         }
854
855         return count;
856     }
857 }
858
Popular Tags