1   /* CachedBdbMapTest
2    * 
3    * Created on Apr 11, 2005
4    *
5    * Copyright (C) 2005 Internet Archive.
6    * 
7    * This file is part of the Heritrix web crawler (crawler.archive.org).
8    * 
9    * Heritrix is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser Public License as published by
11   * the Free Software Foundation; either version 2.1 of the License, or
12   * any later version.
13   * 
14   * Heritrix is distributed in the hope that it will be useful, 
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU Lesser Public License for more details.
18   * 
19   * You should have received a copy of the GNU Lesser Public License
20   * along with Heritrix; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22   */
23  package org.archive.util;
24  
25  import java.io.File;
26  import java.util.HashMap;
27  import java.util.concurrent.atomic.AtomicInteger;
28  import java.util.logging.Handler;
29  import java.util.logging.Level;
30  import java.util.logging.Logger;
31  
32  import org.apache.commons.lang.math.RandomUtils;
33  
34  /***
35   * @author stack
36   * @version $Date: 2009-02-20 05:46:36 +0000 (Fri, 20 Feb 2009) $, $Revision: 6131 $
37   */
38  public class CachedBdbMapTest extends TmpDirTestCase {
39      File envDir; 
40      CachedBdbMap cache = null;
41      
42      @SuppressWarnings("unchecked")
43      protected void setUp() throws Exception {
44          super.setUp();
45          this.envDir = new File(getTmpDir(),"CachedBdbMapTest");
46          this.envDir.mkdirs();
47          
48      }
49      
50      protected void tearDown() throws Exception {
51          if(cache!=null) {
52              cache.close();
53              cache = null;
54          }
55          FileUtils.deleteDir(this.envDir);
56          super.tearDown();
57      }
58      
59      @SuppressWarnings("unchecked")
60      public void testReadConsistencyUnderLoad() throws Exception {
61          final CachedBdbMap<Integer,AtomicInteger> cbdbmap = 
62              new CachedBdbMap(
63                      this.envDir, 
64                      this.getClass().getName(), 
65                      Integer.class, 
66                      AtomicInteger.class);
67          this.cache = cbdbmap;
68          final AtomicInteger level = new AtomicInteger(0);
69          final int keyCount = 128 * 1024; // 128K  keys
70          final int maxLevel = 64; 
71          // initial fill
72          for(int i=0; i < keyCount; i++) {
73              cbdbmap.put(i, new AtomicInteger(level.get()));
74          }
75          // backward checking that all values always at level or higher
76          new Thread() {
77              public void run() {
78                  untilmax: while(true) {
79                      for(int j=keyCount-1; j >= 0; j--) {
80                          int targetValue = level.get(); 
81                          if(targetValue>=maxLevel) {
82                              break untilmax;
83                          }
84                          assertTrue("stale value revseq key "+j,cbdbmap.get(j).get()>=targetValue);
85                          Thread.yield();
86                      }
87                  }
88              }
89          }.start();
90          // random checking that all values always at level or higher
91          new Thread() {
92              public void run() {
93                  untilmax: while(true) {
94                      int j = RandomUtils.nextInt(keyCount);
95                      int targetValue = level.get(); 
96                      if(targetValue>=maxLevel) {
97                          break untilmax;
98                      }
99                      assertTrue("stale value random key "+j,
100                             cbdbmap.get(j).get()>=targetValue);
101                     Thread.yield();
102                 }
103             }
104         }.start();
105         // increment all keys
106         for(; level.get() < maxLevel; level.incrementAndGet()) {
107             for(int k = 0; k < keyCount; k++) {
108                 int foundValue = cbdbmap.get(k).getAndIncrement();
109                 assertEquals("stale value preinc key "+k, level.get(), foundValue);
110             }
111             if(level.get() % 10 == 0) {
112                 System.out.println("level to "+level.get());
113             }
114             Thread.yield(); 
115         }
116         // SUCCESS
117     }
118     
119     @SuppressWarnings("unchecked")
120     public void testBackingDbGetsUpdated() throws Exception {
121         CachedBdbMap<String,HashMap<String,String>> cbdbmap = 
122             new CachedBdbMap(
123                     this.envDir, 
124                     this.getClass().getName(), 
125                     String.class, 
126                     HashMap.class);
127         this.cache = cbdbmap;
128         // Enable all logging. Up the level on the handlers and then
129         // on the big map itself.
130         Handler [] handlers = Logger.getLogger("").getHandlers();
131         for (int index = 0; index < handlers.length; index++) {
132             handlers[index].setLevel(Level.FINEST);
133         }
134         Logger.getLogger(CachedBdbMap.class.getName()).
135             setLevel(Level.FINEST);
136         // Set up values.
137         final String value = "value";
138         final String key = "key";
139         final int upperbound = 3;
140         // First put in empty hashmap.
141         for (int i = 0; i < upperbound; i++) {
142             cbdbmap.put(key + Integer.toString(i), new HashMap<String,String>());
143         }
144         // Now add value to hash map.
145         for (int i = 0; i < upperbound; i++) {
146             HashMap<String,String> m = cbdbmap.get(key + Integer.toString(i));
147             m.put(key, value);
148         }
149         cbdbmap.sync();
150         for (int i = 0; i < upperbound; i++) {
151             HashMap<String,String> m = cbdbmap.get(key + Integer.toString(i));
152             String v = m.get(key);
153             if (v == null || !v.equals(value)) {
154                 Logger.getLogger(CachedBdbMap.class.getName()).
155                     warning("Wrong value " + i);
156             }
157         }
158         cbdbmap.close();
159     }
160     
161     public static void main(String [] args) {
162         junit.textui.TestRunner.run(CachedBdbMapTest.class);
163     }
164 }