View Javadoc
1   /*
2    * Copyright 2021-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.unix.openbsd;
6   
7   import static oshi.jna.platform.unix.OpenBsdLibc.CTL_VFS;
8   import static oshi.jna.platform.unix.OpenBsdLibc.VFS_BCACHESTAT;
9   import static oshi.jna.platform.unix.OpenBsdLibc.VFS_GENERIC;
10  import static oshi.util.Memoizer.defaultExpiration;
11  import static oshi.util.Memoizer.memoize;
12  
13  import java.util.function.Supplier;
14  
15  import com.sun.jna.Memory;
16  
17  import oshi.annotation.concurrent.ThreadSafe;
18  import oshi.hardware.VirtualMemory;
19  import oshi.hardware.common.AbstractGlobalMemory;
20  import oshi.jna.platform.unix.OpenBsdLibc.Bcachestats;
21  import oshi.util.ExecutingCommand;
22  import oshi.util.ParseUtil;
23  import oshi.util.platform.unix.openbsd.OpenBsdSysctlUtil;
24  
25  /**
26   * Memory obtained by sysctl vm.stats
27   */
28  @ThreadSafe
29  final class OpenBsdGlobalMemory extends AbstractGlobalMemory {
30  
31      private final Supplier<Long> available = memoize(OpenBsdGlobalMemory::queryAvailable, defaultExpiration());
32  
33      private final Supplier<Long> total = memoize(OpenBsdGlobalMemory::queryPhysMem);
34  
35      private final Supplier<Long> pageSize = memoize(OpenBsdGlobalMemory::queryPageSize);
36  
37      private final Supplier<VirtualMemory> vm = memoize(this::createVirtualMemory);
38  
39      @Override
40      public long getAvailable() {
41          return available.get() * getPageSize();
42      }
43  
44      @Override
45      public long getTotal() {
46          return total.get();
47      }
48  
49      @Override
50      public long getPageSize() {
51          return pageSize.get();
52      }
53  
54      @Override
55      public VirtualMemory getVirtualMemory() {
56          return vm.get();
57      }
58  
59      private static long queryAvailable() {
60          long free = 0L;
61          long inactive = 0L;
62          for (String line : ExecutingCommand.runNative("vmstat -s")) {
63              if (line.endsWith("pages free")) {
64                  free = ParseUtil.getFirstIntValue(line);
65              } else if (line.endsWith("pages inactive")) {
66                  inactive = ParseUtil.getFirstIntValue(line);
67              }
68          }
69          int[] mib = new int[3];
70          mib[0] = CTL_VFS;
71          mib[1] = VFS_GENERIC;
72          mib[2] = VFS_BCACHESTAT;
73          try (Memory m = OpenBsdSysctlUtil.sysctl(mib)) {
74              Bcachestats cache = new Bcachestats(m);
75              return (cache.numbufpages + free + inactive);
76          }
77      }
78  
79      private static long queryPhysMem() {
80          return OpenBsdSysctlUtil.sysctl("hw.physmem", 0L);
81      }
82  
83      private static long queryPageSize() {
84          return OpenBsdSysctlUtil.sysctl("hw.pagesize", 4096L);
85      }
86  
87      private VirtualMemory createVirtualMemory() {
88          return new OpenBsdVirtualMemory(this);
89      }
90  }