blob: 709a4654753fe9d8b744c77e7658725b3bef5bcb [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2006 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 */
25package sun.management.snmp.jvminstr;
26
27
28// java imports
29//
30import java.io.Serializable;
31import java.util.List;
32import java.util.Map;
33import java.util.TreeMap;
34
35// jmx imports
36//
37import com.sun.jmx.snmp.SnmpOid;
38import com.sun.jmx.snmp.SnmpStatusException;
39
40// jdmk imports
41//
42import com.sun.jmx.snmp.agent.SnmpMib;
43import com.sun.jmx.snmp.agent.SnmpStandardObjectServer;
44
45import java.lang.management.MemoryManagerMXBean;
46import java.lang.management.GarbageCollectorMXBean;
47import java.lang.management.ManagementFactory;
48
49import sun.management.snmp.jvmmib.JvmMemGCTableMeta;
50import sun.management.snmp.util.SnmpCachedData;
51import sun.management.snmp.util.SnmpTableCache;
52import sun.management.snmp.util.SnmpTableHandler;
53import sun.management.snmp.util.MibLogger;
54import sun.management.snmp.util.JvmContextFactory;
55
56/**
57 * The class is used for implementing the "JvmMemGCTable" table.
58 */
59public class JvmMemGCTableMetaImpl extends JvmMemGCTableMeta {
60
61 /**
62 * This class acts as a filter over the SnmpTableHandler
63 * used for the JvmMemoryManagerTable. It filters out
64 * (skip) all MemoryManagerMXBean that are not instances of
65 * GarbageCollectorMXBean so that only Garbage Collectors are
66 * seen. This is a better solution than relying on
67 * ManagementFactory.getGarbageCollectorMXBeans() because it makes it
68 * possible to guarantee the consistency betwen the MemoryManager table
69 * and the GCTable since both will be sharing the same cache.
70 **/
71 protected static class GCTableFilter {
72
73 /**
74 * Returns the index that immediately follows the given
75 * <var>index</var>. The returned index is strictly greater
76 * than the given <var>index</var>, and is contained in the table.
77 * <br>If the given <var>index</var> is null, returns the first
78 * index in the table.
79 * <br>If there are no index after the given <var>index</var>,
80 * returns null.
81 * This method is an optimization for the case where the
82 * SnmpTableHandler is in fact an instance of SnmpCachedData.
83 **/
84 public SnmpOid getNext(SnmpCachedData datas, SnmpOid index) {
85
86 final boolean dbg = log.isDebugOn();
87
88 // We're going to loop until we find an instance of
89 // GarbageCollectorMXBean. First we attempt to find
90 // the next element whose OID follows the given index.
91 // If `index' is null, the insertion point is -1
92 // (the next is 0 = -insertion - 1)
93 //
94 final int insertion = (index==null)?-1:datas.find(index);
95 if (dbg) log.debug("GCTableFilter","oid="+index+
96 " at insertion="+insertion);
97
98 int next;
99 if (insertion > -1) next = insertion+1;
100 else next = -insertion -1;
101
102 // Now `next' points to the element that imediately
103 // follows the given `index'. We're going to loop
104 // through the table, starting at `next' (included),
105 // and return the first element which is an instance
106 // of GarbageCollectorMXBean.
107 //
108 for (;next<datas.indexes.length;next++) {
109 if (dbg) log.debug("GCTableFilter","next="+next);
110 final Object value = datas.datas[next];
111 if (dbg) log.debug("GCTableFilter","value["+next+"]=" +
112 ((MemoryManagerMXBean)value).getName());
113 if (value instanceof GarbageCollectorMXBean) {
114 // That's the next: return it.
115 if (dbg) log.debug("GCTableFilter",
116 ((MemoryManagerMXBean)value).getName() +
117 " is a GarbageCollectorMXBean.");
118 return datas.indexes[next];
119 }
120 if (dbg) log.debug("GCTableFilter",
121 ((MemoryManagerMXBean)value).getName() +
122 " is not a GarbageCollectorMXBean: " +
123 value.getClass().getName());
124 // skip to next index...
125 }
126 return null;
127 }
128
129 /**
130 * Returns the index that immediately follows the given
131 * <var>index</var>. The returned index is strictly greater
132 * than the given <var>index</var>, and is contained in the table.
133 * <br>If the given <var>index</var> is null, returns the first
134 * index in the table.
135 * <br>If there are no index after the given <var>index</var>,
136 * returns null.
137 **/
138 public SnmpOid getNext(SnmpTableHandler handler, SnmpOid index) {
139
140 // try to call the optimized method
141 if (handler instanceof SnmpCachedData)
142 return getNext((SnmpCachedData)handler, index);
143
144 // too bad - revert to non-optimized generic algorithm
145 SnmpOid next = index;
146 do {
147 next = handler.getNext(next);
148 final Object value = handler.getData(next);
149 if (value instanceof GarbageCollectorMXBean)
150 // That's the next! return it
151 return next;
152 // skip to next index...
153 } while (next != null);
154 return null;
155 }
156
157 /**
158 * Returns the data associated with the given index.
159 * If the given index is not found, null is returned.
160 * Note that returning null does not necessarily means that
161 * the index was not found.
162 **/
163 public Object getData(SnmpTableHandler handler, SnmpOid index) {
164 final Object value = handler.getData(index);
165 if (value instanceof GarbageCollectorMXBean) return value;
166 // Behaves as if there was nothing at this index...
167 //
168 return null;
169 }
170
171 /**
172 * Returns true if the given <var>index</var> is present.
173 **/
174 public boolean contains(SnmpTableHandler handler, SnmpOid index) {
175 if (handler.getData(index) instanceof GarbageCollectorMXBean)
176 return true;
177 // Behaves as if there was nothing at this index...
178 //
179 return false;
180 }
181 }
182
183
184 private transient JvmMemManagerTableMetaImpl managers = null;
185 private static GCTableFilter filter = new GCTableFilter();
186
187
188 /**
189 * Constructor for the table. Initialize metadata for "JvmMemGCTableMeta".
190 */
191 public JvmMemGCTableMetaImpl(SnmpMib myMib,
192 SnmpStandardObjectServer objserv) {
193 super(myMib,objserv);
194 }
195
196 // Returns a pointer to the JvmMemManager meta node - we're going
197 // to reuse its SnmpTableHandler by filtering out all that is
198 // not a GarbageCollectorMXBean.
199 private final JvmMemManagerTableMetaImpl getManagers(SnmpMib mib) {
200 if (managers == null) {
201 managers = (JvmMemManagerTableMetaImpl)
202 mib.getRegisteredTableMeta("JvmMemManagerTable");
203 }
204 return managers;
205 }
206
207 /**
208 * Returns the JvmMemManagerTable SnmpTableHandler
209 **/
210 protected SnmpTableHandler getHandler(Object userData) {
211 JvmMemManagerTableMetaImpl managerTable= getManagers(theMib);
212 return managerTable.getHandler(userData);
213 }
214
215 // See com.sun.jmx.snmp.agent.SnmpMibTable
216 protected SnmpOid getNextOid(Object userData)
217 throws SnmpStatusException {
218 // null means get the first OID.
219 return getNextOid(null,userData);
220 }
221
222 // See com.sun.jmx.snmp.agent.SnmpMibTable
223 protected SnmpOid getNextOid(SnmpOid oid, Object userData)
224 throws SnmpStatusException {
225 final boolean dbg = log.isDebugOn();
226 try {
227 if (dbg) log.debug("getNextOid", "previous=" + oid);
228
229 // Get the data handler.
230 //
231 SnmpTableHandler handler = getHandler(userData);
232 if (handler == null) {
233 // This should never happen.
234 // If we get here it's a bug.
235 //
236 if (dbg) log.debug("getNextOid", "handler is null!");
237 throw new
238 SnmpStatusException(SnmpStatusException.noSuchInstance);
239 }
240
241
242 // Get the next oid, using the GC filter.
243 //
244 final SnmpOid next = filter.getNext(handler,oid);
245 if (dbg) log.debug("getNextOid", "next=" + next);
246
247 // if next is null: we reached the end of the table.
248 //
249 if (next == null)
250 throw new
251 SnmpStatusException(SnmpStatusException.noSuchInstance);
252
253 return next;
254 } catch (RuntimeException x) {
255 // debug. This should never happen.
256 //
257 if (dbg) log.debug("getNextOid",x);
258 throw x;
259 }
260 }
261
262
263 // See com.sun.jmx.snmp.agent.SnmpMibTable
264 protected boolean contains(SnmpOid oid, Object userData) {
265 // Get the handler.
266 //
267 SnmpTableHandler handler = getHandler(userData);
268
269 // handler should never be null.
270 //
271 if (handler == null)
272 return false;
273 return filter.contains(handler,oid);
274 }
275
276 // See com.sun.jmx.snmp.agent.SnmpMibTable
277 public Object getEntry(SnmpOid oid)
278 throws SnmpStatusException {
279
280 if (oid == null)
281 throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
282
283 // Get the request contextual cache (userData).
284 //
285 final Map<Object, Object> m = JvmContextFactory.getUserData();
286
287 // First look in the request contextual cache: maybe we've already
288 // created this entry...
289 //
290
291 // We know in the case of this table that the index is an integer,
292 // it is thus the first OID arc of the index OID.
293 //
294 final long index = oid.getOidArc(0);
295
296 // We're going to use this name to store/retrieve the entry in
297 // the request contextual cache.
298 //
299 // Revisit: Probably better programming to put all these strings
300 // in some interface.
301 //
302 final String entryTag = ((m==null)?null:("JvmMemGCTable.entry." +
303 index));
304
305 // If the entry is in the cache, simply return it.
306 //
307 if (m != null) {
308 final Object entry = m.get(entryTag);
309 if (entry != null) return entry;
310 }
311
312 // Entry was not in request cache. Make a new one.
313 //
314 // Get the data hanler.
315 //
316 SnmpTableHandler handler = getHandler(m);
317
318 // handler should never be null.
319 //
320 if (handler == null)
321 throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
322
323 // Use the filter to retrieve only GarabageCollectorMBean data.
324 //
325 final Object data = filter.getData(handler,oid);
326
327 // data may be null if the OID we were given is not valid.
328 // (e.g. it identifies a MemoryManager which is not a
329 // GarbageCollector)
330 //
331 if (data == null)
332 throw new SnmpStatusException(SnmpStatusException.noSuchInstance);
333
334 // Make a new entryy (transient object that will be kept only
335 // for the duration of the request.
336 //
337 final Object entry =
338 new JvmMemGCEntryImpl((GarbageCollectorMXBean)data,(int)index);
339
340 // Put the entry in the request cache in case we need it later
341 // in the processing of the request. Note that we could have
342 // optimized this by making JvmMemGCEntryImpl extend
343 // JvmMemManagerEntryImpl, and then make sure that
344 // JvmMemManagerTableMetaImpl creates an instance of JvmMemGCEntryImpl
345 // instead of JvmMemManagerEntryImpl when the associated data is
346 // an instance of GarbageCollectorMXBean. This would have made it
347 // possible to share the transient entry object.
348 // As it is, we may have two transient objects that points to
349 // the same underlying MemoryManagerMXBean (which is definitely
350 // not a problem - but is only a small dysatisfaction)
351 //
352 if (m != null && entry != null) {
353 m.put(entryTag,entry);
354 }
355
356 return entry;
357 }
358
359 static final MibLogger log = new MibLogger(JvmMemGCTableMetaImpl.class);
360}