001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tctest;
005:
006: import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;
007:
008: import com.tc.object.config.ConfigLockLevel;
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.object.config.spec.CyclicBarrierSpec;
013: import com.tc.object.util.ReadOnlyException;
014: import com.tc.simulator.app.ApplicationConfig;
015: import com.tc.simulator.listener.ListenerProvider;
016: import com.tctest.runner.AbstractErrorCatchingTransparentApp;
017:
018: import java.util.ArrayList;
019: import java.util.Collection;
020: import java.util.HashMap;
021: import java.util.HashSet;
022: import java.util.Hashtable;
023: import java.util.Iterator;
024: import java.util.LinkedList;
025: import java.util.List;
026: import java.util.Map;
027: import java.util.Set;
028: import java.util.Vector;
029:
030: public class LogicalIteratorTestApp extends
031: AbstractErrorCatchingTransparentApp {
032:
033: private final Set set = new HashSet();
034: private final Map map = new HashMap();
035: private final List llist = new LinkedList();
036: private final List alist = new ArrayList();
037: private final Vector vector = new Vector();
038: private final Hashtable hashtable = new Hashtable();
039: private final CyclicBarrier barrier;
040:
041: public LogicalIteratorTestApp(String appId, ApplicationConfig cfg,
042: ListenerProvider listenerProvider) {
043: super (appId, cfg, listenerProvider);
044: this .barrier = new CyclicBarrier(getParticipantCount());
045: }
046:
047: protected void runTest() throws Throwable {
048: String me = getApplicationId();
049: init(me);
050: barrier.barrier();
051: readOnly();
052: barrier.barrier();
053: remove(me);
054: barrier.barrier();
055: verifySize();
056: }
057:
058: private void verifySize() {
059: synchronized (set) {
060: if (vector.size() != 0) {
061: throw new RuntimeException("vector not empty: "
062: + vector.size());
063: }
064: if (map.size() != 0) {
065: throw new RuntimeException("map not empty: "
066: + map.size());
067: }
068: if (alist.size() != 0) {
069: throw new RuntimeException("alist not empty"
070: + alist.size());
071: }
072: if (set.size() != 0) {
073: throw new RuntimeException("set not empty: "
074: + set.size());
075: }
076: if (llist.size() != 0) {
077: throw new RuntimeException("llist not empty: "
078: + llist.size());
079: }
080: if (hashtable.size() != 0) {
081: throw new RuntimeException("hashtable not empty: "
082: + hashtable.size());
083: }
084: }
085: }
086:
087: private void init(String id) {
088: synchronized (barrier) {
089: vector.add(id);
090: map.put("key" + id, id);
091: map.put(id, "value" + id);
092: alist.add(id);
093: set.add(id);
094: llist.add(id);
095: hashtable.put("key" + id, id);
096: hashtable.put(id, "value" + id);
097: }
098: }
099:
100: private void remove(String id) {
101: synchronized (barrier) {
102: remove(vector.iterator(), id);
103: remove(map.keySet().iterator(), "key" + id);
104: remove(map.values().iterator(), "value" + id);
105: remove(alist.iterator(), id);
106: remove(set.iterator(), id);
107: remove(llist.iterator(), id);
108: remove(hashtable.keySet().iterator(), "key" + id);
109: remove(hashtable.values().iterator(), "value" + id);
110: }
111: }
112:
113: private void remove(Iterator iter, String id) {
114: while (iter.hasNext()) {
115: if (id.equals(iter.next())) {
116: iter.remove();
117: return;
118: }
119: }
120: }
121:
122: private void readOnly() {
123: synchronized (barrier) {
124: attemptRemove(map.keySet());
125: attemptRemove(map.values());
126: attemptRemove(alist);
127: attemptRemove(set);
128: attemptRemove(llist);
129: }
130: }
131:
132: private void attemptRemove(Collection collection) {
133: String type = collection.getClass().getName();
134: final int startSize = collection.size();
135:
136: Iterator iter = collection.iterator();
137: iter.next();
138:
139: try {
140: iter.remove();
141: throw new RuntimeException(
142: "Iterator remove() allowed in read-only transaction on type "
143: + type);
144: } catch (ReadOnlyException roe) {
145: // expected
146: }
147:
148: int endSize = collection.size();
149: if (startSize != endSize) {
150: // collection size changed
151: throw new AssertionError("Collection of type " + type
152: + " changed size during read-only TXN: ("
153: + startSize + " != " + endSize + ")");
154: }
155:
156: }
157:
158: public static void visitL1DSOConfig(ConfigVisitor visitor,
159: DSOClientConfigHelper config) {
160: String testClass = LogicalIteratorTestApp.class.getName();
161: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
162:
163: new CyclicBarrierSpec().visit(visitor, config);
164:
165: String method = "* " + testClass + ".init(..)";
166: config.addWriteAutolock(method);
167:
168: method = "* " + testClass + ".readOnly(..)";
169: config.addAutolock(method, ConfigLockLevel.READ);
170:
171: method = "* " + testClass + ".remove(..)";
172: config.addWriteAutolock(method);
173:
174: method = "* " + testClass + ".runTest()";
175: config.addWriteAutolock(method);
176:
177: method = "* " + testClass + ".verifySize(..)";
178: config.addWriteAutolock(method);
179:
180: spec.addRoot("hashtable", "hashtableLock");
181: spec.addRoot("set", "setLock");
182: spec.addRoot("vector", "vectorLock");
183: spec.addRoot("map", "mapLock");
184: spec.addRoot("llist", "llistLock");
185: spec.addRoot("alist", "alistLock");
186: spec.addRoot("barrier", "barrierLock");
187: }
188:
189: }
|