1 | package de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.impl; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Collection; |
5 | import java.util.Collections; |
6 | import java.util.List; |
7 | |
8 | import org.apache.log4j.Logger; |
9 | import org.opt4j.core.Objective; |
10 | import org.opt4j.core.problem.Genotype; |
11 | import org.opt4j.operator.copy.Copy; |
12 | |
13 | import de.uka.ipd.sdq.context.aggregatedUsageContext.AggregatedCommunication; |
14 | import de.uka.ipd.sdq.context.aggregatedUsageContext.AggregatedResourceDemand; |
15 | import de.uka.ipd.sdq.context.aggregatedUsageContext.ComputedAggregatedUsage; |
16 | import de.uka.ipd.sdq.context.aggregatedUsageContext.ServiceExecutionContext; |
17 | import de.uka.ipd.sdq.dsexplore.helper.EMFHelper; |
18 | import de.uka.ipd.sdq.dsexplore.helper.Pair; |
19 | import de.uka.ipd.sdq.dsexplore.launch.DSEWorkflowConfiguration; |
20 | import de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.AbstractTactic; |
21 | import de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.TacticsResultCandidate; |
22 | import de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.UtilisationResultCacheAndHelper; |
23 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividual; |
24 | import de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividualBuilder; |
25 | import de.uka.ipd.sdq.dsexplore.opt4j.start.Opt4JStarter; |
26 | import de.uka.ipd.sdq.dsexplore.qml.handling.QMLConstantsContainer; |
27 | import de.uka.ipd.sdq.dsexplore.qml.reader.QMLDimensionReader; |
28 | import de.uka.ipd.sdq.pcm.allocation.AllocationContext; |
29 | import de.uka.ipd.sdq.pcm.designdecision.AllocationDegree; |
30 | import de.uka.ipd.sdq.pcm.designdecision.CapacityDegree; |
31 | import de.uka.ipd.sdq.pcm.designdecision.Choice; |
32 | import de.uka.ipd.sdq.pcm.designdecision.DiscreteRangeChoice; |
33 | import de.uka.ipd.sdq.pcm.designdecision.ClassChoice; |
34 | import de.uka.ipd.sdq.pcm.designdecision.ClassDegree; |
35 | import de.uka.ipd.sdq.pcm.designdecision.SchedulingPolicyChoice; |
36 | import de.uka.ipd.sdq.pcm.designdecision.SchedulingPolicyDegree; |
37 | import de.uka.ipd.sdq.pcm.repository.BasicComponent; |
38 | import de.uka.ipd.sdq.pcm.repository.PassiveResource; |
39 | import de.uka.ipd.sdq.pcm.repository.Repository; |
40 | import de.uka.ipd.sdq.pcm.repository.RepositoryComponent; |
41 | import de.uka.ipd.sdq.pcm.resourceenvironment.CommunicationLinkResourceSpecification; |
42 | import de.uka.ipd.sdq.pcm.resourceenvironment.ProcessingResourceSpecification; |
43 | import de.uka.ipd.sdq.pcm.resourceenvironment.ResourceContainer; |
44 | import de.uka.ipd.sdq.pcm.resourceenvironment.SchedulingPolicy; |
45 | import de.uka.ipd.sdq.pcm.resourcetype.ResourceType; |
46 | import de.uka.ipd.sdq.pcm.resultdecorator.ResultDecoratorRepository; |
47 | import de.uka.ipd.sdq.pcm.resultdecorator.repositorydecorator.ServiceResult; |
48 | import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.PassiveResourceResult; |
49 | import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.ProcessingResourceSpecificationResult; |
50 | import de.uka.ipd.sdq.pcm.resultdecorator.resourceenvironmentdecorator.UtilisationResult; |
51 | import de.uka.ipd.sdq.pcm.usagemodel.UsageScenario; |
52 | import de.uka.ipd.sdq.pcmsolver.models.PCMInstance; |
53 | |
54 | public class ConcurrentProcessingSystemImplCatia extends AbstractTactic { |
55 | |
56 | private Objective performance; |
57 | |
58 | |
59 | protected static Logger logger = Logger |
60 | .getLogger(ConcurrentProcessingSystemImplCatia.class.getName()); |
61 | |
62 | public ConcurrentProcessingSystemImplCatia(Copy<Genotype> copy, |
63 | DSEIndividualBuilder individualBuilder, |
64 | DSEWorkflowConfiguration configuration) { |
65 | super(copy, individualBuilder, configuration, new String[] {QMLConstantsContainer.QUALITY_ATTRIBUTE_DIMENSION_RESPONSETIME_DEFINITION_PATH, |
66 | QMLConstantsContainer.QUALITY_ATTRIBUTE_DIMENSION_THROUGHPUT_DEFINITION_PATH}); |
67 | try { |
68 | Collection<Objective> objectives = Opt4JStarter.getDSEEvaluator() |
69 | .getObjectives(); |
70 | for (Objective objective : objectives) { |
71 | //XXX: Read the dimension name from definition rather than the constants container |
72 | if (objective.getName().contains( |
73 | new QMLDimensionReader().getDimension(QMLConstantsContainer.QUALITY_ATTRIBUTE_DIMENSION_RESPONSETIME_DEFINITION_PATH).getEntityName()) |
74 | || objective.getName().contains( |
75 | new QMLDimensionReader().getDimension(QMLConstantsContainer.QUALITY_ATTRIBUTE_DIMENSION_THROUGHPUT_DEFINITION_PATH).getEntityName())) { |
76 | //DSEConstantsContainer.MEAN_RESPONSE_TIME_QUALITY)) { |
77 | this.performance = objective; |
78 | break; |
79 | } |
80 | } |
81 | } catch (Exception e) { |
82 | // TODO: handle exception |
83 | } |
84 | |
85 | } |
86 | |
87 | //@author catia: find the max utilised cpu |
88 | public int getMaxUtilisedCpu(List<ActiveResInfo> list) { |
89 | int position = 0; |
90 | int temp = 0; |
91 | for (ActiveResInfo el : list) { |
92 | if (el.type.getEntityName().equals("CPU") && (el.utilisation > list.get(position).utilisation)) { |
93 | position = temp; |
94 | } |
95 | temp++; |
96 | } |
97 | return position; |
98 | } |
99 | |
100 | //@author catia: find the max utilised hdd |
101 | public int getMaxUtilisedHdd(List<ActiveResInfo> list) { |
102 | int position = 0; |
103 | int temp = 0; |
104 | for (ActiveResInfo el : list) { |
105 | if (el.type.getEntityName().equals("HDD") && (el.utilisation > list.get(position).utilisation)) { |
106 | position = temp; |
107 | } |
108 | temp++; |
109 | } |
110 | return position; |
111 | } |
112 | |
113 | //@author catia: find the max utilised active resource |
114 | public int getMaxUtilisedActiveRes(List<ActiveResInfo> list) { |
115 | int position = 0; |
116 | int temp = 0; |
117 | for (ActiveResInfo el : list) { |
118 | if (el.utilisation > list.get(position).utilisation) { |
119 | position = temp; |
120 | } |
121 | temp++; |
122 | } |
123 | return position; |
124 | } |
125 | |
126 | //@author catia: get over used CPU resources whose queue length exceeds a threshold |
127 | public List<ActiveResInfo> getOverUsedCpu(List<ActiveResInfo> list){ |
128 | List<ActiveResInfo> result = new ArrayList<ActiveResInfo>(0); |
129 | |
130 | //@author catia: threshold value for max CPU utilisation |
131 | double thresholdMaxCpu = new Thresholds().thresholdMaxCpu; |
132 | |
133 | // @author catia: threshold value for max queue length |
134 | double thresholdCpuQL = new Thresholds().thresholdCpuQL; |
135 | |
136 | for (ActiveResInfo el : list) { |
137 | if((el.type.getEntityName().equals("CPU")) && (el.utilisation > thresholdMaxCpu) && (el.queueLength > thresholdCpuQL)){ |
138 | result.add(el); |
139 | } |
140 | } |
141 | return result; |
142 | } |
143 | |
144 | //@author catia: get under used CPU resources |
145 | public List<ActiveResInfo> getUnderUsedCpu(List<ActiveResInfo> list){ |
146 | List<ActiveResInfo> result = new ArrayList<ActiveResInfo>(0); |
147 | |
148 | //@author catia: threshold value for min CPU utilisation |
149 | double thresholdMinCpu = new Thresholds().thresholdMinCpu; |
150 | |
151 | for (ActiveResInfo el : list) { |
152 | if((el.type.getEntityName().equals("CPU")) && (el.utilisation < thresholdMinCpu)){ |
153 | result.add(el); |
154 | } |
155 | } |
156 | return result; |
157 | } |
158 | |
159 | //@author catia: get over used HDD resources whose queue length exceeds a threshold |
160 | public List<ActiveResInfo> getOverUsedHDD(List<ActiveResInfo> list){ |
161 | List<ActiveResInfo> result = new ArrayList<ActiveResInfo>(0); |
162 | |
163 | //@author catia: threshold value for max HDD utilisation |
164 | double thresholdMaxHdd = new Thresholds().thresholdMaxHdd; |
165 | |
166 | // @author catia: threshold value for max queue length |
167 | double thresholdHddQL = new Thresholds().thresholdHddQL; |
168 | |
169 | for (ActiveResInfo el : list) { |
170 | if((el.type.getEntityName().equals("HDD")) && (el.utilisation > thresholdMaxHdd) && (el.queueLength > thresholdHddQL)){ |
171 | result.add(el); |
172 | } |
173 | } |
174 | return result; |
175 | } |
176 | |
177 | //@author catia: get under used HDD resources |
178 | public List<ActiveResInfo> getUnderUsedHDD(List<ActiveResInfo> list){ |
179 | List<ActiveResInfo> result = new ArrayList<ActiveResInfo>(0); |
180 | |
181 | //@author catia: threshold value for min CPU utilisation |
182 | double thresholdMinHdd = new Thresholds().thresholdMinHdd; |
183 | |
184 | for (ActiveResInfo el : list) { |
185 | if((el.type.getEntityName().equals("HDD")) && (el.utilisation < thresholdMinHdd)){ |
186 | result.add(el); |
187 | } |
188 | } |
189 | return result; |
190 | } |
191 | |
192 | //@author catia: get critical passive resources |
193 | //Assumption: a passive resource is considered "critical" if its queue length exceeds a threshold value |
194 | //and the waiting time is more than the double of the holding time |
195 | public List<PassiveResInfo> getCriticalPassiveRes(List<PassiveResInfo> list){ |
196 | List<PassiveResInfo> result = new ArrayList<PassiveResInfo>(0); |
197 | |
198 | //@author catia: threshold value for max queue length of passive resources |
199 | double thresholdPrQL = new Thresholds().thresholdPrQL; |
200 | |
201 | for (PassiveResInfo el : list) { |
202 | if((el.queueLength > thresholdPrQL) && (el.waitingTime > (el.holdingTime * 2))){ |
203 | result.add(el); |
204 | } |
205 | } |
206 | return result; |
207 | } |
208 | |
209 | //@author catia: check if a component is already stored for its resource demand (cpu, hdd) |
210 | public boolean compOccurrence(List<CompInfoResDemand> list, AllocationContext a) { |
211 | boolean value = false; |
212 | for (CompInfoResDemand compInfoResDemand : list) { |
213 | if (compInfoResDemand.ac == a) { |
214 | value = true; |
215 | } |
216 | } |
217 | return value; |
218 | } |
219 | |
220 | //@author catia: increment the computation (cpu demand) of a component |
221 | public void incrementComputation(List<CompInfoResDemand> list, |
222 | AllocationContext b, double value) { |
223 | for (CompInfoResDemand compInfoResDemand : list) { |
224 | if (compInfoResDemand.ac == b) { |
225 | compInfoResDemand.computation = compInfoResDemand.computation |
226 | + value; |
227 | } |
228 | } |
229 | } |
230 | |
231 | //@author catia: increment the storage (hdd demand) of a component |
232 | public void incrementStorage(List<CompInfoResDemand> list, |
233 | AllocationContext b, double value) { |
234 | for (CompInfoResDemand compInfoResDemand : list) { |
235 | if (compInfoResDemand.ac == b) { |
236 | compInfoResDemand.storage = compInfoResDemand.storage + value; |
237 | } |
238 | } |
239 | } |
240 | |
241 | //@author catia: update the frequency of a seff |
242 | public void updateFrequency (List<ServiceInfo> list, String seffName, String compName, double f){ |
243 | for (ServiceInfo el: list){ |
244 | if (el.serviceName.equals(seffName) && el.compName.equals(compName)){ |
245 | el.frequency = f; |
246 | } |
247 | } |
248 | } |
249 | |
250 | //@author catia: check if the list of seffs is unbalanced |
251 | //Assumption - a list of seffs is considered "unbalanced" if the maximum and |
252 | //the minimum response time among them is higher than a threshold value |
253 | public boolean unbalancedSeffs(List<ServiceInfo> list){ |
254 | boolean result = false; |
255 | // threshold value, i.e. the allowed gap between the maximum and the minimum response time of seffs |
256 | double gapRT = 0.5; |
257 | |
258 | if ( (getMaxRT(list) - getMinRT(list)) > gapRT ){ |
259 | result = true; |
260 | logger.info("The list of seffs is unbalanced, the maximum resp. time is " |
261 | + getMaxRT(list) + " and the minimum one is " + getMinRT(list)); |
262 | } |
263 | return result; |
264 | } |
265 | |
266 | //@author catia: detection of the antipattern CPS (Concurrent Processing Systems) |
267 | public boolean cps(List<ActiveResInfo> list) { |
268 | boolean result = false; |
269 | if ((getOverUsedCpu(list).size() != 0 && getUnderUsedCpu(list).size() != 0) |
270 | || (getOverUsedHDD(list).size() != 0 && getUnderUsedHDD(list).size() != 0)) { |
271 | logger.info("The antipattern CONCURRENT PROCESSING SYSTEMS has been detected"); |
272 | result = true; |
273 | } |
274 | return result; |
275 | } |
276 | |
277 | //@author catia: detection of the antipattern OLB (One-Lane Bridge) |
278 | public boolean olb(List<ServiceInfo> list, PassiveResInfo criticPassiveRes) { |
279 | boolean result = false; |
280 | for (ServiceInfo el : list) { |
281 | if (el.compName.equals(criticPassiveRes.component)) { |
282 | if (el.respT > el.userReq) { |
283 | result = true; |
284 | } |
285 | } |
286 | } |
287 | if (result) { |
288 | logger.info("The antipattern ONE-LANE BRIDGE has been detected"); |
289 | } |
290 | return result; |
291 | } |
292 | |
293 | //@author catia: detection of the antipattern EP (Extensive Processing) |
294 | public boolean ep(ActiveResInfo activeRes, List<ServiceInfo> list) { |
295 | boolean result = false; |
296 | if ( (activeRes.schedulingPolicy.equals("FCFS")) && (unbalancedSeffs(list))) { |
297 | result = true; |
298 | logger.info("The antipattern EXTENSIVE PROCESSING has been detected"); |
299 | } |
300 | return result; |
301 | } |
302 | |
303 | //@author catia: find the component that requires the most high cpu demand |
304 | public int getCompMaxCPUdemand(List<CompInfoResDemand> list) { |
305 | int position = 0; |
306 | int temp = 0; |
307 | for (CompInfoResDemand compInfoResDemand : list) { |
308 | if (compInfoResDemand != null) { |
309 | if (list.get(position).computation < compInfoResDemand.computation) { |
310 | position = temp; |
311 | } |
312 | } |
313 | temp++; |
314 | } |
315 | return position; |
316 | } |
317 | |
318 | //@author catia: find the component that requires the most high hdd demand |
319 | public int getCompMaxHDDdemand(List<CompInfoResDemand> list) { |
320 | int position = 0; |
321 | int temp = 0; |
322 | for (CompInfoResDemand compInfoResDemand : list) { |
323 | if (compInfoResDemand != null) { |
324 | if (list.get(position).storage < compInfoResDemand.storage) { |
325 | position = temp; |
326 | } |
327 | } |
328 | temp++; |
329 | } |
330 | return position; |
331 | } |
332 | |
333 | //@author catia: give the components deployed on a node |
334 | public List<CompInfoResDemand> deployedComponents(List<CompInfoResDemand> comp, ResourceContainer node) { |
335 | List<CompInfoResDemand> result = new ArrayList<CompInfoResDemand>(0); |
336 | for (CompInfoResDemand compInfoResDemand : comp) { |
337 | if (compInfoResDemand.rc == node) { |
338 | result.add(compInfoResDemand); |
339 | } |
340 | } |
341 | return result; |
342 | } |
343 | |
344 | //@author catia: give the seffs provided by a basic component |
345 | public List<ServiceInfo> getSeffsOfComp(List<ServiceInfo> list, String comp) { |
346 | List<ServiceInfo> result = new ArrayList<ServiceInfo>(0); |
347 | for (ServiceInfo el : list) { |
348 | if (el.compName.equals(comp)) { |
349 | result.add(el); |
350 | } |
351 | } |
352 | return result; |
353 | } |
354 | |
355 | //@author catia: provide the maximum response time among a list of seffs |
356 | public double getMaxRT(List<ServiceInfo> list) { |
357 | double temp = 0.0; |
358 | for (ServiceInfo el : list) { |
359 | if (el.respT > temp) { |
360 | temp = el.respT; |
361 | } |
362 | } |
363 | return temp; |
364 | } |
365 | |
366 | //@author catia: provide the minimum response time among a list of seffs |
367 | public double getMinRT(List<ServiceInfo> list) { |
368 | double temp = getMaxRT(list); |
369 | for (ServiceInfo el : list) { |
370 | if (el.respT < temp) { |
371 | temp = el.respT; |
372 | } |
373 | } |
374 | return temp; |
375 | } |
376 | |
377 | |
378 | /* |
379 | * (non-Javadoc) |
380 | * |
381 | * @see |
382 | * de.uka.ipd.sdq.dsexplore.opt4j.optimizer.heuristic.operators.ITactic# |
383 | * doesMatchPrecondition |
384 | * (de.uka.ipd.sdq.dsexplore.opt4j.representation.DSEIndividual) |
385 | */ |
386 | public boolean doesMatchPrecondition(DSEIndividual i) { |
387 | return getSolution(i) != null; |
388 | } |
389 | |
390 | public List<TacticsResultCandidate> getSolution(DSEIndividual i) { |
391 | // check that performance is optimised |
392 | if (performance != null |
393 | && i.getObjectives().getResultDecoratorFor(this.performance) != null) { |
394 | |
395 | ResultDecoratorRepository resultRepo = i.getObjectives().getResultDecoratorFor(this.performance); |
396 | |
397 | logger.info("---------------------------------------------------------------------"); |
398 | logger.info("System response time: " + i.getObjectives().get(performance).getDouble()); |
399 | logger.info("---------------------------------------------------------------------"); |
400 | |
401 | // AM: response time of SEFFs |
402 | List<ServiceResult> serviceResultList = resultRepo.getServiceResult_ResultDecoratorRepository(); |
403 | |
404 | //@author catia: the list of SEFFs is stored in the ServiceInfo data structure |
405 | List<ServiceInfo> serviceInfoList = new ArrayList<ServiceInfo>(serviceResultList.size()); |
406 | |
407 | //@author catia: user requirements for all services are currently set to 0.001 |
408 | |
409 | for (ServiceResult serviceResult : serviceResultList) { |
410 | |
411 | serviceInfoList.add(new ServiceInfo(serviceResult.getServiceEffectSpecification_ServiceResult().getDescribedService__SEFF().getEntityName(), |
412 | serviceResult.getServiceEffectSpecification_ServiceResult().getBasicComponent_ServiceEffectSpecification().getEntityName(), |
413 | 0.001, serviceResult.getMeanResponseTime(), 0.0)); |
414 | } |
415 | |
416 | |
417 | |
418 | //@author catia: the list of services is printed when the frequency is set (according to the usage model) |
419 | |
420 | // select the results of active resources (CPU, HDD, ...), and passive resources |
421 | // not network yet. |
422 | List<UtilisationResult> allUtilResults = resultRepo.getUtilisationResults_ResultDecoratorRepository(); |
423 | |
424 | // List to contain all active resource results |
425 | List<ProcessingResourceSpecificationResult> utilResults = new ArrayList<ProcessingResourceSpecificationResult>(allUtilResults.size()); |
426 | |
427 | // list to contain all passive resource results |
428 | List<PassiveResourceResult> passiveResourceUtilResults = new ArrayList<PassiveResourceResult>(5); |
429 | |
430 | //iterate through utilisation results and add them to the right list. |
431 | for (UtilisationResult anyUtilResult : allUtilResults) { |
432 | if (anyUtilResult instanceof ProcessingResourceSpecificationResult) { |
433 | utilResults.add((ProcessingResourceSpecificationResult) anyUtilResult); |
434 | } else if (anyUtilResult instanceof PassiveResourceResult ){ |
435 | passiveResourceUtilResults.add((PassiveResourceResult)anyUtilResult); |
436 | ((PassiveResourceResult)anyUtilResult).getAverageQueueLength(); |
437 | ((PassiveResourceResult)anyUtilResult).getAverageWaitTime(); |
438 | } |
439 | } |
440 | |
441 | // util results can be network util (not yet filled with values) or active resource utils |
442 | |
443 | //@author catia: the list of active resources is stored in the ActiveResInfo data structure |
444 | List<ActiveResInfo> activeResInfoList = new ArrayList<ActiveResInfo>(utilResults.size()); |
445 | |
446 | for (UtilisationResult utilisationResult : utilResults) { |
447 | if (utilisationResult instanceof ProcessingResourceSpecificationResult) { |
448 | ProcessingResourceSpecificationResult activeProcUtilResult = (ProcessingResourceSpecificationResult) utilisationResult; |
449 | // retrieve the processor for which this is the result |
450 | ProcessingResourceSpecification resource = activeProcUtilResult.getProcessingResourceSpecification_ProcessingResourceSpecificationResult(); |
451 | // You can retrieve the utilisation value |
452 | // double util = activeProcUtilResult.getResourceUtilisation(); |
453 | // double averageQueueLength = activeProcUtilResult.getAverageQueueLength(); |
454 | // does not work with the LQN solver, and is not tested yet for SimuCom. |
455 | // int maxQueueLength = activeProcUtilResult.getMaxQueueLength(); |
456 | |
457 | // AM: added queue length and scheduling here |
458 | activeResInfoList.add(new ActiveResInfo(resource.getResourceContainer_ProcessingResourceSpecification(), |
459 | resource.getActiveResourceType_ActiveResourceSpecification(), |
460 | activeProcUtilResult.getResourceUtilisation(), |
461 | activeProcUtilResult.getAverageQueueLength(), resource.getSchedulingPolicy().getName())); |
462 | |
463 | } |
464 | // Other possible results are for network: |
465 | // LinkingResourceResults or for the whole resource container: |
466 | // ResourceContainerResult, both are not yet filled with values. |
467 | } |
468 | |
469 | logger.info("List of Active Resources: "); |
470 | |
471 | for (ActiveResInfo el : activeResInfoList) { |
472 | el.print(); |
473 | } |
474 | |
475 | logger.info("---------------------------------------------------------------------"); |
476 | logger.info("Max utilised hardware resources: "); |
477 | |
478 | //@author catia: select the active resource maximum utilised |
479 | logger.info("Max utilised active resource: "); |
480 | ActiveResInfo maxUtilised = new ActiveResInfo(activeResInfoList.get(getMaxUtilisedActiveRes(activeResInfoList))); |
481 | maxUtilised.print(); |
482 | |
483 | //@author catia: select the cpu maximum utilised |
484 | logger.info("Max utilised cpu resource: "); |
485 | ActiveResInfo maxUtilisedCpu = new ActiveResInfo(activeResInfoList.get(getMaxUtilisedCpu(activeResInfoList))); |
486 | maxUtilisedCpu.print(); |
487 | |
488 | //@author catia: select the hdd maximum utilised |
489 | logger.info("Max utilised hdd resource: "); |
490 | ActiveResInfo maxUtilisedHdd = new ActiveResInfo(activeResInfoList.get(getMaxUtilisedHdd(activeResInfoList))); |
491 | maxUtilisedHdd.print(); |
492 | |
493 | logger.info("---------------------------------------------------------------------"); |
494 | |
495 | // results for the services |
496 | ComputedAggregatedUsage computedUsage = i.getObjectives().getComputedAggregatedUsageFor(this.performance); |
497 | List<ServiceExecutionContext> serviceContexts = computedUsage.getServiceExecutionContexts_ComputedAggregatedUsage(); |
498 | |
499 | //@author catia: store the components and their resource demands according to the usage model |
500 | List<CompInfoResDemand> listCompIDs = new ArrayList<CompInfoResDemand>(serviceContexts.size()); |
501 | |
502 | for (ServiceExecutionContext serviceExecutionContext : serviceContexts) { |
503 | |
504 | // the global frequency of calling this service if its usage |
505 | // scenario is called once. |
506 | // Note that there may be several ServiceExecutionContext for |
507 | // one service in this list because |
508 | // there is up to one ServiceExecutionContext for each |
509 | // AssemblyContext (= component instance) |
510 | // and each UsageScenario. |
511 | // We cannot combine the frequencies of |
512 | // usage scenarios on the dependency solver level for closed |
513 | // workloads, because the throughput is depending |
514 | // on the performance prediction. |
515 | |
516 | UsageScenario usageScenario = serviceExecutionContext.getUsageScenario_ServiceExecutionContext(); |
517 | |
518 | AllocationContext allocationContext = serviceExecutionContext.getAllocationContext_ServiceExecutionContext(); |
519 | |
520 | // AM: this is the execution probability for a SEFF (see above, |
521 | // for one execution of the usage scenario!) |
522 | double frequency = serviceExecutionContext |
523 | .getGlobalExecutionFrequency(); |
524 | |
525 | //@author catia: store the current basic component the "serviceExecutionContext" refers to. |
526 | BasicComponent currentBasicComp = serviceExecutionContext.getDescribedSEFF_ServiceExecutionContext().getBasicComponent_ServiceEffectSpecification(); |
527 | |
528 | //@author catia: store the current allocation context the "serviceExecutionContext" refers to. |
529 | AllocationContext currentCompAllCont = serviceExecutionContext.getAllocationContext_ServiceExecutionContext(); |
530 | |
531 | if (!compOccurrence(listCompIDs, currentCompAllCont)) { |
532 | listCompIDs.add(new CompInfoResDemand(currentBasicComp, currentCompAllCont, |
533 | allocationContext.getResourceContainer_AllocationContext(), 0.0, 0.0)); |
534 | } |
535 | |
536 | //logger.info("TEST seff " + serviceExecutionContext.getDescribedSEFF_ServiceExecutionContext().getDescribedService__SEFF().getEntityName() + " frequency: " + frequency); |
537 | |
538 | String seffName = serviceExecutionContext.getDescribedSEFF_ServiceExecutionContext().getDescribedService__SEFF().getEntityName(); |
539 | |
540 | //@author catia: update the frequency of the seff - to be checked |
541 | updateFrequency (serviceInfoList, seffName, currentBasicComp.getEntityName(), frequency ); |
542 | |
543 | logger.info(" "); |
544 | logger.info("Service "+serviceExecutionContext.getDescribedSEFF_ServiceExecutionContext().getDescribedService__SEFF().getEntityName() |
545 | + " of component " + |
546 | serviceExecutionContext.getDescribedSEFF_ServiceExecutionContext().getBasicComponent_ServiceEffectSpecification().getEntityName() |
547 | + " in allocation context "+ |
548 | allocationContext.getEntityName() |
549 | + " on server "+ |
550 | allocationContext.getResourceContainer_AllocationContext().getEntityName() |
551 | + " has frequency "+frequency |
552 | + " in usage scenario "+usageScenario.getEntityName()); |
553 | // + " The resource demands are the following: "); |
554 | |
555 | // the weighted average resource demands per resource type as a list |
556 | List<AggregatedResourceDemand> aggregatedResourceDemandList = serviceExecutionContext |
557 | .getAggregatedResourceDemands_ServiceExecutionContext(); |
558 | for (AggregatedResourceDemand aggregatedResourceDemand : aggregatedResourceDemandList) { |
559 | // the resource type of this resource demand |
560 | ResourceType resourceType = aggregatedResourceDemand |
561 | .getResourceType_AggregatedResourceDemand(); |
562 | |
563 | // the weighted average resource demand for this resource type |
564 | double demand = aggregatedResourceDemand |
565 | .getAggregatedResourceDemand(); |
566 | |
567 | // logger.info("Demand "+demand+" on the "+resourceType.getEntityName()); |
568 | |
569 | // @author catia: if the "resourceType" is a CPU then increment computation demand |
570 | if (resourceType.getEntityName().equals("CPU")) { |
571 | incrementComputation(listCompIDs, currentCompAllCont, demand); |
572 | } |
573 | // @author catia: if the "resourceType" is a HDD then increment storage demand |
574 | if (resourceType.getEntityName().equals("HDD")) { |
575 | incrementStorage(listCompIDs, currentCompAllCont, demand); |
576 | } |
577 | } |
578 | |
579 | // logger.info("The service sends the following messages: "); |
580 | // the message information |
581 | List<AggregatedCommunication> communicationInfoList = serviceExecutionContext |
582 | .getSentAggregatedCommunications_ServiceExecutionContext(); |
583 | // The list contains one AggregatedCommunication per |
584 | // communication betwen two ServiceExcecutionContexts. |
585 | for (AggregatedCommunication aggregatedCommunication : communicationInfoList) { |
586 | |
587 | // the message frequency is relative to the probability of |
588 | // the caller being executed |
589 | // That means, if the caller has just a probability of 0.5 |
590 | // of being executed in a usage scenario, and |
591 | // the relativeMessageFrequency here has a frequency of 0.3, |
592 | // then the overall probability |
593 | // that this message is sent in this UsageScenario is 0.15. |
594 | //double relativeMessageFrequency = aggregatedCommunication |
595 | // .getAverageMessageFrequency(); |
596 | |
597 | // the communication link resource that is used. Is null if |
598 | // this is a local call. |
599 | CommunicationLinkResourceSpecification link = aggregatedCommunication |
600 | .getUsedCommunicationLinkResourceSpecification_AggregatedCommunication(); |
601 | |
602 | // not yet implemented |
603 | //double averageMessageSize = aggregatedCommunication |
604 | // .getAverageMessageSize(); |
605 | |
606 | // logger.info(relativeMessageFrequency |
607 | // + |
608 | // " messages to service "+aggregatedCommunication.getCommunicationPartner_AggregatedCommunication().getDescribedSEFF_ServiceExecutionContext().getDescribedService__SEFF().getEntityName() |
609 | // + " of component " + |
610 | // aggregatedCommunication.getCommunicationPartner_AggregatedCommunication().getDescribedSEFF_ServiceExecutionContext().getBasicComponent_ServiceEffectSpecification().getEntityName() |
611 | // + " in allocation context "+ |
612 | // aggregatedCommunication.getCommunicationPartner_AggregatedCommunication().getAllocationContext_ServiceExecutionContext().getEntityName() |
613 | // + ". The average message size is "+averageMessageSize); |
614 | if (link != null) { |
615 | // logger.info("The communication is remote over link "+link.getId() |
616 | // + |
617 | // " of type "+link.getCommunicationLinkResourceType_CommunicationLinkResourceSpecification().getEntityName()); |
618 | } |
619 | } |
620 | |
621 | } |
622 | |
623 | logger.info("List of all SEFFs with the frequency value: "); |
624 | for (ServiceInfo el : serviceInfoList) { |
625 | el.print(); |
626 | } |
627 | logger.info("---------------------------------------------------------------------"); |
628 | |
629 | List<TacticsResultCandidate> listPairs = new ArrayList<TacticsResultCandidate>(); |
630 | |
631 | // AM: Example how to reach the initial PCM model |
632 | PCMInstance pcm = Opt4JStarter.getProblem().getInitialInstance(); |
633 | |
634 | // AM: Example for getting a passive resource capacity. Note that |
635 | // the passive resource belongs to a component, not to a service |
636 | List<Repository> repositoryList = pcm.getRepositories(); |
637 | |
638 | //@author catia: the list of passive resources is stored in the PassiveResInfo data structure |
639 | List<PassiveResInfo> passiveResInfoList = new ArrayList<PassiveResInfo>(repositoryList.size()); |
640 | |
641 | for (Repository repository : repositoryList) { |
642 | List<RepositoryComponent> repoComponents = repository |
643 | .getComponents__Repository(); |
644 | for (RepositoryComponent repositoryComponent : repoComponents) { |
645 | if (repositoryComponent instanceof BasicComponent) { |
646 | BasicComponent basicComponent = (BasicComponent) repositoryComponent; |
647 | List<PassiveResource> passiveResourceList = basicComponent |
648 | .getPassiveResource_BasicComponent(); |
649 | for (PassiveResource passiveResource : passiveResourceList) { |
650 | |
651 | //@author catia: (1) queue length, (2) waiting and (3) holding time of passive resources are currently set to pre-defined values |
652 | passiveResInfoList.add(new PassiveResInfo(passiveResource, basicComponent |
653 | .getEntityName(), Integer.parseInt(passiveResource |
654 | .getCapacity_PassiveResource().getSpecification()), 0.8, 1.0, 0.4)); |
655 | } |
656 | |
657 | } |
658 | } |
659 | } |
660 | |
661 | logger.info("List of Passive Resources: "); |
662 | for (PassiveResInfo el : passiveResInfoList) { |
663 | el.print(); |
664 | } |
665 | logger.info("---------------------------------------------------------------------"); |
666 | |
667 | //@author catia: select the critical passive resources |
668 | List<PassiveResInfo> criticalPassiveResInfoList = getCriticalPassiveRes(passiveResInfoList); |
669 | |
670 | if(criticalPassiveResInfoList.size()!= 0){ |
671 | for (PassiveResInfo criticalPassiveResInfo: criticalPassiveResInfoList){ |
672 | |
673 | //@author catia: detection of the antipattern OLB - the rules are verified for each critical passive resource |
674 | if (olb(serviceInfoList, criticalPassiveResInfo)) { |
675 | |
676 | //@author catia: solution of the antipattern OLB - "IncreaseCapacity" action |
677 | |
678 | //criticalPassiveResInfo.pr.getCapacity_PassiveResource().setSpecification("5"); |
679 | //Note that the capacity is increased by adding 5 units to the current one |
680 | TacticsResultCandidate candidate = createIncreasedCapacityCandidate(i,criticalPassiveResInfo.pr, criticalPassiveResInfo.capacity + 5); |
681 | listPairs.add(candidate); |
682 | |
683 | logger.info("The capacity of the passive resource " + criticalPassiveResInfo.pr.getEntityName() + " must be increased"); |
684 | |
685 | } |
686 | } |
687 | } |
688 | |
689 | //@author catia: print the resource demand (cpu, hdd) of the components involved in services specified in the usage model |
690 | logger.info("---------------------------------------------------------------------"); |
691 | logger.info("List of components involved in services specified in the usage model: "); |
692 | for (CompInfoResDemand el : listCompIDs) { |
693 | el.print(); |
694 | } |
695 | |
696 | //@author catia: list of components deployed on the max utilised CPU |
697 | List<CompInfoResDemand> depCompCpu = deployedComponents(listCompIDs, maxUtilisedCpu.rc); |
698 | |
699 | //@author catia: list of components deployed on the max utilised HDD |
700 | List<CompInfoResDemand> depCompHdd = deployedComponents(listCompIDs, maxUtilisedHdd.rc); |
701 | |
702 | |
703 | //@author catia: list of components deployed on the max utilised active resource |
704 | List<CompInfoResDemand> depComp = deployedComponents(listCompIDs, maxUtilised.rc); |
705 | |
706 | logger.info("---------------------------------------------------------------------"); |
707 | logger.info("List of seffs provided in the max utilised Active Resource : " + maxUtilised.rc.getEntityName()); |
708 | |
709 | //@author catia: list of seffs executed on the max utilised active resource |
710 | List<ServiceInfo> seffsOfMaxUtilised = new ArrayList<ServiceInfo>(0); |
711 | |
712 | for (CompInfoResDemand el: depComp){ |
713 | //@author catia: list of seffs provided by a basic component |
714 | List<ServiceInfo> seffsTempList = getSeffsOfComp(serviceInfoList, el.bc.getEntityName()); |
715 | |
716 | for (ServiceInfo elseff: seffsTempList){ |
717 | seffsOfMaxUtilised.add(elseff); |
718 | } |
719 | } |
720 | |
721 | for (ServiceInfo el : seffsOfMaxUtilised) { |
722 | el.print(); |
723 | } |
724 | logger.info("---------------------------------------------------------------------"); |
725 | |
726 | //@author catia: detection of the antipattern EP - the rules are verified for the active resorce maximum utilised (to be checked) |
727 | if (ep(maxUtilised, seffsOfMaxUtilised)) { |
728 | |
729 | // AM: example how to change the scheduling policy. Values are |
730 | // SchedulingPolicy.FCFS for first come first serve |
731 | // SchedulingPolicy.PROCESSOR_SHARING for processor sharing |
732 | // resource.setSchedulingPolicy(SchedulingPolicy.PROCESSOR_SHARING); |
733 | |
734 | // @author catia: solution of the antipattern EP - "UnblockExecution" action |
735 | //maxUtilised.setSchedulingPolicy(SchedulingPolicy.PROCESSOR_SHARING); |
736 | listPairs.add(createUpdatedSchedulingCandidate(i,maxUtilised,SchedulingPolicy.PROCESSOR_SHARING)); |
737 | |
738 | //listPairs.add(createUpdatedSchedulingCandidate(i,maxUtilised,SchedulingPolicy.DELAY)); |
739 | //listPairs.add(createUpdatedSchedulingCandidate(i,maxUtilised,SchedulingPolicy.EXACT)); |
740 | |
741 | logger.info("The scheduling policy of the active resource " + maxUtilised.rc.getEntityName() + " must be changed"); |
742 | } |
743 | |
744 | logger.info("---------------------------------------------------------------------"); |
745 | // @author catia: print the most critical components |
746 | logger.info("List of the most critical components: "); |
747 | |
748 | if (depCompCpu.size() !=0){ |
749 | CompInfoResDemand mostCriticalCpu = depCompCpu.get(getCompMaxCPUdemand(depCompCpu)); |
750 | logger.info("Most CPU critical"); |
751 | mostCriticalCpu.print(); |
752 | } |
753 | |
754 | if(depCompHdd.size() !=0){ |
755 | |
756 | CompInfoResDemand mostCriticalHdd = depCompHdd.get(getCompMaxHDDdemand(depCompCpu)); |
757 | logger.info("Most HDD critical"); |
758 | mostCriticalHdd.print(); |
759 | } |
760 | |
761 | logger.info("---------------------------------------------------------------------"); |
762 | |
763 | //@author catia: detection of the antipattern CPS |
764 | if (cps(activeResInfoList)) { |
765 | |
766 | //@author catia: solution of the antipattern CPS (Concurrent Processing Systems) |
767 | |
768 | List<ActiveResInfo> getUnderUsedCPUList = getUnderUsedCpu(activeResInfoList); |
769 | List<ActiveResInfo> getUnderUsedHDDList = getUnderUsedHDD(activeResInfoList); |
770 | |
771 | // @author catia: solution of the antipattern CPS - "Redeploy Action" with feature F1 : check the computation resource demand of the PCM components |
772 | // It means that the most cpu critical component is re-deployed on all under used cpu(s) available in the system, each redeployment action provides a new candidate (i.e. a pair p) |
773 | // Es: Redeploy component Cx in one of the following servers: S1, S2 |
774 | // Two candidates are evaluated: the first one in which Cx is redeployed on S1, and the second one in which Cx is redeployed on S2 |
775 | |
776 | if ((getUnderUsedCPUList.size() != 0) && (depCompCpu.size() !=0)) { |
777 | logger.info("Redeploy component " |
778 | + depCompCpu.get(getCompMaxCPUdemand(depCompCpu)).bc.getEntityName() |
779 | + " in the following servers: "); |
780 | for (ActiveResInfo el : getUnderUsedCPUList) { |
781 | //if (utilisationResult instanceof ProcessingResourceSpecificationResult) { |
782 | //ProcessingResourceSpecificationResult activeProcUtilResult = (ProcessingResourceSpecificationResult) utilisationResult; |
783 | // retrieve the processor for which this is the result |
784 | //ProcessingResourceSpecification resource = activeProcUtilResult.getProcessingresourcespecification(); |
785 | logger |
786 | .info(//resource.getResourceContainer_ProcessingResourceSpecification() |
787 | el.rc.getEntityName()); |
788 | Pair<CompInfoResDemand, ResourceContainer> p = new Pair<CompInfoResDemand, ResourceContainer>( |
789 | depCompCpu.get(getCompMaxCPUdemand(depCompCpu)), el.rc); |
790 | //resource.getResourceContainer_ProcessingResourceSpecification()); |
791 | listPairs.add(createCPSCandidate(i, p)); |
792 | } |
793 | } |
794 | |
795 | // @author catia: solution of the antipattern CPS - "Redeploy Action" with feature F1 : check the storage resource demand of the PCM components |
796 | // It means that the most hdd critical component is re-deployed on all under used hdd(s) available in the system, each redeployment action provides a new candidate (i.e. a pair p) |
797 | |
798 | if ((getUnderUsedHDDList.size() != 0) && (depCompHdd.size() !=0)) { |
799 | logger.info("Redeploy component " |
800 | + depCompHdd.get(getCompMaxHDDdemand(depCompHdd)).bc.getEntityName() |
801 | + " in the following servers: "); |
802 | for (ActiveResInfo el : getUnderUsedHDDList) { |
803 | //if (utilisationResult instanceof ProcessingResourceSpecificationResult) { |
804 | //ProcessingResourceSpecificationResult activeProcUtilResult = (ProcessingResourceSpecificationResult) utilisationResult; |
805 | // retrieve the processor for which this is the result |
806 | //ProcessingResourceSpecification resource = activeProcUtilResult.getProcessingresourcespecification(); |
807 | logger |
808 | .info(//resource.getResourceContainer_ProcessingResourceSpecification() |
809 | el.rc.getEntityName()); |
810 | Pair<CompInfoResDemand, ResourceContainer> p = new Pair<CompInfoResDemand, ResourceContainer>( |
811 | depCompHdd.get(getCompMaxHDDdemand(depCompHdd)), el.rc); |
812 | //resource.getResourceContainer_ProcessingResourceSpecification()); |
813 | listPairs.add(createCPSCandidate(i, p)); |
814 | } |
815 | } |
816 | |
817 | } |
818 | logger.info("---------------------------------------------------------------------"); |
819 | return listPairs; |
820 | } else { |
821 | logger |
822 | .warn("No performance objective or no result decorator for it found. Skipping " |
823 | + this.getClass().getName()); |
824 | } |
825 | return null; |
826 | } |
827 | |
828 | |
829 | @Override |
830 | public List<TacticsResultCandidate> getHeuristicCandidates(DSEIndividual i, |
831 | UtilisationResultCacheAndHelper resultsCache) { |
832 | |
833 | if (performance != null) { |
834 | List<TacticsResultCandidate> resultsTRC = getSolution(i); |
835 | |
836 | if (resultsTRC != null){ |
837 | return resultsTRC; |
838 | } |
839 | } |
840 | return Collections.emptyList(); |
841 | |
842 | } |
843 | |
844 | private TacticsResultCandidate createCPSCandidate(DSEIndividual i, |
845 | Pair<CompInfoResDemand, ResourceContainer> result) { |
846 | TacticsResultCandidate candidate = individualBuilder |
847 | .buildCandidate(copy.copy(i.getGenotype()), i); |
848 | |
849 | // apply change |
850 | for (Choice choice : candidate.getGenotype()) { |
851 | if (choice instanceof ClassChoice) { |
852 | ClassChoice classChoice = (ClassChoice) choice; |
853 | if (classChoice.getDegreeOfFreedomInstance() instanceof AllocationDegree) { |
854 | |
855 | if (EMFHelper.checkIdentity( |
856 | classChoice.getDegreeOfFreedomInstance().getPrimaryChanged(), |
857 | result.getFirst().ac)) { |
858 | |
859 | // if (ClassChoice.getDegreeOfFreedomInstance().g) |
860 | |
861 | classChoice.setChosenValue(EMFHelper.retrieveEntityByID( |
862 | ((ClassDegree)classChoice.getDegreeOfFreedomInstance()).getClassDesignOptions(), |
863 | result.getSecond())); |
864 | |
865 | // set weight to one for now, maybe later find a better value. |
866 | candidate.setCandidateWeight(1); |
867 | candidate.setHeuristic(this); |
868 | increaseCounterOfGeneratedCandidates(); |
869 | |
870 | logger.info("Applied CPS solution"); |
871 | return candidate; |
872 | |
873 | } |
874 | } |
875 | } |
876 | } |
877 | throw new RuntimeException("Changing the allocation of "+result.getFirst().ac.getEntityName()+" is not allowed with the current designdecision model."); |
878 | } |
879 | |
880 | private TacticsResultCandidate createIncreasedCapacityCandidate( |
881 | DSEIndividual i, PassiveResource pr, int newCapacity) { |
882 | TacticsResultCandidate candidate = individualBuilder |
883 | .buildCandidate(copy.copy(i.getGenotype()), i); |
884 | |
885 | // apply change |
886 | for (Choice choice : candidate.getGenotype()) { |
887 | if (choice instanceof DiscreteRangeChoice) { |
888 | DiscreteRangeChoice schedChoice = (DiscreteRangeChoice) choice; |
889 | if (schedChoice.getDegreeOfFreedomInstance() instanceof CapacityDegree) { |
890 | |
891 | if (EMFHelper.checkIdentity(schedChoice |
892 | .getDegreeOfFreedomInstance().getPrimaryChanged(), pr)) { |
893 | |
894 | // if (ClassChoice.getDegreeOfFreedomInstance().g) |
895 | |
896 | schedChoice.setChosenValue(newCapacity); |
897 | |
898 | // set weight to one for now, maybe later find a better value. |
899 | candidate.setCandidateWeight(1); |
900 | candidate.setHeuristic(this); |
901 | increaseCounterOfGeneratedCandidates(); |
902 | |
903 | logger.info("Increased capacity of "+pr.getEntityName()+" to "+newCapacity); |
904 | return candidate; |
905 | |
906 | } |
907 | } |
908 | } |
909 | } |
910 | throw new RuntimeException("Increasing the capacity of passive resource "+pr.getEntityName()+" is not allowed with the current designdecision model."); |
911 | } |
912 | |
913 | |
914 | private TacticsResultCandidate createUpdatedSchedulingCandidate( |
915 | DSEIndividual i, ActiveResInfo resourceToChange, |
916 | SchedulingPolicy schedulingPolicy) { |
917 | TacticsResultCandidate candidate = individualBuilder.buildCandidate( |
918 | copy.copy(i.getGenotype()), i); |
919 | |
920 | // apply change |
921 | for (Choice choice : candidate.getGenotype()) { |
922 | if (choice instanceof SchedulingPolicyChoice) { |
923 | SchedulingPolicyChoice ClassChoice = (SchedulingPolicyChoice) choice; |
924 | if (ClassChoice.getDegreeOfFreedomInstance() instanceof SchedulingPolicyDegree) { |
925 | |
926 | SchedulingPolicyDegree schedDegree = (SchedulingPolicyDegree)ClassChoice.getDegreeOfFreedomInstance(); |
927 | if (EMFHelper.checkIdentity(schedDegree.getPrimaryChanged(),resourceToChange.rc) |
928 | && EMFHelper.checkIdentity(schedDegree.getProcessingresourcetype(),resourceToChange.type)) { |
929 | |
930 | // if (ClassChoice.getDegreeOfFreedomInstance().g) |
931 | |
932 | ClassChoice.setChosenValue(schedulingPolicy); |
933 | |
934 | // set weight to one for now, maybe later find a better |
935 | // value. |
936 | candidate.setCandidateWeight(1); |
937 | candidate.setHeuristic(this); |
938 | increaseCounterOfGeneratedCandidates(); |
939 | |
940 | logger.info("Changed scheduling policy of "+resourceToChange.type.getEntityName()+" of " |
941 | + resourceToChange.rc.getEntityName() + " to " + schedulingPolicy.getLiteral()); |
942 | return candidate; |
943 | |
944 | } |
945 | } |
946 | } |
947 | } |
948 | throw new RuntimeException( |
949 | "Changing the scheduling of "+resourceToChange.type.getEntityName()+" of " |
950 | + resourceToChange.rc.getEntityName()+ " is not allowed with the current designdecision model."); |
951 | |
952 | } |
953 | |
954 | |
955 | |
956 | } |