View Javadoc
1   /*
2    * Copyright 2020-2024 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.unix.aix;
6   
7   import static oshi.util.Memoizer.defaultExpiration;
8   import static oshi.util.Memoizer.memoize;
9   
10  import java.util.ArrayList;
11  import java.util.List;
12  import java.util.function.Supplier;
13  
14  import com.sun.jna.platform.unix.aix.Perfstat.perfstat_memory_total_t;
15  
16  import oshi.annotation.concurrent.ThreadSafe;
17  import oshi.driver.unix.aix.perfstat.PerfstatMemory;
18  import oshi.hardware.PhysicalMemory;
19  import oshi.hardware.VirtualMemory;
20  import oshi.hardware.common.AbstractGlobalMemory;
21  import oshi.util.Constants;
22  import oshi.util.ParseUtil;
23  
24  /**
25   * Memory obtained by perfstat_memory_total_t
26   */
27  @ThreadSafe
28  final class AixGlobalMemory extends AbstractGlobalMemory {
29  
30      private final Supplier<perfstat_memory_total_t> perfstatMem = memoize(AixGlobalMemory::queryPerfstat,
31              defaultExpiration());
32      private final Supplier<List<String>> lscfg;
33  
34      // AIX has multiple page size units, but for purposes of "pages" in perfstat,
35      // the docs specify 4KB pages so we hardcode this
36      private static final long PAGESIZE = 4096L;
37  
38      private final Supplier<VirtualMemory> vm = memoize(this::createVirtualMemory);
39  
40      AixGlobalMemory(Supplier<List<String>> lscfg) {
41          this.lscfg = lscfg;
42      }
43  
44      @Override
45      public long getAvailable() {
46          return perfstatMem.get().real_avail * PAGESIZE;
47      }
48  
49      @Override
50      public long getTotal() {
51          return perfstatMem.get().real_total * PAGESIZE;
52      }
53  
54      @Override
55      public long getPageSize() {
56          return PAGESIZE;
57      }
58  
59      @Override
60      public VirtualMemory getVirtualMemory() {
61          return vm.get();
62      }
63  
64      @Override
65      public List<PhysicalMemory> getPhysicalMemory() {
66          List<PhysicalMemory> pmList = new ArrayList<>();
67          boolean isMemModule = false;
68          boolean isMemoryDIMM = false;
69          String bankLabel = Constants.UNKNOWN;
70          String locator = "";
71          String partNumber = Constants.UNKNOWN;
72          long capacity = 0L;
73          for (String line : lscfg.get()) {
74              String s = line.trim();
75              if (s.endsWith("memory-module")) {
76                  isMemModule = true;
77              } else if (s.startsWith("Memory DIMM")) {
78                  isMemoryDIMM = true;
79              } else if (isMemModule) {
80                  if (s.startsWith("Node:")) {
81                      bankLabel = s.substring(5).trim();
82                      if (bankLabel.startsWith("IBM,")) {
83                          bankLabel = bankLabel.substring(4);
84                      }
85                  } else if (s.startsWith("Physical Location:")) {
86                      locator = "/" + s.substring(18).trim();
87                  } else if (s.startsWith("Size")) {
88                      capacity = ParseUtil.parseLongOrDefault(ParseUtil.removeLeadingDots(s.substring(4).trim()),
89                              0L) << 20;
90                  } else if (s.startsWith("Hardware Location Code")) {
91                      // Save previous bank
92                      if (capacity > 0) {
93                          pmList.add(new PhysicalMemory(bankLabel + locator, capacity, 0L, "IBM", Constants.UNKNOWN,
94                                  Constants.UNKNOWN, Constants.UNKNOWN));
95                      }
96                      bankLabel = Constants.UNKNOWN;
97                      locator = "";
98                      capacity = 0L;
99                      isMemModule = false;
100                 }
101             } else if (isMemoryDIMM) {
102                 if (s.startsWith("Hardware Location Code")) {
103                     locator = ParseUtil.removeLeadingDots(s.substring(23).trim());
104                 } else if (s.startsWith("Size")) {
105                     capacity = ParseUtil.parseLongOrDefault(ParseUtil.removeLeadingDots(s.substring(4).trim()),
106                             0L) << 20;
107                 } else if (s.startsWith("Part Number") || s.startsWith("FRU Number")) {
108                     partNumber = ParseUtil.removeLeadingDots(s.substring(11).trim());
109                 } else if (s.startsWith("Physical Location:")) {
110                     // Save previous bank
111                     if (capacity > 0) {
112                         pmList.add(new PhysicalMemory(locator, capacity, 0L, "IBM", Constants.UNKNOWN, partNumber,
113                                 Constants.UNKNOWN));
114                     }
115                     partNumber = Constants.UNKNOWN;
116                     locator = "";
117                     capacity = 0L;
118                     isMemoryDIMM = false;
119                 }
120             }
121         }
122         return pmList;
123     }
124 
125     private static perfstat_memory_total_t queryPerfstat() {
126         return PerfstatMemory.queryMemoryTotal();
127     }
128 
129     private VirtualMemory createVirtualMemory() {
130         return new AixVirtualMemory(perfstatMem);
131     }
132 }