KickJava   Java API By Example, From Geeks To Geeks.

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


1 package org.jboss.cache.tests.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.PropertyConfigurator;
10 import org.jboss.cache.TreeCache;
11 import org.jboss.cache.lock.IsolationLevel;
12 import org.jboss.cache.lock.TimeoutException;
13 import org.jboss.cache.transaction.DummyTransactionManager;
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  *
25  * Unit test for local TreeCache with concurrent transactions.
26  * Uses locking and multiple threads to test concurrent r/w access to the tree.
27  *
28  * @author <a HREF="mailto:spohl@users.sourceforge.net">Stefan Pohl</a>
29  * @author Ben Wang
30  * @version $Revision: 1.2 $
31  *
32  */

33 public class ConcurrentBankTest extends TestCase {
34    TreeCache cache;
35    private static Log logger_=LogFactory.getLog(ConcurrentBankTest.class);
36    static Properties JavaDoc p = null;
37    String JavaDoc old_factory = null;
38    final String JavaDoc FACTORY = "org.jboss.cache.transaction.DummyContextFactory";
39    final String JavaDoc NODE = "/cachetest";
40    final int ROLLBACK_CHANCE = 100;
41
42    static String JavaDoc customer[] = { "cu1", "cu2", "cu3" };
43    static final int BOOKINGS = 1000;
44    static boolean _testFailedinThread = false;
45
46    public ConcurrentBankTest(String JavaDoc name)
47    {
48       super(name);
49    }
50
51    public void failMain() {
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          p = new Properties JavaDoc();
63          p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.cache.transaction.DummyContextFactory");
64       }
65
66       cache = new TreeCache();
67
68       PropertyConfigurator config = new PropertyConfigurator();
69       config.configure(cache, "META-INF/local-eviction-service.xml");
70
71       // XML file above only sets REPEATABLE-READ
72
cache.setIsolationLevel(IsolationLevel.SERIALIZABLE);
73
74       cache.createService();
75       cache.startService();
76    }
77
78    public void tearDown() throws Exception JavaDoc
79    {
80       super.tearDown();
81       cache.stopService();
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          System.setProperty(Context.INITIAL_CONTEXT_FACTORY, old_factory);
86          old_factory = null;
87       }
88    }
89
90    public void testConcurrentBooking()
91    {
92       Teller one, two;
93       try {
94          if(cache.get(NODE)==null) {
95             cache.put(NODE, "cu1", new Integer JavaDoc(1000));
96             cache.put(NODE, "cu2", new Integer JavaDoc(1000));
97             cache.put(NODE, "cu3", new Integer JavaDoc(1000));
98          }
99
100          one = new Teller("one", cache);
101          two = new Teller("two", cache);
102
103          one.start();
104          sleep(100);
105          two.start();
106          one.join();
107          two.join();
108
109          log("lock info:\n" + cache.printLockInfo()+_testFailedinThread);
110          if(_testFailedinThread) fail();
111       } catch (Exception JavaDoc e) {
112          e.printStackTrace();
113          fail(e.toString());
114       } finally {
115          /*
116          try {
117             cache.remove(NODE);
118          } catch (Exception e) {
119             e.printStackTrace();
120             fail();
121          }
122          */

123       }
124    }
125
126    void sleep(long timeout)
127    {
128       try {
129          Thread.sleep(timeout);
130       } catch (InterruptedException JavaDoc e) {
131       }
132    }
133
134    static void log(String JavaDoc msg)
135    {
136 // System.out.println("-- [" + Thread.currentThread() + "]: " + msg);
137
logger_.info("-- [" + Thread.currentThread() + "]: " + msg);
138    }
139
140    public static Test suite()
141    {
142       return new TestSuite(ConcurrentBankTest.class);
143    }
144
145    public static void main(String JavaDoc[] args)
146    {
147       junit.textui.TestRunner.run(suite());
148    }
149
150    class Teller extends Thread JavaDoc
151    {
152       TreeCache cache;
153
154       public Teller(String JavaDoc str, TreeCache cache)
155       {
156          super(str);
157          this.cache = cache;
158       }
159
160       public void run()
161       {
162          int count = customer.length;
163          UserTransaction JavaDoc tx = null;
164          try {
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                if(!again) {
174                   src = (int) (Math.random()*count);
175                   dst = (int) (Math.random()*(count-1));
176                   amo =1+ (int) (Math.random()*20);
177                   if(dst>=src) dst++;
178                }
179
180                tx.begin();
181                HashMap JavaDoc accounts = getAccounts(); // read lock on NODE
182
tx.commit(); // releases read lock
183

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

220       public void deposit(String JavaDoc from, String JavaDoc to, int amount, UserTransaction JavaDoc tx) throws Exception JavaDoc {
221          log("deposit("+from+", "+to+", "+amount+") called.");
222          int act;
223          // debit
224
act = ((Integer JavaDoc) cache.get(NODE, from)).intValue();
225          cache.put(NODE, from, new Integer JavaDoc(act-amount));
226          log("deposit("+from+", "+to+", "+amount+") debited.");
227
228          // eventually rollback the transaction
229
if((int) (Math.random()*ROLLBACK_CHANCE) == 0) {
230             log("!!!manually set rollback ("+from+", "+to+", "+amount+").");
231             tx.setRollbackOnly();
232             throw new Exception JavaDoc("Manually set rollback!");
233          }
234
235          // credit
236
act = ((Integer JavaDoc) cache.get(NODE, to)).intValue();
237          cache.put(NODE, to, new Integer JavaDoc(act+amount));
238
239          log("deposit("+from+", "+to+", "+amount+") finished.");
240       }
241       /**
242        * retrieving amounts of accounts
243        */

244       public HashMap JavaDoc getAccounts() throws CacheException {
245          log("getAccounts() called.");
246          HashMap JavaDoc result = new HashMap JavaDoc();
247          try {
248             Set JavaDoc set = cache.getKeys(NODE); // gets read lock
249
Iterator JavaDoc iter = set.iterator();
250             while(iter.hasNext()) {
251                String JavaDoc name = (String JavaDoc) iter.next();
252                result.put(name, cache.get(NODE, name));
253             }
254             return result;
255          } catch(CacheException ce) {
256             throw ce;
257          }
258       }
259       protected int sumAccounts(HashMap JavaDoc map) {
260          Iterator JavaDoc iter = map.values().iterator();
261          int result = 0;
262          while(iter.hasNext()) {
263             result += ((Integer JavaDoc) iter.next()).intValue();
264          }
265          return result;
266       }
267    }
268 }
269
Popular Tags