1
2
3
4
5 package oshi.hardware.platform.linux;
6
7 import static oshi.util.Memoizer.defaultExpiration;
8 import static oshi.util.Memoizer.memoize;
9
10 import java.util.List;
11 import java.util.function.Supplier;
12
13 import oshi.annotation.concurrent.ThreadSafe;
14 import oshi.hardware.common.AbstractVirtualMemory;
15 import oshi.util.FileUtil;
16 import oshi.util.ParseUtil;
17 import oshi.util.platform.linux.ProcPath;
18 import oshi.util.tuples.Pair;
19 import oshi.util.tuples.Triplet;
20
21
22
23
24 @ThreadSafe
25 final class LinuxVirtualMemory extends AbstractVirtualMemory {
26
27 private final LinuxGlobalMemory global;
28
29 private final Supplier<Triplet<Long, Long, Long>> usedTotalCommitLim = memoize(LinuxVirtualMemory::queryMemInfo,
30 defaultExpiration());
31
32 private final Supplier<Pair<Long, Long>> inOut = memoize(LinuxVirtualMemory::queryVmStat, defaultExpiration());
33
34
35
36
37
38
39 LinuxVirtualMemory(LinuxGlobalMemory linuxGlobalMemory) {
40 this.global = linuxGlobalMemory;
41 }
42
43 @Override
44 public long getSwapUsed() {
45 return usedTotalCommitLim.get().getA();
46 }
47
48 @Override
49 public long getSwapTotal() {
50 return usedTotalCommitLim.get().getB();
51 }
52
53 @Override
54 public long getVirtualMax() {
55 return usedTotalCommitLim.get().getC();
56 }
57
58 @Override
59 public long getVirtualInUse() {
60 return this.global.getTotal() - this.global.getAvailable() + getSwapUsed();
61 }
62
63 @Override
64 public long getSwapPagesIn() {
65 return inOut.get().getA();
66 }
67
68 @Override
69 public long getSwapPagesOut() {
70 return inOut.get().getB();
71 }
72
73 private static Triplet<Long, Long, Long> queryMemInfo() {
74 long swapFree = 0L;
75 long swapTotal = 0L;
76 long commitLimit = 0L;
77
78 List<String> procMemInfo = FileUtil.readFile(ProcPath.MEMINFO);
79 for (String checkLine : procMemInfo) {
80 String[] memorySplit = ParseUtil.whitespaces.split(checkLine);
81 if (memorySplit.length > 1) {
82 switch (memorySplit[0]) {
83 case "SwapTotal:":
84 swapTotal = parseMeminfo(memorySplit);
85 break;
86 case "SwapFree:":
87 swapFree = parseMeminfo(memorySplit);
88 break;
89 case "CommitLimit:":
90 commitLimit = parseMeminfo(memorySplit);
91 break;
92 default:
93
94 break;
95 }
96 }
97 }
98 return new Triplet<>(swapTotal - swapFree, swapTotal, commitLimit);
99 }
100
101 private static Pair<Long, Long> queryVmStat() {
102 long swapPagesIn = 0L;
103 long swapPagesOut = 0L;
104 List<String> procVmStat = FileUtil.readFile(ProcPath.VMSTAT);
105 for (String checkLine : procVmStat) {
106 String[] memorySplit = ParseUtil.whitespaces.split(checkLine);
107 if (memorySplit.length > 1) {
108 switch (memorySplit[0]) {
109 case "pswpin":
110 swapPagesIn = ParseUtil.parseLongOrDefault(memorySplit[1], 0L);
111 break;
112 case "pswpout":
113 swapPagesOut = ParseUtil.parseLongOrDefault(memorySplit[1], 0L);
114 break;
115 default:
116
117 break;
118 }
119 }
120 }
121 return new Pair<>(swapPagesIn, swapPagesOut);
122 }
123
124
125
126
127
128
129
130 private static long parseMeminfo(String[] memorySplit) {
131 if (memorySplit.length < 2) {
132 return 0L;
133 }
134 long memory = ParseUtil.parseLongOrDefault(memorySplit[1], 0L);
135 if (memorySplit.length > 2 && "kB".equals(memorySplit[2])) {
136 memory *= 1024;
137 }
138 return memory;
139 }
140 }