View Javadoc
1   package org.apache.commons.jcs;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.ArrayList;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.concurrent.atomic.AtomicInteger;
26  
27  import junit.framework.TestCase;
28  
29  import org.apache.commons.jcs.access.GroupCacheAccess;
30  import org.apache.commons.jcs.access.exception.CacheException;
31  
32  /**
33   * Test Case for JCS-73, modeled after the Groovy code by Alexander Kleymenov
34   *
35   * @author Thomas Vandahl
36   *
37   */
38  public class JCSConcurrentCacheAccessUnitTest extends TestCase
39  {
40      private final static int THREADS = 10;
41      private final static int LOOPS = 10000;
42  
43      /**
44       * the cache instance
45       */
46      protected GroupCacheAccess<Integer, String> cache;
47  
48      /**
49       * the group name
50       */
51      protected String group = "group";
52  
53      /**
54       * the error count
55       */
56      protected AtomicInteger errcount;
57  
58      /**
59       * Collect all value mismatches
60       */
61      protected List<String> valueMismatchList;
62  
63      @Override
64  	protected void setUp() throws Exception
65  	{
66          super.setUp();
67          JCS.setConfigFilename( "/TestJCS-73.ccf" );
68          cache = JCS.getGroupCacheInstance( "cache" );
69          errcount = new AtomicInteger(0);
70          valueMismatchList = Collections.synchronizedList(new ArrayList<String>());
71  	}
72  
73      @Override
74      protected void tearDown()
75          throws Exception
76      {
77          super.tearDown();
78          cache.clear();
79          cache.dispose();
80      }
81  
82      /**
83       * Worker thread
84       */
85      protected class Worker extends Thread
86      {
87      	@Override
88  		public void run()
89  		{
90  			String name = getName();
91  
92  			for (int idx = 0; idx < LOOPS; idx++)
93  			{
94  				if (idx > 0)
95  				{
96  					// get previously stored value
97  		            String res = cache.getFromGroup(Integer.valueOf(idx-1), group);
98  
99  		            if (res == null)
100 		            {
101 		                // null value got inspite of the fact it was placed in cache!
102 		                System.out.println("ERROR: for " + idx + " in " + name);
103 		                errcount.incrementAndGet();
104 
105 		                // try to get the value again:
106 		                int n = 5;
107 		                while (n-- > 0)
108 		                {
109 		                    res = cache.getFromGroup(Integer.valueOf(idx-1), group);
110 		                    if (res != null)
111 		                    {
112 		                        // the value finally appeared in cache
113 		                    	System.out.println("ERROR FIXED for " + idx + ": " + res + " " + name);
114 		                    	errcount.decrementAndGet();
115 		                        break;
116 		                    }
117 
118 		                    System.out.println("ERROR STILL PERSISTS for " + idx + " in " + name);
119 		                    try
120 		                    {
121 								Thread.sleep(1000);
122 							}
123 		                    catch (InterruptedException e)
124 							{
125 								// continue
126 							}
127 		                }
128 		            }
129 
130 		            if (!String.valueOf(idx-1).equals(res))
131 		            {
132 		                valueMismatchList.add(String.format("Values do not match: %s - %s", String.valueOf(idx-1), res));
133 		            }
134 				}
135 
136 				 // put value in the cache
137 		        try
138 		        {
139 					cache.putInGroup(Integer.valueOf(idx), group, String.valueOf(idx));
140 				}
141 		        catch (CacheException e)
142 		        {
143 		        	// continue
144 				}
145 
146 //		        if ((idx % 1000) == 0)
147 //		        {
148 //		        	System.out.println(name + " " + idx);
149 //		        }
150 			}
151 
152 		}
153     }
154 
155 	/**
156      *
157      * @throws Exception
158      */
159     public void testConcurrentAccess()
160         throws Exception
161     {
162     	Worker[] worker = new Worker[THREADS];
163 
164         for (int i = 0; i < THREADS; i++)
165         {
166         	worker[i] = new Worker();
167         	worker[i].start();
168         }
169 
170         for (int i = 0; i < THREADS; i++)
171         {
172         	worker[i].join();
173         }
174 
175         assertEquals("Error count should be 0",  0, errcount.intValue());
176         for (String msg : valueMismatchList)
177         {
178             System.out.println(msg);
179         }
180         assertEquals("Value mismatch count should be 0",  0, valueMismatchList.size());
181     }
182 
183 }