KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > test > cache > test > local > TxConcurrentBankUnitTestCase


1 /*
2 * JBoss, the OpenSource J2EE webOS
3 *
4 * Distributable under LGPL license.
5 * See terms of license at gnu.org.
6 */

7 package org.jboss.test.cache.test.local;
8
9 import junit.framework.Test;
10 import junit.framework.TestCase;
11 import junit.framework.TestSuite;
12 import org.jboss.cache.CacheException;
13 import org.jboss.cache.PropertyConfigurator;
14 import org.jboss.cache.TreeCache;
15 import org.jboss.cache.lock.IsolationLevel;
16 import org.jboss.cache.lock.TimeoutException;
17 import org.jboss.cache.transaction.DummyTransactionManager;
18 import org.jboss.logging.Logger;
19
20 import javax.naming.Context JavaDoc;
21 import javax.naming.InitialContext JavaDoc;
22 import javax.transaction.UserTransaction JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Properties JavaDoc;
26 import java.util.Set JavaDoc;
27
28 /**
29  *
30  * Unit test for local TreeCache with concurrent transactions.
31  * Uses locking and multiple threads to test concurrent r/w access to the tree.
32  *
33  * @author <a HREF="mailto:spohl@users.sourceforge.net">Stefan Pohl</a>
34  * @author Ben Wang
35  * @version $Revision: 1.6.4.2 $
36  *
37  */

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

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

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

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

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