1 | package de.uka.ipd.sdq.simucomframework.model; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.List; |
5 | |
6 | import org.apache.log4j.Logger; |
7 | import org.eclipse.emf.common.notify.Notification; |
8 | import org.eclipse.emf.ecore.util.EContentAdapter; |
9 | |
10 | import de.uka.ipd.sdq.errorhandling.SeverityAndIssue; |
11 | import de.uka.ipd.sdq.probespec.framework.BlackboardFactory; |
12 | import de.uka.ipd.sdq.probespec.framework.ISampleBlackboard; |
13 | import de.uka.ipd.sdq.probespec.framework.ProbeSpecContext; |
14 | import de.uka.ipd.sdq.probfunction.math.IProbabilityFunctionFactory; |
15 | import de.uka.ipd.sdq.probfunction.math.impl.ProbabilityFunctionFactoryImpl; |
16 | import de.uka.ipd.sdq.reliability.core.FailureStatistics; |
17 | import de.uka.ipd.sdq.scheduler.ISchedulingFactory; |
18 | import de.uka.ipd.sdq.scheduler.SchedulerModel; |
19 | import de.uka.ipd.sdq.scheduler.factory.SchedulingFactory; |
20 | import de.uka.ipd.sdq.scheduler.resources.active.AbstractActiveResource; |
21 | import de.uka.ipd.sdq.simucomframework.DiscardInvalidMeasurementsBlackboardDecorator; |
22 | import de.uka.ipd.sdq.simucomframework.ResourceRegistry; |
23 | import de.uka.ipd.sdq.simucomframework.SimuComConfig; |
24 | import de.uka.ipd.sdq.simucomframework.SimuComGarbageCollector; |
25 | import de.uka.ipd.sdq.simucomframework.calculator.CalculatorFactory; |
26 | import de.uka.ipd.sdq.simucomframework.calculator.SetupPipesAndFiltersStrategy; |
27 | import de.uka.ipd.sdq.simucomframework.probes.SimuComProbeStrategyRegistry; |
28 | import de.uka.ipd.sdq.simucomframework.resources.IResourceContainerFactory; |
29 | import de.uka.ipd.sdq.simucomframework.resources.SimulatedLinkingResourceContainer; |
30 | import de.uka.ipd.sdq.simucomframework.resources.SimulatedResourceContainer; |
31 | import de.uka.ipd.sdq.simucomframework.simucomstatus.Action; |
32 | import de.uka.ipd.sdq.simucomframework.simucomstatus.Process; |
33 | import de.uka.ipd.sdq.simucomframework.simucomstatus.SimuComStatus; |
34 | import de.uka.ipd.sdq.simucomframework.simucomstatus.SimucomstatusPackage; |
35 | import de.uka.ipd.sdq.simucomframework.usage.IWorkloadDriver; |
36 | import de.uka.ipd.sdq.simucomframework.variables.cache.StoExCache; |
37 | import de.uka.ipd.sdq.simulation.ISimulationListener; |
38 | import de.uka.ipd.sdq.simulation.SimulationResult; |
39 | import de.uka.ipd.sdq.simulation.abstractsimengine.ISimEngineFactory; |
40 | import de.uka.ipd.sdq.simulation.abstractsimengine.ISimulationControl; |
41 | import de.uka.ipd.sdq.simulation.abstractsimengine.ISimulationModel; |
42 | |
43 | /** |
44 | * Central simulation class needed by desmoj. Keeps the simulation state which is not part of the |
45 | * context of threads |
46 | * |
47 | * @author Steffen Becker |
48 | * |
49 | */ |
50 | public class SimuComModel extends SchedulerModel implements ISimulationModel { |
51 | |
52 | protected static Logger logger = Logger.getLogger(SimuComModel.class); |
53 | |
54 | protected ResourceRegistry resourceRegistry; |
55 | private IWorkloadDriver[] workloadDrivers; |
56 | private SimulationResult status = SimulationResult.OK; |
57 | private Throwable errorMessage; |
58 | private SimuComConfig config; |
59 | private long mainMeasurementsCount; |
60 | private ISimEngineFactory simulationEngineFactory; |
61 | private ISimulationControl simControl; |
62 | private SimuComStatus simulationStatus; |
63 | /** List of issues experience during a simulation run of this configuration. */ |
64 | private List<SeverityAndIssue> issues; |
65 | private ProbeSpecContext probeSpecContext; |
66 | private ISchedulingFactory schedulingFactory; |
67 | |
68 | public SimuComModel(SimuComConfig config, SimuComStatus status, ISimEngineFactory factory, |
69 | boolean isRemoteRun) { |
70 | this.config = config; |
71 | this.simulationEngineFactory = factory; |
72 | factory.setModel(this); |
73 | this.simControl = factory.createSimulationControl(); |
74 | resourceRegistry = new ResourceRegistry(this); |
75 | this.simulationStatus = status; |
76 | issues = new ArrayList<SeverityAndIssue>(); |
77 | |
78 | // All following uses of static objects have severy issues. Nobody really thought of |
79 | // e.g. running Simucom in parallel (e.g. to utilise many cores)! |
80 | |
81 | IProbabilityFunctionFactory probFunctionFactory = ProbabilityFunctionFactoryImpl.getInstance(); |
82 | |
83 | probFunctionFactory.setRandomGenerator(config.getRandomGenerator()); |
84 | |
85 | // TODO: This is not thread and hence concurrency safe... |
86 | // initialise Random Generators |
87 | StoExCache.initialiseStoExCache(probFunctionFactory); |
88 | |
89 | // TODO: This is not thread and hence concurrency safe... |
90 | |
91 | |
92 | // set up the resource scheduler |
93 | schedulingFactory = new SchedulingFactory(this); |
94 | |
95 | // set up the measurement framework |
96 | initialiseProbeSpecification(); |
97 | } |
98 | |
99 | private void initialiseProbeSpecification() { |
100 | // create ProbeSpecification context |
101 | probeSpecContext = new ProbeSpecContext(); |
102 | |
103 | // create a blackboard of the specified type |
104 | ISampleBlackboard blackboard = BlackboardFactory.createBlackboard(config.getBlackboardType(), probeSpecContext |
105 | .getThreadManager()); |
106 | |
107 | // decorate the current blackboard in order to discard any measurement that arrives after |
108 | // the simulation end |
109 | ISampleBlackboard decoratedBlackboard = new DiscardInvalidMeasurementsBlackboardDecorator(blackboard, |
110 | simControl); |
111 | |
112 | // initialise ProbeSpecification context |
113 | probeSpecContext.initialise(decoratedBlackboard, new SimuComProbeStrategyRegistry(), new CalculatorFactory(this, |
114 | new SetupPipesAndFiltersStrategy(this))); |
115 | |
116 | // install a garbage collector which keeps track of the samples stored on the blackboard and |
117 | // removes samples when they become obsolete |
118 | SimuComGarbageCollector garbageCollector = new SimuComGarbageCollector(decoratedBlackboard); |
119 | probeSpecContext.setBlackboardGarbageCollector(garbageCollector); |
120 | } |
121 | |
122 | /** |
123 | * @return Gets the list of issues. |
124 | */ |
125 | public List<SeverityAndIssue> getIssues() { |
126 | return issues; |
127 | } |
128 | |
129 | /**Sets the list of issues. |
130 | * @param issues the list of issues to use. May not be {@code null}. |
131 | */ |
132 | public void setIssues(List<SeverityAndIssue> issues) { |
133 | if (issues == null) { |
134 | throw new IllegalArgumentException("issues must not be null. Create and provide an empty list if the list should be reset."); |
135 | } |
136 | this.issues = issues; |
137 | } |
138 | |
139 | /**Adds an issues to the list of issues. |
140 | * @param issue the issue. |
141 | */ |
142 | public void addIssue(SeverityAndIssue issue) { |
143 | this.issues.add(issue); |
144 | } |
145 | |
146 | private void initialiseSimStatus() { |
147 | if (this.config.getVerboseLogging()) { |
148 | EContentAdapter contentAdapter = new EContentAdapter() { |
149 | |
150 | /* (non-Javadoc) |
151 | * @see org.eclipse.emf.ecore.util.EContentAdapter#notifyChanged(org.eclipse.emf.common.notify.Notification) |
152 | */ |
153 | @Override |
154 | public void notifyChanged(Notification notification) { |
155 | super.notifyChanged(notification); |
156 | if (notification.getEventType() == Notification.SET) { |
157 | if (notification.getFeature() == SimucomstatusPackage.eINSTANCE.getProcess_CurrentAction()) { |
158 | Process p = (Process) notification.getNotifier(); |
159 | Action a = (Action) notification.getNewValue(); |
160 | logger.debug("Process "+p.getId()+" changed currentAction to "+a.getClass().getName()); |
161 | } |
162 | } else |
163 | logger.debug("Simulation Status Updated"); |
164 | } |
165 | |
166 | }; |
167 | simulationStatus.eAdapters().add(contentAdapter); |
168 | } |
169 | |
170 | } |
171 | |
172 | @Override |
173 | public void init() { |
174 | // start the workload |
175 | notifyStartListeners(); |
176 | for (IWorkloadDriver w : workloadDrivers) { |
177 | w.run(); |
178 | } |
179 | } |
180 | |
181 | /** |
182 | * Add the given usage scenarios to this simulation run |
183 | * |
184 | * @param workload |
185 | * Usage scenarios to execute during this simulation run |
186 | */ |
187 | public void setUsageScenarios(IWorkloadDriver[] workload) { |
188 | this.workloadDrivers = workload; |
189 | } |
190 | |
191 | /** |
192 | * @return The resource registry storing all simulated resources and their states |
193 | */ |
194 | public ResourceRegistry getResourceRegistry() { |
195 | return resourceRegistry; |
196 | } |
197 | |
198 | /** |
199 | * Create this simulation run's resources using the resource factory given. |
200 | * The factory is queried for the list of IDs of the resources to create and |
201 | * creates and inialises each of them |
202 | * @param resourceContainerFactory The resource factory used to initialse the simulated |
203 | * resources |
204 | */ |
205 | public void initialiseResourceContainer(IResourceContainerFactory resourceContainerFactory) { |
206 | for (String id : resourceContainerFactory.getResourceContainerIDList()) { |
207 | SimulatedResourceContainer rc = (SimulatedResourceContainer) resourceRegistry.createResourceContainer(id); |
208 | resourceContainerFactory.fillResourceContainerWithResources(rc); |
209 | } |
210 | for (String id : resourceContainerFactory.getResourceContainerIDList()) { |
211 | SimulatedResourceContainer rc = (SimulatedResourceContainer) resourceRegistry.getResourceContainer(id); |
212 | resourceContainerFactory.fillResourceContainerWithNestedResourceContainers(rc); |
213 | } |
214 | for (String id : resourceContainerFactory.getLinkingResourceContainerIDList()) { |
215 | SimulatedLinkingResourceContainer rc = (SimulatedLinkingResourceContainer) resourceRegistry.createLinkingResourceContainer(id); |
216 | resourceContainerFactory.fillLinkingResourceContainer(rc); |
217 | } |
218 | resourceRegistry.activateAllActiveResources(); |
219 | } |
220 | |
221 | /** |
222 | * Set the simulation result |
223 | * @param error The new status |
224 | * @param t The exception message if any, null otherwise |
225 | */ |
226 | public void setStatus(SimulationResult error, Throwable t) { |
227 | this.status = error; |
228 | this.errorMessage = t; |
229 | } |
230 | |
231 | /** |
232 | * @return The simulation status |
233 | */ |
234 | public SimulationResult getErrorStatus(){ |
235 | return status; |
236 | } |
237 | |
238 | /** |
239 | * @return The exception caused during the last simulation run. Null |
240 | * if there was no such exception |
241 | */ |
242 | public Throwable getErrorThrowable(){ |
243 | return this.errorMessage; |
244 | } |
245 | |
246 | /** |
247 | * @return The configuration settings of this simulation model instance |
248 | * @deprecated use {@link #getConfiguration()} instead |
249 | */ |
250 | public SimuComConfig getConfig() { |
251 | return config; |
252 | } |
253 | |
254 | public void increaseMainMeasurementsCount() { |
255 | mainMeasurementsCount++; |
256 | } |
257 | |
258 | public long getMainMeasurementsCount() { |
259 | return mainMeasurementsCount; |
260 | } |
261 | |
262 | public ISimulationControl getSimulationControl() { |
263 | return simControl; |
264 | } |
265 | |
266 | public void setSimulationControl(ISimulationControl control) { |
267 | this.simControl = control; |
268 | } |
269 | |
270 | public void setSimulationEngineFactory(ISimEngineFactory factory) { |
271 | this.simulationEngineFactory = factory; |
272 | } |
273 | |
274 | public ISimEngineFactory getSimEngineFactory() { |
275 | return this.simulationEngineFactory; |
276 | } |
277 | |
278 | public SimuComStatus getSimulationStatus() { |
279 | return simulationStatus; |
280 | } |
281 | |
282 | public ProbeSpecContext getProbeSpecContext() { |
283 | return probeSpecContext; |
284 | } |
285 | |
286 | public ISchedulingFactory getSchedulingFactory() { |
287 | return schedulingFactory; |
288 | } |
289 | |
290 | @Override |
291 | public void finalise() { |
292 | notifyStopListeners(); |
293 | |
294 | this.getResourceRegistry().deactivateAllActiveResources(); |
295 | this.getResourceRegistry().deactivateAllPassiveResources(); |
296 | |
297 | logger.info("Simulation took " + getSimulationControl().getCurrentSimulationTime() + " simulation seconds"); |
298 | |
299 | AbstractActiveResource.cleanProcesses(); |
300 | |
301 | // Print failure statistics: |
302 | if (getConfiguration().getSimulateFailures()) { |
303 | FailureStatistics.getInstance().printFailureStatistics(logger); |
304 | } |
305 | |
306 | this.getProbeSpecContext().getThreadManager().stopThreads(); |
307 | } |
308 | |
309 | @Override |
310 | public SimuComConfig getConfiguration() { |
311 | return config; |
312 | } |
313 | |
314 | private void notifyStartListeners() { |
315 | for (ISimulationListener l : config.getListeners()) { |
316 | l.simulationStart(); |
317 | } |
318 | } |
319 | |
320 | private void notifyStopListeners() { |
321 | for (ISimulationListener l : config.getListeners()) { |
322 | l.simulationStop(); |
323 | } |
324 | } |
325 | |
326 | } |