View Javadoc
1   /*
2    * Copyright 2020-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.driver.linux.proc;
6   
7   import java.util.EnumMap;
8   import java.util.HashMap;
9   import java.util.List;
10  import java.util.Map;
11  
12  import oshi.annotation.concurrent.ThreadSafe;
13  import oshi.util.FileUtil;
14  import oshi.util.ParseUtil;
15  import oshi.util.platform.linux.ProcPath;
16  
17  /**
18   * Utility to read disk statistics from {@code /proc/diskstats}
19   */
20  @ThreadSafe
21  public final class DiskStats {
22  
23      /**
24       * Enum corresponding to the fields in the output of {@code /proc/diskstats}
25       */
26      public enum IoStat {
27          /**
28           * The device major number.
29           */
30          MAJOR,
31          /**
32           * The device minor number.
33           */
34          MINOR,
35          /**
36           * The device name.
37           */
38          NAME,
39          /**
40           * The total number of reads completed successfully.
41           */
42          READS,
43          /**
44           * Reads which are adjacent to each other merged for efficiency.
45           */
46          READS_MERGED,
47          /**
48           * The total number of sectors read successfully.
49           */
50          READS_SECTOR,
51          /**
52           * The total number of milliseconds spent by all reads.
53           */
54          READS_MS,
55          /**
56           * The total number of writes completed successfully.
57           */
58          WRITES,
59          /**
60           * Writes which are adjacent to each other merged for efficiency.
61           */
62          WRITES_MERGED,
63          /**
64           * The total number of sectors written successfully.
65           */
66          WRITES_SECTOR,
67          /**
68           * The total number of milliseconds spent by all writes.
69           */
70          WRITES_MS,
71          /**
72           * Incremented as requests are given to appropriate struct request_queue and decremented as they finish.
73           */
74          IO_QUEUE_LENGTH,
75          /**
76           * The total number of milliseconds spent doing I/Os.
77           */
78          IO_MS,
79          /**
80           * Incremented at each I/O start, I/O completion, I/O merge, or read of these stats by the number of I/Os in
81           * progress {@link #IO_QUEUE_LENGTH} times the number of milliseconds spent doing I/O since the last update of
82           * this field.
83           */
84          IO_MS_WEIGHTED,
85          /**
86           * The total number of discards completed successfully.
87           */
88          DISCARDS,
89          /**
90           * Discards which are adjacent to each other merged for efficiency.
91           */
92          DISCARDS_MERGED,
93          /**
94           * The total number of sectors discarded successfully.
95           */
96          DISCARDS_SECTOR,
97          /**
98           * The total number of milliseconds spent by all discards.
99           */
100         DISCARDS_MS,
101         /**
102          * The total number of flush requests completed successfully.
103          */
104         FLUSHES,
105         /**
106          * The total number of milliseconds spent by all flush requests.
107          */
108         FLUSHES_MS;
109     }
110 
111     private DiskStats() {
112     }
113 
114     /**
115      * Reads the statistics in {@code /proc/diskstats} and returns the results.
116      *
117      * @return A map with each disk's name as the key, and an EnumMap as the value, where the numeric values in
118      *         {@link IoStat} are mapped to a {@link Long} value.
119      */
120     public static Map<String, Map<IoStat, Long>> getDiskStats() {
121         Map<String, Map<IoStat, Long>> diskStatMap = new HashMap<>();
122         IoStat[] enumArray = IoStat.class.getEnumConstants();
123         List<String> diskStats = FileUtil.readFile(ProcPath.DISKSTATS);
124         for (String stat : diskStats) {
125             String[] split = ParseUtil.whitespaces.split(stat.trim());
126             Map<IoStat, Long> statMap = new EnumMap<>(IoStat.class);
127             String name = null;
128             for (int i = 0; i < enumArray.length && i < split.length; i++) {
129                 if (enumArray[i] == IoStat.NAME) {
130                     name = split[i];
131                 } else {
132                     statMap.put(enumArray[i], ParseUtil.parseLongOrDefault(split[i], 0L));
133                 }
134             }
135             if (name != null) {
136                 diskStatMap.put(name, statMap);
137             }
138         }
139         return diskStatMap;
140     }
141 }