analysis.io: Provide information from the IO model
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.os.linux.core / src / org / eclipse / tracecompass / analysis / os / linux / core / inputoutput / Disk.java
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 package org.eclipse.tracecompass.analysis.os.linux.core.inputoutput;
10
11 import java.util.List;
12
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;
21
22 import com.google.common.hash.HashFunction;
23 import com.google.common.hash.Hashing;
24
25 /**
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.
29 *
30 * @author Geneviève Bastien
31 * @since 2.0
32 */
33 public class Disk {
34
35 private static final HashFunction HF = NonNullUtils.checkNotNull(Hashing.goodFastHash(32));
36
37 private static final Integer MINORBITS = 20;
38 private static final Integer MINORMASK = ((1 << MINORBITS) - 1);
39
40 private final Integer fDev;
41 private final int fDiskQuark;
42 private final ITmfStateSystem fSs;
43 private @Nullable String fDiskName = null;
44
45 /**
46 * Constructor
47 *
48 * @param dev
49 * The device number of the disk
50 * @param ss
51 * The state system this disk will be saved to
52 * @param diskQuark
53 * The quark of this disk in the state system
54 */
55 public Disk(Integer dev, ITmfStateSystem ss, int diskQuark) {
56 fDev = dev;
57 fSs = ss;
58 fDiskQuark = diskQuark;
59 ITmfStateInterval diskNameInterval = StateSystemUtils.queryUntilNonNullValue(ss, diskQuark, ss.getStartTime(), ss.getCurrentEndTime());
60 if (diskNameInterval != null) {
61 fDiskName = diskNameInterval.getStateValue().unboxStr();
62 }
63 }
64
65 /**
66 * Get the device ID of this device
67 *
68 * @return The devide ID of this disk
69 */
70 public Integer getDevideId() {
71 return fDev;
72 }
73
74 /**
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()}.
78 *
79 * @return The disk name or the value returned by
80 * {@link #getDeviceIdString()}
81 */
82 public String getDiskName() {
83 String diskName = fDiskName;
84 if (diskName == null) {
85 return getDeviceIdString();
86 }
87 return diskName;
88 }
89
90 /**
91 * Get the quark
92 *
93 * @return The quark of this disk in the state system
94 */
95 public int getQuark() {
96 return fDiskQuark;
97 }
98
99 /**
100 * Set the human readable disk name of this device
101 *
102 * @param diskname
103 * The human readable name of the disk
104 */
105 public void setDiskName(String diskname) {
106 fDiskName = diskname;
107 }
108
109 /**
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.
113 *
114 * @return The device ID string as major,minor
115 */
116 public String getDeviceIdString() {
117 Integer major = fDev >> MINORBITS;
118 Integer minor = fDev & MINORMASK;
119 return major.toString() + ',' + minor.toString();
120 }
121
122 /**
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
125 * progress.
126 *
127 * @param ts
128 * The start of the time range to query
129 * @param type
130 * The type of IO operation to query
131 * @return The number of sectors affected by operation at the end of the
132 * range
133 */
134 public long getSectorsAt(long ts, IoOperationType type) {
135
136 ITmfStateSystem ss = fSs;
137 long currentCount = 0;
138
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);
145 }
146 if (rwSectorQuark == ITmfStateSystem.INVALID_ATTRIBUTE) {
147 return currentCount;
148 }
149
150 int rw = type == IoOperationType.READ ? StateValues.READING_REQUEST : StateValues.WRITING_REQUEST;
151
152 long time = Math.max(ts, ss.getStartTime());
153 time = Math.min(time, ss.getCurrentEndTime());
154
155 try {
156 List<ITmfStateInterval> states = ss.queryFullState(time);
157 long count = states.get(rwSectorQuark).getStateValue().unboxLong();
158 if (count == -1) {
159 count = 0;
160 }
161 Integer driverQ = ss.getQuarkRelative(fDiskQuark, Attributes.DRIVER_QUEUE);
162
163 /*
164 * Interpolate the part of the requests in progress at requested
165 * time
166 */
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) {
172 /*
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
176 */
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);
181 }
182 }
183 }
184 currentCount = count;
185 } catch (StateSystemDisposedException | AttributeNotFoundException e) {
186 Activator.getDefault().logError("Error getting disk IO Activity", e); //$NON-NLS-1$
187 }
188 return currentCount;
189 }
190
191 private static long interpolateCount(long count, long ts, long runningEnd, long runningTime, long size) {
192
193 long newCount = count;
194 if (runningTime > 0) {
195 long runningStart = runningEnd - runningTime;
196 if (ts < runningStart) {
197 return newCount;
198 }
199 double interpolation = (double) (ts - runningStart) * (double) size / (runningTime);
200 /* Will truncate the decimal part */
201 newCount += (long) interpolation;
202 }
203 return newCount;
204 }
205
206 /**
207 * Return whether requests were made on this disk during the trace or not
208 *
209 * @return {@code true} if there was requests on this disk, {@code false}
210 * otherwise
211 */
212 public boolean hasActivity() {
213 try {
214 int wqQuark = fSs.getQuarkRelative(fDiskQuark, Attributes.WAITING_QUEUE);
215 if (fSs.getSubAttributes(wqQuark, false).size() > 0) {
216 return true;
217 }
218 int dqQuark = fSs.getQuarkRelative(fDiskQuark, Attributes.DRIVER_QUEUE);
219 if (fSs.getSubAttributes(dqQuark, false).size() > 0) {
220 return true;
221 }
222 } catch (AttributeNotFoundException e) {
223 }
224 return false;
225 }
226
227 // ----------------------------------------------------
228 // Object methods
229 // ----------------------------------------------------
230
231 @Override
232 public String toString() {
233 return "Disk: [" + getDeviceIdString() + ',' + fDiskName + ']'; //$NON-NLS-1$
234 }
235
236 @Override
237 public int hashCode() {
238 return HF.newHasher().putInt(fDev).hash().asInt();
239 }
240
241 @Override
242 public boolean equals(@Nullable Object o) {
243 if (o instanceof Disk) {
244 Disk disk = (Disk) o;
245 if (fDev.equals(disk.fDev)) {
246 return true;
247 }
248 }
249 return false;
250 }
251
252 }
This page took 0.038261 seconds and 5 git commands to generate.