1
2
3
4
5 package oshi.util.platform.windows;
6
7 import java.util.HashMap;
8 import java.util.Locale;
9 import java.util.Map;
10
11 import org.slf4j.Logger;
12 import org.slf4j.LoggerFactory;
13
14 import oshi.annotation.concurrent.NotThreadSafe;
15 import oshi.jna.ByRef.CloseableHANDLEByReference;
16 import oshi.util.FormatUtil;
17 import oshi.util.platform.windows.PerfDataUtil.PerfCounter;
18
19
20
21
22
23
24
25 @NotThreadSafe
26 public final class PerfCounterQueryHandler implements AutoCloseable {
27
28 private static final Logger LOG = LoggerFactory.getLogger(PerfCounterQueryHandler.class);
29
30
31 private Map<PerfCounter, CloseableHANDLEByReference> counterHandleMap = new HashMap<>();
32
33 private CloseableHANDLEByReference queryHandle = null;
34
35
36
37
38
39
40
41 public boolean addCounterToQuery(PerfCounter counter) {
42
43 if (this.queryHandle == null) {
44 this.queryHandle = new CloseableHANDLEByReference();
45 if (!PerfDataUtil.openQuery(this.queryHandle)) {
46 LOG.warn("Failed to open a query for PDH counter: {}", counter.getCounterPath());
47 this.queryHandle.close();
48 this.queryHandle = null;
49 return false;
50 }
51 }
52
53 CloseableHANDLEByReference p = new CloseableHANDLEByReference();
54 if (!PerfDataUtil.addCounter(this.queryHandle, counter.getCounterPath(), p)) {
55 LOG.warn("Failed to add counter for PDH counter: {}", counter.getCounterPath());
56 p.close();
57 return false;
58 }
59 counterHandleMap.put(counter, p);
60 return true;
61 }
62
63
64
65
66
67
68
69 public boolean removeCounterFromQuery(PerfCounter counter) {
70 boolean success = false;
71 try (CloseableHANDLEByReference href = counterHandleMap.remove(counter)) {
72
73 if (href != null) {
74 success = PerfDataUtil.removeCounter(href);
75 }
76 }
77 if (counterHandleMap.isEmpty()) {
78 PerfDataUtil.closeQuery(this.queryHandle);
79 this.queryHandle.close();
80 this.queryHandle = null;
81 }
82 return success;
83 }
84
85
86
87
88 public void removeAllCounters() {
89
90 for (CloseableHANDLEByReference href : counterHandleMap.values()) {
91 PerfDataUtil.removeCounter(href);
92 href.close();
93 }
94 counterHandleMap.clear();
95
96 if (this.queryHandle != null) {
97 PerfDataUtil.closeQuery(this.queryHandle);
98 this.queryHandle.close();
99 this.queryHandle = null;
100 }
101 }
102
103
104
105
106
107
108
109 public long updateQuery() {
110 if (this.queryHandle == null) {
111 LOG.warn("Query does not exist to update.");
112 return 0L;
113 }
114 return PerfDataUtil.updateQueryTimestamp(queryHandle);
115 }
116
117
118
119
120
121
122
123
124 public long queryCounter(PerfCounter counter) {
125 if (!counterHandleMap.containsKey(counter)) {
126 if (LOG.isWarnEnabled()) {
127 LOG.warn("Counter {} does not exist to query.", counter.getCounterPath());
128 }
129 return 0;
130 }
131 long value = counter.isBaseCounter() ? PerfDataUtil.querySecondCounter(counterHandleMap.get(counter))
132 : PerfDataUtil.queryCounter(counterHandleMap.get(counter));
133 if (value < 0) {
134 if (LOG.isWarnEnabled()) {
135 LOG.warn("Error querying counter {}: {}", counter.getCounterPath(),
136 String.format(Locale.ROOT, FormatUtil.formatError((int) value)));
137 }
138 return 0L;
139 }
140 return value;
141 }
142
143 @Override
144 public void close() {
145 removeAllCounters();
146 }
147 }