001: /*
002: * Copyright (c) 2002-2007 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.oscache.general;
006:
007: import java.util.Properties;
008:
009: import org.apache.commons.logging.Log;
010: import org.apache.commons.logging.LogFactory;
011:
012: import com.opensymphony.oscache.base.AbstractCacheAdministrator;
013: import com.opensymphony.oscache.base.NeedsRefreshException;
014:
015: import junit.framework.Test;
016: import junit.framework.TestCase;
017: import junit.framework.TestSuite;
018:
019: /**
020: * Testing concurrent API accesses.
021: *
022: * @author $Author: larst $
023: * @version $Revision: 385 $
024: */
025: public class TestConcurrent extends TestCase {
026:
027: private static transient final Log log = LogFactory
028: .getLog(GeneralCacheAdministrator.class); //TestConcurrency.class
029:
030: // Static instance of a cache administrator
031: private GeneralCacheAdministrator admin = null;
032:
033: // Constants needed in the tests
034: private final String KEY = "ConcurrentKey";
035: private final String VALUE = "ConcurrentContent";
036: private static final int THREAD_COUNT = 5;
037: private static final int CACHE_SIZE_THREAD = 2000;
038: private static final int CACHE_SIZE = THREAD_COUNT
039: * CACHE_SIZE_THREAD;
040:
041: public TestConcurrent(String str) {
042: super (str);
043: }
044:
045: /**
046: * This methods returns the name of this test class to JUnit
047: * <p>
048: * @return The name of this class
049: */
050: public static Test suite() {
051: return new TestSuite(TestConcurrent.class);
052: }
053:
054: /**
055: * This method is invoked before each testXXXX methods of the
056: * class. It set ups the variables required for each tests.
057: */
058: public void setUp() {
059: // At first invocation, create a new Cache
060: if (admin == null) {
061: Properties config = new Properties();
062: config.setProperty(
063: AbstractCacheAdministrator.CACHE_CAPACITY_KEY,
064: Integer.toString(CACHE_SIZE));
065: admin = new GeneralCacheAdministrator(config);
066: assertNotNull(admin);
067: log.info("Cache Size = " + admin.getCache().getSize());
068: }
069: }
070:
071: /**
072: * Tests concurrent accesses.
073: * @see http://jira.opensymphony.com/browse/CACHE-279
074: */
075: public void testConcurrentCreation10000() {
076: Thread[] thread = new Thread[THREAD_COUNT];
077:
078: log.info("Ramping threads...");
079: for (int idx = 0; idx < THREAD_COUNT; idx++) {
080: CreationTest runner = new CreationTest(idx);
081: thread[idx] = new Thread(runner);
082: thread[idx].start();
083: }
084:
085: log.info("Waiting....");
086: boolean stillAlive;
087: do {
088: try {
089: Thread.sleep(200);
090: } catch (InterruptedException e) {
091: // do nothing
092: }
093:
094: stillAlive = false;
095: for (int i = 0; i < thread.length; i++) {
096: stillAlive |= thread[i].isAlive();
097: }
098: } while (stillAlive);
099: log.info("All threads finished. Cache Size = "
100: + admin.getCache().getSize());
101:
102: assertTrue("Unexpected amount of objects in the cache: "
103: + admin.getCache().getSize(), CACHE_SIZE == admin
104: .getCache().getSize());
105: }
106:
107: private class CreationTest implements Runnable {
108:
109: private String prefixKey;
110:
111: public CreationTest(int idx) {
112: prefixKey = KEY + "_" + Integer.toString(idx) + "_";
113: Thread.currentThread().setName("CreationTest-" + idx);
114: log.info(Thread.currentThread().getName()
115: + " is running...");
116: }
117:
118: public void run() {
119: for (int i = 0; i < CACHE_SIZE_THREAD; i++) {
120: String key = prefixKey + Integer.toString(i);
121: try {
122: // Get from the cache
123: admin.getFromCache(key);
124: } catch (NeedsRefreshException nre) {
125: // Get the value
126: // Store in the cache
127: admin.putInCache(key, VALUE);
128: }
129: }
130: log.info(Thread.currentThread().getName() + " finished.");
131: }
132: }
133:
134: }
|