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