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 *******************************************************************************/
9 package org
.eclipse
.tracecompass
.analysis
.os
.linux
.core
.inputoutput
;
11 import java
.util
.List
;
13 import org
.eclipse
.jdt
.annotation
.Nullable
;
14 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
15 import org
.eclipse
.tracecompass
.internal
.analysis
.os
.linux
.core
.Activator
;
16 import org
.eclipse
.tracecompass
.statesystem
.core
.ITmfStateSystem
;
17 import org
.eclipse
.tracecompass
.statesystem
.core
.StateSystemUtils
;
18 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.AttributeNotFoundException
;
19 import org
.eclipse
.tracecompass
.statesystem
.core
.exceptions
.StateSystemDisposedException
;
20 import org
.eclipse
.tracecompass
.statesystem
.core
.interval
.ITmfStateInterval
;
22 import com
.google
.common
.hash
.HashFunction
;
23 import com
.google
.common
.hash
.Hashing
;
26 * This class represents a storage device in the system that behaves like a disk
27 * from the operating system point of view. Concretely, it can be an HDD, an
28 * SSD, a USB key, etc.
30 * @author Geneviève Bastien
34 private static final HashFunction HF
= NonNullUtils
.checkNotNull(Hashing
.goodFastHash(32));
36 private static final Integer MINORBITS
= 20;
37 private static final Integer MINORMASK
= ((1 << MINORBITS
) - 1);
39 private final Integer fDev
;
40 private final int fDiskQuark
;
41 private final ITmfStateSystem fSs
;
42 private @Nullable String fDiskName
= null;
48 * The device number of the disk
50 * The state system this disk will be saved to
52 * The quark of this disk in the state system
54 public Disk(Integer dev
, ITmfStateSystem ss
, int diskQuark
) {
57 fDiskQuark
= diskQuark
;
58 ITmfStateInterval diskNameInterval
= StateSystemUtils
.queryUntilNonNullValue(ss
, diskQuark
, ss
.getStartTime(), ss
.getCurrentEndTime());
59 if (diskNameInterval
!= null) {
60 fDiskName
= diskNameInterval
.getStateValue().unboxStr();
65 * Get the device ID of this device
67 * @return The devide ID of this disk
69 public Integer
getDevideId() {
74 * Get the disk name if available. If the disk name is not set, this method
75 * will return the string corresponding to the major, minor value of the
76 * disk's ID, ie the return value of {@link #getDeviceIdString()}.
78 * @return The disk name or the value returned by
79 * {@link #getDeviceIdString()}
81 public String
getDiskName() {
82 String diskName
= fDiskName
;
83 if (diskName
== null) {
84 return getDeviceIdString();
92 * @return The quark of this disk in the state system
94 public int getQuark() {
99 * Set the human readable disk name of this device
102 * The human readable name of the disk
104 public void setDiskName(String diskname
) {
105 fDiskName
= diskname
;
109 * Return the disk's device ID as a major,minor string. Those major,minor
110 * numbers correspond to the number of the disk found when listing disk with
111 * ls -al /dev, or using lsblk in Linux.
113 * @return The device ID string as major,minor
115 public String
getDeviceIdString() {
116 Integer major
= fDev
>> MINORBITS
;
117 Integer minor
= fDev
& MINORMASK
;
118 return major
.toString() + ',' + minor
.toString();
122 * Get the total number of sectors either read or written at the end of a
123 * time range. This method will interpolate the requests that are in
127 * The start of the time range to query
129 * The type of IO operation to query
130 * @return The number of sectors affected by operation at the end of the
133 public long getSectorsAt(long ts
, IoOperationType type
) {
135 ITmfStateSystem ss
= fSs
;
136 long currentCount
= 0;
138 /* Get the quark for the number of sector for the requested operation */
139 int rwSectorQuark
= ITmfStateSystem
.INVALID_ATTRIBUTE
;
140 if (type
== IoOperationType
.READ
) {
141 rwSectorQuark
= ss
.optQuarkRelative(fDiskQuark
, Attributes
.SECTORS_READ
);
142 } else if (type
== IoOperationType
.WRITE
) {
143 rwSectorQuark
= ss
.optQuarkRelative(fDiskQuark
, Attributes
.SECTORS_WRITTEN
);
145 if (rwSectorQuark
== ITmfStateSystem
.INVALID_ATTRIBUTE
) {
149 int rw
= type
== IoOperationType
.READ ? StateValues
.READING_REQUEST
: StateValues
.WRITING_REQUEST
;
151 long time
= Math
.max(ts
, ss
.getStartTime());
152 time
= Math
.min(time
, ss
.getCurrentEndTime());
155 List
<ITmfStateInterval
> states
= ss
.queryFullState(time
);
156 long count
= states
.get(rwSectorQuark
).getStateValue().unboxLong();
160 Integer driverQ
= ss
.getQuarkRelative(fDiskQuark
, Attributes
.DRIVER_QUEUE
);
163 * Interpolate the part of the requests in progress at requested
166 for (Integer driverSlotQuark
: ss
.getSubAttributes(driverQ
, false)) {
167 int sizeQuark
= ss
.getQuarkRelative(driverSlotQuark
, Attributes
.REQUEST_SIZE
);
168 ITmfStateInterval interval
= states
.get(sizeQuark
);
169 if (!interval
.getStateValue().isNull()) {
170 if (states
.get(driverSlotQuark
).getStateValue().unboxInt() == rw
) {
172 * The request is fully completed (and included in the
173 * r/w sectors) at interval end time + 1, so at interval
174 * end time, we do not expect the size to be total size
176 long runningTime
= interval
.getEndTime() - interval
.getStartTime() + 1;
177 long runningEnd
= interval
.getEndTime() + 1;
178 long startsize
= interval
.getStateValue().unboxLong();
179 count
= interpolateCount(count
, time
, runningEnd
, runningTime
, startsize
);
183 currentCount
= count
;
184 } catch (StateSystemDisposedException
| AttributeNotFoundException e
) {
185 Activator
.getDefault().logError("Error getting disk IO Activity", e
); //$NON-NLS-1$
190 private static long interpolateCount(long count
, long ts
, long runningEnd
, long runningTime
, long size
) {
192 long newCount
= count
;
193 if (runningTime
> 0) {
194 long runningStart
= runningEnd
- runningTime
;
195 if (ts
< runningStart
) {
198 double interpolation
= (double) (ts
- runningStart
) * (double) size
/ (runningTime
);
199 /* Will truncate the decimal part */
200 newCount
+= (long) interpolation
;
206 * Return whether requests were made on this disk during the trace or not
208 * @return {@code true} if there was requests on this disk, {@code false}
211 public boolean hasActivity() {
213 int wqQuark
= fSs
.getQuarkRelative(fDiskQuark
, Attributes
.WAITING_QUEUE
);
214 if (fSs
.getSubAttributes(wqQuark
, false).size() > 0) {
217 int dqQuark
= fSs
.getQuarkRelative(fDiskQuark
, Attributes
.DRIVER_QUEUE
);
218 if (fSs
.getSubAttributes(dqQuark
, false).size() > 0) {
221 } catch (AttributeNotFoundException e
) {
226 // ----------------------------------------------------
228 // ----------------------------------------------------
231 public String
toString() {
232 return "Disk: [" + getDeviceIdString() + ',' + fDiskName
+ ']'; //$NON-NLS-1$
236 public int hashCode() {
237 return HF
.newHasher().putInt(fDev
).hash().asInt();
241 public boolean equals(@Nullable Object o
) {
242 if (o
instanceof Disk
) {
243 Disk disk
= (Disk
) o
;
244 if (fDev
.equals(disk
.fDev
)) {