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 org.apache.commons.io.FileUtils;
008: import org.apache.commons.io.IOUtils;
009:
010: import com.tc.net.proxy.TCPProxy;
011: import com.tc.object.config.ConfigVisitor;
012: import com.tc.object.config.DSOClientConfigHelper;
013: import com.tc.object.config.TransparencyClassSpec;
014: import com.tc.objectserver.control.ExtraL1ProcessControl;
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.PortChooser;
019: import com.tc.util.concurrent.ThreadUtil;
020: import com.tctest.runner.AbstractTransparentApp;
021:
022: import java.io.File;
023: import java.io.FileInputStream;
024: import java.io.FileOutputStream;
025: import java.net.InetAddress;
026: import java.util.ArrayList;
027: import java.util.List;
028:
029: /**
030: * Test for l1-reconnect feature: CDV-97 An extra L1 is created and connected to L2 through a proxy (TCPProxy) We will
031: * use this proxy to simulate network disconnect to make sure the L1 is still operating correctly upon reconnecting
032: * within a specified time NOT YET FINISHED
033: *
034: * @author hhuynh
035: */
036: public class L1ReconnectTestApp extends AbstractTransparentApp {
037:
038: public static final String CONFIG_FILE = "config-file";
039: public static final String PORT_NUMBER = "port-number";
040: public static final String HOST_NAME = "host-name";
041:
042: private final ApplicationConfig config;
043:
044: // roots
045: private int[] sum = new int[1];
046:
047: public L1ReconnectTestApp(String appId, ApplicationConfig config,
048: ListenerProvider listenerProvider) {
049: super (appId, config, listenerProvider);
050: this .config = config;
051: }
052:
053: public static void visitL1DSOConfig(ConfigVisitor visitor,
054: DSOClientConfigHelper config) {
055: String testClass = L1ReconnectTestApp.class.getName();
056: String methodExpression = "* " + testClass + "*.*(..)";
057: config.addWriteAutolock(methodExpression);
058: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
059: config.addIncludePattern(testClass + "$*");
060: spec.addRoot("sum", "sum");
061: }
062:
063: public void run() {
064: try {
065: runTest();
066: } catch (Throwable t) {
067: notifyError(t);
068: }
069: }
070:
071: private void runTest() throws Throwable {
072: PortChooser pc = new PortChooser();
073: int dsoPort = Integer
074: .parseInt(config.getAttribute(PORT_NUMBER));
075: int dsoProxyPort = pc.chooseRandomPort();
076:
077: // new TCPProxy(int listenPort, InetAddress destHost, int destPort, long delay, boolean logData, File logDir
078: TCPProxy proxy = new TCPProxy(dsoProxyPort, InetAddress
079: .getLocalHost(), dsoPort, 0L, false, new File("."));
080: proxy.setReuseAddress(true);
081: proxy.start();
082:
083: ExtraL1ProcessControl client = spawnNewClient(dsoProxyPort);
084: // this L1 client will take approximately 100s to finish
085:
086: boolean stopProxy = false;
087: while (!stopProxy) {
088: synchronized (sum) {
089: if (sum[0] > 10)
090: stopProxy = true;
091: }
092: }
093: System.err.println("\n\n### stopping proxy...");
094: proxy.stop();
095: System.err.println("\n\n### stopping proxy...done");
096:
097: ThreadUtil.reallySleep(1 * 1000);
098: System.err.println("\n\n### starting proxy...");
099: proxy.start();
100: System.err.println("\n\n### starting proxy...done");
101:
102: // here we want to simulate network glitches by
103: // turn off the proxy and turn it back on
104:
105: int exitCode = client.waitFor();
106: proxy.status();
107: proxy.stop();
108:
109: if (exitCode != 0) {
110: Assert.failure("L1Client threw exception!");
111: }
112:
113: synchronized (sum) {
114: System.out.println("SUM = " + sum[0]);
115: Assert.assertEquals(99, sum[0]);
116: }
117: }
118:
119: public static class L1Client {
120: // roots
121: private int[] sum = new int[1];
122:
123: // takes roughly 100 seconds to finish
124: public void calculateSum() throws Exception {
125: for (int i = 0; i < 100; i++) {
126: if (i > 0 && (i % 10) == 0)
127: ThreadUtil.reallySleep(10 * 100);
128: synchronized (sum) {
129: sum[0] = i;
130: }
131: System.err.println("\n\n### Transaction # " + i);
132: }
133: }
134:
135: public static void main(String args[]) {
136: try {
137: new L1Client().calculateSum();
138: } catch (Exception e) {
139: e.printStackTrace();
140: System.exit(1);
141: }
142: }
143: }
144:
145: private ExtraL1ProcessControl spawnNewClient(int dsoProxyPort)
146: throws Exception {
147: final String hostName = config.getAttribute(HOST_NAME);
148: final File configFile = new File(config
149: .getAttribute(CONFIG_FILE));
150: final File proxyConfigFile = createNewConfigFile(configFile,
151: dsoProxyPort);
152: File workingDir = new File(configFile.getParentFile(),
153: "l1client");
154: FileUtils.forceMkdir(workingDir);
155:
156: ArrayList jvmArgs = new ArrayList();
157: jvmArgs.add("-Dcom.tc.l1.reconnect.enabled=true");
158:
159: ExtraL1ProcessControl client = new ExtraL1ProcessControl(
160: hostName, 0 /* not used */, L1Client.class,
161: proxyConfigFile.getAbsolutePath(), new String[0],
162: workingDir, jvmArgs);
163: client.start();
164: client.mergeSTDERR();
165: client.mergeSTDOUT();
166: System.err.println("\n### Started New Client");
167: return client;
168: }
169:
170: private File createNewConfigFile(File configFile, int dsoProxyPort)
171: throws Exception {
172: List lines = IOUtils.readLines(new FileInputStream(configFile));
173: for (int i = 0; i < lines.size(); i++) {
174: String line = (String) lines.get(i);
175: if (line.indexOf("dso-port") > 0) {
176: String newLine = line.replaceAll("\\d+", dsoProxyPort
177: + "");
178: lines.set(i, newLine);
179: break;
180: }
181: }
182:
183: File newConfigFile = new File(configFile.getParent(),
184: "tc-config-proxy.xml");
185: IOUtils.writeLines(lines, "\n", new FileOutputStream(
186: newConfigFile));
187:
188: return newConfigFile;
189: }
190:
191: }
|