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 ; 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 31 public class ConcurrentBankTest extends TestCase 32 { 33 CacheImpl cache; 34 private static Log logger_ = LogFactory.getLog(ConcurrentBankTest.class); 35 static Properties p = null; 36 String old_factory = null; 37 final String FACTORY = "org.jboss.cache.transaction.DummyContextFactory"; 38 final String NODE = "/cachetest"; 39 final int ROLLBACK_CHANCE = 100; 40 41 static String customer[] = {"cu1", "cu2", "cu3"}; 42 static final int BOOKINGS = 1000; 43 static boolean _testFailedinThread = false; 44 45 public ConcurrentBankTest(String name) 46 { 47 super(name); 48 } 49 50 public void failMain() 51 { 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 { 63 p = new Properties (); 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 cache.getConfiguration().setIsolationLevel(IsolationLevel.SERIALIZABLE); 73 74 cache.create(); 75 cache.start(); 76 } 77 78 public void tearDown() throws Exception 79 { 80 super.tearDown(); 81 cache.stop(); 82 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 e) 116 { 117 e.printStackTrace(); 118 fail(e.toString()); 119 } 120 finally 121 { 122 130 } 131 } 132 133 static void log(String msg) 134 { 135 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 [] args) 145 { 146 junit.textui.TestRunner.run(suite()); 147 } 148 149 class Teller extends Thread 150 { 151 CacheImpl cache; 152 153 public Teller(String 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 tx = null; 163 try 164 { 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 { 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 accounts = getAccounts(); tx.commit(); 186 int sum = sumAccounts(accounts); 187 log(anz + ": " + accounts + " Summe: " + sum); 188 if (sum != 3000) 190 { 191 failMain(); 192 return; } 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); tx.commit(); 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 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 t) 220 { 221 t.printStackTrace(); 222 fail(t.toString()); 223 } 224 } 225 226 229 public void deposit(String from, String to, int amount, UserTransaction tx) throws Exception 230 { 231 log("deposit(" + from + ", " + to + ", " + amount + ") called."); 232 int act; 233 act = (Integer ) cache.get(NODE, from); 235 cache.put(NODE, from, act - amount); 236 log("deposit(" + from + ", " + to + ", " + amount + ") debited."); 237 238 if ((int) (Math.random() * ROLLBACK_CHANCE) == 0) 240 { 241 log("!!!manually set rollback (" + from + ", " + to + ", " + amount + ")."); 242 tx.setRollbackOnly(); 243 throw new Exception ("Manually set rollback!"); 244 } 245 246 act = (Integer ) cache.get(NODE, to); 248 cache.put(NODE, to, act + amount); 249 250 log("deposit(" + from + ", " + to + ", " + amount + ") finished."); 251 } 252 253 256 public HashMap getAccounts() throws CacheException 257 { 258 log("getAccounts() called."); 259 HashMap result = new HashMap (); 260 try 261 { 262 Set set = cache.getKeys(NODE); Iterator iter = set.iterator(); 264 while (iter.hasNext()) 265 { 266 String name = (String ) 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 map) 278 { 279 Iterator iter = map.values().iterator(); 280 int result = 0; 281 while (iter.hasNext()) 282 { 283 result += (Integer ) iter.next(); 284 } 285 return result; 286 } 287 } 288 } 289 | Popular Tags |