KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tctest > LockManagerSystemTest


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tctest;
6
7 import org.apache.xmlbeans.XmlObject;
8
9 import com.tc.cluster.Cluster;
10 import com.tc.config.schema.NewCommonL2Config;
11 import com.tc.config.schema.NewSystemConfig;
12 import com.tc.config.schema.dynamic.BooleanConfigItem;
13 import com.tc.config.schema.dynamic.ConfigItem;
14 import com.tc.config.schema.dynamic.ConfigItemListener;
15 import com.tc.config.schema.dynamic.IntConfigItem;
16 import com.tc.config.schema.setup.ConfigurationSetupException;
17 import com.tc.config.schema.setup.L1TVSConfigurationSetupManager;
18 import com.tc.config.schema.setup.L2TVSConfigurationSetupManager;
19 import com.tc.config.schema.setup.TestTVSConfigurationSetupManagerFactory;
20 import com.tc.lang.StartupHelper;
21 import com.tc.lang.TCThreadGroup;
22 import com.tc.lang.ThrowableHandler;
23 import com.tc.lang.StartupHelper.StartupAction;
24 import com.tc.logging.TCLogging;
25 import com.tc.net.protocol.transport.NullConnectionPolicy;
26 import com.tc.object.BaseDSOTestCase;
27 import com.tc.object.DistributedObjectClient;
28 import com.tc.object.bytecode.MockClassProvider;
29 import com.tc.object.bytecode.NullManager;
30 import com.tc.object.bytecode.hook.impl.PreparedComponentsFromL2Connection;
31 import com.tc.object.config.DSOClientConfigHelper;
32 import com.tc.object.config.StandardDSOClientConfigHelper;
33 import com.tc.object.config.schema.NewDSOApplicationConfig;
34 import com.tc.object.config.schema.NewL2DSOConfig;
35 import com.tc.object.lockmanager.api.LockID;
36 import com.tc.object.lockmanager.api.LockLevel;
37 import com.tc.object.lockmanager.api.ThreadID;
38 import com.tc.object.lockmanager.impl.ClientLockManagerImpl;
39 import com.tc.objectserver.impl.DistributedObjectServer;
40 import com.tc.objectserver.lockmanager.api.DeadlockChain;
41 import com.tc.objectserver.lockmanager.api.DeadlockResults;
42 import com.tc.objectserver.managedobject.ManagedObjectStateFactory;
43 import com.tc.server.NullTCServerInfo;
44 import com.tc.util.concurrent.SetOnceFlag;
45 import com.tc.util.concurrent.ThreadUtil;
46
47 import java.io.InputStream JavaDoc;
48 import java.util.ArrayList JavaDoc;
49 import java.util.List JavaDoc;
50
51 public class LockManagerSystemTest extends BaseDSOTestCase {
52
53   // please keep this set to true so that tests on slow/loaded machines don't fail. When working on this test though, it
54
// can be convenient to temporarily flip it to false
55
private static final boolean slow = true;
56
57   private DistributedObjectServer server;
58   private DistributedObjectClient client;
59   private ClientLockManagerImpl lockManager;
60   private TCThreadGroup group = new TCThreadGroup(new ThrowableHandler(TCLogging
61                                          .getLogger(DistributedObjectServer.class)));
62
63   static {
64     /*
65      * This test run against JDK1.4 and creates and executes multiple embedded
66      * DistributedObjectServers. L2Management creates an RMI registry on the JMX port,
67      * which is randomly changing in this test. In 1.4 it's not possible to create
68      * multiple RMI Registries in a single VM. Remove this when we no longer support 1.4.
69      */

70     System.setProperty("org.terracotta.server.disableJmxConnector", "true");
71   }
72
73   private class StartAction implements StartupAction {
74     private final L2TVSConfigurationSetupManager l2Manager;
75
76     StartAction(L2TVSConfigurationSetupManager l2manager) {
77       this.l2Manager = l2manager;
78     }
79
80     public void execute() throws Throwable JavaDoc {
81       server = new DistributedObjectServer(new ConfigOverride(l2Manager),
82                                            group, new NullConnectionPolicy(),
83                                            new NullTCServerInfo());
84       server.start();
85     }
86   }
87
88   public void setUp() throws Exception JavaDoc {
89     TestTVSConfigurationSetupManagerFactory factory = createDistributedConfigFactory();
90
91     ManagedObjectStateFactory.disableSingleton(true);
92     L2TVSConfigurationSetupManager l2Manager = factory.createL2TVSConfigurationSetupManager(null);
93
94     new StartupHelper(group, new StartAction(l2Manager)).startUp();
95
96     makeClientUsePort(server.getListenPort());
97
98     L1TVSConfigurationSetupManager manager = super.createL1ConfigManager();
99     DSOClientConfigHelper configHelper = new StandardDSOClientConfigHelper(manager);
100
101     PreparedComponentsFromL2Connection components = new PreparedComponentsFromL2Connection(manager);
102
103     client = new DistributedObjectClient(configHelper, new TCThreadGroup(new ThrowableHandler(TCLogging
104         .getLogger(DistributedObjectClient.class))), new MockClassProvider(), components, NullManager.getInstance(), new Cluster());
105     client.start();
106
107     lockManager = (ClientLockManagerImpl) client.getLockManager();
108   }
109
110   protected void tearDown() {
111     if (client != null) {
112       client.stop();
113     }
114
115     if (server != null) {
116       server.stop();
117     }
118   }
119
120   public void testUpgradeDeadlock() throws Exception JavaDoc {
121     final LockID l1 = new LockID("1");
122
123     final ThreadID tid1 = new ThreadID(1);
124     final ThreadID tid2 = new ThreadID(2);
125
126     lockManager.lock(l1, tid1, LockLevel.READ);
127     lockManager.lock(l1, tid2, LockLevel.READ);
128
129     Thread JavaDoc t1 = new Thread JavaDoc() {
130       public void run() {
131         LockManagerSystemTest.this.lockManager.lock(l1, tid1, LockLevel.WRITE);
132       }
133     };
134
135     Thread JavaDoc t2 = new Thread JavaDoc() {
136       public void run() {
137         LockManagerSystemTest.this.lockManager.lock(l1, tid2, LockLevel.WRITE);
138       }
139     };
140
141     t1.start();
142     t2.start();
143
144     t1.join(2000);
145     t2.join(2000);
146
147     assertTrue(t1.isAlive());
148     assertTrue(t2.isAlive());
149
150     // make sure we "see" the deadlock on the server side
151
final List JavaDoc deadlocks = new ArrayList JavaDoc();
152     DeadlockResults results = new DeadlockResults() {
153       public void foundDeadlock(DeadlockChain chain) {
154         deadlocks.add(chain);
155       }
156     };
157
158     server.getContext().getLockManager().scanForDeadlocks(results);
159
160     assertEquals(1, deadlocks.size());
161     DeadlockChain chain = (DeadlockChain) deadlocks.remove(0);
162
163     ThreadID id1 = chain.getWaiter().getClientThreadID();
164     LockID lid1 = chain.getWaitingOn();
165     chain = chain.getNextLink();
166     ThreadID id2 = chain.getWaiter().getClientThreadID();
167     LockID lid2 = chain.getWaitingOn();
168
169     assertEquals(id1, chain.getNextLink().getWaiter().getClientThreadID());
170
171     assertEquals(lid1, l1);
172     assertEquals(lid2, l1);
173     assertEquals(lid1, lid2);
174
175     if (id1.equals(tid1)) {
176       assertEquals(id2, tid2);
177     } else {
178       assertEquals(id1, tid2);
179     }
180
181   }
182
183   private static void sleep(long amount) {
184     amount *= (slow ? 300 : 50);
185     ThreadUtil.reallySleep(amount);
186   }
187
188   public void testUpgrade() throws Exception JavaDoc {
189     final LockID l1 = new LockID("1");
190
191     final ThreadID tid1 = new ThreadID(1);
192     final ThreadID tid2 = new ThreadID(2);
193     final ThreadID tid3 = new ThreadID(3);
194
195     final SetOnceFlag flag = new SetOnceFlag();
196     lockManager.lock(l1, tid1, LockLevel.READ);
197     lockManager.lock(l1, tid2, LockLevel.READ);
198     lockManager.lock(l1, tid3, LockLevel.READ);
199
200     Thread JavaDoc t = new Thread JavaDoc() {
201       public void run() {
202         LockManagerSystemTest.this.lockManager.lock(l1, tid1, LockLevel.WRITE);
203         flag.set();
204       }
205     };
206     t.start();
207
208     sleep(5);
209     assertFalse(flag.isSet());
210
211     lockManager.unlock(l1, tid2);
212     sleep(5);
213     assertFalse(flag.isSet());
214
215     lockManager.unlock(l1, tid3);
216     sleep(5);
217     assertTrue(flag.isSet());
218
219     t.join();
220
221     Thread JavaDoc secondReader = new Thread JavaDoc() {
222       public void run() {
223         System.out.println("Read requested !");
224         LockManagerSystemTest.this.lockManager.lock(l1, tid2, LockLevel.READ);
225         System.out.println("Got Read !");
226       }
227     };
228     secondReader.start();
229
230     Thread JavaDoc secondWriter = new Thread JavaDoc() {
231       public void run() {
232         System.out.println("Write requested !");
233         LockManagerSystemTest.this.lockManager.lock(l1, tid3, LockLevel.WRITE);
234         System.out.println("Got Write !");
235       }
236     };
237     secondWriter.start();
238
239     sleep(5);
240     lockManager.unlock(l1, tid1);
241     sleep(5);
242     secondReader.join(5000);
243     assertFalse(secondReader.isAlive());
244     assertTrue(secondWriter.isAlive());
245
246     lockManager.unlock(l1, tid1);
247     sleep(5);
248     assertTrue(secondWriter.isAlive());
249     lockManager.unlock(l1, tid2);
250     secondWriter.join(60000);
251     assertFalse(secondWriter.isAlive());
252   }
253
254   public void testBasic() throws Exception JavaDoc {
255     final LockID l1 = new LockID("1");
256     final LockID l3 = new LockID("3");
257
258     final ThreadID tid1 = new ThreadID(1);
259     final ThreadID tid2 = new ThreadID(2);
260     final ThreadID tid3 = new ThreadID(3);
261     final ThreadID tid4 = new ThreadID(4);
262
263     // Get the lock for threadID 1
264
System.out.println("Asked for first lock");
265     lockManager.lock(l1, tid1, LockLevel.WRITE);
266
267     System.out.println("Got first lock");
268
269     // Try to get it again, this should pretty much be a noop as we handle recursive lock calls
270
lockManager.lock(l1, tid1, LockLevel.WRITE);
271     System.out.println("Got first lock again");
272
273     final boolean[] done = new boolean[2];
274
275     // try obtaining a write lock on l1 in a second thread. This should block initially since a write lock is already
276
// held on l1
277
Thread JavaDoc t = new Thread JavaDoc() {
278       public void run() {
279         System.out.println("Asked for second lock");
280         lockManager.lock(l1, tid2, LockLevel.WRITE);
281         System.out.println("Got second lock");
282         done[0] = true;
283       }
284     };
285
286     t.start();
287     sleep(5);
288     assertFalse(done[0]);
289     lockManager.unlock(l1, tid1);
290     lockManager.unlock(l1, tid1); // should unblock thread above
291
sleep(5);
292     assertTrue(done[0]); // thread should have been unblocked and finished
293

294     // Get a bunch of read locks on l3
295
lockManager.lock(l3, tid1, LockLevel.READ);
296     lockManager.lock(l3, tid2, LockLevel.READ);
297     lockManager.lock(l3, tid3, LockLevel.READ);
298     done[0] = false;
299     t = new Thread JavaDoc() {
300       public void run() {
301         System.out.println("Asking for write lock");
302         lockManager.lock(l3, tid4, LockLevel.WRITE);
303         System.out.println("Got write lock");
304         done[0] = true;
305       }
306     };
307     t.start();
308     sleep(5);
309     assertFalse(done[0]);
310
311     lockManager.unlock(l3, tid1);
312     sleep(5);
313     assertFalse(done[0]);
314
315     lockManager.unlock(l3, tid2);
316     sleep(5);
317     assertFalse(done[0]);
318
319     lockManager.unlock(l3, tid3);
320     sleep(5);
321     assertTrue(done[0]);
322
323     done[0] = false;
324     t = new Thread JavaDoc() {
325       public void run() {
326         System.out.println("Asking for read lock");
327         lockManager.lock(l3, tid1, LockLevel.READ);
328         System.out.println("Got read lock");
329         done[0] = true;
330       }
331     };
332     t.start();
333
334     done[1] = false;
335     t = new Thread JavaDoc() {
336       public void run() {
337         System.out.println("Asking for read lock");
338         lockManager.lock(l3, tid2, LockLevel.READ);
339         System.out.println("Got read lock");
340         done[1] = true;
341       }
342     };
343
344     t.start();
345     sleep(5);
346     assertFalse(done[0]);
347     assertFalse(done[1]);
348     lockManager.unlock(l3, tid4);
349     sleep(5);
350     assertTrue(done[0]);
351     assertTrue(done[1]);
352     lockManager.unlock(l3, tid1);
353     lockManager.unlock(l3, tid2);
354   }
355
356   private static class ConfigOverride implements L2TVSConfigurationSetupManager {
357
358     private final L2TVSConfigurationSetupManager realConfig;
359
360     ConfigOverride(L2TVSConfigurationSetupManager realConfig) {
361       this.realConfig = realConfig;
362     }
363
364     public String JavaDoc[] allCurrentlyKnownServers() {
365       return realConfig.allCurrentlyKnownServers();
366     }
367
368     public String JavaDoc[] applicationNames() {
369       return realConfig.applicationNames();
370     }
371
372     public NewCommonL2Config commonl2Config() {
373       return realConfig.commonl2Config();
374     }
375
376     public NewCommonL2Config commonL2ConfigFor(String JavaDoc name) throws ConfigurationSetupException {
377       return realConfig.commonL2ConfigFor(name);
378     }
379
380     public String JavaDoc describeSources() {
381       return realConfig.describeSources();
382     }
383
384     public NewDSOApplicationConfig dsoApplicationConfigFor(String JavaDoc applicationName) {
385       return realConfig.dsoApplicationConfigFor(applicationName);
386     }
387
388     public NewL2DSOConfig dsoL2Config() {
389       return new L2ConfigOverride(realConfig.dsoL2Config());
390     }
391
392     public NewL2DSOConfig dsoL2ConfigFor(String JavaDoc name) throws ConfigurationSetupException {
393       return realConfig.dsoL2ConfigFor(name);
394     }
395
396     public InputStream JavaDoc rawConfigFile() {
397       return realConfig.rawConfigFile();
398     }
399
400     public NewSystemConfig systemConfig() {
401       return realConfig.systemConfig();
402     }
403
404     private static class L2ConfigOverride implements NewL2DSOConfig {
405
406       private final NewL2DSOConfig config;
407
408       public L2ConfigOverride(NewL2DSOConfig config) {
409         this.config = config;
410       }
411
412       public void changesInItemForbidden(ConfigItem item) {
413         config.changesInItemForbidden(item);
414       }
415
416       public void changesInItemIgnored(ConfigItem item) {
417         config.changesInItemIgnored(item);
418       }
419
420       public IntConfigItem clientReconnectWindow() {
421         return config.clientReconnectWindow();
422       }
423
424       public BooleanConfigItem garbageCollectionEnabled() {
425         return config.garbageCollectionEnabled();
426       }
427
428       public IntConfigItem garbageCollectionInterval() {
429         return config.garbageCollectionInterval();
430       }
431
432       public BooleanConfigItem garbageCollectionVerbose() {
433         return config.garbageCollectionVerbose();
434       }
435
436       public IntConfigItem listenPort() {
437         return new IntConfigItem() {
438           public int getInt() {
439             return 0;
440           }
441
442           public void addListener(ConfigItemListener changeListener) {
443             //
444
}
445
446           public Object JavaDoc getObject() {
447             return new Integer JavaDoc(0);
448           }
449
450           public void removeListener(ConfigItemListener changeListener) {
451             //
452
}
453         };
454       }
455
456       public ConfigItem persistenceMode() {
457         return config.persistenceMode();
458       }
459
460       public XmlObject getBean() {
461         return config.getBean();
462       }
463
464     }
465
466   }
467
468 }
469
Popular Tags