1 /*******************************************************************************
2 * Copyright (c) 2016 École Polytechnique de Montréal
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 *******************************************************************************/
10 package org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.inputoutput
;
12 import java
.util
.HashMap
;
15 import org
.eclipse
.jdt
.annotation
.Nullable
;
16 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.inputoutput
.Attributes
;
17 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.inputoutput
.Disk
;
18 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.inputoutput
.IoOperationType
;
19 import org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.inputoutput
.StateValues
;
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
;
33 * Class that represents a disk on a system. This class provides operation to
34 * save the analysis data in a state system.
36 * @author Houssem Daoud
39 public class DiskWriteModel
extends Disk
{
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
;
43 private final TmfAttributePool fWaitingQueueAttrib
;
44 private final TmfAttributePool fDriverQueueAttrib
;
50 * The device number of the disk
52 * The state system this disk will be saved to
54 public DiskWriteModel(Integer dev
, ITmfStateSystemBuilder ss
) {
55 super(dev
, ss
, ss
.getQuarkAbsoluteAndAdd(Attributes
.DISKS
, String
.valueOf(dev
)));
57 int diskQuark
= getQuark();
58 /* Initialize the state system for this disk */
59 fSs
.getQuarkRelativeAndAdd(diskQuark
, Attributes
.SECTORS_WRITTEN
);
60 fSs
.getQuarkRelativeAndAdd(diskQuark
, Attributes
.SECTORS_READ
);
61 int wqQuark
= fSs
.getQuarkRelativeAndAdd(diskQuark
, Attributes
.WAITING_QUEUE
);
62 fWaitingQueueAttrib
= new TmfAttributePool(fSs
, wqQuark
, QueueType
.PRIORITY
);
63 fSs
.getQuarkRelativeAndAdd(diskQuark
, Attributes
.WAITING_QUEUE_LENGTH
);
64 int dqQuark
= fSs
.getQuarkRelativeAndAdd(diskQuark
, Attributes
.DRIVER_QUEUE
);
65 fDriverQueueAttrib
= new TmfAttributePool(fSs
, dqQuark
, QueueType
.PRIORITY
);
66 fSs
.getQuarkRelativeAndAdd(diskQuark
, Attributes
.DRIVER_QUEUE_LENGTH
);
70 public void setDiskName(String diskname
) {
71 super.setDiskName(diskname
);
73 fSs
.modifyAttribute(fSs
.getCurrentEndTime(), TmfStateValue
.newValueString(diskname
), getQuark());
74 } catch (StateValueTypeException e
) {
75 Activator
.getDefault().logError("Cannot set the diskname for disk " + diskname
, e
); //$NON-NLS-1$
80 * Return a request from the waiting queue starting at requested base sector
83 * The sector where the requests starts
84 * @return The request corresponding to this sector, or null if no request
87 public @Nullable Request
getWaitingRequest(Long sector
) {
88 Pair
<Request
, Integer
> reqQuark
= fWaitingQueue
.get(sector
);
89 if (reqQuark
== null) {
92 return reqQuark
.getFirst();
96 * Removes the request starting at sector from the waiting queue
99 * The timestamp at which to add this request
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
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
;
111 int slotQuark
= reqQuark
.getSecond();
112 fWaitingQueueAttrib
.recycle(slotQuark
, ts
);
117 * Add a request to the waiting queue. Also saves this request to the state
121 * The timestamp at which to add this request
123 * The requests to put
124 * @return The quark of the request that has been added
126 public int addWaitingRequest(long ts
, Request request
) {
127 int slotQuark
= insertInWaitingQueue(ts
, request
);
128 updateQueuesLength(ts
);
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();
136 /* Insertion in waiting queue */
138 fSs
.modifyAttribute(ts
, statusState
, slotQuark
);
140 int currentRequestQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.CURRENT_REQUEST
);
141 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueLong(request
.getSector()), currentRequestQuark
);
143 int requestSizeQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.REQUEST_SIZE
);
144 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueInt(request
.getNrSector()), requestSizeQuark
);
146 int mergedInQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.MERGED_IN
);
147 fSs
.modifyAttribute(ts
, TmfStateValue
.nullValue(), mergedInQuark
);
148 } catch (StateValueTypeException e
) {
149 Activator
.getDefault().logError("Error inserting request", e
); //$NON-NLS-1$
151 fWaitingQueue
.put(request
.getSector(), new Pair
<>(request
, slotQuark
));
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
164 * The timestamp at which to add this 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
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
);
175 } else if (!initialSector
.equals(request
.getSector())) {
176 fWaitingQueue
.remove(initialSector
);
177 fWaitingQueue
.put(request
.getSector(), reqQuark
);
180 int slotQuark
= reqQuark
.getSecond();
183 * Update the sector, number of sectors and merged in request in waiting
187 int currentRequestQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.CURRENT_REQUEST
);
188 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueLong(request
.getSector()), currentRequestQuark
);
190 int requestSizeQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.REQUEST_SIZE
);
191 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueInt(request
.getNrSector()), requestSizeQuark
);
193 int mergedInQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.MERGED_IN
);
194 fSs
.modifyAttribute(ts
, TmfStateValue
.nullValue(), mergedInQuark
);
195 } catch (StateValueTypeException e
) {
196 Activator
.getDefault().logError("Error inserting request", e
); //$NON-NLS-1$
199 updateQueuesLength(ts
);
204 * Get the size of the waiting queue
206 * @return The waiting queue size
208 public int getWaitingQueueSize() {
209 return fWaitingQueue
.size();
213 * Return a request from the driver queue starting at requested base sector
216 * The sector where the requests starts
217 * @return The request corresponding to this sector, or null if no request
220 public @Nullable Request
getDriverRequest(Long sector
) {
221 Pair
<Request
, Integer
> reqQuark
= fDriverQueue
.get(sector
);
222 if (reqQuark
== null) {
225 return reqQuark
.getFirst();
229 * Removes the request starting at sector from the driver queue
232 * The timestamp at which to add this request
234 * The sector where the requests starts
236 private void removeDriverRequest(long ts
, Long sector
) {
237 Pair
<Request
, Integer
> reqQuark
= fDriverQueue
.remove(sector
);
238 if (reqQuark
== null) {
241 fDriverQueueAttrib
.recycle(reqQuark
.getSecond(), ts
);
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.
249 * The timestamp of this operation
251 * The requests to put
252 * @return The quark of the request that was just issued
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
));
263 ITmfStateValue statusState
= request
.getType() == IoOperationType
.READ ? StateValues
.READING_REQUEST_VALUE
: StateValues
.WRITING_REQUEST_VALUE
;
264 int slotQuark
= fDriverQueueAttrib
.getAvailable();
266 /* Insertion in driver queue */
268 fSs
.modifyAttribute(ts
, statusState
, slotQuark
);
270 int currentRequestQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.CURRENT_REQUEST
);
271 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueLong(request
.getSector()), currentRequestQuark
);
273 int requestSizeQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.REQUEST_SIZE
);
274 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueInt(request
.getNrSector()), requestSizeQuark
);
276 int issuedFromQuark
= fSs
.getQuarkRelativeAndAdd(slotQuark
, Attributes
.ISSUED_FROM
);
277 fSs
.modifyAttribute(ts
, issuedFromValue
, issuedFromQuark
);
278 } catch (StateValueTypeException e
) {
279 Activator
.getDefault().logError("Error issuing request", e
); //$NON-NLS-1$
282 fDriverQueue
.put(request
.getSector(), new Pair
<>(request
, slotQuark
));
283 updateQueuesLength(ts
);
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
293 * The timestamp of this operation
295 * The requests to put
297 public void completeRequest(long ts
, Request request
) {
298 /* Add the total number of sectors read or written */
300 switch (request
.getType()) {
302 int readQuark
= fSs
.getQuarkRelativeAndAdd(getQuark(), Attributes
.SECTORS_READ
);
303 StateSystemBuilderUtils
.incrementAttributeInt(fSs
, ts
, readQuark
, request
.getNrSector());
306 int writtenQuark
= fSs
.getQuarkRelativeAndAdd(getQuark(), Attributes
.SECTORS_WRITTEN
);
307 StateSystemBuilderUtils
.incrementAttributeInt(fSs
, ts
, writtenQuark
, request
.getNrSector());
310 throw new IllegalStateException("Complete request: the request cannot be other than READ or WRITE:" + request
.getType()); //$NON-NLS-1$
312 } catch (StateValueTypeException
| AttributeNotFoundException e
) {
313 Activator
.getDefault().logError("Error completing request", e
); //$NON-NLS-1$
316 /* Remove the request from driver queue */
317 removeDriverRequest(ts
, request
.getSector());
318 updateQueuesLength(ts
);
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
326 * The timestamp of this operation
328 * The base request that will be kept
329 * @param mergedRequest
330 * The merged request to be removed from the queue
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 */
340 String reqQueueId
= fSs
.getAttributeName(baseQuark
);
342 int issuedFromQuark
= fSs
.getQuarkRelativeAndAdd(mergedQuark
, Attributes
.MERGED_IN
);
343 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueInt(Integer
.parseInt(reqQueueId
)), issuedFromQuark
);
344 } catch (StateValueTypeException e
) {
345 Activator
.getDefault().logError("Error adding the merged request information", e
); //$NON-NLS-1$
348 updateQueuesLength(ts
);
352 * Get the size of the driver queue
354 * @return The driver queue size
356 public int getDriverQueueSize() {
357 return fDriverQueue
.size();
360 private void updateQueuesLength(long ts
) {
362 int fDriverQueueLength
= fSs
.getQuarkRelativeAndAdd(getQuark(), Attributes
.DRIVER_QUEUE_LENGTH
);
363 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueInt(getDriverQueueSize()), fDriverQueueLength
);
364 int fWaitinQueueLength
= fSs
.getQuarkRelativeAndAdd(getQuark(), Attributes
.WAITING_QUEUE_LENGTH
);
365 fSs
.modifyAttribute(ts
, TmfStateValue
.newValueInt(getWaitingQueueSize()), fWaitinQueueLength
);
366 } catch (StateValueTypeException e
) {
367 Activator
.getDefault().logError("Error updating queues lengths", e
); //$NON-NLS-1$