View Javadoc
1   /*
2    * Copyright 2020-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.unix.aix;
6   
7   import java.util.ArrayList;
8   import java.util.Comparator;
9   import java.util.List;
10  import java.util.Map;
11  import java.util.function.Supplier;
12  import java.util.stream.Collectors;
13  
14  import com.sun.jna.Native;
15  import com.sun.jna.platform.unix.aix.Perfstat.perfstat_disk_t;
16  
17  import oshi.annotation.concurrent.ThreadSafe;
18  import oshi.driver.unix.aix.Ls;
19  import oshi.driver.unix.aix.Lscfg;
20  import oshi.driver.unix.aix.Lspv;
21  import oshi.hardware.HWDiskStore;
22  import oshi.hardware.HWPartition;
23  import oshi.hardware.common.AbstractHWDiskStore;
24  import oshi.util.Constants;
25  import oshi.util.tuples.Pair;
26  
27  /**
28   * AIX hard disk implementation.
29   */
30  @ThreadSafe
31  public final class AixHWDiskStore extends AbstractHWDiskStore {
32  
33      private final Supplier<perfstat_disk_t[]> diskStats;
34  
35      private long reads = 0L;
36      private long readBytes = 0L;
37      private long writes = 0L;
38      private long writeBytes = 0L;
39      private long currentQueueLength = 0L;
40      private long transferTime = 0L;
41      private long timeStamp = 0L;
42      private List<HWPartition> partitionList;
43  
44      private AixHWDiskStore(String name, String model, String serial, long size, Supplier<perfstat_disk_t[]> diskStats) {
45          super(name, model, serial, size);
46          this.diskStats = diskStats;
47      }
48  
49      @Override
50      public synchronized long getReads() {
51          return reads;
52      }
53  
54      @Override
55      public synchronized long getReadBytes() {
56          return readBytes;
57      }
58  
59      @Override
60      public synchronized long getWrites() {
61          return writes;
62      }
63  
64      @Override
65      public synchronized long getWriteBytes() {
66          return writeBytes;
67      }
68  
69      @Override
70      public synchronized long getCurrentQueueLength() {
71          return currentQueueLength;
72      }
73  
74      @Override
75      public synchronized long getTransferTime() {
76          return transferTime;
77      }
78  
79      @Override
80      public synchronized long getTimeStamp() {
81          return timeStamp;
82      }
83  
84      @Override
85      public List<HWPartition> getPartitions() {
86          return this.partitionList;
87      }
88  
89      @Override
90      public synchronized boolean updateAttributes() {
91          long now = System.currentTimeMillis();
92          for (perfstat_disk_t stat : diskStats.get()) {
93              String name = Native.toString(stat.name);
94              if (name.equals(this.getName())) {
95                  // we only have total transfers so estimate read/write ratio from blocks
96                  long blks = stat.rblks + stat.wblks;
97                  if (blks == 0L) {
98                      this.reads = stat.xfers;
99                      this.writes = 0L;
100                 } else {
101                     long approximateReads = Math.round(stat.xfers * stat.rblks / (double) blks);
102                     long approximateWrites = stat.xfers - approximateReads;
103                     // Enforce monotonic increase
104                     if (approximateReads > this.reads) {
105                         this.reads = approximateReads;
106                     }
107                     if (approximateWrites > this.writes) {
108                         this.writes = approximateWrites;
109                     }
110                 }
111                 this.readBytes = stat.rblks * stat.bsize;
112                 this.writeBytes = stat.wblks * stat.bsize;
113                 this.currentQueueLength = stat.qdepth;
114                 this.transferTime = stat.time;
115                 this.timeStamp = now;
116                 return true;
117             }
118         }
119         return false;
120     }
121 
122     /**
123      * Gets the disks on this machine
124      *
125      * @param diskStats Memoized supplier of disk statistics
126      *
127      * @return a list of {@link HWDiskStore} objects representing the disks
128      */
129     public static List<HWDiskStore> getDisks(Supplier<perfstat_disk_t[]> diskStats) {
130         Map<String, Pair<Integer, Integer>> majMinMap = Ls.queryDeviceMajorMinor();
131         List<AixHWDiskStore> storeList = new ArrayList<>();
132         for (perfstat_disk_t disk : diskStats.get()) {
133             String storeName = Native.toString(disk.name);
134             Pair<String, String> ms = Lscfg.queryModelSerial(storeName);
135             String model = ms.getA() == null ? Native.toString(disk.description) : ms.getA();
136             String serial = ms.getB() == null ? Constants.UNKNOWN : ms.getB();
137             storeList.add(createStore(storeName, model, serial, disk.size << 20, diskStats, majMinMap));
138         }
139         return storeList.stream()
140                 .sorted(Comparator.comparingInt(
141                         s -> s.getPartitions().isEmpty() ? Integer.MAX_VALUE : s.getPartitions().get(0).getMajor()))
142                 .collect(Collectors.toList());
143     }
144 
145     private static AixHWDiskStore createStore(String diskName, String model, String serial, long size,
146             Supplier<perfstat_disk_t[]> diskStats, Map<String, Pair<Integer, Integer>> majMinMap) {
147         AixHWDiskStore store = new AixHWDiskStore(diskName, model.isEmpty() ? Constants.UNKNOWN : model, serial, size,
148                 diskStats);
149         store.partitionList = Lspv.queryLogicalVolumes(diskName, majMinMap);
150         store.updateAttributes();
151         return store;
152     }
153 }