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.BrokenBarrierException;
007: import EDU.oswego.cs.dl.util.concurrent.CyclicBarrier;
008: import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
009:
010: import com.tc.object.config.ConfigVisitor;
011: import com.tc.object.config.DSOClientConfigHelper;
012: import com.tc.object.config.TransparencyClassSpec;
013: import com.tc.object.config.spec.CyclicBarrierSpec;
014: import com.tc.object.config.spec.SynchronizedIntSpec;
015: import com.tc.simulator.app.ApplicationConfig;
016: import com.tc.simulator.listener.ListenerProvider;
017: import com.tc.util.Assert;
018: import com.tc.util.StringUtil;
019: import com.tctest.runner.AbstractErrorCatchingTransparentApp;
020:
021: import java.text.DateFormat;
022: import java.text.SimpleDateFormat;
023: import java.util.ArrayList;
024: import java.util.Date;
025: import java.util.HashMap;
026: import java.util.Hashtable;
027: import java.util.IdentityHashMap;
028: import java.util.Iterator;
029: import java.util.LinkedHashMap;
030: import java.util.List;
031: import java.util.Map;
032: import java.util.TreeMap;
033: import java.util.Map.Entry;
034:
035: public class MapOfMapsTestApp extends
036: AbstractErrorCatchingTransparentApp {
037:
038: private static final int LOOP_COUNT = 10;
039: private static final int DEPTH_COUNT = 5;
040: private static final int BREATH_COUNT = 3;
041:
042: final Map root = new HashMap();
043: final SynchronizedInt uid = new SynchronizedInt(0);
044: CyclicBarrier barrier;
045:
046: public MapOfMapsTestApp(String appId, ApplicationConfig cfg,
047: ListenerProvider listenerProvider) {
048: super (appId, cfg, listenerProvider);
049: }
050:
051: public static void visitL1DSOConfig(ConfigVisitor visitor,
052: DSOClientConfigHelper config) {
053: String testClass = MapOfMapsTestApp.class.getName();
054: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
055: spec.addRoot("root", "root");
056: spec.addRoot("uid", "uid");
057: spec.addRoot("barrier", "barrier");
058: String methodExpression = "* " + testClass + ".read(..)";
059: config.addReadAutolock(methodExpression);
060: methodExpression = "* " + testClass + ".add2Root(..)";
061: config.addWriteAutolock(methodExpression);
062: methodExpression = "* " + testClass + ".populateMyRoot(..)";
063: config.addWriteAutolock(methodExpression);
064: new SynchronizedIntSpec().visit(visitor, config);
065: new CyclicBarrierSpec().visit(visitor, config);
066: }
067:
068: public void runTest() throws BrokenBarrierException,
069: InterruptedException {
070: setCyclicBarrier();
071: int myid = uid.increment();
072: if (myid == 1) {
073: // Writer
074: runCreateMaps();
075: } else {
076: // readers
077: runReadMaps();
078: }
079: }
080:
081: private void runReadMaps() throws BrokenBarrierException,
082: InterruptedException {
083: int count = 0;
084: int mapCountNo = calculateMapCount(DEPTH_COUNT, BREATH_COUNT);
085: while (count++ < LOOP_COUNT) {
086: barrier.barrier();
087: log("Readers : Loop Count : " + count);
088: Map myRoot = read(String.valueOf(count), root);
089: int mapCount = countMaps(myRoot);
090: log("Readers : No Of Maps = " + mapCount);
091: Assert.assertEquals(mapCountNo, mapCount);
092: }
093: }
094:
095: private int calculateMapCount(int depth, int breath) {
096: int pow = breath;
097: int count = 0;
098: for (int i = 0; i <= depth; i++) {
099: count += pow;
100: pow *= breath;
101: }
102: return count;
103: }
104:
105: private int countMaps(Map m) {
106:
107: int count = 0;
108: for (Iterator i = m.entrySet().iterator(); i.hasNext();) {
109: Map.Entry e = (Entry) i.next();
110: if (e.getValue() instanceof Map) {
111: count = count + 1 + countMaps((Map) e.getValue());
112: }
113: }
114: return count;
115: }
116:
117: private void runCreateMaps() throws BrokenBarrierException,
118: InterruptedException {
119: int count = 0;
120: while (count++ < LOOP_COUNT) {
121: log("Writer : Loop Count : " + count);
122: Map myRoot = new HashMap();
123: add2Root(String.valueOf(count), myRoot);
124: populateMyRoot(myRoot, DEPTH_COUNT, BREATH_COUNT);
125: barrier.barrier();
126: }
127: }
128:
129: private void populateMyRoot(Map myRoot, int depth, int breath) {
130: List childs = new ArrayList();
131: int b = breath;
132: synchronized (myRoot) {
133: while (b-- > 0) {
134: childs.add(addToMap(String.valueOf(b), myRoot));
135: }
136: }
137: if (depth-- > 0) {
138: for (Iterator i = childs.iterator(); i.hasNext();) {
139: Map child = (Map) i.next();
140: populateMyRoot(child, depth, breath);
141: }
142: }
143: }
144:
145: private void setCyclicBarrier() {
146: int participationCount = getParticipantCount();
147: log("Participation Count = " + participationCount);
148: barrier = new CyclicBarrier(participationCount);
149: }
150:
151: private void add2Root(String id, Map myRoot) {
152: synchronized (root) {
153: root.put(id, myRoot);
154: }
155: }
156:
157: static DateFormat formatter = new SimpleDateFormat("hh:mm:ss,S");
158:
159: private static void log(String message) {
160: System.err.println(Thread.currentThread().getName()
161: + " :: "
162: + formatter
163: .format(new Date(System.currentTimeMillis()))
164: + " : " + message);
165: }
166:
167: private Map addToMap(String id, Map m) {
168: Map child = getChild(m);
169: m.put(id, child);
170: return child;
171: }
172:
173: /**
174: * HashMap, Hashtable and LinkedHashMap supports partial collection and IdentityHashMap and TreeMap doesnt support it.
175: * So both should be tested
176: */
177: private Map getChild(Map m) {
178: if (m instanceof HashMap) {
179: return getPopulatedMap(new Hashtable());
180: } else if (m instanceof Hashtable) {
181: return getPopulatedMap(new LinkedHashMap());
182: } else if (m instanceof LinkedHashMap) {
183: return getPopulatedMap(new IdentityHashMap());
184: } else if (m instanceof IdentityHashMap) {
185: return getPopulatedMap(new TreeMap());
186: } else if (m instanceof TreeMap) {
187: return getPopulatedMap(new HashMap());
188: } else {
189: throw new AssertionError("Should never get here");
190: }
191: }
192:
193: private Map getPopulatedMap(Map m) {
194: for (int i = 0; i < 10; i++) {
195: m
196: .put(
197: StringUtil.reduce("Hello - " + i),
198: StringUtil
199: .reduce("Hehehehehehehehehehehehehehehehehheheheheheheheheheheheheheheheheh-"
200: + i));
201: }
202: return m;
203: }
204:
205: private Map read(String id, Map m) {
206: synchronized (m) {
207: return (Map) m.get(id);
208: }
209: }
210:
211: }
|