001: /*
002: * All content copyright (c) 2003-2007 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tctest;
006:
007: import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;
008:
009: import com.tc.object.config.ConfigVisitor;
010: import com.tc.object.config.DSOClientConfigHelper;
011: import com.tc.object.config.TransparencyClassSpec;
012: import com.tc.simulator.app.ApplicationConfig;
013: import com.tc.simulator.listener.ListenerProvider;
014: import com.tctest.runner.AbstractTransparentApp;
015:
016: import java.util.HashMap;
017: import java.util.Map;
018:
019: /**
020: * This test was written specifically to expose a dead lock in sleepcat in persistence map
021: */
022: public class MapClearDeadLocksSleepycatTestApp extends
023: AbstractTransparentApp {
024:
025: private static final int LOOP_COUNT = 10000;
026:
027: private static final int MAP_SIZE = 28;
028:
029: private final Map root = new HashMap();
030:
031: private final CyclicBarrier barrier;
032:
033: public MapClearDeadLocksSleepycatTestApp(String appId,
034: ApplicationConfig cfg, ListenerProvider listenerProvider) {
035: super (appId, cfg, listenerProvider);
036: barrier = new CyclicBarrier(getParticipantCount());
037: }
038:
039: public void run() {
040: try {
041: int idx = barrier.barrier();
042: if (idx == 0) {
043: initialize();
044: }
045: barrier.barrier();
046: testModifyAndClear(idx);
047: } catch (Throwable t) {
048: notifyError(t);
049: }
050: }
051:
052: private void testModifyAndClear(int idx) {
053: int debugPrint = 0;
054: for (int i = 0; i < LOOP_COUNT; i++) {
055: // This synchronization is there only to create transaction boundry and to not throw unlocked shared object
056: // exception. The data is partitioned so that threads shouldnt contend.
057: if (idx % 2 == 0) {
058: iterateForwards(idx, i);
059: } else {
060: iterateBackwards(idx, i);
061: }
062: if (debugPrint++ % 100 == 0) {
063: System.err.println(Thread.currentThread().getName()
064: + " : Map Iteration count : " + i);
065: }
066: }
067: }
068:
069: private void iterateBackwards(int idx, int i) {
070: synchronized (new Integer(idx)) {
071: for (int j = MAP_SIZE - 1; j >= 0; j--) {
072: if (j % getParticipantCount() == idx) {
073: Map m = getMapReadOnly(j);
074: modifyAndClear(m, i);
075: }
076: }
077: }
078: }
079:
080: private void iterateForwards(int idx, int i) {
081: synchronized (new Integer(idx)) {
082: for (int j = 0; j < MAP_SIZE; j++) {
083: if (j % getParticipantCount() == idx) {
084: Map m = getMapReadOnly(j);
085: modifyAndClear(m, i);
086: }
087: }
088: }
089: }
090:
091: private void modifyAndClear(Map m, int i) {
092: if (i % 5 == 0) {
093: m.clear();
094: } else {
095: m.put(new Long(i), "String : " + i);
096: m.put(new Long(i++), "String : " + i);
097: m.put(new Long(i++), "String : " + i);
098: m.put(new Long(i++), "String : " + i);
099: m.put(new Long(i++), "String : " + i);
100: }
101: }
102:
103: private Map getMapReadOnly(int idx) {
104: synchronized (root) {
105: Integer index = new Integer(idx);
106: return (Map) root.get(index);
107: }
108: }
109:
110: private void initialize() {
111: synchronized (root) {
112: for (int i = 0; i < MAP_SIZE; i++) {
113: root.put(new Integer(i), new HashMap());
114: }
115: }
116: }
117:
118: public static void visitL1DSOConfig(ConfigVisitor visitor,
119: DSOClientConfigHelper config) {
120: visitL1DSOConfig(visitor, config, new HashMap());
121: }
122:
123: public static void visitL1DSOConfig(ConfigVisitor visitor,
124: DSOClientConfigHelper config, Map optionalAttributes) {
125:
126: TransparencyClassSpec spec = config
127: .getOrCreateSpec(CyclicBarrier.class.getName());
128: addWriteAutolock(config, "* " + CyclicBarrier.class.getName()
129: + "*.*(..)");
130:
131: String testClass = MapClearDeadLocksSleepycatTestApp.class
132: .getName();
133: spec = config.getOrCreateSpec(testClass);
134:
135: String writeAllowdMethodExpression = "* " + testClass
136: + "*.*(..)";
137: addWriteAutolock(config, writeAllowdMethodExpression);
138: String readOnlyMethodExpression = "* " + testClass
139: + "*.*ReadOnly*(..)";
140: config.addReadAutolock(readOnlyMethodExpression);
141:
142: spec.addRoot("root", "root");
143: spec.addRoot("barrier", "barrier");
144: }
145:
146: private static void addWriteAutolock(DSOClientConfigHelper config,
147: String methodPattern) {
148: config.addWriteAutolock(methodPattern);
149: }
150:
151: }
|