View Javadoc
1   /*
2    * Copyright 2019-2022 The OSHI Project Contributors
3    * SPDX-License-Identifier: MIT
4    */
5   package oshi.hardware.platform.windows;
6   
7   import static oshi.util.Memoizer.defaultExpiration;
8   import static oshi.util.Memoizer.memoize;
9   
10  import java.util.Map;
11  import java.util.function.Supplier;
12  
13  import org.slf4j.Logger;
14  import org.slf4j.LoggerFactory;
15  
16  import com.sun.jna.platform.win32.Kernel32;
17  import com.sun.jna.platform.win32.Psapi;
18  
19  import oshi.annotation.concurrent.ThreadSafe;
20  import oshi.driver.windows.perfmon.MemoryInformation;
21  import oshi.driver.windows.perfmon.MemoryInformation.PageSwapProperty;
22  import oshi.driver.windows.perfmon.PagingFile;
23  import oshi.driver.windows.perfmon.PagingFile.PagingPercentProperty;
24  import oshi.hardware.common.AbstractVirtualMemory;
25  import oshi.jna.Struct.CloseablePerformanceInformation;
26  import oshi.util.tuples.Pair;
27  import oshi.util.tuples.Triplet;
28  
29  /**
30   * Memory obtained from WMI
31   */
32  @ThreadSafe
33  final class WindowsVirtualMemory extends AbstractVirtualMemory {
34  
35      private static final Logger LOG = LoggerFactory.getLogger(WindowsVirtualMemory.class);
36  
37      private final WindowsGlobalMemory global;
38  
39      private final Supplier<Long> used = memoize(WindowsVirtualMemory::querySwapUsed, defaultExpiration());
40  
41      private final Supplier<Triplet<Long, Long, Long>> totalVmaxVused = memoize(
42              WindowsVirtualMemory::querySwapTotalVirtMaxVirtUsed, defaultExpiration());
43  
44      private final Supplier<Pair<Long, Long>> swapInOut = memoize(WindowsVirtualMemory::queryPageSwaps,
45              defaultExpiration());
46  
47      /**
48       * Constructor for WindowsVirtualMemory.
49       *
50       * @param windowsGlobalMemory The parent global memory class instantiating this
51       */
52      WindowsVirtualMemory(WindowsGlobalMemory windowsGlobalMemory) {
53          this.global = windowsGlobalMemory;
54      }
55  
56      @Override
57      public long getSwapUsed() {
58          return this.global.getPageSize() * used.get();
59      }
60  
61      @Override
62      public long getSwapTotal() {
63          return this.global.getPageSize() * totalVmaxVused.get().getA();
64      }
65  
66      @Override
67      public long getVirtualMax() {
68          return this.global.getPageSize() * totalVmaxVused.get().getB();
69      }
70  
71      @Override
72      public long getVirtualInUse() {
73          return this.global.getPageSize() * totalVmaxVused.get().getC();
74      }
75  
76      @Override
77      public long getSwapPagesIn() {
78          return swapInOut.get().getA();
79      }
80  
81      @Override
82      public long getSwapPagesOut() {
83          return swapInOut.get().getB();
84      }
85  
86      private static long querySwapUsed() {
87          return PagingFile.querySwapUsed().getOrDefault(PagingPercentProperty.PERCENTUSAGE, 0L);
88      }
89  
90      private static Triplet<Long, Long, Long> querySwapTotalVirtMaxVirtUsed() {
91          try (CloseablePerformanceInformation perfInfo = new CloseablePerformanceInformation()) {
92              if (!Psapi.INSTANCE.GetPerformanceInfo(perfInfo, perfInfo.size())) {
93                  LOG.error("Failed to get Performance Info. Error code: {}", Kernel32.INSTANCE.GetLastError());
94                  return new Triplet<>(0L, 0L, 0L);
95              }
96              return new Triplet<>(perfInfo.CommitLimit.longValue() - perfInfo.PhysicalTotal.longValue(),
97                      perfInfo.CommitLimit.longValue(), perfInfo.CommitTotal.longValue());
98          }
99      }
100 
101     private static Pair<Long, Long> queryPageSwaps() {
102         Map<PageSwapProperty, Long> valueMap = MemoryInformation.queryPageSwaps();
103         return new Pair<>(valueMap.getOrDefault(PageSwapProperty.PAGESINPUTPERSEC, 0L),
104                 valueMap.getOrDefault(PageSwapProperty.PAGESOUTPUTPERSEC, 0L));
105     }
106 }