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
35 private static final HashFunction HF
= NonNullUtils
.checkNotNull(Hashing
.goodFastHash(32));
37 private static final Integer MINORBITS
= 20;
38 private static final Integer MINORMASK
= ((1 << MINORBITS
) - 1);
40 private final Integer fDev
;
41 private final int fDiskQuark
;
42 private final ITmfStateSystem fSs
;
43 private @Nullable String fDiskName
= null;
49 * The device number of the disk
51 * The state system this disk will be saved to
53 * The quark of this disk in the state system
55 public Disk(Integer dev
, ITmfStateSystem ss
, int diskQuark
) {
58 fDiskQuark
= diskQuark
;
59 ITmfStateInterval diskNameInterval
= StateSystemUtils
.queryUntilNonNullValue(ss
, diskQuark
, ss
.getStartTime(), ss
.getCurrentEndTime());
60 if (diskNameInterval
!= null) {
61 fDiskName
= diskNameInterval
.getStateValue().unboxStr();
66 * Get the device ID of this device
68 * @return The devide ID of this disk
70 public Integer
getDevideId() {
75 * Get the disk name if available. If the disk name is not set, this method
76 * will return the string corresponding to the major, minor value of the
77 * disk's ID, ie the return value of {@link #getDeviceIdString()}.
79 * @return The disk name or the value returned by
80 * {@link #getDeviceIdString()}
82 public String
getDiskName() {
83 String diskName
= fDiskName
;
84 if (diskName
== null) {
85 return getDeviceIdString();
93 * @return The quark of this disk in the state system
95 public int getQuark() {
100 * Set the human readable disk name of this device
103 * The human readable name of the disk
105 public void setDiskName(String diskname
) {
106 fDiskName
= diskname
;
110 * Return the disk's device ID as a major,minor string. Those major,minor
111 * numbers correspond to the number of the disk found when listing disk with
112 * ls -al /dev, or using lsblk in Linux.
114 * @return The device ID string as major,minor
116 public String
getDeviceIdString() {
117 Integer major
= fDev
>> MINORBITS
;
118 Integer minor
= fDev
& MINORMASK
;
119 return major
.toString() + ',' + minor
.toString();
123 * Get the total number of sectors either read or written at the end of a
124 * time range. This method will interpolate the requests that are in
128 * The start of the time range to query
130 * The type of IO operation to query
131 * @return The number of sectors affected by operation at the end of the
134 public long getSectorsAt(long ts
, IoOperationType type
) {
136 ITmfStateSystem ss
= fSs
;
137 long currentCount
= 0;
139 /* Get the quark for the number of sector for the requested operation */
140 int rwSectorQuark
= ITmfStateSystem
.INVALID_ATTRIBUTE
;
141 if (type
== IoOperationType
.READ
) {
142 rwSectorQuark
= ss
.optQuarkRelative(fDiskQuark
, Attributes
.SECTORS_READ
);
143 } else if (type
== IoOperationType
.WRITE
) {
144 rwSectorQuark
= ss
.optQuarkRelative(fDiskQuark
, Attributes
.SECTORS_WRITTEN
);
146 if (rwSectorQuark
== ITmfStateSystem
.INVALID_ATTRIBUTE
) {
150 int rw
= type
== IoOperationType
.READ ? StateValues
.READING_REQUEST
: StateValues
.WRITING_REQUEST
;
152 long time
= Math
.max(ts
, ss
.getStartTime());
153 time
= Math
.min(time
, ss
.getCurrentEndTime());
156 List
<ITmfStateInterval
> states
= ss
.queryFullState(time
);
157 long count
= states
.get(rwSectorQuark
).getStateValue().unboxLong();
161 Integer driverQ
= ss
.getQuarkRelative(fDiskQuark
, Attributes
.DRIVER_QUEUE
);
164 * Interpolate the part of the requests in progress at requested
167 for (Integer driverSlotQuark
: ss
.getSubAttributes(driverQ
, false)) {
168 int sizeQuark
= ss
.getQuarkRelative(driverSlotQuark
, Attributes
.REQUEST_SIZE
);
169 ITmfStateInterval interval
= states
.get(sizeQuark
);
170 if (!interval
.getStateValue().isNull()) {
171 if (states
.get(driverSlotQuark
).getStateValue().unboxInt() == rw
) {
173 * The request is fully completed (and included in the
174 * r/w sectors) at interval end time + 1, so at interval
175 * end time, we do not expect the size to be total size
177 long runningTime
= interval
.getEndTime() - interval
.getStartTime() + 1;
178 long runningEnd
= interval
.getEndTime() + 1;
179 long startsize
= interval
.getStateValue().unboxLong();
180 count
= interpolateCount(count
, time
, runningEnd
, runningTime
, startsize
);
184 currentCount
= count
;
185 } catch (StateSystemDisposedException
| AttributeNotFoundException e
) {
186 Activator
.getDefault().logError("Error getting disk IO Activity", e
); //$NON-NLS-1$
191 private static long interpolateCount(long count
, long ts
, long runningEnd
, long runningTime
, long size
) {
193 long newCount
= count
;
194 if (runningTime
> 0) {
195 long runningStart
= runningEnd
- runningTime
;
196 if (ts
< runningStart
) {
199 double interpolation
= (double) (ts
- runningStart
) * (double) size
/ (runningTime
);
200 /* Will truncate the decimal part */
201 newCount
+= (long) interpolation
;
207 * Return whether requests were made on this disk during the trace or not
209 * @return {@code true} if there was requests on this disk, {@code false}
212 public boolean hasActivity() {
214 int wqQuark
= fSs
.getQuarkRelative(fDiskQuark
, Attributes
.WAITING_QUEUE
);
215 if (fSs
.getSubAttributes(wqQuark
, false).size() > 0) {
218 int dqQuark
= fSs
.getQuarkRelative(fDiskQuark
, Attributes
.DRIVER_QUEUE
);
219 if (fSs
.getSubAttributes(dqQuark
, false).size() > 0) {
222 } catch (AttributeNotFoundException e
) {
227 // ----------------------------------------------------
229 // ----------------------------------------------------
232 public String
toString() {
233 return "Disk: [" + getDeviceIdString() + ',' + fDiskName
+ ']'; //$NON-NLS-1$
237 public int hashCode() {
238 return HF
.newHasher().putInt(fDev
).hash().asInt();
242 public boolean equals(@Nullable Object o
) {
243 if (o
instanceof Disk
) {
244 Disk disk
= (Disk
) o
;
245 if (fDev
.equals(disk
.fDev
)) {