KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > cache > transaction > ConcurrentBankTest


1 package org.jboss.cache.transaction;
2
3 import junit.framework.Test;
4 import junit.framework.TestCase;
5 import junit.framework.TestSuite;
6 import org.apache.commons.logging.Log;
7 import org.apache.commons.logging.LogFactory;
8 import org.jboss.cache.CacheException;
9 import org.jboss.cache.CacheImpl;
10 import org.jboss.cache.factories.XmlConfigurationParser;
11 import org.jboss.cache.lock.IsolationLevel;
12 import org.jboss.cache.lock.TimeoutException;
13 import org.jboss.cache.misc.TestingUtil;
14
15 import javax.naming.Context JavaDoc;
16 import javax.naming.InitialContext JavaDoc;
17 import javax.transaction.UserTransaction JavaDoc;
18 import java.util.HashMap JavaDoc;
19 import java.util.Iterator JavaDoc;
20 import java.util.Properties JavaDoc;
21 import java.util.Set JavaDoc;
22
23 /**
24  * Unit test for local CacheImpl with concurrent transactions.
25  * Uses locking and multiple threads to test concurrent r/w access to the tree.
26  *
27  * @author <a HREF="mailto:spohl@users.sourceforge.net">Stefan Pohl</a>
28  * @author Ben Wang
29  * @version $Revision: 1.8 $
30  */

