1 package org.apache.ojb.broker; 2 3 import org.apache.commons.lang.SerializationUtils; 4 import org.apache.ojb.broker.util.logging.LoggerFactory; 5 import org.apache.ojb.junit.JUnitExtensions; 6 7 15 public class OptimisticLockingMultithreadedTest extends JUnitExtensions.MultiThreadedTestCase 16 { 17 private static int threadCount; 18 static final String msg = "Thread write order: "; 19 20 public static void main(String [] args) 21 { 22 String [] arr = {OptimisticLockingMultithreadedTest.class.getName()}; 23 junit.textui.TestRunner.main(arr); 24 } 25 26 public OptimisticLockingMultithreadedTest(String s) 27 { 28 super(s); 29 } 30 31 protected void setUp() throws Exception 32 { 33 super.setUp(); 34 } 35 36 protected void tearDown() throws Exception 37 { 38 super.tearDown(); 39 } 40 41 public void testLockingOfObject() throws Exception 42 { 43 LockedByVersion targetObject = createLockedByVersion(); 44 storeObject(targetObject); 45 46 int threads = 6; 48 int objectUpdates = 20; 50 51 TestCaseRunnable tct [] = new TestCaseRunnable[threads]; 52 for (int i = 0; i < threads; i++) 53 { 54 58 if (i % 2 == 0) 59 tct[i] = new LockHandle(targetObject, objectUpdates); 60 else 61 tct[i] = new LockHandle( 62 (LockedByVersion) SerializationUtils.clone(targetObject), objectUpdates); 63 } 64 System.out.println("*** START - Multithreaded lock test ***"); 65 System.out.println("Number of concurrent threads: " + threads); 66 System.out.println("Number of object updates per thread: " + objectUpdates); 67 System.out.println("Each thread try to update the same object. If an OptimisticLockException" + 68 " was thrown, the thread wait and try later again (200 attempts, then fail)"); 69 runTestCaseRunnables(tct); 71 System.out.println(targetObject.getValue()); 72 System.out.println("An '-' indicate write success at first attempt"); 73 System.out.println("An '+' indicate write success after several OptimisticLockException"); 74 System.out.println("*** END - Multithreaded lock test ***"); 75 } 76 77 private LockedByVersion createLockedByVersion() 78 { 79 int number = newThreadKey(); 80 LockedByVersion lo = new LockedByVersion(); 81 lo.setValue(msg + number); 82 return lo; 83 } 84 85 private void storeObject(Object obj) throws Exception 86 { 87 PersistenceBroker broker = PersistenceBrokerFactory.defaultPersistenceBroker(); 88 try 89 { 90 broker.beginTransaction(); 91 broker.store(obj); 92 broker.commitTransaction(); 93 } 94 finally 95 { 96 if(broker != null) broker.close(); 97 } 98 } 99 100 public static synchronized int newThreadKey() 101 { 102 return threadCount++; 103 } 104 105 109 class LockHandle extends TestCaseRunnable 110 { 111 LockedByVersion obj; 112 int threadNumber; 113 int objectUpdates = 30; 114 115 public LockHandle(LockedByVersion obj, int objectUpdates) 116 { 117 super(); 118 this.objectUpdates = objectUpdates; 119 this.obj = obj; 120 } 121 122 public void runTestCase() throws Throwable 123 { 124 threadNumber = newThreadKey(); 125 for (int i = 0; i < objectUpdates; i++) 126 { 127 updateObject(obj, false); 128 } 129 } 130 131 private int counter = 0; 132 private static final int maxAttempts = 200; 133 private static final int nearMax = (int) (maxAttempts * 0.9); 134 135 private void updateObject(LockedByVersion obj, boolean LNGEthrown) throws Exception 136 { 137 PersistenceBroker broker = PersistenceBrokerFactory.defaultPersistenceBroker(); 138 try 139 { 140 broker.beginTransaction(); 141 updateName(obj, LNGEthrown); 142 broker.store(obj); 143 broker.commitTransaction(); 144 } 145 catch (OptimisticLockException e) 146 { 147 if(broker != null) 148 { 149 broker.abortTransaction(); 150 broker.close(); 151 } 152 if (counter < maxAttempts) 154 { 155 counter++; 156 if (counter > nearMax) 157 LoggerFactory.getDefaultLogger().warn("OptimisticLockingMultithreadedTest: thread " 158 + threadNumber + " waits " + counter 159 + " times to update object. Maximal attempts before fail are " + maxAttempts 160 + ". This can be a result of low hardware."); 161 Thread.sleep(10); 162 PersistenceBroker pb = PersistenceBrokerFactory.defaultPersistenceBroker(); 163 LockedByVersion temp; 164 try 165 { 166 Identity oid = pb.serviceIdentity().buildIdentity(obj); 168 temp = (LockedByVersion) pb.getObjectByIdentity(oid); 169 } 170 finally 171 { 172 if(pb != null) pb.close(); 173 } 174 updateObject(temp, true); 175 } 176 else 177 { 178 LoggerFactory.getDefaultLogger().error("* Can't lock given object, will throw exception" + 179 " for thread number " + threadNumber + " *"); 180 throw e; 181 } 182 } 183 finally 184 { 185 counter = 0; 186 if(broker != null) 187 { 188 broker.close(); 189 } 190 } 191 } 192 193 private void updateName(LockedByVersion obj, boolean LNGEthrown) 194 { 195 String token; 196 if(LNGEthrown) 197 { 198 token = "+"; 199 } 200 else 201 { 202 token = "-"; 203 } 204 if (obj.getValue().length() < 120) 205 { 206 obj.setValue(obj.getValue() + token + threadNumber); 207 } 208 else 209 { 210 System.out.println(obj.getValue()); 211 obj.setValue(msg + threadNumber); 212 } 213 } 214 } 215 } 216 | Popular Tags |