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 com.tc.object.config.ConfigVisitor;
008: import com.tc.object.config.DSOClientConfigHelper;
009: import com.tc.object.config.TransparencyClassSpec;
010: import com.tc.simulator.app.ApplicationConfig;
011: import com.tc.simulator.listener.ListenerProvider;
012: import com.tc.util.Assert;
013:
014: import java.util.Iterator;
015: import java.util.LinkedHashMap;
016: import java.util.Random;
017: import java.util.Set;
018:
019: public class LinkedHashMapMutateValidateTestApp extends
020: AbstractMutateValidateTransparentApp {
021:
022: private int upbound = 1000;
023: private final String appId;
024: private final MapRoot map1 = new MapRoot(upbound);
025: private final MapRoot map2 = new MapRoot(upbound + 100);
026: private final EventNode eventIndex = new EventNode(0, "test");
027:
028: public LinkedHashMapMutateValidateTestApp(String appId,
029: ApplicationConfig cfg, ListenerProvider listenerProvider) {
030: super (appId, cfg, listenerProvider);
031: this .appId = appId;
032: }
033:
034: protected void mutate() throws Throwable {
035: EventNode event = null;
036: Random r = new Random();
037: boolean empty;
038:
039: while (true) {
040: boolean todoPut = r.nextBoolean();
041:
042: // if empty then do put
043: synchronized (map1) {
044: empty = map1.getMap().isEmpty();
045: if (empty || todoPut) {
046: synchronized (eventIndex) {
047: event = eventIndex.produce();
048: }
049: map1.getMap()
050: .put(new Integer(event.getId()), event);
051: System.out.println("*** Add item " + event.getId());
052: }
053: }
054:
055: if (!todoPut && !empty) {
056: // move first item from map1 to map2
057: synchronized (map1) {
058: Set s = map1.getMap().keySet();
059: Iterator it = s.iterator();
060: if (it.hasNext()) {
061: Integer key = (Integer) it.next();
062: event = (EventNode) map1.getMap().remove(key);
063: map2.getMap().put(new Integer(event.getId()),
064: event);
065: System.out.println("*** Move item "
066: + event.getId());
067:
068: if (event.getId() >= upbound)
069: break;
070: }
071: // debugPrintln("*** map1 size="+map1.getMap().size()+ " map2 size=" + map2.getMap().size());
072: }
073: }
074: Thread.sleep(r.nextInt(10));
075: }
076: System.out.println("*** Done with mutation");
077: Thread.sleep(100); // wait for others to complete
078: }
079:
080: protected void validate() throws Throwable {
081: Random r = new Random();
082: int id = 0;
083:
084: debugPrintln("*** Start verification");
085: // check size
086: synchronized (map1) {
087: int mapSize = map1.getMap().size() + map2.getMap().size();
088: if (eventIndex.getId() != mapSize) {
089: notifyError("*** Expected total events "
090: + eventIndex.getId() + " but got " + mapSize);
091: }
092: Assert.assertTrue(eventIndex.getId() == mapSize);
093: }
094:
095: while (id < eventIndex.getId()) {
096: synchronized (map1) {
097: Integer key = new Integer(id);
098: boolean inMap1 = map1.getMap().containsKey(key);
099: boolean inMap2 = map2.getMap().containsKey(key);
100: if ((inMap1 && inMap2) || (!inMap1 && !inMap2)) {
101: notifyError("Item " + id
102: + (inMap1 ? " in both maps" : " not found"));
103: }
104: Assert.assertTrue((inMap1 && !inMap2)
105: || (!inMap1 && inMap2));
106: id++;
107: }
108: // debugPrintln("*** Verify id=" + id);
109: Thread.sleep(r.nextInt(3));
110: }
111: System.out.println("*** Verification Successful");
112: }
113:
114: public static void visitL1DSOConfig(ConfigVisitor visitor,
115: DSOClientConfigHelper config) {
116: String testClass = LinkedHashMapMutateValidateTestApp.class
117: .getName();
118: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
119: config.addIncludePattern(testClass + "$*", false, false, true);
120:
121: String methodExpression = "* " + testClass + "*.*(..)";
122: config.addWriteAutolock(methodExpression);
123: methodExpression = "* " + MapRoot.class.getName() + "*.*(..)";
124: config.addWriteAutolock(methodExpression);
125: methodExpression = "* " + EventNode.class.getName() + "*.*(..)";
126: config.addWriteAutolock(methodExpression);
127:
128: spec.addRoot("map1", "map1");
129: spec.addRoot("map2", "map2");
130: spec.addRoot("eventIndex", "eventIndex");
131: }
132:
133: private static class MapRoot {
134: private final LinkedHashMap map;
135:
136: public MapRoot(int cap) {
137: map = new LinkedHashMap(cap);
138: }
139:
140: public LinkedHashMap getMap() {
141: return (map);
142: }
143:
144: public void clear() {
145: map.clear();
146: }
147: }
148:
149: private static class EventNode {
150: String name;
151: int id;
152:
153: public EventNode produce() {
154: EventNode node;
155: node = new EventNode(getId(), "Event" + getId());
156: setId(getId() + 1);
157: // System.out.println("*** Produce id=" + node.getId());
158: return (node);
159: }
160:
161: public EventNode(int id, String name) {
162: this .id = id;
163: this .name = name;
164: }
165:
166: public int getId() {
167: return (id);
168: }
169:
170: public void setId(int id) {
171: this.id = id;
172: }
173: }
174:
175: }
|