View Javadoc

1   /**
2    *  Copyright 2003-2006 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache;
18  
19  import net.sf.ehcache.store.DiskStore;
20  import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
21  import net.sf.ehcache.distribution.JVMUtil;
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  
25  import java.io.File;
26  import java.io.FileNotFoundException;
27  import java.io.FileOutputStream;
28  import java.io.IOException;
29  import java.io.RandomAccessFile;
30  import java.util.ArrayList;
31  import java.util.List;
32  import java.util.Random;
33  
34  /**
35   * Test cases for the DiskStore.
36   *
37   * @author <a href="mailto:amurdoch@thoughtworks.com">Adam Murdoch</a>
38   * @author <a href="mailto:gluck@thoughtworks.com">Greg Luck</a>
39   * @version $Id: DiskStoreTest.java 51 2006-04-24 09:21:10Z gregluck $
40   *          <p/>
41   *          total time 149 old i/o
42   *          total time 133, 131, 130 nio
43   */
44  public class DiskStoreTest extends AbstractCacheTest {
45      private static final Log LOG = LogFactory.getLog(DiskStoreTest.class.getName());
46      private static final int ELEMENT_ON_DISK_SIZE = 1255;
47  
48      /**
49       * teardown
50       */
51      protected void tearDown() throws Exception {
52          super.tearDown();
53          deleteFile("persistentLongExpiryIntervalCache");
54          deleteFile("fileTest");
55          deleteFile("testPersistent");
56      }
57  
58      /**
59       * Creates a store which is non-expiring so that we can check for
60       * size-related characteristics without elements being deleted under us.
61       */
62      private DiskStore createNonExpiringDiskStore() {
63          Cache cache = new Cache("testNonPersistent", 10000, true, true, 2, 1, false, 1);
64          cache.initialise();
65          DiskStore diskStore = cache.getDiskStore();
66          return diskStore;
67      }
68  
69      private DiskStore createDiskStore() {
70          Cache cache = new Cache("testNonPersistent", 10000, true, false, 2, 1, false, 1);
71          cache.initialise();
72          DiskStore diskStore = cache.getDiskStore();
73          return diskStore;
74      }
75  
76      private DiskStore createPersistentDiskStore(String cacheName) {
77          Cache cache = new Cache(cacheName, 10000, true, true, 5, 1, true, 600);
78          cache.initialise();
79          DiskStore diskStore = cache.getDiskStore();
80          return diskStore;
81      }
82  
83      private DiskStore createPersistentDiskStoreFromCacheManager() {
84          Cache cache = manager.getCache("persistentLongExpiryIntervalCache");
85          return cache.getDiskStore();
86      }
87  
88      /**
89       * Tests that a file is created with the right size after puts, and that the file is
90       * deleted on disposal
91       */
92      public void testNonPersistentStore() throws IOException, InterruptedException {
93          DiskStore diskStore = createNonExpiringDiskStore();
94          File dataFile = new File(diskStore.getDataFilePath() + File.separator + diskStore.getDataFileName());
95  
96          for (int i = 0; i < 100; i++) {
97              byte[] data = new byte[1024];
98              diskStore.put(new Element("key" + (i + 100), data));
99              waitForFlush(diskStore);
100             int predictedSize = ELEMENT_ON_DISK_SIZE * (i + 1);
101             long actualSize = diskStore.getDataFileSize();
102             assertEquals("On the " + i + " iteration: ", predictedSize, actualSize);
103         }
104 
105         assertEquals(100, diskStore.getSize());
106         diskStore.dispose();
107         Thread.sleep(1);
108         assertFalse("File exists", dataFile.exists());
109     }
110 
111     /**
112      * Tests that a file is created with the right size after puts, and that the file is not
113      * deleted on disposal
114      * <p/>
115      * This test uses a preconfigured cache from the test cache.xml. Note that teardown causes
116      * an exception because the disk store is being shut down twice.
117      */
118     public void testPersistentStore() throws IOException, InterruptedException, CacheException {
119         //initialise
120         DiskStore diskStore = createPersistentDiskStoreFromCacheManager();
121         diskStore.removeAll();
122 
123         File dataFile = new File(diskStore.getDataFilePath() + File.separator + diskStore.getDataFileName());
124 
125         for (int i = 0; i < 100; i++) {
126             byte[] data = new byte[1024];
127             diskStore.put(new Element("key" + (i + 100), data));
128         }
129         waitForFlush(diskStore);
130         assertEquals(100, diskStore.getSize());
131         diskStore.dispose();
132 
133         assertTrue("File exists", dataFile.exists());
134         assertEquals(100 * ELEMENT_ON_DISK_SIZE, dataFile.length());
135     }
136 
137     /**
138      * Tests that the expiry thread dies on dispose.
139      */
140     public void testExpiryThreadDiesOnDispose() throws IOException, InterruptedException {
141         Cache cache = new Cache("testNonPersistent", 10000, true, false, 5, 1, false, 100);
142         cache.initialise();
143         DiskStore diskStore = cache.getDiskStore();
144 
145         //Put in some data
146         for (int i = 0; i < 100; i++) {
147             byte[] data = new byte[1024];
148             diskStore.put(new Element("key" + (i + 100), data));
149         }
150         waitForFlush(diskStore);
151 
152         diskStore.dispose();
153         //Give the expiry thread time to be interrupted and die
154         Thread.sleep(100);
155         assertTrue(!diskStore.isExpiryThreadAlive());
156 
157 
158     }
159 
160     /**
161      * Tests that we can save and load a persistent store in a repeatable way
162      */
163     public void testLoadPersistentStore() throws IOException, InterruptedException {
164         //initialise
165         String cacheName = "testPersistent";
166         DiskStore diskStore = createPersistentDiskStore(cacheName);
167         diskStore.removeAll();
168 
169 
170         for (int i = 0; i < 100; i++) {
171             byte[] data = new byte[1024];
172             diskStore.put(new Element("key" + (i + 100), data));
173 
174             waitForFlush(diskStore);
175             assertEquals("On the " + i + " iteration: ", ELEMENT_ON_DISK_SIZE * (i + 1), diskStore.getDataFileSize());
176         }
177         assertEquals(100, diskStore.getSize());
178         diskStore.dispose();
179         Thread.sleep(3000);
180         //check that we can create and dispose several times with no problems and no lost data
181         for (int i = 0; i < 10; i++) {
182             diskStore = createPersistentDiskStore(cacheName);
183             File dataFile = new File(diskStore.getDataFilePath() + File.separator + diskStore.getDataFileName());
184             assertTrue("File exists", dataFile.exists());
185             assertEquals(100 * ELEMENT_ON_DISK_SIZE, dataFile.length());
186             assertEquals(100, diskStore.getSize());
187 
188             diskStore.dispose();
189 
190             assertTrue("File exists", dataFile.exists());
191             assertEquals(100 * ELEMENT_ON_DISK_SIZE, dataFile.length());
192         }
193     }
194 
195     /**
196      * Tests that we can save and load a persistent store in a repeatable way,
197      * and delete and add data.
198      */
199     public void testLoadPersistentStoreWithDelete() throws IOException, InterruptedException {
200         //initialise
201         String cacheName = "testPersistent";
202         DiskStore diskStore = createPersistentDiskStore(cacheName);
203         diskStore.removeAll();
204 
205 
206         for (int i = 0; i < 100; i++) {
207             byte[] data = new byte[1024];
208             diskStore.put(new Element("key" + (i + 100), data));
209             waitForFlush(diskStore);
210             assertEquals("On the " + i + " iteration: ", ELEMENT_ON_DISK_SIZE * (i + 1), diskStore.getDataFileSize());
211         }
212         assertEquals(100, diskStore.getSize());
213         diskStore.dispose();
214 
215         diskStore = createPersistentDiskStore(cacheName);
216         File dataFile = new File(diskStore.getDataFilePath() + File.separator + diskStore.getDataFileName());
217         assertTrue("File exists", dataFile.exists());
218         assertEquals(100 * ELEMENT_ON_DISK_SIZE, dataFile.length());
219         assertEquals(100, diskStore.getSize());
220 
221         diskStore.remove("key100");
222         assertEquals(100 * ELEMENT_ON_DISK_SIZE, dataFile.length());
223         assertEquals(99, diskStore.getSize());
224 
225         diskStore.dispose();
226 
227         assertTrue("File exists", dataFile.exists());
228         assertEquals(100 * ELEMENT_ON_DISK_SIZE, dataFile.length());
229     }
230 
231     /**
232      * Tests that we can load a store after the index has been corrupted
233      */
234     public void testLoadPersistentStoreAfterCorruption() throws IOException, InterruptedException {
235         //initialise
236         String cacheName = "testPersistent";
237         DiskStore diskStore = createPersistentDiskStore(cacheName);
238         diskStore.removeAll();
239 
240 
241         for (int i = 0; i < 100; i++) {
242             byte[] data = new byte[1024];
243             diskStore.put(new Element("key" + (i + 100), data));
244             waitForFlush(diskStore);
245             assertEquals("On the " + i + " iteration: ", ELEMENT_ON_DISK_SIZE * (i + 1), diskStore.getDataFileSize());
246         }
247         assertEquals(100, diskStore.getSize());
248         diskStore.dispose();
249 
250         File indexFile = new File(diskStore.getDataFilePath() + File.separator + diskStore.getIndexFileName());
251         FileOutputStream fout = new FileOutputStream(indexFile);
252         //corrupt the index file
253         fout.write(new byte[]{'q', 'w', 'e', 'r', 't', 'y'});
254         fout.close();
255         diskStore = createPersistentDiskStore(cacheName);
256         File dataFile = new File(diskStore.getDataFilePath() + File.separator + diskStore.getDataFileName());
257         assertTrue("File exists", dataFile.exists());
258 
259         //Make sure the data file got recreated since the index was corrupt
260         assertEquals("Data file was not recreated", 0, dataFile.length());
261         assertEquals(0, diskStore.getSize());
262     }
263 
264 
265     /**
266      * Tests that we can save and load a persistent store in a repeatable way,
267      * and delete and add data.
268      */
269     public void testFreeSpaceBehaviour() throws IOException, InterruptedException {
270         //initialise
271         String cacheName = "testPersistent";
272         DiskStore diskStore = createPersistentDiskStore(cacheName);
273         diskStore.removeAll();
274 
275         byte[] data = new byte[1024];
276         for (int i = 0; i < 100; i++) {
277             diskStore.put(new Element("key" + (i + 100), data));
278             waitForFlush(diskStore);
279             int predictedSize = ELEMENT_ON_DISK_SIZE * (i + 1);
280             long actualSize = diskStore.getDataFileSize();
281             assertEquals("On the " + i + " iteration: ", predictedSize, actualSize);
282         }
283 
284         assertEquals(100, diskStore.getSize());
285         diskStore.dispose();
286 
287         diskStore = createPersistentDiskStore(cacheName);
288         File dataFile = new File(diskStore.getDataFilePath() + File.separator + diskStore.getDataFileName());
289         assertTrue("File exists", dataFile.exists());
290         assertEquals(100 * ELEMENT_ON_DISK_SIZE, dataFile.length());
291         assertEquals(100, diskStore.getSize());
292 
293         diskStore.remove("key100");
294         diskStore.remove("key101");
295         diskStore.remove("key102");
296         diskStore.remove("key103");
297         diskStore.remove("key104");
298 
299         diskStore.put(new Element("key100", data));
300         diskStore.put(new Element("key101", data));
301         waitForFlush(diskStore);
302         //The file does not shrink.
303         assertEquals(100 * ELEMENT_ON_DISK_SIZE, dataFile.length());
304         assertEquals(97, diskStore.getSize());
305 
306         diskStore.put(new Element("key102", data));
307         diskStore.put(new Element("key103", data));
308         diskStore.put(new Element("key104", data));
309         diskStore.put(new Element("key201", data));
310         diskStore.put(new Element("key202", data));
311         waitForFlush(diskStore);
312         assertEquals(102 * ELEMENT_ON_DISK_SIZE, dataFile.length());
313         assertEquals(102, diskStore.getSize());
314         diskStore.dispose();
315         assertTrue("File exists", dataFile.exists());
316         assertEquals(102 * ELEMENT_ON_DISK_SIZE, dataFile.length());
317     }
318 
319     /**
320      * Tests looking up an entry that does not exist.
321      */
322     public void testGetUnknown() throws Exception {
323         final DiskStore diskStore = createDiskStore();
324         final Element element = diskStore.get("key");
325         assertNull(element);
326     }
327 
328     /**
329      * Tests adding an entry.
330      */
331     public void testPut() throws Exception {
332         final DiskStore diskStore = createDiskStore();
333 
334         // Make sure the element is not found
335         assertEquals(0, diskStore.getSize());
336         Element element = diskStore.get("key");
337         assertNull(element);
338 
339         // Add the element
340         final String value = "value";
341         element = new Element("key", value);
342         diskStore.put(element);
343 
344         // Get the element
345         assertEquals(1, diskStore.getSize());
346         element = diskStore.get("key");
347         assertNotNull(element);
348         assertEquals(value, element.getObjectValue());
349     }
350 
351     /**
352      * Tests adding an entry and waiting for it to be written.
353      */
354     public void testPutSlow() throws Exception {
355         final DiskStore diskStore = createDiskStore();
356 
357         // Make sure the element is not found
358         assertEquals(0, diskStore.getSize());
359         Element element = diskStore.get("key");
360         assertNull(element);
361 
362         // Add the element
363         final String value = "value";
364         element = new Element("key", value);
365         diskStore.put(element);
366 
367         // Wait
368         waitForFlush(diskStore);
369 
370         // Get the element
371         assertEquals(1, diskStore.getSize());
372         element = diskStore.get("key");
373         assertNotNull(element);
374         assertEquals(value, element.getObjectValue());
375     }
376 
377     /**
378      * Tests removing an entry.
379      */
380     public void testRemove() throws Exception {
381         final DiskStore diskStore = createDiskStore();
382 
383         // Add the entry
384         final String value = "value";
385         Element element = new Element("key", value);
386         diskStore.put(element);
387 
388         // Check the entry is there
389         assertEquals(1, diskStore.getSize());
390         element = diskStore.get("key");
391         assertNotNull(element);
392 
393         // Remove it
394         diskStore.remove("key");
395 
396         // Check the entry is not there
397         assertEquals(0, diskStore.getSize());
398         element = diskStore.get("key");
399         assertNull(element);
400     }
401 
402     /**
403      * Tests removing an entry, after it has been written
404      */
405     public void testRemoveSlow() throws Exception {
406         final DiskStore diskStore = createDiskStore();
407 
408         // Add the entry
409         final String value = "value";
410         Element element = new Element("key", value);
411         diskStore.put(element);
412 
413         // Wait for the entry
414         waitForFlush(diskStore);
415 
416         // Check the entry is there
417         assertEquals(1, diskStore.getSize());
418         element = diskStore.get("key");
419         assertNotNull(element);
420 
421         // Remove it
422         diskStore.remove("key");
423 
424         // Check the entry is not there
425         assertEquals(0, diskStore.getSize());
426         element = diskStore.get("key");
427         assertNull(element);
428     }
429 
430     /**
431      * Tests removing all the entries.
432      */
433     public void testRemoveAll() throws Exception {
434         final DiskStore diskStore = createDiskStore();
435 
436         // Add the entry
437         final String value = "value";
438         Element element = new Element("key", value);
439         diskStore.put(element);
440 
441         // Check the entry is there
442         element = diskStore.get("key");
443         assertNotNull(element);
444 
445         // Remove it
446         diskStore.removeAll();
447 
448         // Check the entry is not there
449         assertEquals(0, diskStore.getSize());
450         element = diskStore.get("key");
451         assertNull(element);
452     }
453 
454     /**
455      * Tests removing all the entries, after they have been written to disk.
456      */
457     public void testRemoveAllSlow() throws Exception {
458         final DiskStore diskStore = createDiskStore();
459 
460         // Add the entry
461         final String value = "value";
462         Element element = new Element("key", value);
463         diskStore.put(element);
464 
465         // Wait
466         waitForFlush(diskStore);
467 
468         // Check the entry is there
469         element = diskStore.get("key");
470         assertNotNull(element);
471 
472         // Remove it
473         diskStore.removeAll();
474 
475         // Check the entry is not there
476         assertEquals(0, diskStore.getSize());
477         element = diskStore.get("key");
478         assertNull(element);
479     }
480 
481     /**
482      * Tests bulk load.
483      */
484     public void testBulkLoad() throws Exception {
485         final DiskStore diskStore = createDiskStore();
486 
487         final Random random = new Random();
488 
489         // Add a bunch of entries
490         for (int i = 0; i < 500; i++) {
491             // Use a random length value
492             final String key = "key" + i;
493             final String value = "This is a value" + random.nextInt(1000);
494 
495             // Add an element, and make sure it is present
496             Element element = new Element(key, value);
497             diskStore.put(element);
498             element = diskStore.get(key);
499             assertNotNull(element);
500 
501             // Chuck in a delay, to give the spool thread a chance to catch up
502             Thread.sleep(2);
503 
504             // Remove the element
505             diskStore.remove(key);
506             element = diskStore.get(key);
507             assertNull(element);
508 
509             element = new Element(key, value);
510             diskStore.put(element);
511             element = diskStore.get(key);
512             assertNotNull(element);
513 
514             // Chuck in a delay
515             Thread.sleep(2);
516         }
517     }
518 
519     /**
520      * Tests for element expiry.
521      */
522     public void testExpiry() throws Exception {
523         // Create a diskStore with a cranked up expiry thread
524         final DiskStore diskStore = createDiskStore();
525 
526         // Add an element that will expire.
527         Element element = new Element("key", "value");
528         diskStore.put(element);
529         assertEquals(1, diskStore.getSize());
530 
531         assertNotNull(diskStore.get("key"));
532 
533 
534         waitForFlush(diskStore);
535 
536         // Wait a couple of seconds
537         Thread.sleep(3000);
538 
539         assertNull(diskStore.get("key"));
540 
541     }
542 
543     /**
544      * Waits for all spooled elements to be written to disk.
545      */
546     private static void waitForFlush(DiskStore diskStore) throws InterruptedException {
547         while (true) {
548             if (diskStore.isSpoolEmpty()) {
549                 //Do not return until spool is empty
550                 return;
551             } else {
552                 //Wait for 100ms before checking again
553                 Thread.sleep(5);
554             }
555         }
556     }
557 
558     /**
559      * Multi-thread read-only test. Will fail on memory constrained VMs
560      */
561     public void testReadOnlyMultipleThreads() throws Exception {
562         final DiskStore diskStore = createNonExpiringDiskStore();
563 
564         // Add a couple of elements
565         diskStore.put(new Element("key0", "value"));
566         diskStore.put(new Element("key1", "value"));
567 
568         // Wait for the elements to be written
569         waitForFlush(diskStore);
570 
571         // Run a set of threads, that attempt to fetch the elements
572         final List executables = new ArrayList();
573         for (int i = 0; i < 10; i++) {
574             final String key = "key" + (i % 2);
575             final Executable executable = new Executable() {
576                 public void execute() throws Exception {
577                     final Element element = diskStore.get(key);
578                     assertNotNull(element);
579                     assertEquals("value", element.getObjectValue());
580                 }
581             };
582             executables.add(executable);
583         }
584         runThreads(executables);
585     }
586 
587     /**
588      * Multi-thread concurrent read remove test.
589      */
590     public void testReadRemoveMultipleThreads() throws Exception {
591         final Random random = new Random();
592         final DiskStore diskStore = createDiskStore();
593 
594         diskStore.put(new Element("key", "value"));
595 
596         // Run a set of threads that get, put and remove an entry
597         final List executables = new ArrayList();
598         for (int i = 0; i < 5; i++) {
599             final Executable executable = new Executable() {
600                 public void execute() throws Exception {
601                     for (int i = 0; i < 100; i++) {
602                         diskStore.put(new Element("key" + random.nextInt(100), "value"));
603                     }
604                 }
605             };
606             executables.add(executable);
607         }
608         for (int i = 0; i < 5; i++) {
609             final Executable executable = new Executable() {
610                 public void execute() throws Exception {
611                     for (int i = 0; i < 100; i++) {
612                         diskStore.remove("key" + random.nextInt(100));
613                     }
614                 }
615             };
616             executables.add(executable);
617         }
618 
619         runThreads(executables);
620     }
621 
622     /**
623      * Runs a set of threads, for a fixed amount of time.
624      */
625     private static void runThreads(final List executables) throws Exception {
626 
627         final long endTime = System.currentTimeMillis() + 3000;
628         final ArrayList errors = new ArrayList();
629 
630         // Spin up the threads
631         final Thread[] threads = new Thread[executables.size()];
632         for (int i = 0; i < threads.length; i++) {
633             final Executable executable = (Executable) executables.get(i);
634             threads[i] = new Thread() {
635                 public void run() {
636                     try {
637                         // Run the thread until the given end time
638                         while (System.currentTimeMillis() < endTime) {
639                             executable.execute();
640                         }
641                     } catch (Throwable t) {
642                         // Hang on to any errors
643                         LOG.error(t.getMessage(), t);
644                         errors.add(t);
645                     }
646                 }
647             };
648             threads[i].start();
649         }
650 
651         // Wait for the threads to finish
652         for (int i = 0; i < threads.length; i++) {
653             threads[i].join();
654         }
655 
656         // Fail if any error happened
657         if (errors.size() > 0) {
658             fail(errors.size() + " errors");
659         }
660     }
661 
662     /**
663      * A runnable, that can throw an exception.
664      */
665     private interface Executable {
666         /**
667          * Executes this object.
668          */
669         void execute() throws Exception;
670     }
671 
672     /**
673      * Tests how data is written to a random access file.
674      * <p/>
675      * It makes sure that bytes are immediately written to disk after a write.
676      */
677     public void testWriteToFile() throws IOException {
678         // Create and set up file
679         String dataFileName = "fileTest";
680         RandomAccessFile file = getRandomAccessFile(dataFileName);
681 
682         //write data to the file
683         byte[] buffer = new byte[1024];
684         for (int i = 0; i < 100; i++) {
685             file.write(buffer);
686         }
687 
688         assertEquals(1024 * 100, file.length());
689 
690     }
691 
692     private RandomAccessFile getRandomAccessFile(String name) throws FileNotFoundException {
693         String diskPath = System.getProperty("java.io.tmpdir");
694         final File diskDir = new File(diskPath);
695         File dataFile = new File(diskDir, name + ".data");
696         return new RandomAccessFile(dataFile, "rw");
697     }
698 
699     /**
700      * Test overflow to disk = true, using 100000 records.
701      * 15 seconds v1.38 DiskStore
702      * 2 seconds v1.42 DiskStore
703      * Adjusted for change to laptop
704      */
705     public void testOverflowToDiskWithLargeNumberofCacheEntries() throws Exception {
706 
707         //Set size so the second element overflows to disk.
708         Cache cache = new Cache("test", 1000, MemoryStoreEvictionPolicy.LRU, true, null, true, 500, 500, false, 1, null);
709         manager.addCache(cache);
710         int i = 0;
711         StopWatch stopWatch = new StopWatch();
712         for (; i < 100000; i++) {
713             cache.put(new Element("" + i,
714                     "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
715                             + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
716                             + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
717                             + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
718                             + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
719         }
720     }
721 
722     /**
723      * Test overflow to disk = true, using 100000 records.
724      * 35 seconds v1.38 DiskStore
725      * 26 seconds v1.42 DiskStore
726      */
727     public void testOverflowToDiskWithLargeNumberofCacheEntriesAndGets() throws Exception {
728 
729         //Set size so the second element overflows to disk.
730         Cache cache = new Cache("test", 1000, MemoryStoreEvictionPolicy.LRU, true, null, true, 500, 500, false, 60, null);
731         manager.addCache(cache);
732         Random random = new Random();
733         StopWatch stopWatch = new StopWatch();
734         for (int i = 0; i < 100000; i++) {
735             cache.put(new Element("" + i,
736                     "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
737                             + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
738                             + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
739                             + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
740                             + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
741 
742             cache.get("" + random.nextInt(100000));
743         }
744 
745 
746         long elapsed = stopWatch.getElapsedTime();
747         LOG.info("Elapsed time: " + elapsed / 1000);
748         assertEquals(100000, cache.getSize());
749         //Some entries may be in the Memory Store and Disk Store. cache.getSize removes dupes. a look at the
750         //disk store size directly does not.
751         assertTrue(99000 <= cache.getDiskStore().getSize());
752     }
753 
754 
755     /**
756      * Runs out of memory at 5,099,999 elements with the standard 64MB VM size.
757      * <p/>
758      * The reason that it is not infinite is because of a small amount of memory used (about 12 bytes) used for
759      * the disk store index in this case.
760      */
761     public void testMaximumCacheEntriesIn64MBWithOverflowToDisk() throws Exception {
762 
763         Cache cache = new Cache("test", 1000, MemoryStoreEvictionPolicy.LRU, true, null, true, 500, 500, false, 1, null);
764         manager.addCache(cache);
765         StopWatch stopWatch = new StopWatch();
766         int i = 0;
767         int j = 0;
768         Integer index = null;
769         try {
770             for (; i < 100; i++) {
771                 for (j = 0; j < 100000; j++) {
772                     index = new Integer(((1000000 * i) + j));
773                     cache.put(new Element(index,
774                             "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
775                                     + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
776                                     + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
777                                     + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
778                                     + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
779                 }
780                 //wait to write entries
781                 int size = cache.getSize();
782                 Thread.sleep(2000);
783             }
784             long elapsed = stopWatch.getElapsedTime();
785             LOG.info("Elapsed time: " + elapsed / 1000);
786             fail();
787         } catch (OutOfMemoryError e) {
788             LOG.info("Failed at " + index);
789             if (JVMUtil.isJDK15()) {
790                 assertTrue(index.intValue() > 5000000);
791             } else {
792                 assertTrue(index.intValue() > 4099000);
793             }
794         }
795     }
796 
797     /**
798      * Perf test used by Venkat Subramani
799      * Get took 119s with Cache svn21
800      * Get took 42s
801      * The change was to stop adding DiskStore retrievals into the MemoryStore. This made sense when the only
802      * policy was LRU. In the new version an Elment, once evicted from the MemoryStore, stays in the DiskStore
803      * until expiry or removal. This avoids a lot of serialization overhead.
804      */
805     public void testLargePutGetPerformanceWithOverflowToDisk() throws Exception {
806 
807         Cache cache = new Cache("test", 1000, MemoryStoreEvictionPolicy.LRU, true, null, true, 500, 500, false, 10000, null);
808         manager.addCache(cache);
809         StopWatch stopWatch = new StopWatch();
810         int i = 0;
811         int j = 0;
812         Integer index = null;
813         for (; i < 5; i++) {
814             for (j = 0; j < 100000; j++) {
815                 index = new Integer(((1000000 * i) + j));
816                 cache.put(new Element(index,
817                         "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
818                                 + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
819                                 + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
820                                 + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
821                                 + "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
822             }
823             //wait to write entries
824             Thread.sleep(2000);
825         }
826         long elapsed = stopWatch.getElapsedTime();
827         long putTime = ((elapsed / 1000) - 10);
828         LOG.info("Put Elapsed time: " + putTime);
829         assertTrue(putTime < 8);
830 
831         //wait for Disk Store to finish spooling
832         Thread.sleep(2000);
833         Random random = new Random();
834         StopWatch getStopWatch = new StopWatch();
835         long getStart = stopWatch.getElapsedTime();
836 
837         for (int k = 0; k < 1000000; k++) {
838             Integer key = new Integer(random.nextInt(500000));
839             cache.get(key);
840         }
841 
842         long getElapsedTime = getStopWatch.getElapsedTime();
843         int time = (int) ((getElapsedTime - getStart) / 1000);
844         LOG.info("Get Elapsed time: " + time);
845 
846         assertTrue(time < 200);
847     }
848 }