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 }