1 | package de.uka.ipd.sdq.reliability.solver.pcm2markov; |
2 | |
3 | import java.util.ArrayList; |
4 | import java.util.Collection; |
5 | import java.util.Collections; |
6 | import java.util.Comparator; |
7 | import java.util.List; |
8 | |
9 | import org.apache.log4j.Logger; |
10 | |
11 | import de.uka.ipd.sdq.pcm.resourceenvironment.ProcessingResourceSpecification; |
12 | import de.uka.ipd.sdq.pcm.resourceenvironment.ResourceContainer; |
13 | import de.uka.ipd.sdq.pcm.resourcetype.ProcessingResourceType; |
14 | import de.uka.ipd.sdq.pcm.seff.seff_performance.ParametricResourceDemand; |
15 | import de.uka.ipd.sdq.pcmsolver.models.PCMInstance; |
16 | import de.uka.ipd.sdq.pcmsolver.transformations.ContextWrapper; |
17 | |
18 | /** |
19 | * Holds state information required during the PCM2Markov transformation. |
20 | * |
21 | * Holds a PCM instance as basis for the transformation, and keeps track of the |
22 | * physical system states (i.e., states of processing resources) that are |
23 | * considered during the transformation. |
24 | * |
25 | * @author brosch |
26 | * |
27 | */ |
28 | public class MarkovTransformationSource { |
29 | |
30 | /** |
31 | * A logger to give detailed information about the PCM instance traversal. |
32 | */ |
33 | private static Logger logger = Logger |
34 | .getLogger(MarkovTransformationSource.class.getName()); |
35 | |
36 | /** |
37 | * The PCM instance. |
38 | */ |
39 | private PCMInstance model; |
40 | |
41 | /** |
42 | * The list of descriptors for processing resources. |
43 | */ |
44 | private List<ProcessingResourceDescriptor> resourceDescriptors; |
45 | |
46 | /** |
47 | * The list of descriptors for processing resources which have a failure |
48 | * probability greater than zero. |
49 | */ |
50 | private List<ProcessingResourceDescriptor> unreliableResourceDescriptors; |
51 | |
52 | /** |
53 | * Initializes a PCMInformationProvider and creates the corresponding |
54 | * resource descriptors. |
55 | * |
56 | * @param model |
57 | * the PCM instance |
58 | * @param sortDescriptors |
59 | * indicates if the list of resource descriptors shall be sorted |
60 | */ |
61 | public MarkovTransformationSource(final PCMInstance model, |
62 | final boolean sortDescriptors) { |
63 | this.model = model; |
64 | this.resourceDescriptors = buildResourceDescriptors(sortDescriptors); |
65 | this.unreliableResourceDescriptors = buildUnreliableResourceDescriptors(); |
66 | } |
67 | |
68 | /** |
69 | * Builds a list of resource descriptors based on the given PCM instance. |
70 | * |
71 | * @param sort |
72 | * indicates if the result list shall be sorted according to |
73 | * state probabilities |
74 | * @return the list of resource descriptors |
75 | */ |
76 | private List<ProcessingResourceDescriptor> buildResourceDescriptors( |
77 | final boolean sort) { |
78 | |
79 | // Create the result list: |
80 | ArrayList<ProcessingResourceDescriptor> resultList = new ArrayList<ProcessingResourceDescriptor>(); |
81 | |
82 | // Get the PCM resource containers, but only the ones that are used in |
83 | // the ComputedAllocation |
84 | Collection<ResourceContainer> resourceContainers = model |
85 | .getUsedResourceContainer(); |
86 | |
87 | // Go through the resource container list: |
88 | for (ResourceContainer container : resourceContainers) { |
89 | |
90 | // Special case: ignore resource containers with the name |
91 | // "SystemExternalResourceContainer", as they have been internally |
92 | // created by the dependency solver: |
93 | if (container.getEntityName().equals( |
94 | "SystemExternalResourceContainer")) { |
95 | continue; |
96 | } |
97 | |
98 | // Go through the list of resources in the container: |
99 | for (ProcessingResourceSpecification resource : container |
100 | .getActiveResourceSpecifications_ResourceContainer()) { |
101 | |
102 | // Special case: Ignore resource specifications |
103 | |
104 | // Each resource has a type and MTTF/MTTR values: |
105 | Double resourceMTTF = resource.getMTTF(); |
106 | Double resourceMTTR = resource.getMTTR(); |
107 | ProcessingResourceType type = resource |
108 | .getActiveResourceType_ActiveResourceSpecification(); |
109 | |
110 | // Check the proper MTTF/MTTR specification: |
111 | if ((resourceMTTF <= 0.0) || (resourceMTTR <= 0.0)) { |
112 | logger |
113 | .warn("Improper MTTF/MTTR specification for resource " |
114 | + type.getEntityName() |
115 | + " in container " |
116 | + container.getEntityName() |
117 | + ": Both values should be positive. Assuming that resource is always ok"); |
118 | resourceMTTF = 1.0; |
119 | resourceMTTR = 0.0; |
120 | } |
121 | |
122 | // Generate a new descriptor: |
123 | ProcessingResourceDescriptor descriptor = new ProcessingResourceDescriptor(); |
124 | descriptor.setContainerId(container.getId()); |
125 | descriptor.setId(type.getId()); |
126 | descriptor.setContainerName(container.getEntityName()); |
127 | descriptor.setName(type.getEntityName()); |
128 | descriptor.setRequiredByContainer(resource |
129 | .isRequiredByContainer()); |
130 | descriptor.setStateProbability(MarkovResourceState.OK, |
131 | resourceMTTF / (resourceMTTF + resourceMTTR)); |
132 | descriptor.setStateProbability(MarkovResourceState.NA, |
133 | resourceMTTR / (resourceMTTF + resourceMTTR)); |
134 | descriptor.setCurrentState(descriptor.getDefaultState()); |
135 | resultList.add(descriptor); |
136 | } |
137 | } |
138 | |
139 | // Sort the descriptors if required: |
140 | if (sort) { |
141 | sort(resultList); |
142 | } |
143 | |
144 | // Return the result: |
145 | return resultList; |
146 | } |
147 | |
148 | /** |
149 | * Builds a list of resource descriptors whose resources can fail, i.e., |
150 | * have a greater than 0 probability for the N/A state . |
151 | * |
152 | * @return the list of such resource descriptors |
153 | */ |
154 | private List<ProcessingResourceDescriptor> buildUnreliableResourceDescriptors() { |
155 | List<ProcessingResourceDescriptor> unreliableResourceDescriptorsList = new ArrayList<ProcessingResourceDescriptor>( |
156 | resourceDescriptors.size()); |
157 | for (int i = 0; i < resourceDescriptors.size(); i++) { |
158 | // consider only resources that can fail (i.e., whose N/A state |
159 | // probability is greater than 0) |
160 | if (resourceDescriptors.get(i).getStateProbability( |
161 | MarkovResourceState.NA) != 0d) { |
162 | unreliableResourceDescriptorsList.add(resourceDescriptors |
163 | .get(i)); |
164 | } |
165 | } |
166 | |
167 | return unreliableResourceDescriptorsList; |
168 | } |
169 | |
170 | /** |
171 | * Retrieves a resource descriptor corresponding to the given resource |
172 | * demand. |
173 | * |
174 | * @param demand |
175 | * the resource demand |
176 | * @param contextWrapper |
177 | * a contextWrapper providing a link to the actual resource |
178 | * @return the descriptor; NULL if no corresponding descriptor could be |
179 | * found |
180 | */ |
181 | public ProcessingResourceDescriptor getDescriptor( |
182 | final ParametricResourceDemand demand, |
183 | final ContextWrapper contextWrapper) { |
184 | |
185 | // Map the resource demand to a concrete resource: |
186 | ProcessingResourceSpecification resource = contextWrapper |
187 | .getConcreteProcessingResource(demand); |
188 | if (resource == null) { |
189 | return null; |
190 | } |
191 | |
192 | // Get the IDs of the resource type and resource container: |
193 | String resourceTypeId = resource |
194 | .getActiveResourceType_ActiveResourceSpecification().getId(); |
195 | String containerId = contextWrapper.getAllCtx() |
196 | .getResourceContainer_AllocationContext().getId(); |
197 | |
198 | // Search for the right descriptor: |
199 | for (ProcessingResourceDescriptor descriptor : resourceDescriptors) { |
200 | |
201 | // Compare the IDs to those of the descriptor: |
202 | if ((descriptor.getType().getId().equals(resourceTypeId)) |
203 | && (descriptor.getResourceContainerId().equals(containerId))) { |
204 | return descriptor; |
205 | } |
206 | } |
207 | |
208 | // No descriptor found: |
209 | return null; |
210 | } |
211 | |
212 | /** |
213 | * Retrieves a resource descriptor corresponding to the given processing |
214 | * resource specification. |
215 | * |
216 | * @param resource |
217 | * the processing resource specification |
218 | * @return the descriptor; NULL if no corresponding descriptor could be |
219 | * found |
220 | */ |
221 | public ProcessingResourceDescriptor getDescriptor( |
222 | final ProcessingResourceSpecification resource) { |
223 | |
224 | // Search for the right descriptor: |
225 | for (ProcessingResourceDescriptor descriptor : resourceDescriptors) { |
226 | |
227 | // Compare the IDs to those of the descriptor: |
228 | if (descriptor |
229 | .getResourceContainerId() |
230 | .equals( |
231 | resource |
232 | .getResourceContainer_ProcessingResourceSpecification() |
233 | .getId()) |
234 | && descriptor |
235 | .getType() |
236 | .getId() |
237 | .equals( |
238 | resource |
239 | .getActiveResourceType_ActiveResourceSpecification() |
240 | .getId())) { |
241 | return descriptor; |
242 | } |
243 | } |
244 | |
245 | // No descriptor found: |
246 | return null; |
247 | } |
248 | |
249 | /** |
250 | * Retrieves the PCM instance. |
251 | * |
252 | * @return the PCM instance |
253 | */ |
254 | public PCMInstance getModel() { |
255 | return model; |
256 | } |
257 | |
258 | /** |
259 | * Returns a list of resource descriptors whose resources can fail, i.e., |
260 | * whose N/A state probability is greater than 0. |
261 | * |
262 | * @return the list of resource descriptors whose resources can fail, i.e., |
263 | * whose N/A state probability is greater than 0 |
264 | */ |
265 | public List<ProcessingResourceDescriptor> getUnreliableResourceDescriptors() { |
266 | return unreliableResourceDescriptors; |
267 | } |
268 | |
269 | /** |
270 | * Prints the current permutation for debugging purposes. |
271 | * |
272 | * @param descriptors |
273 | * the list of resource descriptors |
274 | */ |
275 | public void printCurrentResourceStates() { |
276 | for (int i = 0; i < unreliableResourceDescriptors.size(); i++) { |
277 | System.out.print(unreliableResourceDescriptors.get(i) |
278 | .getCurrentState() == MarkovResourceState.OK ? "1" : "0"); |
279 | } |
280 | System.out.println(); |
281 | } |
282 | |
283 | /** |
284 | * Sorts a list of resource descriptors. |
285 | * |
286 | * @param descriptors |
287 | * the list to sort |
288 | */ |
289 | private void sort(final List<ProcessingResourceDescriptor> descriptors) { |
290 | /* |
291 | * Sort the list of descriptors in a way that states, whose failure |
292 | * probabilities are higher, appear first in the list, successively |
293 | * succeeded by those, whose failure probabilities are lower. I.e., the |
294 | * list is sorted in descending order according to failure |
295 | * probabilities. |
296 | */ |
297 | Collections.sort(descriptors, |
298 | new Comparator<ProcessingResourceDescriptor>() { |
299 | public int compare(final ProcessingResourceDescriptor o1, |
300 | final ProcessingResourceDescriptor o2) { |
301 | if (o1.getStateProbability(MarkovResourceState.NA) > o2 |
302 | .getStateProbability(MarkovResourceState.NA)) { |
303 | return -1; |
304 | } else if (o1 |
305 | .getStateProbability(MarkovResourceState.NA) < o2 |
306 | .getStateProbability(MarkovResourceState.NA)) { |
307 | return 1; |
308 | } else { |
309 | return 0; |
310 | } |
311 | } |
312 | }); |
313 | } |
314 | } |