View Javadoc
1   /*
2    * Copyright 2020-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.unix.freebsd;
6   
7   import java.util.ArrayList;
8   import java.util.Arrays;
9   import java.util.Collections;
10  import java.util.Comparator;
11  import java.util.List;
12  import java.util.Map;
13  import java.util.stream.Collectors;
14  
15  import oshi.annotation.concurrent.ThreadSafe;
16  import oshi.driver.unix.freebsd.disk.GeomDiskList;
17  import oshi.driver.unix.freebsd.disk.GeomPartList;
18  import oshi.hardware.HWDiskStore;
19  import oshi.hardware.HWPartition;
20  import oshi.hardware.common.AbstractHWDiskStore;
21  import oshi.util.Constants;
22  import oshi.util.ExecutingCommand;
23  import oshi.util.ParseUtil;
24  import oshi.util.platform.unix.freebsd.BsdSysctlUtil;
25  import oshi.util.tuples.Triplet;
26  
27  /**
28   * FreeBSD hard disk implementation.
29   */
30  @ThreadSafe
31  public final class FreeBsdHWDiskStore extends AbstractHWDiskStore {
32  
33      private long reads = 0L;
34      private long readBytes = 0L;
35      private long writes = 0L;
36      private long writeBytes = 0L;
37      private long currentQueueLength = 0L;
38      private long transferTime = 0L;
39      private long timeStamp = 0L;
40      private List<HWPartition> partitionList;
41  
42      private FreeBsdHWDiskStore(String name, String model, String serial, long size) {
43          super(name, model, serial, size);
44      }
45  
46      @Override
47      public long getReads() {
48          return reads;
49      }
50  
51      @Override
52      public long getReadBytes() {
53          return readBytes;
54      }
55  
56      @Override
57      public long getWrites() {
58          return writes;
59      }
60  
61      @Override
62      public long getWriteBytes() {
63          return writeBytes;
64      }
65  
66      @Override
67      public long getCurrentQueueLength() {
68          return currentQueueLength;
69      }
70  
71      @Override
72      public long getTransferTime() {
73          return transferTime;
74      }
75  
76      @Override
77      public long getTimeStamp() {
78          return timeStamp;
79      }
80  
81      @Override
82      public List<HWPartition> getPartitions() {
83          return this.partitionList;
84      }
85  
86      @Override
87      public boolean updateAttributes() {
88          List<String> output = ExecutingCommand.runNative("iostat -Ix " + getName());
89          long now = System.currentTimeMillis();
90          boolean diskFound = false;
91          for (String line : output) {
92              String[] split = ParseUtil.whitespaces.split(line);
93              if (split.length < 7 || !split[0].equals(getName())) {
94                  continue;
95              }
96              diskFound = true;
97              this.reads = (long) ParseUtil.parseDoubleOrDefault(split[1], 0d);
98              this.writes = (long) ParseUtil.parseDoubleOrDefault(split[2], 0d);
99              // In KB
100             this.readBytes = (long) (ParseUtil.parseDoubleOrDefault(split[3], 0d) * 1024);
101             this.writeBytes = (long) (ParseUtil.parseDoubleOrDefault(split[4], 0d) * 1024);
102             // # transactions
103             this.currentQueueLength = ParseUtil.parseLongOrDefault(split[5], 0L);
104             // In seconds, multiply for ms
105             this.transferTime = (long) (ParseUtil.parseDoubleOrDefault(split[6], 0d) * 1000);
106             this.timeStamp = now;
107         }
108         return diskFound;
109     }
110 
111     /**
112      * Gets the disks on this machine
113      *
114      * @return a list of {@link HWDiskStore} objects representing the disks
115      */
116     public static List<HWDiskStore> getDisks() {
117         // Result
118         List<HWDiskStore> diskList = new ArrayList<>();
119 
120         // Get map of disk names to partitions
121         Map<String, List<HWPartition>> partitionMap = GeomPartList.queryPartitions();
122 
123         // Get map of disk names to disk info
124         Map<String, Triplet<String, String, Long>> diskInfoMap = GeomDiskList.queryDisks();
125 
126         // Get list of disks from sysctl
127         List<String> devices = Arrays.asList(ParseUtil.whitespaces.split(BsdSysctlUtil.sysctl("kern.disks", "")));
128 
129         // Run iostat -Ix to enumerate disks by name and get kb r/w
130         List<String> iostat = ExecutingCommand.runNative("iostat -Ix");
131         long now = System.currentTimeMillis();
132         for (String line : iostat) {
133             String[] split = ParseUtil.whitespaces.split(line);
134             if (split.length > 6 && devices.contains(split[0])) {
135                 Triplet<String, String, Long> storeInfo = diskInfoMap.get(split[0]);
136                 FreeBsdHWDiskStore store = (storeInfo == null)
137                         ? new FreeBsdHWDiskStore(split[0], Constants.UNKNOWN, Constants.UNKNOWN, 0L)
138                         : new FreeBsdHWDiskStore(split[0], storeInfo.getA(), storeInfo.getB(), storeInfo.getC());
139                 store.reads = (long) ParseUtil.parseDoubleOrDefault(split[1], 0d);
140                 store.writes = (long) ParseUtil.parseDoubleOrDefault(split[2], 0d);
141                 // In KB
142                 store.readBytes = (long) (ParseUtil.parseDoubleOrDefault(split[3], 0d) * 1024);
143                 store.writeBytes = (long) (ParseUtil.parseDoubleOrDefault(split[4], 0d) * 1024);
144                 // # transactions
145                 store.currentQueueLength = ParseUtil.parseLongOrDefault(split[5], 0L);
146                 // In seconds, multiply for ms
147                 store.transferTime = (long) (ParseUtil.parseDoubleOrDefault(split[6], 0d) * 1000);
148                 store.partitionList = Collections
149                         .unmodifiableList(partitionMap.getOrDefault(split[0], Collections.emptyList()).stream()
150                                 .sorted(Comparator.comparing(HWPartition::getName)).collect(Collectors.toList()));
151                 store.timeStamp = now;
152                 diskList.add(store);
153             }
154         }
155         return diskList;
156     }
157 }