1 | package de.uka.ipd.sdq.simucomframework.resources; |
2 | |
3 | import de.uka.ipd.sdq.probespec.framework.ISampleBlackboard; |
4 | import de.uka.ipd.sdq.probespec.framework.ProbeSample; |
5 | import de.uka.ipd.sdq.probespec.framework.ProbeSpecContext; |
6 | import de.uka.ipd.sdq.probespec.framework.ProbeType; |
7 | import de.uka.ipd.sdq.probespec.framework.RequestContext; |
8 | import de.uka.ipd.sdq.probespec.framework.calculator.DemandCalculator; |
9 | import de.uka.ipd.sdq.probespec.framework.calculator.HoldTimeCalculator; |
10 | import de.uka.ipd.sdq.probespec.framework.calculator.StateCalculator; |
11 | import de.uka.ipd.sdq.probespec.framework.calculator.WaitingTimeCalculator; |
12 | import de.uka.ipd.sdq.probespec.framework.probes.IProbeStrategy; |
13 | import de.uka.ipd.sdq.probespec.framework.utils.ProbeSpecUtils; |
14 | import de.uka.ipd.sdq.scheduler.IPassiveResource; |
15 | import de.uka.ipd.sdq.scheduler.ISchedulableProcess; |
16 | import de.uka.ipd.sdq.scheduler.sensors.IPassiveResourceSensor; |
17 | import de.uka.ipd.sdq.simucomframework.DiscardInvalidMeasurementsBlackboardDecorator; |
18 | import de.uka.ipd.sdq.simucomframework.SimuComSimProcess; |
19 | import de.uka.ipd.sdq.simucomframework.model.SimuComModel; |
20 | import de.uka.ipd.sdq.simulation.abstractsimengine.ISimulationControl; |
21 | |
22 | /** |
23 | * Offers static methods to setup different types of calculators for resources like |
24 | * {@link AbstractScheduledResource} and {@link IPassiveResource}. |
25 | * |
26 | * @author Philipp Merkle |
27 | * |
28 | */ |
29 | public class CalculatorHelper { |
30 | |
31 | /** |
32 | * Sets up a {@link WaitingTimeCalculator} for the specified resource. Also a |
33 | * {@link IPassiveResourceSensor} will be registered at the resource which gets notified of |
34 | * events that are relevant for calculating the waiting time. When such an event arrives, an |
35 | * appropriate {@link ProbeSample} will be taken and published at the {@link ISampleBlackboard}. |
36 | * |
37 | * @param r |
38 | * the resource |
39 | */ |
40 | public static void setupWaitingTimeCalculator(final IPassiveResource resource, final SimuComModel model) { |
41 | final ProbeSpecContext ctx = model.getProbeSpecContext(); |
42 | |
43 | // build waiting time calculator |
44 | final Integer startWaitingProbeSetId = ctx.obtainProbeSetId("startWaitingPsvRes_" + resource.getId()); |
45 | final Integer stopWaitingProbeSetId = ctx.obtainProbeSetId("stopWaitingPsvRes_" + resource.getId()); |
46 | ctx.getCalculatorFactory().buildWaitingTimeCalculator( |
47 | "Passive Resource " + resource.getName() + " " + resource.getId(), startWaitingProbeSetId, |
48 | stopWaitingProbeSetId); |
49 | |
50 | resource.addObserver(new IPassiveResourceSensor() { |
51 | |
52 | @Override |
53 | public void request(ISchedulableProcess process, int num) { |
54 | // take current time |
55 | ProbeSample currentTimeSample = takeCurrentTimeSample(model.getSimulationControl(), ctx); |
56 | |
57 | // build ProbeSetSample and publish it on the blackboard |
58 | ctx.getSampleBlackboard().addSample( |
59 | ProbeSpecUtils.buildProbeSetSample(currentTimeSample, ((SimuComSimProcess) process) |
60 | .getRequestContext(), "", startWaitingProbeSetId)); |
61 | } |
62 | |
63 | @Override |
64 | public void acquire(ISchedulableProcess process, int num) { |
65 | // take current time |
66 | ProbeSample currentTimeSample = takeCurrentTimeSample(model.getSimulationControl(), ctx); |
67 | |
68 | // build ProbeSetSample and publish it on the blackboard |
69 | ctx.getSampleBlackboard().addSample( |
70 | ProbeSpecUtils.buildProbeSetSample(currentTimeSample, ((SimuComSimProcess) process) |
71 | .getRequestContext(), "", stopWaitingProbeSetId)); |
72 | |
73 | } |
74 | |
75 | @Override |
76 | public void release(ISchedulableProcess process, int num) { |
77 | // nothing to do here |
78 | |
79 | } |
80 | |
81 | }); |
82 | |
83 | } |
84 | |
85 | /** |
86 | * Sets up a {@link HoldTimeCalculator} for the specified resource. Also a |
87 | * {@link IPassiveResourceSensor} will be registered at the resource which gets notified of |
88 | * events that are relevant for calculating the hold time. When such an event arrives, an |
89 | * appropriate {@link ProbeSample} will be taken and published at the {@link ISampleBlackboard}. |
90 | * |
91 | * @param r |
92 | * the resource |
93 | */ |
94 | public static void setupHoldTimeCalculator(final IPassiveResource resource, final SimuComModel model) { |
95 | final ProbeSpecContext ctx = model.getProbeSpecContext(); |
96 | |
97 | // build hold time calculator |
98 | final Integer startHoldProbeSetId = ctx.obtainProbeSetId("startHoldPsvRes_" + resource.getId()); |
99 | final Integer stopHoldProbeSetId = ctx.obtainProbeSetId("stopHoldPsvRes_" + resource.getId()); |
100 | ctx.getCalculatorFactory().buildHoldTimeCalculator( |
101 | "Passive Resource " + resource.getName() + " " + resource.getId(), startHoldProbeSetId, |
102 | stopHoldProbeSetId); |
103 | |
104 | resource.addObserver(new IPassiveResourceSensor() { |
105 | |
106 | @Override |
107 | public void request(ISchedulableProcess process, int num) { |
108 | // nothing to do here |
109 | } |
110 | |
111 | @Override |
112 | public void acquire(ISchedulableProcess process, int num) { |
113 | // take current time |
114 | ProbeSample currentTimeSample = takeCurrentTimeSample(model.getSimulationControl(), ctx); |
115 | |
116 | // build ProbeSetSample and publish it on the blackboard |
117 | ctx.getSampleBlackboard().addSample( |
118 | ProbeSpecUtils.buildProbeSetSample(currentTimeSample, ((SimuComSimProcess) process) |
119 | .getRequestContext(), "", startHoldProbeSetId)); |
120 | } |
121 | |
122 | @Override |
123 | public void release(ISchedulableProcess process, int num) { |
124 | // take current time |
125 | ProbeSample currentTimeSample = takeCurrentTimeSample(model.getSimulationControl(), ctx); |
126 | |
127 | // build ProbeSetSample and publish it on the blackboard |
128 | ctx.getSampleBlackboard().addSample( |
129 | ProbeSpecUtils.buildProbeSetSample(currentTimeSample, ((SimuComSimProcess) process) |
130 | .getRequestContext(), "", stopHoldProbeSetId)); |
131 | } |
132 | }); |
133 | } |
134 | |
135 | /** |
136 | * Sets up a {@link DemandCalculator} for the specified resource. Also a {@link IDemandListener} |
137 | * will be registered at the resource which gets notified of events that are relevant for |
138 | * calculating the demanded time. When such an event arrives, an appropriate {@link ProbeSample} |
139 | * will be taken and published at the {@link ISampleBlackboard}. |
140 | * |
141 | * @param r |
142 | * the resource |
143 | */ |
144 | public static void setupDemandCalculator(final AbstractScheduledResource r, SimuComModel model) { |
145 | final ProbeSpecContext ctx = model.getProbeSpecContext(); |
146 | |
147 | // build demand calculator |
148 | final Integer demandedTimeProbeSetId = ctx.obtainProbeSetId("demandedTimeSchedRes_" + r.getDescription()); |
149 | ctx.getCalculatorFactory().buildDemandCalculator(r.getDescription(), demandedTimeProbeSetId); |
150 | |
151 | r.addDemandListener(new IDemandListener() { |
152 | |
153 | public void demand(double demand) { |
154 | // take current time |
155 | ProbeSample currentTimeSample = takeCurrentTimeSample(r, ctx); |
156 | |
157 | // take demanded time |
158 | ProbeSample demandedTimeSample = takeDemandedTimeSample(r, demand, ctx); |
159 | |
160 | // TODO Check whether the context is unique so that there is at |
161 | // most one job per SimProcess |
162 | // RequestContext context = ((SimProcess) job.getJobParent()) |
163 | // .getRequestContext() |
164 | // .append("_" + job.getCreationTime()); |
165 | |
166 | // build ProbeSetSample and publish it on the blackboard |
167 | RequestContext context = new RequestContext(""); |
168 | ctx.getSampleBlackboard().addSample( |
169 | ProbeSpecUtils.buildProbeSetSample(currentTimeSample, demandedTimeSample, context, "", |
170 | demandedTimeProbeSetId)); |
171 | } |
172 | |
173 | public void demandCompleted(ISchedulableProcess simProcess) { |
174 | // Do nothing. |
175 | } |
176 | }); |
177 | } |
178 | |
179 | /** |
180 | * Sets up a {@link StateCalculator} for the specified resource. Also a {@link IStateListener} |
181 | * will be registered at the resource which gets notified of events that are relevant for |
182 | * calculating the state. When such an event arrives, an appropriate {@link ProbeSample} will be |
183 | * taken and published at the {@link ISampleBlackboard}. |
184 | * |
185 | * @param r |
186 | * the resource |
187 | */ |
188 | public static void setupStateCalculator(final AbstractScheduledResource r, SimuComModel model) { |
189 | final ProbeSpecContext ctx = model.getProbeSpecContext(); |
190 | |
191 | // setup a calculator for each instance |
192 | for (int instance = 0; instance < r.getNumberOfInstances(); instance++) { |
193 | String instanceDescription = r.getDescription(); |
194 | if (r.getNumberOfInstances() > 1) { |
195 | instanceDescription = "Core " + (instance + 1) + " " + instanceDescription; |
196 | } |
197 | |
198 | // build state calculator |
199 | final Integer stateProbeSetID = ctx.obtainProbeSetId("state_" + instanceDescription); |
200 | ctx.getCalculatorFactory().buildStateCalculator(instanceDescription, stateProbeSetID); |
201 | |
202 | r.addStateListener(new IStateListener() { |
203 | @SuppressWarnings("unchecked") |
204 | @Override |
205 | public void stateChanged(int state, int instanceId) { |
206 | // take current time |
207 | ProbeSample currentTimeSample = takeCurrentTimeSample(r, ctx); |
208 | |
209 | // take state |
210 | ProbeSample stateSample = takeStateProbe(state, ctx); |
211 | |
212 | // build ProbeSetSample and publish it on the blackboard |
213 | // TODO maybe null instead of empty string is better here |
214 | RequestContext context = new RequestContext(""); |
215 | ctx.getSampleBlackboard().addSample( |
216 | ProbeSpecUtils.buildProbeSetSample(currentTimeSample, stateSample, context, "", |
217 | stateProbeSetID)); |
218 | } |
219 | }, instance); |
220 | } |
221 | } |
222 | |
223 | public static void setupOverallUtilizationCalculator(final AbstractScheduledResource r, SimuComModel model) { |
224 | final ProbeSpecContext ctx = model.getProbeSpecContext(); |
225 | |
226 | // build state calculator |
227 | final Integer stateProbeSetID = ctx.obtainProbeSetId("overallUtilization_" + r.getDescription()); |
228 | ctx.getCalculatorFactory().buildOverallUtilizationCalculator(r.getDescription(), stateProbeSetID); |
229 | |
230 | r.addOverallUtilizationListener(new IOverallUtilizationListener() { |
231 | |
232 | @Override |
233 | public void utilizationChanged(double resourceDemand, double totalTime) { |
234 | // FIXME This is a hack that allows to add samples to the blackboard even when |
235 | // the simulation has stopped. |
236 | if (!(ctx.getSampleBlackboard() instanceof DiscardInvalidMeasurementsBlackboardDecorator)) { |
237 | return; |
238 | } |
239 | DiscardInvalidMeasurementsBlackboardDecorator blackboard = (DiscardInvalidMeasurementsBlackboardDecorator) ctx |
240 | .getSampleBlackboard(); |
241 | |
242 | // build ProbeSetSamples and publish them on the blackboard |
243 | // TODO maybe null instead of empty string is better here |
244 | RequestContext context = new RequestContext(""); |
245 | blackboard.addSampleAfterSimulationEnd(ProbeSpecUtils.buildProbeSetSample(takeTimeSample(0.0, ctx), |
246 | takeStateProbe(1, ctx), context, "", stateProbeSetID)); |
247 | blackboard.addSampleAfterSimulationEnd(ProbeSpecUtils.buildProbeSetSample(takeTimeSample( |
248 | resourceDemand, ctx), takeStateProbe(0, ctx), context, "", stateProbeSetID)); |
249 | blackboard.addSampleAfterSimulationEnd(ProbeSpecUtils.buildProbeSetSample( |
250 | takeTimeSample(totalTime, ctx), takeStateProbe(1, ctx), context, "", stateProbeSetID)); |
251 | } |
252 | }); |
253 | } |
254 | |
255 | public static void setupStateCalculator(final IPassiveResource resource, final SimuComModel model) { |
256 | final ProbeSpecContext ctx = model.getProbeSpecContext(); |
257 | |
258 | // build state calculator |
259 | final Integer stateProbeSetID = ctx.obtainProbeSetId("state_" + resource.getName() + " " + resource.getId()); |
260 | ctx.getCalculatorFactory().buildStateCalculator( |
261 | "Passive Resource " + resource.getName() + " " + resource.getId(), stateProbeSetID); |
262 | |
263 | resource.addObserver(new IPassiveResourceSensor() { |
264 | |
265 | @Override |
266 | public void request(ISchedulableProcess process, int num) { |
267 | // nothing to do here |
268 | } |
269 | |
270 | @Override |
271 | public void release(ISchedulableProcess process, int num) { |
272 | measureState(); |
273 | } |
274 | |
275 | @Override |
276 | public void acquire(ISchedulableProcess process, int num) { |
277 | measureState(); |
278 | } |
279 | |
280 | @SuppressWarnings("unchecked") |
281 | private void measureState() { |
282 | // take current time |
283 | ProbeSample currentTimeSample = takeCurrentTimeSample(model.getSimulationControl(), ctx); |
284 | |
285 | // take state |
286 | ProbeSample stateSample = takeStateProbe(resource, ctx); |
287 | |
288 | // build ProbeSetSample and publish it on the blackboard |
289 | // TODO maybe null instead of empty string is better here |
290 | RequestContext context = new RequestContext(""); |
291 | ctx.getSampleBlackboard().addSample( |
292 | ProbeSpecUtils |
293 | .buildProbeSetSample(currentTimeSample, stateSample, context, "", stateProbeSetID)); |
294 | } |
295 | |
296 | }); |
297 | } |
298 | |
299 | @SuppressWarnings("unchecked") |
300 | private static ProbeSample takeCurrentTimeSample(SimuComSimProcess thread, ProbeSpecContext ctx) { |
301 | IProbeStrategy probeStrategy = ctx.getProbeStrategyRegistry().getProbeStrategy(ProbeType.CURRENT_TIME, null); |
302 | ProbeSample currentTimeSample = probeStrategy.takeSample("TODO: probeId", |
303 | // TODO add probeID as soon as a ProbeSpec model is used |
304 | thread.getModel().getSimulationControl()); |
305 | return currentTimeSample; |
306 | } |
307 | |
308 | @SuppressWarnings("unchecked") |
309 | private static ProbeSample takeCurrentTimeSample(ISimulationControl simControl, ProbeSpecContext ctx) { |
310 | IProbeStrategy probeStrategy = ctx.getProbeStrategyRegistry().getProbeStrategy(ProbeType.CURRENT_TIME, null); |
311 | ProbeSample currentTimeSample = probeStrategy.takeSample("TODO: probeId", |
312 | // TODO add probeID as soon as a ProbeSpec model is used |
313 | simControl); |
314 | return currentTimeSample; |
315 | } |
316 | |
317 | @SuppressWarnings("unchecked") |
318 | private static ProbeSample takeCurrentTimeSample(final AbstractScheduledResource r, ProbeSpecContext ctx) { |
319 | IProbeStrategy probeStrategy = ctx.getProbeStrategyRegistry().getProbeStrategy(ProbeType.CURRENT_TIME, null); |
320 | ProbeSample currentTimeSample = probeStrategy.takeSample("TODO: probeId", r.getModel().getSimulationControl()); |
321 | return currentTimeSample; |
322 | } |
323 | |
324 | @SuppressWarnings("unchecked") |
325 | private static ProbeSample takeTimeSample(Double time, ProbeSpecContext ctx) { |
326 | IProbeStrategy probeStrategy = ctx.getProbeStrategyRegistry().getProbeStrategy(ProbeType.CURRENT_TIME, null); |
327 | ProbeSample currentTimeSample = probeStrategy.takeSample("TODO: probeId", time); |
328 | return currentTimeSample; |
329 | } |
330 | |
331 | @SuppressWarnings("unchecked") |
332 | private static ProbeSample takeDemandedTimeSample(AbstractScheduledResource r, Double demand, ProbeSpecContext ctx) { |
333 | IProbeStrategy probeStrategy = ctx.getProbeStrategyRegistry().getProbeStrategy(ProbeType.RESOURCE_DEMAND, |
334 | AbstractScheduledResource.class); |
335 | ProbeSample demandedTimeSample = probeStrategy.takeSample("TODO: probeId", |
336 | // TODO add probeID as soon as a ProbeSpec model is used |
337 | demand); |
338 | return demandedTimeSample; |
339 | } |
340 | |
341 | @SuppressWarnings("unchecked") |
342 | private static ProbeSample takeStateProbe(int state, ProbeSpecContext ctx) { |
343 | IProbeStrategy probeStrategy = ctx.getProbeStrategyRegistry().getProbeStrategy(ProbeType.RESOURCE_STATE, |
344 | AbstractScheduledResource.class); |
345 | ProbeSample stateSample = probeStrategy.takeSample("TODO: probeId", state); |
346 | return stateSample; |
347 | } |
348 | |
349 | @SuppressWarnings("unchecked") |
350 | private static ProbeSample takeStateProbe(final IPassiveResource r, ProbeSpecContext ctx) { |
351 | IProbeStrategy probeStrategy = ctx.getProbeStrategyRegistry().getProbeStrategy(ProbeType.RESOURCE_STATE, |
352 | IPassiveResource.class); |
353 | ProbeSample stateSample = probeStrategy.takeSample("TODO: probeId", r); |
354 | return stateSample; |
355 | } |
356 | |
357 | } |