1 package org.apache.ojb.odmg; 2 3 import org.apache.commons.lang.SystemUtils; 4 import org.apache.ojb.broker.TestHelper; 5 import org.apache.ojb.junit.JUnitExtensions; 6 import org.odmg.Database; 7 import org.odmg.Implementation; 8 import org.odmg.LockNotGrantedException; 9 import org.odmg.Transaction; 10 11 19 public class LockingMultithreadedTest extends JUnitExtensions.MultiThreadedTestCase 20 { 21 private static int threadCount; 22 private static Implementation odmg; 23 private static Database db; 24 private final StringBuffer result = new StringBuffer (2000); 25 private static final String eol = SystemUtils.LINE_SEPARATOR; 26 private final int concurrentThreads = 10; 28 private final int objectUpdates = 30; 30 private static final int maxAttempts = 100; 32 private static final int nearMax = (int) (maxAttempts * 0.75); 33 34 35 public static void main(String [] args) 36 { 37 String [] arr = {LockingMultithreadedTest.class.getName()}; 38 junit.textui.TestRunner.main(arr); 39 } 40 41 public LockingMultithreadedTest(String s) 42 { 43 super(s); 44 } 45 46 protected void setUp() throws Exception 47 { 48 super.setUp(); 49 } 50 51 protected void tearDown() throws Exception 52 { 53 super.tearDown(); 54 } 55 56 public void testLockingOfObject() throws Exception 57 { 58 62 odmg = OJB.getInstance(); 63 db = odmg.newDatabase(); 64 db.open(TestHelper.DEF_DATABASE_NAME, Database.OPEN_READ_WRITE); 65 66 LockObject targetObject = createLockObjectWithRef(); 67 storeObject(targetObject); 68 69 TestCaseRunnable tct [] = new TestCaseRunnable[concurrentThreads]; 70 for (int i = 0; i < concurrentThreads; i++) 71 { 72 76 if (i % 2 == 0) 77 tct[i] = new LockHandle(targetObject); 78 else 79 tct[i] = new LockHandle(targetObject.makeCopy()); 80 } 81 runTestCaseRunnables(tct); 83 System.out.println("*** Result of multithreaded lock test ***"); 84 System.out.println(result.toString()); 85 } 87 88 private LockObject createLockObjectWithRef() 89 { 90 int number = newThreadKey(); 91 LockObject lo = new LockObject(); 92 lo.setName("modified by thread: " + number); 93 94 LockObjectRef lor = new LockObjectRef(); 95 lor.setName("modified by thread: " + number); 96 97 lo.setReference(lor); 98 99 return lo; 100 } 101 102 private void storeObject(Object obj) throws Exception 103 { 104 Transaction tx = odmg.newTransaction(); 105 106 tx.begin(); 107 tx.lock(obj, Transaction.WRITE); 108 tx.commit(); 109 } 110 111 public static synchronized int newThreadKey() 112 { 113 return threadCount++; 114 } 115 116 120 class LockHandle extends JUnitExtensions.MultiThreadedTestCase.TestCaseRunnable 121 { 122 final LockObject obj; 123 int threadNumber; 124 private int counter = 0; 125 126 public LockHandle(LockObject obj) 127 { 128 super(); 129 this.obj = obj; 130 } 131 132 public void runTestCase() throws Throwable 133 { 134 threadNumber = newThreadKey(); 135 Transaction tx = odmg.newTransaction(); 136 for (int i = 0; i < objectUpdates; i++) 137 { 138 tx.begin(); 139 updateObject(tx, obj); 140 tx.commit(); 141 counter = 0; 142 } 143 } 144 145 private void updateObject(final Transaction tx, final LockObject obj) throws Exception 146 { 147 try 148 { 149 tx.lock(obj, Transaction.WRITE); 150 tx.lock(obj.getReference(), Transaction.WRITE); 151 updateName(obj); 152 updateName(obj.getReference()); 153 } 154 catch (LockNotGrantedException e) 155 { 156 if (counter < maxAttempts) 157 { 158 counter++; 159 if (counter > nearMax) 160 System.out.println("LockingMultithreadedTest: thread " 161 + threadNumber + " waits " + counter 162 + " times to update object. Maximal attempts before fail are " + maxAttempts 163 + ". This can be a result of low hardware."); 164 try 165 { 166 Thread.sleep(30); 167 } 168 catch(InterruptedException e1) 169 { 170 } 171 updateObject(tx, obj); 172 } 173 else 174 { 175 System.out.println("* Can't lock given object, will throw exception" + 176 " for thread number " + threadNumber + " *"); 177 throw e; 178 } 179 } 180 } 181 182 private void updateName(LockObject obj) 183 { 184 if (obj.getName().length() < 100) 185 { 186 obj.setName(obj.getName() + "-" + threadNumber); 187 } 188 else 189 { 190 result.append(eol).append(obj.getName()); 191 obj.setName("modified by thread: " + threadNumber); 192 } 193 } 194 195 private void updateName(LockObjectRef obj) 196 { 197 if (obj.getName().length() < 100) 198 { 199 obj.setName(obj.getName() + "-" + threadNumber); 200 } 201 else 202 { 203 obj.setName("modified by thread: " + threadNumber); 204 } 205 } 206 } 207 208 public static class LockObject 209 { 210 private Integer id; 211 private String name; 212 private Integer version; 213 private LockObjectRef reference; 214 215 public LockObject() 216 { 217 } 218 219 private LockObject(Integer id, String name, Integer version, LockObjectRef reference) 220 { 221 this.id = id; 222 this.name = name; 223 this.version = version; 224 this.reference = reference; 225 } 226 227 public LockObject makeCopy() 228 { 229 return new LockObject(id, name, version, reference != null ? reference.makeCopy() : null); 230 } 231 232 public Integer getId() 233 { 234 return id; 235 } 236 237 public void setId(Integer id) 238 { 239 this.id = id; 240 } 241 242 public String getName() 243 { 244 return name; 245 } 246 247 public void setName(String name) 248 { 249 this.name = name; 250 } 251 252 public Integer getVersion() 253 { 254 return version; 255 } 256 257 public void setVersion(Integer version) 258 { 259 this.version = version; 260 } 261 262 public LockObjectRef getReference() 263 { 264 return reference; 265 } 266 267 public void setReference(LockObjectRef reference) 268 { 269 this.reference = reference; 270 } 271 } 272 273 public static class LockObjectRef 274 { 275 private Integer id; 276 private String name; 277 private Integer version; 278 279 public LockObjectRef() 280 { 281 } 282 283 private LockObjectRef(Integer id, String name, Integer version) 284 { 285 this.id = id; 286 this.name = name; 287 this.version = version; 288 } 289 290 public LockObjectRef makeCopy() 291 { 292 return new LockObjectRef(id, name, version); 293 } 294 295 public Integer getId() 296 { 297 return id; 298 } 299 300 public void setId(Integer id) 301 { 302 this.id = id; 303 } 304 305 public String getName() 306 { 307 return name; 308 } 309 310 public void setName(String name) 311 { 312 this.name = name; 313 } 314 315 public Integer getVersion() 316 { 317 return version; 318 } 319 320 public void setVersion(Integer version) 321 { 322 this.version = version; 323 } 324 } 325 } 326 | Popular Tags |