blob: 1c156eff1b4f9527574a6b01dbe1132939b33c39 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package sun.jvmstat.perfdata.monitor;
27
28import sun.jvmstat.monitor.*;
29import java.util.*;
30import java.nio.*;
31import java.io.*;
32import java.net.*;
33import java.util.regex.*;
34
35/**
36 * The base classes for the concrete implementations of the HotSpot
37 * PerfData instrumentation buffer.
38 *
39 * @author Brian Doherty
40 * @since 1.5
41 * @see AbstractPerfDataBuffer
42 */
43public abstract class PerfDataBufferImpl {
44
45 /**
46 * The buffer containing the instrumentation data.
47 */
48 protected ByteBuffer buffer;
49
50 /**
51 * A Map of monitor objects found in the instrumentation buffer.
52 */
53 protected Map<String, Monitor> monitors;
54
55 /**
56 * The Local Java Virtual Machine Identifier for this buffer.
57 */
58 protected int lvmid;
59
60 /**
61 * A Map of monitor object names to aliases as read in from the alias map
62 * file.
63 */
64 protected Map<String, ArrayList<String>> aliasMap;
65
66 /**
67 * A cache of resolved monitor aliases.
68 */
69 protected Map aliasCache;
70
71
72 /**
73 * Constructor.
74 *
75 * @param buffer the ByteBuffer containing the instrumentation data.
76 * @param lvmid the Local Java Virtual Machine Identifier for this
77 * instrumentation buffer.
78 */
79 protected PerfDataBufferImpl(ByteBuffer buffer, int lvmid) {
80 this.buffer = buffer;
81 this.lvmid = lvmid;
82 this.monitors = new TreeMap<String, Monitor>();
83 this.aliasMap = new HashMap<String, ArrayList<String>>();
84 this.aliasCache = new HashMap();
85 }
86
87 /**
88 * Get the Local Java Virtual Machine Identifier, or <em>lvmid</em>
89 * for the target JVM associated with this instrumentation buffer.
90 *
91 * @return int - the lvmid
92 */
93 public int getLocalVmId() {
94 return lvmid;
95 }
96
97 /**
98 * Get a copy of the raw instrumentation data.
99 * This method is used to get a copy of the current bytes in the
100 * instrumentation buffer. It is generally used for transporting
101 * those bytes over the network.
102 *
103 * @return byte[] - a copy of the bytes in the instrumentation buffer.
104 */
105 public byte[] getBytes() {
106 ByteBuffer bb = null;
107 synchronized (this) {
108 /*
109 * this operation is potentially time consuming, and the result
110 * is unused when the getBytes() interface is used. However, the
111 * call is necessary in order to synchronize this monitoring
112 * client with the target jvm, which assures that the receiver
113 * of the byte[] gets an image that is initialized to a usable
114 * state. Otherwise, they might only get a snapshot of an
115 * empty instrumentation buffer immediately after it was created.
116 */
117 try {
118 if (monitors.isEmpty()) {
119 buildMonitorMap(monitors);
120 }
121 } catch (MonitorException e) {
122 /*
123 * just ignore this here and let the reciever of the
124 * byte[] detect and handle the problem.
125 */
126 }
127 bb = buffer.duplicate();
128 }
129 bb.rewind();
130 byte[] bytes = new byte[bb.limit()];
131 bb.get(bytes);
132 return bytes;
133 }
134
135 /**
136 * Get the capacity of the instrumentation buffer.
137 *
138 * @return int - the capacity, or size, of the instrumentation buffer.
139 */
140 public int getCapacity() {
141 return buffer.capacity();
142 }
143
144 /**
145 * Get the ByteBuffer containing the instrumentation data.
146 *
147 * @return ByteBuffer - a ByteBuffer object that refers to the
148 * instrumentation data.
149 */
150 ByteBuffer getByteBuffer() {
151 // receiver is responsible for assuring that the buffer's state
152 // is that of an initialized target.
153 return buffer;
154 }
155
156 /**
157 * Build the alias mapping. Uses the default alias map file unless
158 * the sun.jvmstat.perfdata.aliasmap file indicates some other
159 * file as the source.
160 */
161 private void buildAliasMap() {
162 assert Thread.holdsLock(this);
163
164 URL aliasURL = null;
165 String filename = System.getProperty("sun.jvmstat.perfdata.aliasmap");
166
167 if (filename != null) {
168 File f = new File(filename);
169 try {
170 aliasURL = f.toURL();
171
172 } catch (MalformedURLException e) {
173 throw new IllegalArgumentException(e);
174 }
175 } else {
176 aliasURL = getClass().getResource(
177 "/sun/jvmstat/perfdata/resources/aliasmap");
178 }
179
180 assert aliasURL != null;
181
182 AliasFileParser aliasParser = new AliasFileParser(aliasURL);
183
184 try {
185 aliasParser.parse(aliasMap);
186
187 } catch (IOException e) {
188 System.err.println("Error processing " + filename + ": "
189 + e.getMessage());
190 } catch (SyntaxException e) {
191 System.err.println("Syntax error parsing " + filename + ": "
192 + e.getMessage());
193 }
194 }
195
196 /**
197 * Find the Monitor object for the named counter by using one of its
198 * aliases.
199 */
200 protected Monitor findByAlias(String name) {
201 assert Thread.holdsLock(this);
202
203 Monitor m = (Monitor)aliasCache.get(name);
204 if (m == null) {
205 ArrayList al = aliasMap.get(name);
206 if (al != null) {
207 for (Iterator i = al.iterator(); i.hasNext() && m == null; ) {
208 String alias = (String)i.next();
209 m = (Monitor)monitors.get(alias);
210 }
211 }
212 }
213 return m;
214 }
215
216
217 /**
218 * Find a named Instrumentation object.
219 *
220 * This method will look for the named instrumentation object in the
221 * instrumentation exported by this Java Virtual Machine. If an
222 * instrumentation object with the given name exists, a Monitor interface
223 * to that object will be return. Otherwise, the method returns
224 * <tt>null</tt>. The method will map requests for instrumention objects
225 * using old names to their current names, if applicable.
226 *
227 *
228 *
229 * @param name the name of the Instrumentation object to find.
230 * @return Monitor - the {@link Monitor} object that can be used to
231 * monitor the the named instrumentation object, or
232 * <tt>null</tt> if the named object doesn't exist.
233 * @throws MonitorException Thrown if an error occurs while communicating
234 * with the target Java Virtual Machine.
235 */
236 public Monitor findByName(String name) throws MonitorException {
237 Monitor m = null;
238
239 synchronized (this) {
240 if (monitors.isEmpty()) {
241 buildMonitorMap(monitors);
242 buildAliasMap();
243 }
244
245 // look for the requested monitor
246 m = monitors.get(name);
247 if (m == null) {
248 // not found - load any new monitors, and try again.
249 getNewMonitors(monitors);
250 m = monitors.get(name);
251 }
252 if (m == null) {
253 // still not found, look for aliases
254 m = findByAlias(name);
255 }
256 }
257 return m;
258 }
259
260 /**
261 * Find all Instrumentation objects with names matching the given pattern.
262 *
263 * This method returns a {@link List} of Monitor objects such that
264 * the name of each object matches the given pattern.
265 *
266 * @param patternString a string containing a pattern as described in
267 * {@link java.util.regex.Pattern}.
268 * @return List<Monitor> - a List of {@link Monitor} objects that can be used to
269 * monitor the instrumentation objects whose names match
270 * the given pattern. If no instrumentation objects have`
271 * names matching the given pattern, then an empty List
272 * is returned.
273 * @throws MonitorException Thrown if an error occurs while communicating
274 * with the target Java Virtual Machine.
275 * @see java.util.regex.Pattern
276 */
277 public List<Monitor> findByPattern(String patternString)
278 throws MonitorException, PatternSyntaxException {
279
280 synchronized(this) {
281 if (monitors.isEmpty()) {
282 buildMonitorMap(monitors);
283 } else {
284 getNewMonitors(monitors);
285 }
286 }
287
288 Pattern pattern = Pattern.compile(patternString);
289 Matcher matcher = pattern.matcher("");
290 List<Monitor> matches = new ArrayList<Monitor>();
291
292 Set monitorSet = monitors.entrySet();
293
294 for (Iterator i = monitorSet.iterator(); i.hasNext(); /* empty */) {
295 Map.Entry me = (Map.Entry)i.next();
296 String name = (String)me.getKey();
297 Monitor m = (Monitor)me.getValue();
298
299 // apply pattern to monitor item name
300 matcher.reset(name);
301
302 // if the pattern matches, then add monitor to list
303 if (matcher.lookingAt()) {
304 matches.add((Monitor)me.getValue());
305 }
306 }
307 return matches;
308 }
309
310 /**
311 * Get a list of the inserted and removed monitors since last called.
312 *
313 * @return MonitorStatus - the status of available Monitors for the
314 * target Java Virtual Machine.
315 * @throws MonitorException Thrown if communications errors occur
316 * while communicating with the target.
317 */
318 public MonitorStatus getMonitorStatus() throws MonitorException {
319 synchronized(this) {
320 if (monitors.isEmpty()) {
321 buildMonitorMap(monitors);
322 }
323 return getMonitorStatus(monitors);
324 }
325 }
326
327 // PerfDataBuffer implementation specific classes
328
329 /**
330 * get the list of inserted and removed monitors since last called.
331 *
332 * @param m the map of Monitors.
333 * @throws MonitorException Thrown if communications errors occur
334 * while communicating with the target.
335 */
336 protected abstract MonitorStatus getMonitorStatus(Map<String, Monitor> m)
337 throws MonitorException;
338
339 /**
340 * build the map of Monitor objects.
341 *
342 * @param m the map of Monitors.
343 * @throws MonitorException Thrown if communications errors occur
344 * while communicating with the target.
345 */
346 protected abstract void buildMonitorMap(Map<String, Monitor> m) throws MonitorException;
347
348 /**
349 * get the new Monitor objects from the Map of Monitor objects.
350 *
351 * @param m the map of Monitors.
352 * @throws MonitorException Thrown if communications errors occur
353 * while communicating with the target.
354 */
355 protected abstract void getNewMonitors(Map<String, Monitor> m) throws MonitorException;
356}