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:
009: import com.tc.management.JMXConnectorProxy;
010: import com.tc.management.beans.L2MBeanNames;
011: import com.tc.object.bytecode.ManagerUtil;
012: import com.tc.object.config.ConfigVisitor;
013: import com.tc.object.config.DSOClientConfigHelper;
014: import com.tc.object.config.TransparencyClassSpec;
015: import com.tc.objectserver.control.ExtraL1ProcessControl;
016: import com.tc.simulator.app.ApplicationConfig;
017: import com.tc.simulator.listener.ListenerProvider;
018: import com.tc.stats.DSOClientMBean;
019: import com.tc.stats.DSOMBean;
020: import com.tc.util.Assert;
021: import com.tc.util.concurrent.ThreadUtil;
022: import com.tctest.runner.AbstractErrorCatchingTransparentApp;
023:
024: import java.io.File;
025: import java.util.ArrayList;
026: import java.util.HashSet;
027: import java.util.List;
028: import java.util.Set;
029: import java.util.concurrent.CyclicBarrier;
030:
031: import javax.management.MBeanServerConnection;
032: import javax.management.MBeanServerInvocationHandler;
033: import javax.management.Notification;
034: import javax.management.NotificationListener;
035: import javax.management.ObjectName;
036:
037: public class ClientDetectionTestApp extends
038: AbstractErrorCatchingTransparentApp implements
039: NotificationListener {
040: public static final String CONFIG_FILE = "config-file";
041: public static final String PORT_NUMBER = "port-number";
042: public static final String HOST_NAME = "host-name";
043: public static final String JMX_PORT = "jmx-port";
044:
045: private ApplicationConfig appConfig;
046: private JMXConnectorProxy jmxc;
047: private MBeanServerConnection mbsc;
048: private DSOMBean dsoMBean;
049:
050: private CyclicBarrier barrier4;
051: private Set channelIdSet = new HashSet();
052:
053: public ClientDetectionTestApp(String appId, ApplicationConfig cfg,
054: ListenerProvider listenerProvider) {
055: super (appId, cfg, listenerProvider);
056: appConfig = cfg;
057:
058: barrier4 = new CyclicBarrier(4);
059: }
060:
061: protected void runTest() throws Throwable {
062: jmxc = new JMXConnectorProxy("localhost", Integer
063: .valueOf(appConfig.getAttribute(JMX_PORT)));
064: mbsc = jmxc.getMBeanServerConnection();
065: dsoMBean = (DSOMBean) MBeanServerInvocationHandler
066: .newProxyInstance(mbsc, L2MBeanNames.DSO,
067: DSOMBean.class, false);
068: getCurrentChannelIds();
069: mbsc
070: .addNotificationListener(L2MBeanNames.DSO, this , null,
071: null);
072:
073: System.out.println("@@@@@@@ I'm online.... id = "
074: + ManagerUtil.getClientID());
075:
076: ExtraL1ProcessControl client1 = spawnNewClient(1);
077: ExtraL1ProcessControl client2 = spawnNewClient(2);
078: ExtraL1ProcessControl client3 = spawnNewClient(3);
079:
080: barrier4.await();
081: assertClientPresent(getDSOClientMBeans(), 4);
082: barrier4.await();
083: client1.attemptShutdown();
084: client2.attemptShutdown();
085: client3.attemptShutdown();
086:
087: Thread.sleep(3000);
088: assertClientPresent(getDSOClientMBeans(), 1);
089: }
090:
091: private DSOClientMBean[] getDSOClientMBeans() {
092: ObjectName[] clientObjectNames = dsoMBean.getClients();
093: DSOClientMBean[] clients = new DSOClientMBean[clientObjectNames.length];
094: for (int i = 0; i < clients.length; i++) {
095: clients[i] = (DSOClientMBean) MBeanServerInvocationHandler
096: .newProxyInstance(mbsc, clientObjectNames[i],
097: DSOClientMBean.class, false);
098: }
099: return clients;
100: }
101:
102: private void getCurrentChannelIds() {
103: for (DSOClientMBean c : getDSOClientMBeans()) {
104: channelIdSet.add(String.valueOf(c.getChannelID().toLong()));
105: }
106: }
107:
108: private void assertClientPresent(DSOClientMBean[] clientMBeans,
109: int expectedCount) throws Exception {
110: ThreadUtil.reallySleep(5000);
111: System.out.println("assertClientPresent: expectedCount = "
112: + expectedCount);
113: Set set = new HashSet<String>();
114: for (DSOClientMBean bean : clientMBeans) {
115: System.out.println("got channel Id from dso bean: "
116: + bean.getChannelID().toLong());
117: set.add(bean.getChannelID().toString()
118: + bean.getRemoteAddress());
119: }
120: System.out.println(set);
121: Assert.assertEquals(expectedCount, clientMBeans.length);
122: Assert.assertEquals(expectedCount, set.size());
123: }
124:
125: private ExtraL1ProcessControl spawnNewClient(int id)
126: throws Exception {
127: final String hostName = appConfig.getAttribute(HOST_NAME);
128: final int port = Integer.parseInt(appConfig
129: .getAttribute(PORT_NUMBER));
130: final File configFile = new File(appConfig
131: .getAttribute(CONFIG_FILE));
132: File workingDir = new File(configFile.getParentFile(),
133: "client-" + id);
134: FileUtils.forceMkdir(workingDir);
135:
136: List jvmArgs = new ArrayList();
137: ExtraL1ProcessControl client = new ExtraL1ProcessControl(
138: hostName, port, L1Client.class, configFile
139: .getAbsolutePath(), new String[0], workingDir,
140: jvmArgs);
141: client.start();
142:
143: client.mergeSTDERR();
144: client.mergeSTDOUT();
145:
146: return client;
147: }
148:
149: public static void visitL1DSOConfig(ConfigVisitor visitor,
150: DSOClientConfigHelper config) {
151:
152: String testClass = ClientDetectionTestApp.class.getName();
153: TransparencyClassSpec spec = config.getOrCreateSpec(testClass);
154: config.addIncludePattern(testClass + "$*", false, false, true);
155:
156: String methodExpression = "* " + testClass + "*.*(..)";
157: config.addWriteAutolock(methodExpression);
158:
159: spec.addRoot("barrier4", "barrier4");
160: }
161:
162: public static class L1Client {
163: CyclicBarrier barrier4 = new CyclicBarrier(4);
164:
165: public static void main(String args[]) throws Exception {
166: System.out.println("@@@@@@@ I'm online.... id = "
167: + ManagerUtil.getClientID());
168: L1Client l1 = new L1Client();
169:
170: System.out.println("entering barrier4");
171: l1.barrier4.await();
172: l1.barrier4.await();
173: }
174: }
175:
176: public void handleNotification(Notification notification,
177: Object handback) {
178: if ("dso.client.attached".equalsIgnoreCase(notification
179: .getType())) {
180: // extract channel id
181: String source = notification.getSource().toString();
182: int index = source.lastIndexOf('=');
183: String channelId = source.substring(index + 1);
184:
185: System.out.println(">>>>> notification of channelId: "
186: + channelId);
187: Assert.assertFalse("duplicate clients notification found",
188: channelIdSet.contains(channelId));
189: channelIdSet.add(channelId);
190: }
191:
192: }
193:
194: }
|