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