blob: 7781e8d4df909415984d0b1577ca9a5166d98b3a [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// java imports
28//
29import java.util.Hashtable;
30import java.util.List;
31import java.util.ArrayList;
32import java.util.Iterator;
33import java.lang.ref.WeakReference;
34
35// jmx imports
36//
37import javax.management.MBeanServer;
38import javax.management.ObjectName;
39import javax.management.InstanceAlreadyExistsException;
40import javax.management.NotificationEmitter;
41import javax.management.NotificationListener;
42import javax.management.Notification;
43import javax.management.ListenerNotFoundException;
44import javax.management.openmbean.CompositeData;
45
46// jdmk imports
47//
48import com.sun.jmx.snmp.agent.SnmpMib;
49import com.sun.jmx.snmp.daemon.SnmpAdaptorServer;
50import com.sun.jmx.snmp.SnmpPeer;
51import com.sun.jmx.snmp.SnmpParameters;
52
53import com.sun.jmx.snmp.SnmpOidTable;
54import com.sun.jmx.snmp.SnmpOid;
55import com.sun.jmx.snmp.SnmpVarBindList;
56import com.sun.jmx.snmp.SnmpVarBind;
57import com.sun.jmx.snmp.SnmpCounter;
58import com.sun.jmx.snmp.SnmpCounter64;
59import com.sun.jmx.snmp.SnmpString;
60import com.sun.jmx.snmp.SnmpInt;
61import com.sun.jmx.snmp.Enumerated;
62import com.sun.jmx.snmp.agent.SnmpMibTable;
63
64import sun.management.snmp.jvmmib.JVM_MANAGEMENT_MIBOidTable;
65import sun.management.snmp.jvmmib.JVM_MANAGEMENT_MIB;
66import sun.management.snmp.jvmmib.JvmMemoryMeta;
67import sun.management.snmp.jvmmib.JvmThreadingMeta;
68import sun.management.snmp.jvmmib.JvmRuntimeMeta;
69import sun.management.snmp.jvmmib.JvmClassLoadingMeta;
70import sun.management.snmp.jvmmib.JvmCompilationMeta;
71import sun.management.snmp.util.MibLogger;
72import sun.management.snmp.util.SnmpCachedData;
73import sun.management.snmp.util.SnmpTableHandler;
74
75//java management imports
76import java.lang.management.ManagementFactory;
77import java.lang.management.MemoryPoolMXBean;
78import java.lang.management.MemoryNotificationInfo;
79import java.lang.management.MemoryType;
80
81public class JVM_MANAGEMENT_MIB_IMPL extends JVM_MANAGEMENT_MIB {
82 private static final long serialVersionUID = -8104825586888859831L;
83
84 private static final MibLogger log =
85 new MibLogger(JVM_MANAGEMENT_MIB_IMPL.class);
86
87 private static WeakReference<SnmpOidTable> tableRef;
88
89 public static SnmpOidTable getOidTable() {
90 SnmpOidTable table = null;
91 if(tableRef == null) {
92 table = new JVM_MANAGEMENT_MIBOidTable();
93 tableRef = new WeakReference<SnmpOidTable>(table);
94 return table;
95 }
96
97 table = tableRef.get();
98 if(table == null) {
99 table = new JVM_MANAGEMENT_MIBOidTable();
100 tableRef = new WeakReference<SnmpOidTable>(table);
101 }
102
103 return table;
104 }
105
106 /**
107 * Handler waiting for memory <CODE>Notification</CODE>.
108 * Translate each JMX notification in SNMP trap.
109 */
110 private class NotificationHandler implements NotificationListener {
111 public void handleNotification(Notification notification,
112 Object handback) {
113 log.debug("handleNotification", "Received notification [ " +
114 notification.getType() + "]");
115
116 String type = notification.getType();
117 if (type.equals(MemoryNotificationInfo.MEMORY_THRESHOLD_EXCEEDED) ||
118 type.equals(MemoryNotificationInfo.
119 MEMORY_COLLECTION_THRESHOLD_EXCEEDED)) {
120 MemoryNotificationInfo minfo = MemoryNotificationInfo.
121 from((CompositeData) notification.getUserData());
122 SnmpCounter64 count = new SnmpCounter64(minfo.getCount());
123 SnmpCounter64 used =
124 new SnmpCounter64(minfo.getUsage().getUsed());
125 SnmpString poolName = new SnmpString(minfo.getPoolName());
126 SnmpOid entryIndex =
127 getJvmMemPoolEntryIndex(minfo.getPoolName());
128
129 if (entryIndex == null) {
130 log.error("handleNotification",
131 "Error: Can't find entry index for Memory Pool: "
132 + minfo.getPoolName() +": " +
133 "No trap emitted for " + type);
134 return;
135 }
136
137 SnmpOid trap = null;
138
139 final SnmpOidTable mibTable = getOidTable();
140 try {
141 SnmpOid usedOid = null;
142 SnmpOid countOid = null;
143
144 if (type.equals(MemoryNotificationInfo.
145 MEMORY_THRESHOLD_EXCEEDED)) {
146 trap = new SnmpOid(mibTable.
147 resolveVarName("jvmLowMemoryPoolUsageNotif").getOid());
148 usedOid =
149 new SnmpOid(mibTable.
150 resolveVarName("jvmMemPoolUsed").getOid() +
151 "." + entryIndex);
152 countOid =
153 new SnmpOid(mibTable.
154 resolveVarName("jvmMemPoolThreshdCount").getOid()
155 + "." + entryIndex);
156 } else if (type.equals(MemoryNotificationInfo.
157 MEMORY_COLLECTION_THRESHOLD_EXCEEDED)) {
158 trap = new SnmpOid(mibTable.
159 resolveVarName("jvmLowMemoryPoolCollectNotif").
160 getOid());
161 usedOid =
162 new SnmpOid(mibTable.
163 resolveVarName("jvmMemPoolCollectUsed").getOid() +
164 "." + entryIndex);
165 countOid =
166 new SnmpOid(mibTable.
167 resolveVarName("jvmMemPoolCollectThreshdCount").
168 getOid() +
169 "." + entryIndex);
170 }
171
172 //Datas
173 SnmpVarBindList list = new SnmpVarBindList();
174 SnmpOid poolNameOid =
175 new SnmpOid(mibTable.
176 resolveVarName("jvmMemPoolName").getOid() +
177 "." + entryIndex);
178
179 SnmpVarBind varCount = new SnmpVarBind(countOid, count);
180 SnmpVarBind varUsed = new SnmpVarBind(usedOid, used);
181 SnmpVarBind varPoolName = new SnmpVarBind(poolNameOid,
182 poolName);
183
184 list.add(varPoolName);
185 list.add(varCount);
186 list.add(varUsed);
187
188 sendTrap(trap, list);
189 }catch(Exception e) {
190 log.error("handleNotification",
191 "Exception occured : " + e);
192 }
193 }
194 }
195 }
196
197 /**
198 * List of notification targets.
199 */
200 private ArrayList<NotificationTarget> notificationTargets =
201 new ArrayList<NotificationTarget>();
202 private final NotificationEmitter emitter;
203 private final NotificationHandler handler;
204
205
206 /**
207 * Instantiate a JVM MIB intrusmentation.
208 * A <CODE>NotificationListener</CODE> is added to the <CODE>MemoryMXBean</CODE>
209 * <CODE>NotificationEmitter</CODE>
210 */
211 public JVM_MANAGEMENT_MIB_IMPL() {
212 handler = new NotificationHandler();
213 emitter = (NotificationEmitter) ManagementFactory.getMemoryMXBean();
214 emitter.addNotificationListener(handler, null, null);
215 }
216
217 private synchronized void sendTrap(SnmpOid trap, SnmpVarBindList list) {
218 final Iterator iterator = notificationTargets.iterator();
219 final SnmpAdaptorServer adaptor =
220 (SnmpAdaptorServer) getSnmpAdaptor();
221
222 if (adaptor == null) {
223 log.error("sendTrap", "Cannot send trap: adaptor is null.");
224 return;
225 }
226
227 if (!adaptor.isActive()) {
228 log.config("sendTrap", "Adaptor is not active: trap not sent.");
229 return;
230 }
231
232 while(iterator.hasNext()) {
233 NotificationTarget target = null;
234 try {
235 target = (NotificationTarget) iterator.next();
236 SnmpPeer peer =
237 new SnmpPeer(target.getAddress(), target.getPort());
238 SnmpParameters p = new SnmpParameters();
239 p.setRdCommunity(target.getCommunity());
240 peer.setParams(p);
241 log.debug("handleNotification", "Sending trap to " +
242 target.getAddress() + ":" + target.getPort());
243 adaptor.snmpV2Trap(peer, trap, list, null);
244 }catch(Exception e) {
245 log.error("sendTrap",
246 "Exception occured while sending trap to [" +
247 target + "]. Exception : " + e);
248 log.debug("sendTrap",e);
249 }
250 }
251 }
252
253 /**
254 * Add a notification target.
255 * @param target The target to add
256 * @throws IllegalArgumentException If target parameter is null.
257 */
258 public synchronized void addTarget(NotificationTarget target)
259 throws IllegalArgumentException {
260 if(target == null)
261 throw new IllegalArgumentException("Target is null");
262
263 notificationTargets.add(target);
264 }
265
266 /**
267 * Remove notification listener.
268 */
269 public void terminate() {
270 try {
271 emitter.removeNotificationListener(handler);
272 }catch(ListenerNotFoundException e) {
273 log.error("terminate", "Listener Not found : " + e);
274 }
275 }
276
277 /**
278 * Add notification targets.
279 * @param targets A list of
280 * <CODE>sun.management.snmp.jvminstr.NotificationTarget</CODE>
281 * @throws IllegalArgumentException If targets parameter is null.
282 */
283 public synchronized void addTargets(List<NotificationTarget> targets)
284 throws IllegalArgumentException {
285 if(targets == null)
286 throw new IllegalArgumentException("Target list is null");
287
288 notificationTargets.addAll(targets);
289 }
290
291 /**
292 * Factory method for "JvmMemory" group MBean.
293 *
294 * You can redefine this method if you need to replace the default
295 * generated MBean class with your own customized class.
296 *
297 * @param groupName Name of the group ("JvmMemory")
298 * @param groupOid OID of this group
299 * @param groupObjname ObjectName for this group (may be null)
300 * @param server MBeanServer for this group (may be null)
301 *
302 * @return An instance of the MBean class generated for the
303 * "JvmMemory" group (JvmMemory)
304 *
305 * Note that when using standard metadata,
306 * the returned object must implement the "JvmMemoryMBean"
307 * interface.
308 **/
309 protected Object createJvmMemoryMBean(String groupName,
310 String groupOid, ObjectName groupObjname,
311 MBeanServer server) {
312
313 // Note that when using standard metadata,
314 // the returned object must implement the "JvmMemoryMBean"
315 // interface.
316 //
317 if (server != null)
318 return new JvmMemoryImpl(this,server);
319 else
320 return new JvmMemoryImpl(this);
321 }
322
323 /**
324 * Factory method for "JvmMemory" group metadata class.
325 *
326 * You can redefine this method if you need to replace the default
327 * generated metadata class with your own customized class.
328 *
329 * @param groupName Name of the group ("JvmMemory")
330 * @param groupOid OID of this group
331 * @param groupObjname ObjectName for this group (may be null)
332 * @param server MBeanServer for this group (may be null)
333 *
334 * @return An instance of the metadata class generated for the
335 * "JvmMemory" group (JvmMemoryMeta)
336 *
337 **/
338 protected JvmMemoryMeta createJvmMemoryMetaNode(String groupName,
339 String groupOid,
340 ObjectName groupObjname,
341 MBeanServer server) {
342 return new JvmMemoryMetaImpl(this, objectserver);
343 }
344
345 /**
346 * Factory method for "JvmThreading" group metadata class.
347 *
348 * You can redefine this method if you need to replace the default
349 * generated metadata class with your own customized class.
350 *
351 * @param groupName Name of the group ("JvmThreading")
352 * @param groupOid OID of this group
353 * @param groupObjname ObjectName for this group (may be null)
354 * @param server MBeanServer for this group (may be null)
355 *
356 * @return An instance of the metadata class generated for the
357 * "JvmThreading" group (JvmThreadingMeta)
358 *
359 **/
360 protected JvmThreadingMeta createJvmThreadingMetaNode(String groupName,
361 String groupOid,
362 ObjectName groupObjname,
363 MBeanServer server) {
364 return new JvmThreadingMetaImpl(this, objectserver);
365 }
366
367 /**
368 * Factory method for "JvmThreading" group MBean.
369 *
370 * You can redefine this method if you need to replace the default
371 * generated MBean class with your own customized class.
372 *
373 * @param groupName Name of the group ("JvmThreading")
374 * @param groupOid OID of this group
375 * @param groupObjname ObjectName for this group (may be null)
376 * @param server MBeanServer for this group (may be null)
377 *
378 * @return An instance of the MBean class generated for the
379 * "JvmThreading" group (JvmThreading)
380 *
381 * Note that when using standard metadata,
382 * the returned object must implement the "JvmThreadingMBean"
383 * interface.
384 **/
385 protected Object createJvmThreadingMBean(String groupName,
386 String groupOid,
387 ObjectName groupObjname,
388 MBeanServer server) {
389
390 // Note that when using standard metadata,
391 // the returned object must implement the "JvmThreadingMBean"
392 // interface.
393 //
394 if (server != null)
395 return new JvmThreadingImpl(this,server);
396 else
397 return new JvmThreadingImpl(this);
398 }
399
400 /**
401 * Factory method for "JvmRuntime" group metadata class.
402 *
403 * You can redefine this method if you need to replace the default
404 * generated metadata class with your own customized class.
405 *
406 * @param groupName Name of the group ("JvmRuntime")
407 * @param groupOid OID of this group
408 * @param groupObjname ObjectName for this group (may be null)
409 * @param server MBeanServer for this group (may be null)
410 *
411 * @return An instance of the metadata class generated for the
412 * "JvmRuntime" group (JvmRuntimeMeta)
413 *
414 **/
415 protected JvmRuntimeMeta createJvmRuntimeMetaNode(String groupName,
416 String groupOid,
417 ObjectName groupObjname,
418 MBeanServer server) {
419 return new JvmRuntimeMetaImpl(this, objectserver);
420 }
421
422 /**
423 * Factory method for "JvmRuntime" group MBean.
424 *
425 * You can redefine this method if you need to replace the default
426 * generated MBean class with your own customized class.
427 *
428 * @param groupName Name of the group ("JvmRuntime")
429 * @param groupOid OID of this group
430 * @param groupObjname ObjectName for this group (may be null)
431 * @param server MBeanServer for this group (may be null)
432 *
433 * @return An instance of the MBean class generated for the
434 * "JvmRuntime" group (JvmRuntime)
435 *
436 * Note that when using standard metadata,
437 * the returned object must implement the "JvmRuntimeMBean"
438 * interface.
439 **/
440 protected Object createJvmRuntimeMBean(String groupName,
441 String groupOid,
442 ObjectName groupObjname,
443 MBeanServer server) {
444
445 // Note that when using standard metadata,
446 // the returned object must implement the "JvmRuntimeMBean"
447 // interface.
448 //
449 if (server != null)
450 return new JvmRuntimeImpl(this,server);
451 else
452 return new JvmRuntimeImpl(this);
453 }
454
455 /**
456 * Factory method for "JvmCompilation" group metadata class.
457 *
458 * You can redefine this method if you need to replace the default
459 * generated metadata class with your own customized class.
460 *
461 * @param groupName Name of the group ("JvmCompilation")
462 * @param groupOid OID of this group
463 * @param groupObjname ObjectName for this group (may be null)
464 * @param server MBeanServer for this group (may be null)
465 *
466 * @return An instance of the metadata class generated for the
467 * "JvmCompilation" group (JvmCompilationMeta)
468 *
469 **/
470 protected JvmCompilationMeta
471 createJvmCompilationMetaNode(String groupName,
472 String groupOid,
473 ObjectName groupObjname,
474 MBeanServer server) {
475 // If there is no compilation system, the jvmCompilation will not
476 // be instantiated.
477 //
478 if (ManagementFactory.getCompilationMXBean() == null) return null;
479 return super.createJvmCompilationMetaNode(groupName,groupOid,
480 groupObjname,server);
481 }
482
483 /**
484 * Factory method for "JvmCompilation" group MBean.
485 *
486 * You can redefine this method if you need to replace the default
487 * generated MBean class with your own customized class.
488 *
489 * @param groupName Name of the group ("JvmCompilation")
490 * @param groupOid OID of this group
491 * @param groupObjname ObjectName for this group (may be null)
492 * @param server MBeanServer for this group (may be null)
493 *
494 * @return An instance of the MBean class generated for the
495 * "JvmCompilation" group (JvmCompilation)
496 *
497 * Note that when using standard metadata,
498 * the returned object must implement the "JvmCompilationMBean"
499 * interface.
500 **/
501 protected Object createJvmCompilationMBean(String groupName,
502 String groupOid, ObjectName groupObjname, MBeanServer server) {
503
504 // Note that when using standard metadata,
505 // the returned object must implement the "JvmCompilationMBean"
506 // interface.
507 //
508 if (server != null)
509 return new JvmCompilationImpl(this,server);
510 else
511 return new JvmCompilationImpl(this);
512 }
513
514 /**
515 * Factory method for "JvmOS" group MBean.
516 *
517 * You can redefine this method if you need to replace the default
518 * generated MBean class with your own customized class.
519 *
520 * @param groupName Name of the group ("JvmOS")
521 * @param groupOid OID of this group
522 * @param groupObjname ObjectName for this group (may be null)
523 * @param server MBeanServer for this group (may be null)
524 *
525 * @return An instance of the MBean class generated for the
526 * "JvmOS" group (JvmOS)
527 *
528 * Note that when using standard metadata,
529 * the returned object must implement the "JvmOSMBean"
530 * interface.
531 **/
532 protected Object createJvmOSMBean(String groupName,
533 String groupOid, ObjectName groupObjname, MBeanServer server) {
534
535 // Note that when using standard metadata,
536 // the returned object must implement the "JvmOSMBean"
537 // interface.
538 //
539 if (server != null)
540 return new JvmOSImpl(this,server);
541 else
542 return new JvmOSImpl(this);
543 }
544
545
546 /**
547 * Factory method for "JvmClassLoading" group MBean.
548 *
549 * You can redefine this method if you need to replace the default
550 * generated MBean class with your own customized class.
551 *
552 * @param groupName Name of the group ("JvmClassLoading")
553 * @param groupOid OID of this group
554 * @param groupObjname ObjectName for this group (may be null)
555 * @param server MBeanServer for this group (may be null)
556 *
557 * @return An instance of the MBean class generated for the
558 * "JvmClassLoading" group (JvmClassLoading)
559 *
560 * Note that when using standard metadata,
561 * the returned object must implement the "JvmClassLoadingMBean"
562 * interface.
563 **/
564 protected Object createJvmClassLoadingMBean(String groupName,
565 String groupOid,
566 ObjectName groupObjname,
567 MBeanServer server) {
568
569 // Note that when using standard metadata,
570 // the returned object must implement the "JvmClassLoadingMBean"
571 // interface.
572 //
573 if (server != null)
574 return new JvmClassLoadingImpl(this,server);
575 else
576 return new JvmClassLoadingImpl(this);
577 }
578
579 static String validDisplayStringTC(String str) {
580
581 if(str == null) return "";
582
583 if(str.length() > DISPLAY_STRING_MAX_LENGTH) {
584 return str.substring(0, DISPLAY_STRING_MAX_LENGTH);
585 }
586 else
587 return str;
588 }
589
590 static String validJavaObjectNameTC(String str) {
591
592 if(str == null) return "";
593
594 if(str.length() > JAVA_OBJECT_NAME_MAX_LENGTH) {
595 return str.substring(0, JAVA_OBJECT_NAME_MAX_LENGTH);
596 }
597 else
598 return str;
599 }
600
601 static String validPathElementTC(String str) {
602
603 if(str == null) return "";
604
605 if(str.length() > PATH_ELEMENT_MAX_LENGTH) {
606 return str.substring(0, PATH_ELEMENT_MAX_LENGTH);
607 }
608 else
609 return str;
610 }
611 static String validArgValueTC(String str) {
612
613 if(str == null) return "";
614
615 if(str.length() > ARG_VALUE_MAX_LENGTH) {
616 return str.substring(0, ARG_VALUE_MAX_LENGTH);
617 }
618 else
619 return str;
620 }
621
622 /**
623 * WARNING: This should probably be moved to JvmMemPoolTableMetaImpl
624 **/
625 private SnmpTableHandler getJvmMemPoolTableHandler(Object userData) {
626 final SnmpMibTable meta =
627 getRegisteredTableMeta("JvmMemPoolTable");
628 if (! (meta instanceof JvmMemPoolTableMetaImpl)) {
629 final String err = ((meta==null)?"No metadata for JvmMemPoolTable":
630 "Bad metadata class for JvmMemPoolTable: " +
631 meta.getClass().getName());
632 log.error("getJvmMemPoolTableHandler", err);
633 return null;
634 }
635 final JvmMemPoolTableMetaImpl memPoolTable =
636 (JvmMemPoolTableMetaImpl) meta;
637 return memPoolTable.getHandler(userData);
638 }
639
640 /**
641 * WARNING: This should probably be moved to JvmMemPoolTableMetaImpl
642 **/
643 private int findInCache(SnmpTableHandler handler,
644 String poolName) {
645
646 if (!(handler instanceof SnmpCachedData)) {
647 if (handler != null) {
648 final String err = "Bad class for JvmMemPoolTable datas: " +
649 handler.getClass().getName();
650 log.error("getJvmMemPoolEntry", err);
651 }
652 return -1;
653 }
654
655 final SnmpCachedData data = (SnmpCachedData)handler;
656 final int len = data.datas.length;
657 for (int i=0; i < data.datas.length ; i++) {
658 final MemoryPoolMXBean pool = (MemoryPoolMXBean) data.datas[i];
659 if (poolName.equals(pool.getName())) return i;
660 }
661 return -1;
662 }
663
664 /**
665 * WARNING: This should probably be moved to JvmMemPoolTableMetaImpl
666 **/
667 private SnmpOid getJvmMemPoolEntryIndex(SnmpTableHandler handler,
668 String poolName) {
669 final int index = findInCache(handler,poolName);
670 if (index < 0) return null;
671 return ((SnmpCachedData)handler).indexes[index];
672 }
673
674 private SnmpOid getJvmMemPoolEntryIndex(String poolName) {
675 return getJvmMemPoolEntryIndex(getJvmMemPoolTableHandler(null),
676 poolName);
677 }
678
679 // cache validity
680 //
681 // Should we define a property for this? Should we have different
682 // cache validity periods depending on which table we cache?
683 //
684 public long validity() {
685 return DEFAULT_CACHE_VALIDITY_PERIOD;
686 }
687
688 // Defined in RFC 2579
689 private final static int DISPLAY_STRING_MAX_LENGTH=255;
690 private final static int JAVA_OBJECT_NAME_MAX_LENGTH=1023;
691 private final static int PATH_ELEMENT_MAX_LENGTH=1023;
692 private final static int ARG_VALUE_MAX_LENGTH=1023;
693 private final static int DEFAULT_CACHE_VALIDITY_PERIOD=1000;
694}