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 ; 16 import javax.naming.InitialContext ; 17 import javax.transaction.UserTransaction ; 18 import java.util.HashMap ; 19 import java.util.Iterator ; 20 import java.util.Properties ; 21 import java.util.Set ; 22 23 33 public class ConcurrentBankTest extends TestCase { 34 TreeCache cache; 35 private static Log logger_=LogFactory.getLog(ConcurrentBankTest.class); 36 static Properties p = null; 37 String old_factory = null; 38 final String FACTORY = "org.jboss.cache.transaction.DummyContextFactory"; 39 final String NODE = "/cachetest"; 40 final int ROLLBACK_CHANCE = 100; 41 42 static String customer[] = { "cu1", "cu2", "cu3" }; 43 static final int BOOKINGS = 1000; 44 static boolean _testFailedinThread = false; 45 46 public ConcurrentBankTest(String name) 47 { 48 super(name); 49 } 50 51 public void failMain() { 52 _testFailedinThread=true; 53 } 54 55 public void setUp() throws Exception 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 (); 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 cache.setIsolationLevel(IsolationLevel.SERIALIZABLE); 73 74 cache.createService(); 75 cache.startService(); 76 } 77 78 public void tearDown() throws Exception 79 { 80 super.tearDown(); 81 cache.stopService(); 82 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 (1000)); 96 cache.put(NODE, "cu2", new Integer (1000)); 97 cache.put(NODE, "cu3", new Integer (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 e) { 112 e.printStackTrace(); 113 fail(e.toString()); 114 } finally { 115 123 } 124 } 125 126 void sleep(long timeout) 127 { 128 try { 129 Thread.sleep(timeout); 130 } catch (InterruptedException e) { 131 } 132 } 133 134 static void log(String msg) 135 { 136 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 [] args) 146 { 147 junit.textui.TestRunner.run(suite()); 148 } 149 150 class Teller extends Thread 151 { 152 TreeCache cache; 153 154 public Teller(String 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 tx = null; 164 try { 165 tx = (UserTransaction ) new InitialContext (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 accounts = getAccounts(); tx.commit(); 184 int sum = sumAccounts(accounts); 185 log(anz+": "+accounts+" Summe: "+sum); 186 if(sum!=3000) { 188 failMain(); 189 return; } 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); tx.commit(); 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 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 t) { 213 t.printStackTrace(); 214 fail(t.toString()); 215 } 216 } 217 220 public void deposit(String from, String to, int amount, UserTransaction tx) throws Exception { 221 log("deposit("+from+", "+to+", "+amount+") called."); 222 int act; 223 act = ((Integer ) cache.get(NODE, from)).intValue(); 225 cache.put(NODE, from, new Integer (act-amount)); 226 log("deposit("+from+", "+to+", "+amount+") debited."); 227 228 if((int) (Math.random()*ROLLBACK_CHANCE) == 0) { 230 log("!!!manually set rollback ("+from+", "+to+", "+amount+")."); 231 tx.setRollbackOnly(); 232 throw new Exception ("Manually set rollback!"); 233 } 234 235 act = ((Integer ) cache.get(NODE, to)).intValue(); 237 cache.put(NODE, to, new Integer (act+amount)); 238 239 log("deposit("+from+", "+to+", "+amount+") finished."); 240 } 241 244 public HashMap getAccounts() throws CacheException { 245 log("getAccounts() called."); 246 HashMap result = new HashMap (); 247 try { 248 Set set = cache.getKeys(NODE); Iterator iter = set.iterator(); 250 while(iter.hasNext()) { 251 String name = (String ) 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 map) { 260 Iterator iter = map.values().iterator(); 261 int result = 0; 262 while(iter.hasNext()) { 263 result += ((Integer ) iter.next()).intValue(); 264 } 265 return result; 266 } 267 } 268 } 269 | Popular Tags |