Commit | Line | Data |
---|---|---|
6d02c5c1 HD |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 École Polytechnique de Montréal | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | *******************************************************************************/ | |
9 | ||
10 | package org.eclipse.tracecompass.internal.analysis.os.linux.core.inputoutput; | |
11 | ||
12 | import java.util.HashMap; | |
13 | import java.util.Map; | |
14 | ||
15 | import org.eclipse.jdt.annotation.Nullable; | |
16 | import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.Attributes; | |
d0043318 | 17 | import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.Disk; |
6d02c5c1 HD |
18 | import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.IoOperationType; |
19 | import org.eclipse.tracecompass.analysis.os.linux.core.inputoutput.StateValues; | |
6d02c5c1 HD |
20 | import org.eclipse.tracecompass.internal.analysis.os.linux.core.Activator; |
21 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; | |
22 | import org.eclipse.tracecompass.statesystem.core.ITmfStateSystemBuilder; | |
23 | import org.eclipse.tracecompass.statesystem.core.StateSystemBuilderUtils; | |
24 | import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; | |
25 | import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; | |
26 | import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; | |
27 | import org.eclipse.tracecompass.statesystem.core.statevalue.TmfStateValue; | |
28 | import org.eclipse.tracecompass.tmf.core.statesystem.TmfAttributePool; | |
29 | import org.eclipse.tracecompass.tmf.core.statesystem.TmfAttributePool.QueueType; | |
30 | import org.eclipse.tracecompass.tmf.core.util.Pair; | |
31 | ||
6d02c5c1 HD |
32 | /** |
33 | * Class that represents a disk on a system. This class provides operation to | |
34 | * save the analysis data in a state system. | |
35 | * | |
36 | * @author Houssem Daoud | |
37 | * @since 2.0 | |
38 | */ | |
d0043318 | 39 | public class DiskWriteModel extends Disk { |
6d02c5c1 HD |
40 | private final Map<Long, Pair<Request, Integer>> fDriverQueue = new HashMap<>(); |
41 | private final Map<Long, Pair<Request, Integer>> fWaitingQueue = new HashMap<>(); | |
42 | private final ITmfStateSystemBuilder fSs; | |
6d02c5c1 HD |
43 | private final TmfAttributePool fWaitingQueueAttrib; |
44 | private final TmfAttributePool fDriverQueueAttrib; | |
6d02c5c1 HD |
45 | |
46 | /** | |
47 | * Constructor | |
48 | * | |
49 | * @param dev | |
50 | * The device number of the disk | |
51 | * @param ss | |
52 | * The state system this disk will be saved to | |
53 | */ | |
d0043318 GB |
54 | public DiskWriteModel(Integer dev, ITmfStateSystemBuilder ss) { |
55 | super(dev, ss, ss.getQuarkAbsoluteAndAdd(Attributes.DISKS, String.valueOf(dev))); | |
6d02c5c1 | 56 | fSs = ss; |
d0043318 | 57 | int diskQuark = getQuark(); |
6d02c5c1 | 58 | /* Initialize the state system for this disk */ |
d0043318 GB |
59 | fSs.getQuarkRelativeAndAdd(diskQuark, Attributes.SECTORS_WRITTEN); |
60 | fSs.getQuarkRelativeAndAdd(diskQuark, Attributes.SECTORS_READ); | |
61 | int wqQuark = fSs.getQuarkRelativeAndAdd(diskQuark, Attributes.WAITING_QUEUE); | |
6d02c5c1 | 62 | fWaitingQueueAttrib = new TmfAttributePool(fSs, wqQuark, QueueType.PRIORITY); |
d0043318 GB |
63 | fSs.getQuarkRelativeAndAdd(diskQuark, Attributes.WAITING_QUEUE_LENGTH); |
64 | int dqQuark = fSs.getQuarkRelativeAndAdd(diskQuark, Attributes.DRIVER_QUEUE); | |
6d02c5c1 | 65 | fDriverQueueAttrib = new TmfAttributePool(fSs, dqQuark, QueueType.PRIORITY); |
d0043318 | 66 | fSs.getQuarkRelativeAndAdd(diskQuark, Attributes.DRIVER_QUEUE_LENGTH); |
6d02c5c1 HD |
67 | } |
68 | ||
d0043318 | 69 | @Override |
6d02c5c1 | 70 | public void setDiskName(String diskname) { |
d0043318 | 71 | super.setDiskName(diskname); |
6d02c5c1 | 72 | try { |
d0043318 | 73 | fSs.modifyAttribute(fSs.getCurrentEndTime(), TmfStateValue.newValueString(diskname), getQuark()); |
ed48dc75 | 74 | } catch (StateValueTypeException e) { |
6d02c5c1 HD |
75 | Activator.getDefault().logError("Cannot set the diskname for disk " + diskname, e); //$NON-NLS-1$ |
76 | } | |
77 | } | |
78 | ||
79 | /** | |
80 | * Return a request from the waiting queue starting at requested base sector | |
81 | * | |
82 | * @param sector | |
83 | * The sector where the requests starts | |
84 | * @return The request corresponding to this sector, or null if no request | |
85 | * available | |
86 | */ | |
87 | public @Nullable Request getWaitingRequest(Long sector) { | |
88 | Pair<Request, Integer> reqQuark = fWaitingQueue.get(sector); | |
89 | if (reqQuark == null) { | |
90 | return null; | |
91 | } | |
92 | return reqQuark.getFirst(); | |
93 | } | |
94 | ||
95 | /** | |
96 | * Removes the request starting at sector from the waiting queue | |
97 | * | |
98 | * @param ts | |
99 | * The timestamp at which to add this request | |
100 | * @param sector | |
101 | * The sector where the requests starts | |
102 | * @return The quark of the request that was removed or | |
103 | * {@link ITmfStateSystem.INVALID_ATTRIBUTE} if the request was not | |
104 | * present | |
105 | */ | |
106 | private int removeWaitingRequest(long ts, Long sector) { | |
107 | Pair<Request, Integer> reqQuark = fWaitingQueue.remove(sector); | |
108 | if (reqQuark == null) { | |
109 | return ITmfStateSystem.INVALID_ATTRIBUTE; | |
110 | } | |
111 | int slotQuark = reqQuark.getSecond(); | |
112 | fWaitingQueueAttrib.recycle(slotQuark, ts); | |
113 | return slotQuark; | |
114 | } | |
115 | ||
116 | /** | |
117 | * Add a request to the waiting queue. Also saves this request to the state | |
118 | * system | |
119 | * | |
120 | * @param ts | |
121 | * The timestamp at which to add this request | |
122 | * @param request | |
123 | * The requests to put | |
124 | * @return The quark of the request that has been added | |
125 | */ | |
126 | public int addWaitingRequest(long ts, Request request) { | |
127 | int slotQuark = insertInWaitingQueue(ts, request); | |
128 | updateQueuesLength(ts); | |
129 | return slotQuark; | |
130 | } | |
131 | ||
132 | private int insertInWaitingQueue(long ts, Request request) { | |
133 | ITmfStateValue statusState = request.getType() == IoOperationType.READ ? StateValues.READING_REQUEST_VALUE : StateValues.WRITING_REQUEST_VALUE; | |
134 | int slotQuark = fWaitingQueueAttrib.getAvailable(); | |
135 | ||
136 | /* Insertion in waiting queue */ | |
137 | try { | |
138 | fSs.modifyAttribute(ts, statusState, slotQuark); | |
139 | ||
140 | int currentRequestQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.CURRENT_REQUEST); | |
141 | fSs.modifyAttribute(ts, TmfStateValue.newValueLong(request.getSector()), currentRequestQuark); | |
142 | ||
143 | int requestSizeQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.REQUEST_SIZE); | |
144 | fSs.modifyAttribute(ts, TmfStateValue.newValueInt(request.getNrSector()), requestSizeQuark); | |
145 | ||
146 | int mergedInQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.MERGED_IN); | |
147 | fSs.modifyAttribute(ts, TmfStateValue.nullValue(), mergedInQuark); | |
ed48dc75 | 148 | } catch (StateValueTypeException e) { |
6d02c5c1 HD |
149 | Activator.getDefault().logError("Error inserting request", e); //$NON-NLS-1$ |
150 | } | |
151 | fWaitingQueue.put(request.getSector(), new Pair<>(request, slotQuark)); | |
152 | ||
153 | return slotQuark; | |
154 | } | |
155 | ||
156 | /** | |
157 | * Update a request in the waiting queue. Also saves this request to the | |
158 | * state system. If the request did not exist previously, it will be added | |
159 | * to the queue. Since the sector may have been updated, the initialSector | |
160 | * parameters allows to say which was the original sector this request was | |
161 | * known for. | |
162 | * | |
163 | * @param ts | |
164 | * The timestamp at which to add this request | |
165 | * @param request | |
166 | * The requests to put | |
167 | * @param initialSector | |
168 | * The original base sector of this request. | |
169 | * @return The quark of the request that has been updated | |
170 | */ | |
171 | public int updateWaitingRequest(long ts, Request request, Long initialSector) { | |
172 | Pair<Request, Integer> reqQuark = fWaitingQueue.get(initialSector); | |
173 | if (reqQuark == null) { | |
174 | return addWaitingRequest(ts, request); | |
abba5403 | 175 | } else if (!initialSector.equals(request.getSector())) { |
6d02c5c1 HD |
176 | fWaitingQueue.remove(initialSector); |
177 | fWaitingQueue.put(request.getSector(), reqQuark); | |
178 | } | |
179 | ||
180 | int slotQuark = reqQuark.getSecond(); | |
181 | ||
182 | /* | |
183 | * Update the sector, number of sectors and merged in request in waiting | |
184 | * queue | |
185 | */ | |
186 | try { | |
187 | int currentRequestQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.CURRENT_REQUEST); | |
188 | fSs.modifyAttribute(ts, TmfStateValue.newValueLong(request.getSector()), currentRequestQuark); | |
189 | ||
190 | int requestSizeQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.REQUEST_SIZE); | |
191 | fSs.modifyAttribute(ts, TmfStateValue.newValueInt(request.getNrSector()), requestSizeQuark); | |
192 | ||
193 | int mergedInQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.MERGED_IN); | |
194 | fSs.modifyAttribute(ts, TmfStateValue.nullValue(), mergedInQuark); | |
ed48dc75 | 195 | } catch (StateValueTypeException e) { |
6d02c5c1 HD |
196 | Activator.getDefault().logError("Error inserting request", e); //$NON-NLS-1$ |
197 | } | |
198 | ||
199 | updateQueuesLength(ts); | |
200 | return slotQuark; | |
201 | } | |
202 | ||
203 | /** | |
204 | * Get the size of the waiting queue | |
205 | * | |
206 | * @return The waiting queue size | |
207 | */ | |
208 | public int getWaitingQueueSize() { | |
209 | return fWaitingQueue.size(); | |
210 | } | |
211 | ||
212 | /** | |
213 | * Return a request from the driver queue starting at requested base sector | |
214 | * | |
215 | * @param sector | |
216 | * The sector where the requests starts | |
217 | * @return The request corresponding to this sector, or null if no request | |
218 | * available | |
219 | */ | |
220 | public @Nullable Request getDriverRequest(Long sector) { | |
221 | Pair<Request, Integer> reqQuark = fDriverQueue.get(sector); | |
222 | if (reqQuark == null) { | |
223 | return null; | |
224 | } | |
225 | return reqQuark.getFirst(); | |
226 | } | |
227 | ||
228 | /** | |
229 | * Removes the request starting at sector from the driver queue | |
230 | * | |
231 | * @param ts | |
232 | * The timestamp at which to add this request | |
233 | * @param sector | |
234 | * The sector where the requests starts | |
235 | */ | |
236 | private void removeDriverRequest(long ts, Long sector) { | |
237 | Pair<Request, Integer> reqQuark = fDriverQueue.remove(sector); | |
238 | if (reqQuark == null) { | |
239 | return; | |
240 | } | |
241 | fDriverQueueAttrib.recycle(reqQuark.getSecond(), ts); | |
242 | } | |
243 | ||
244 | /** | |
245 | * Issues a request to the disk. This method removes the request from the | |
246 | * waiting queue if necessary and adds it to the driver queue. | |
247 | * | |
248 | * @param ts | |
249 | * The timestamp of this operation | |
250 | * @param request | |
251 | * The requests to put | |
252 | * @return The quark of the request that was just issued | |
253 | */ | |
254 | public int issueRequest(long ts, Request request) { | |
255 | /* Remove from waiting queue */ | |
256 | TmfStateValue issuedFromValue = TmfStateValue.nullValue(); | |
257 | int fromQuark = removeWaitingRequest(ts, request.getSector()); | |
258 | if (fromQuark != ITmfStateSystem.INVALID_ATTRIBUTE) { | |
259 | String reqQueueId = fSs.getAttributeName(fromQuark); | |
260 | issuedFromValue = TmfStateValue.newValueInt(Integer.parseInt(reqQueueId)); | |
261 | } | |
262 | ||
263 | ITmfStateValue statusState = request.getType() == IoOperationType.READ ? StateValues.READING_REQUEST_VALUE : StateValues.WRITING_REQUEST_VALUE; | |
264 | int slotQuark = fDriverQueueAttrib.getAvailable(); | |
265 | ||
266 | /* Insertion in driver queue */ | |
267 | try { | |
268 | fSs.modifyAttribute(ts, statusState, slotQuark); | |
269 | ||
270 | int currentRequestQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.CURRENT_REQUEST); | |
271 | fSs.modifyAttribute(ts, TmfStateValue.newValueLong(request.getSector()), currentRequestQuark); | |
272 | ||
273 | int requestSizeQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.REQUEST_SIZE); | |
274 | fSs.modifyAttribute(ts, TmfStateValue.newValueInt(request.getNrSector()), requestSizeQuark); | |
275 | ||
276 | int issuedFromQuark = fSs.getQuarkRelativeAndAdd(slotQuark, Attributes.ISSUED_FROM); | |
277 | fSs.modifyAttribute(ts, issuedFromValue, issuedFromQuark); | |
ed48dc75 | 278 | } catch (StateValueTypeException e) { |
6d02c5c1 HD |
279 | Activator.getDefault().logError("Error issuing request", e); //$NON-NLS-1$ |
280 | } | |
281 | ||
282 | fDriverQueue.put(request.getSector(), new Pair<>(request, slotQuark)); | |
283 | updateQueuesLength(ts); | |
284 | return slotQuark; | |
285 | } | |
286 | ||
287 | /** | |
288 | * Completes a request on the disk. It adds to the total of sectors read and | |
289 | * written on this disk. It also removes the request from the driver queue | |
290 | * if necessary. | |
291 | * | |
292 | * @param ts | |
293 | * The timestamp of this operation | |
294 | * @param request | |
295 | * The requests to put | |
296 | */ | |
297 | public void completeRequest(long ts, Request request) { | |
298 | /* Add the total number of sectors read or written */ | |
299 | try { | |
300 | switch (request.getType()) { | |
301 | case READ: | |
d0043318 | 302 | int readQuark = fSs.getQuarkRelativeAndAdd(getQuark(), Attributes.SECTORS_READ); |
6d02c5c1 HD |
303 | StateSystemBuilderUtils.incrementAttributeInt(fSs, ts, readQuark, request.getNrSector()); |
304 | break; | |
305 | case WRITE: | |
d0043318 | 306 | int writtenQuark = fSs.getQuarkRelativeAndAdd(getQuark(), Attributes.SECTORS_WRITTEN); |
6d02c5c1 HD |
307 | StateSystemBuilderUtils.incrementAttributeInt(fSs, ts, writtenQuark, request.getNrSector()); |
308 | break; | |
309 | default: | |
310 | throw new IllegalStateException("Complete request: the request cannot be other than READ or WRITE:" + request.getType()); //$NON-NLS-1$ | |
311 | } | |
312 | } catch (StateValueTypeException | AttributeNotFoundException e) { | |
313 | Activator.getDefault().logError("Error completing request", e); //$NON-NLS-1$ | |
314 | } | |
315 | ||
316 | /* Remove the request from driver queue */ | |
317 | removeDriverRequest(ts, request.getSector()); | |
318 | updateQueuesLength(ts); | |
319 | } | |
320 | ||
321 | /** | |
322 | * Merges 2 requests from the waiting queue. The second request will be | |
323 | * removed from the queue while the first one will be udpated | |
324 | * | |
325 | * @param ts | |
326 | * The timestamp of this operation | |
327 | * @param baseRequest | |
328 | * The base request that will be kept | |
329 | * @param mergedRequest | |
330 | * The merged request to be removed from the queue | |
331 | */ | |
332 | public void mergeRequests(long ts, Request baseRequest, Request mergedRequest) { | |
333 | int mergedQuark = removeWaitingRequest(ts, mergedRequest.getSector()); | |
334 | Long baseSector = baseRequest.getSector(); | |
335 | baseRequest.mergeRequest(mergedRequest); | |
336 | int baseQuark = updateWaitingRequest(ts, baseRequest, baseSector); | |
337 | if (mergedQuark != ITmfStateSystem.INVALID_ATTRIBUTE) { | |
338 | /* Add the merge information */ | |
339 | try { | |
340 | String reqQueueId = fSs.getAttributeName(baseQuark); | |
341 | ||
342 | int issuedFromQuark = fSs.getQuarkRelativeAndAdd(mergedQuark, Attributes.MERGED_IN); | |
343 | fSs.modifyAttribute(ts, TmfStateValue.newValueInt(Integer.parseInt(reqQueueId)), issuedFromQuark); | |
ed48dc75 | 344 | } catch (StateValueTypeException e) { |
6d02c5c1 HD |
345 | Activator.getDefault().logError("Error adding the merged request information", e); //$NON-NLS-1$ |
346 | } | |
347 | } | |
348 | updateQueuesLength(ts); | |
349 | } | |
350 | ||
351 | /** | |
352 | * Get the size of the driver queue | |
353 | * | |
354 | * @return The driver queue size | |
355 | */ | |
356 | public int getDriverQueueSize() { | |
357 | return fDriverQueue.size(); | |
358 | } | |
359 | ||
6d02c5c1 HD |
360 | private void updateQueuesLength(long ts) { |
361 | try { | |
d0043318 | 362 | int fDriverQueueLength = fSs.getQuarkRelativeAndAdd(getQuark(), Attributes.DRIVER_QUEUE_LENGTH); |
6d02c5c1 | 363 | fSs.modifyAttribute(ts, TmfStateValue.newValueInt(getDriverQueueSize()), fDriverQueueLength); |
d0043318 | 364 | int fWaitinQueueLength = fSs.getQuarkRelativeAndAdd(getQuark(), Attributes.WAITING_QUEUE_LENGTH); |
6d02c5c1 | 365 | fSs.modifyAttribute(ts, TmfStateValue.newValueInt(getWaitingQueueSize()), fWaitinQueueLength); |
ed48dc75 | 366 | } catch (StateValueTypeException e) { |
6d02c5c1 HD |
367 | Activator.getDefault().logError("Error updating queues lengths", e); //$NON-NLS-1$ |
368 | } | |
369 | } | |
370 | ||
6d02c5c1 | 371 | } |