1 4 package com.tc.simulator.container; 5 6 import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean; 7 8 import com.tc.simulator.app.Application; 9 import com.tc.simulator.app.ApplicationBuilder; 10 import com.tc.simulator.app.ApplicationInstantiationException; 11 import com.tc.simulator.app.ErrorContext; 12 import com.tc.simulator.app.GlobalIdGenerator; 13 import com.tc.simulator.control.Control; 14 import com.tc.simulator.control.TCBrokenBarrierException; 15 import com.tc.simulator.listener.OutputListener; 16 import com.tc.simulator.listener.ResultsListener; 17 import com.tc.simulator.listener.StatsListenerFactory; 18 import com.tc.util.Assert; 19 import com.tc.util.TCTimeoutException; 20 import com.tcsimulator.ControlImpl; 21 import com.tcsimulator.listener.ApplicationListenerProvider; 22 23 import java.util.ArrayList ; 24 import java.util.Iterator ; 25 import java.util.List ; 26 27 public final class Container implements Runnable { 28 29 private final ContainerConfig config; 30 private final ContainerState containerState; 31 private final GlobalIdGenerator idGenerator; 32 private final Control control; 33 private final ResultsListener resultsListener; 34 private final ApplicationBuilder applicationBuilder; 35 private final String globalId; 36 37 public Container(ContainerConfig config, ContainerStateFactory containerStateFactory, GlobalIdGenerator idGenerator, 38 Control control, ResultsListener resultsListener, ApplicationBuilder applicationBuilder) { 39 this.config = config; 40 this.idGenerator = idGenerator; 41 this.control = control; 42 this.resultsListener = resultsListener; 43 this.applicationBuilder = applicationBuilder; 44 this.globalId = this.idGenerator.nextId() + ""; 45 46 this.containerState = containerStateFactory.newContainerState(this.globalId); 47 Assert.assertNoNullElements(new Object [] { this.config, this.idGenerator, this.control, this.resultsListener, 48 this.applicationBuilder }); 49 } 50 51 54 public synchronized void run() { 55 Thread.currentThread().setContextClassLoader(applicationBuilder.getContextClassLoader()); 56 57 SynchronizedBoolean isRunning = new SynchronizedBoolean(true); 58 try { 59 if (!validateConfig()) return; 60 if (!waitForStart()) return; 61 Control applicationControl = new ControlImpl(this.config.getApplicationInstanceCount(), this.config 62 .getApplicationInstanceCount()); 63 ContainerExecutionInstance containerExecution = new ContainerExecutionInstance(); 64 65 startInstances(containerExecution, applicationControl); 66 67 if (!waitForAllComplete(applicationControl)) return; 68 notifyResult(containerExecution); 69 } catch (Throwable t) { 70 notifyError("Unexpected error executing application.", t); 71 } finally { 72 isRunning.set(false); 73 this.control.notifyComplete(); 74 try { 75 this.control.waitForAllComplete(this.config.getApplicationExecutionTimeout()); 76 } catch (InterruptedException e) { 77 e.printStackTrace(); 78 } 79 } 80 } 81 82 private boolean validateConfig() { 83 if (this.config.getContainerStartTimeout() < 1) { 84 notifyError(new ContainerConfigException("Container start timeout must be greater than zero.", 85 ContainerConfigException.INVALID_CONTAINER_START_TIMEOUT)); 86 return false; 87 } 88 if (this.config.getApplicationStartTimeout() < 1) { 89 notifyError(new ContainerConfigException("Application start timeout must be greater than zero.", 90 ContainerConfigException.INVALID_APPLICATION_START_TIMEOUT)); 91 return false; 92 } 93 if (this.config.getApplicationExecutionTimeout() == 0) { 94 notifyError(new ContainerConfigException("Application execution timeout must be greater than or less than zero.", 95 ContainerConfigException.INVALID_APPLICATION_EXECUTION_TIMEOUT)); 96 return false; 97 } 98 if (this.config.getApplicationInstanceCount() < 1) { 99 notifyError(new ContainerConfigException("Application instance count must be greater than zero.", 100 ContainerConfigException.INVALID_APPLICATION_INSTANCE_COUNT)); 101 return false; 102 } 103 return true; 104 } 105 106 private boolean waitForStart() throws TCBrokenBarrierException, InterruptedException { 107 boolean rv = false; 108 try { 109 println("Waiting for all containers to start..."); 110 this.control.waitForStart(this.config.getContainerStartTimeout()); 111 rv = true; 112 } catch (TCTimeoutException e) { 113 rv = false; 114 this.resultsListener.notifyStartTimeout(); 115 notifyFailure(); 116 } 117 println("Done waiting for all containers to start."); 118 return rv; 119 } 120 121 124 125 private ApplicationExecutionInstance newExecutionInstance(ContainerExecutionInstance containerExecution, 126 Control applicationControl) 127 throws ApplicationInstantiationException { 128 String appId = this.idGenerator.nextId() + ""; 129 System.err.println("Creating new execution instance: " + appId); 130 OutputListener outputListener = this.containerState.newOutputListener(); 131 ApplicationExecutionInstance executionInstance = new ApplicationExecutionInstance(containerExecution, 132 applicationControl, this.containerState); 133 134 ApplicationListenerProvider appListeners = new ApplicationListenerProvider(outputListener, executionInstance, 135 this.containerState); 136 Application application = applicationBuilder.newApplication(appId, appListeners); 137 executionInstance.setApplication(application); 138 139 return executionInstance; 140 } 141 142 private void println(String msg) { 143 System.out.println("Container: " + msg); 144 } 145 146 private void startInstances(ContainerExecutionInstance containerExecution, Control applicationControl) 147 throws ApplicationInstantiationException { 148 println("Starting application execution..."); 149 for (int i = 0; i < config.getApplicationInstanceCount(); i++) { 150 println("exeution " + (i + 1) + " of " + config.getApplicationInstanceCount()); 151 ApplicationExecutionInstance executionInstance = newExecutionInstance(containerExecution, applicationControl); 152 containerExecution.addExecution(executionInstance); 153 executionInstance.start(); 154 } 155 println("All application executions are started."); 156 } 157 158 private boolean waitForAllComplete(Control applicationControl) throws InterruptedException { 159 println("Waiting for all containers to complete. Timeout: " + config.getApplicationExecutionTimeout()); 160 if (!applicationControl.waitForAllComplete(config.getApplicationExecutionTimeout())) { 161 resultsListener.notifyExecutionTimeout(); 162 notifyFailure(); 163 println("Application execution timed out."); 164 return false; 165 } 166 println("Application execution completed."); 167 return true; 168 } 169 170 private void notifyError(Throwable t) { 171 notifyError("", t); 172 } 173 174 private void notifyError(String message, Throwable t) { 175 notifyError(new ErrorContext(message, t)); 176 } 177 178 private void notifyError(ErrorContext ctxt) { 179 ctxt.dump(System.err); 180 this.resultsListener.notifyError(ctxt); 181 notifyFailure(); 182 } 183 184 private void notifyFailure() { 185 System.err.println(Thread.currentThread() + ": failure"); 186 Thread.dumpStack(); 187 this.resultsListener.notifyResult(new ContainerResult()); 188 } 189 190 private void notifyResult(ContainerExecutionInstance containerExecution) { 191 this.resultsListener.notifyResult(new ContainerResult(containerExecution)); 192 } 193 194 private ApplicationRunner newApplicationRunner(Control applicationControl, ResultsListener appRunnerResultsListener, 195 Application application, StatsListenerFactory statsListenerFactory) { 196 197 ApplicationRunnerConfig exeConfig = new ApplicationRunnerConfig() { 198 public long getStartTimeout() { 199 return config.getApplicationStartTimeout(); 200 } 201 }; 202 203 ApplicationRunner runner = new ApplicationRunner(exeConfig, applicationControl, appRunnerResultsListener, 204 application, statsListenerFactory); 205 206 return runner; 207 } 208 209 212 213 static final class ContainerExecutionInstance { 214 private final List executions = new ArrayList (); 215 private boolean applicationStartTimeout = false; 216 private boolean applicationExecutionTimeout = false; 217 218 synchronized void addExecution(ApplicationExecutionInstance execution) { 219 this.executions.add(execution); 220 } 221 222 synchronized int getExecutionCount() { 223 return this.executions.size(); 224 } 225 226 synchronized void notifyApplicationStartTimeout() { 227 this.applicationStartTimeout = true; 228 } 229 230 synchronized void notifyApplicationExecutionTimeout() { 231 this.applicationExecutionTimeout = true; 232 } 233 234 private synchronized boolean compileResults() { 235 boolean result = true; 236 for (Iterator i = executions.iterator(); i.hasNext();) { 237 ApplicationExecutionInstance execution = (ApplicationExecutionInstance) i.next(); 238 if (!execution.application.interpretResult(execution.result)) result = false; 239 } 240 return result; 241 } 242 243 synchronized boolean getResult() { 244 boolean compiledResults = compileResults(); 245 System.err.println("start timeout: " + this.applicationStartTimeout); 246 System.err.println("execution timeout: " + this.applicationExecutionTimeout); 247 System.err.println("compiled results: " + compiledResults); 248 return !this.applicationStartTimeout && !this.applicationExecutionTimeout && compiledResults; 249 } 250 } 251 252 final class ApplicationExecutionInstance implements ResultsListener { 253 private final ContainerExecutionInstance containerExecution; 254 private final Control applicationControl; 255 private Application application; 256 private Object result; 257 private final StatsListenerFactory statsListenerFactory; 258 259 ApplicationExecutionInstance(ContainerExecutionInstance containerExecution, Control control, 260 StatsListenerFactory statsListenerFactory) { 261 this.containerExecution = containerExecution; 262 this.applicationControl = control; 263 this.statsListenerFactory = statsListenerFactory; 264 } 265 266 void setApplication(Application app) { 267 this.application = app; 268 } 269 270 void start() { 271 ApplicationRunner runner = newApplicationRunner(applicationControl, this, this.application, this.statsListenerFactory); 272 273 ClassLoader loader = application.getClass().getClassLoader(); 274 Thread thread = new Thread (runner); 275 thread.setContextClassLoader(loader); 276 thread.start(); 277 } 278 279 Application getApplication() { 280 return this.application; 281 } 282 283 public void setGlobalId(long globalId) { 284 return; 285 } 286 287 public void notifyStartTimeout() { 288 this.containerExecution.notifyApplicationStartTimeout(); 289 } 290 291 public void notifyExecutionTimeout() { 292 this.containerExecution.notifyApplicationExecutionTimeout(); 293 } 294 295 public void notifyError(ErrorContext ectxt) { 296 Container.this.notifyError(ectxt); 297 } 298 299 public void notifyResult(Object theResult) { 300 this.result = theResult; 301 } 302 303 Object getResult() { 304 return this.result; 305 } 306 307 } 308 309 } | Popular Tags |