31 public class ConcurrentBankTest extends TestCase
32 {
33    CacheImpl cache;
34    private static Log logger_ = LogFactory.getLog(ConcurrentBankTest.class);
35    static Properties JavaDoc p = null;
36    String JavaDoc old_factory = null;
37    final String JavaDoc FACTORY = "org.jboss.cache.transaction.DummyContextFactory";
38    final String JavaDoc NODE = "/cachetest";
39    final int ROLLBACK_CHANCE = 100;
40
41    static String JavaDoc customer[] = {"cu1", "cu2", "cu3"};
42    static final int BOOKINGS = 1000;
43    static boolean _testFailedinThread = false;
44
45    public ConcurrentBankTest(String JavaDoc name)
46    {
47       super(name);
48    }
49
50    public void failMain()
51    {
52       _testFailedinThread = true;
53    }
54
55    public void setUp() throws Exception JavaDoc
56    {
57       super.setUp();
58       old_factory = System.getProperty(Context.INITIAL_CONTEXT_FACTORY);
59       System.setProperty(Context.INITIAL_CONTEXT_FACTORY, FACTORY);
60       DummyTransactionManager.getInstance();
61       if (p == null)
62       {
63          p = new Properties JavaDoc();
64          p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
65       }
66
67       cache = new CacheImpl();
68
69       cache.setConfiguration(new XmlConfigurationParser().parseFile("META-INF/local-lru-eviction-service.xml"));
70
71       // XML file above only sets REPEATABLE-READ
72
cache.getConfiguration().setIsolationLevel(IsolationLevel.SERIALIZABLE);
73
74       cache.create();
75       cache.start();
76    }
77
78    public void tearDown() throws Exception JavaDoc
79    {
80       super.tearDown();
81       cache.stop();
82       // BW. kind of a hack to destroy jndi binding and thread local tx before next run.
83
DummyTransactionManager.destroy();
84       if (old_factory != null)
85       {
86          System.setProperty(Context.INITIAL_CONTEXT_FACTORY, old_factory);
87          old_factory = null;
88       }
89    }
90
91    public void testConcurrentBooking()
92    {
93       Teller one, two;
94       try
95       {
96          if (cache.get(NODE) == null)
97          {
98             cache.put(NODE, "cu1", 1000);
99             cache.put(NODE, "cu2", 1000);
100             cache.put(NODE, "cu3", 1000);
101          }
102
103          one = new Teller("one", cache);
104          two = new Teller("two", cache);
105
106          one.start();
107          TestingUtil.sleepThread((long) 100);
108          two.start();
109          one.join();
110          two.join();
111
112          log("lock info:\n" + cache.printLockInfo() + _testFailedinThread);
113          if (_testFailedinThread) fail();
114       }
115       catch (Exception JavaDoc e)
116       {
117          e.printStackTrace();
118          fail(e.toString());
119       }
120       finally
121       {
122          /*
123          try {
124             cache.remove(NODE);
125          } catch (Exception e) {
126             e.printStackTrace();
127             fail();
128          }
129          */

130       }
131    }
132
133    static void log(String JavaDoc msg)
134    {
135 // System.out.println("-- [" + Thread.currentThread() + "]: " + msg);
136
logger_.info("-- [" + Thread.currentThread() + "]: " + msg);
137    }
138
139    public static Test suite()
140    {
141       return new TestSuite(ConcurrentBankTest.class);
142    }
143
144    public static void main(String JavaDoc[] args)
145    {
146       junit.textui.TestRunner.run(suite());
147    }
148
149    class Teller extends Thread JavaDoc
150    {
151       CacheImpl cache;
152
153       public Teller(String JavaDoc str, CacheImpl cache)
154       {
155          super(str);
156          this.cache = cache;
157       }
158
159       public void run()
160       {
161          int count = customer.length;
162          UserTransaction JavaDoc tx = null;
163          try
164          {
165             tx = (UserTransaction JavaDoc) new InitialContext JavaDoc(p).lookup("UserTransaction");
166
167             boolean again = false;
168             int src = 0;
169             int dst = 0;
170             int amo = 0;
171             int anz = 0;
172             while (anz < BOOKINGS)
173             {
174                if (!again)
175                {
176                   src = (int) (Math.random() * count);
177                   dst = (int) (Math.random() * (count - 1));
178                   amo = 1 + (int) (Math.random() * 20);
179                   if (dst >= src) dst++;
180                }
181
182                tx.begin();
183                HashMap JavaDoc accounts = getAccounts(); // read lock on NODE
184
tx.commit(); // releases read lock
185

186                int sum = sumAccounts(accounts);
187                log(anz + ": " + accounts + " Summe: " + sum);
188                // the sum of all accounts always has to be 3000
189
if (sum != 3000)
190                {
191                   failMain();
192                   return; // terminate thread
193
}
194                assertEquals("the sum of all accounts always has to be 3000", 3000, sum);
195
196                try
197                {
198                   tx.begin();
199                   deposit(customer[src], customer[dst], amo, tx); // gets write lock
200
tx.commit(); // releases write lock
201
again = false;
202                }
203                catch (TimeoutException timeout_ex)
204                {
205                   System.out.println("transaction is rolled back, will try again (ex=" + timeout_ex.getClass() + ")");
206                   tx.rollback();
207                   again = true;
208                }
209                catch (Throwable JavaDoc e)
210                {
211                   System.out.println("transaction is rolled back, will try again (ex=" + e.getMessage() + ")");
212                   tx.rollback();
213                   again = true;
214                }
215                anz++;
216                yield();
217             }
218          }
219          catch (Throwable JavaDoc t)
220          {
221             t.printStackTrace();
222             fail(t.toString());
223          }
224       }
225
226       /**
227        * Posting
228        */

229       public void deposit(String JavaDoc from, String JavaDoc to, int amount, UserTransaction JavaDoc tx) throws Exception JavaDoc
230       {
231          log("deposit(" + from + ", " + to + ", " + amount + ") called.");
232          int act;
233          // debit
234
act = (Integer JavaDoc) cache.get(NODE, from);
235          cache.put(NODE, from, act - amount);
236          log("deposit(" + from + ", " + to + ", " + amount + ") debited.");
237
238          // eventually rollback the transaction
239
if ((int) (Math.random() * ROLLBACK_CHANCE) == 0)
240          {
241             log("!!!manually set rollback (" + from + ", " + to + ", " + amount + ").");
242             tx.setRollbackOnly();
243             throw new Exception JavaDoc("Manually set rollback!");
244          }
245
246          // credit
247
act = (Integer JavaDoc) cache.get(NODE, to);
248          cache.put(NODE, to, act + amount);
249
250          log("deposit(" + from + ", " + to + ", " + amount + ") finished.");
251       }
252
253       /**
254        * retrieving amounts of accounts
255        */

256       public HashMap JavaDoc getAccounts() throws CacheException
257       {
258          log("getAccounts() called.");
259          HashMap JavaDoc result = new HashMap JavaDoc();
260          try
261          {
262             Set JavaDoc set = cache.getKeys(NODE); // gets read lock
263
Iterator JavaDoc iter = set.iterator();
264             while (iter.hasNext())
265             {
266                String JavaDoc name = (String JavaDoc) iter.next();
267                result.put(name, cache.get(NODE, name));
268             }
269             return result;
270          }
271          catch (CacheException ce)
272          {
273             throw ce;
274          }
275       }
276
277       protected int sumAccounts(HashMap JavaDoc map)
278       {
279          Iterator JavaDoc iter = map.values().iterator();
280          int result = 0;
281          while (iter.hasNext())
282          {
283             result += (Integer JavaDoc) iter.next();
284          }
285          return result;
286       }
287    }
288 }
289
Popular Tags