|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package sun.management.snmp.jvminstr; |
|
|
|
|
|
// java imports |
|
|
|
import java.io.Serializable; |
|
import java.util.List; |
|
import java.util.Map; |
|
import java.util.TreeMap; |
|
|
|
// jmx imports |
|
|
|
import com.sun.jmx.snmp.SnmpOid; |
|
import com.sun.jmx.snmp.SnmpStatusException; |
|
|
|
// jdmk imports |
|
|
|
import com.sun.jmx.snmp.agent.SnmpMib; |
|
import com.sun.jmx.snmp.agent.SnmpStandardObjectServer; |
|
|
|
import java.lang.management.MemoryManagerMXBean; |
|
import java.lang.management.GarbageCollectorMXBean; |
|
import java.lang.management.ManagementFactory; |
|
|
|
import sun.management.snmp.jvmmib.JvmMemGCTableMeta; |
|
import sun.management.snmp.util.SnmpCachedData; |
|
import sun.management.snmp.util.SnmpTableCache; |
|
import sun.management.snmp.util.SnmpTableHandler; |
|
import sun.management.snmp.util.MibLogger; |
|
import sun.management.snmp.util.JvmContextFactory; |
|
|
|
|
|
|
|
*/ |
|
public class JvmMemGCTableMetaImpl extends JvmMemGCTableMeta { |
|
|
|
static final long serialVersionUID = 8250461197108867607L; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
protected static class GCTableFilter { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public SnmpOid getNext(SnmpCachedData datas, SnmpOid index) { |
|
|
|
final boolean dbg = log.isDebugOn(); |
|
|
|
// We're going to loop until we find an instance of |
|
// GarbageCollectorMXBean. First we attempt to find |
|
// the next element whose OID follows the given index. |
|
// If `index' is null, the insertion point is -1 |
|
// (the next is 0 = -insertion - 1) |
|
|
|
final int insertion = (index==null)?-1:datas.find(index); |
|
if (dbg) log.debug("GCTableFilter","oid="+index+ |
|
" at insertion="+insertion); |
|
|
|
int next; |
|
if (insertion > -1) next = insertion+1; |
|
else next = -insertion -1; |
|
|
|
// Now `next' points to the element that imediately |
|
// follows the given `index'. We're going to loop |
|
// through the table, starting at `next' (included), |
|
// and return the first element which is an instance |
|
// of GarbageCollectorMXBean. |
|
|
|
for (;next<datas.indexes.length;next++) { |
|
if (dbg) log.debug("GCTableFilter","next="+next); |
|
final Object value = datas.datas[next]; |
|
if (dbg) log.debug("GCTableFilter","value["+next+"]=" + |
|
((MemoryManagerMXBean)value).getName()); |
|
if (value instanceof GarbageCollectorMXBean) { |
|
|
|
if (dbg) log.debug("GCTableFilter", |
|
((MemoryManagerMXBean)value).getName() + |
|
" is a GarbageCollectorMXBean."); |
|
return datas.indexes[next]; |
|
} |
|
if (dbg) log.debug("GCTableFilter", |
|
((MemoryManagerMXBean)value).getName() + |
|
" is not a GarbageCollectorMXBean: " + |
|
value.getClass().getName()); |
|
// skip to next index... |
|
} |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public SnmpOid getNext(SnmpTableHandler handler, SnmpOid index) { |
|
|
|
|
|
if (handler instanceof SnmpCachedData) |
|
return getNext((SnmpCachedData)handler, index); |
|
|
|
|
|
SnmpOid next = index; |
|
do { |
|
next = handler.getNext(next); |
|
final Object value = handler.getData(next); |
|
if (value instanceof GarbageCollectorMXBean) |
|
|
|
return next; |
|
// skip to next index... |
|
} while (next != null); |
|
return null; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
**/ |
|
public Object getData(SnmpTableHandler handler, SnmpOid index) { |
|
final Object value = handler.getData(index); |
|
if (value instanceof GarbageCollectorMXBean) return value; |
|
// Behaves as if there was nothing at this index... |
|
|
|
return null; |
|
} |
|
|
|
|
|
|
|
**/ |
|
public boolean contains(SnmpTableHandler handler, SnmpOid index) { |
|
if (handler.getData(index) instanceof GarbageCollectorMXBean) |
|
return true; |
|
// Behaves as if there was nothing at this index... |
|
|
|
return false; |
|
} |
|
} |
|
|
|
|
|
private transient JvmMemManagerTableMetaImpl managers = null; |
|
private static GCTableFilter filter = new GCTableFilter(); |
|
|
|
|
|
|
|
|
|
*/ |
|
public JvmMemGCTableMetaImpl(SnmpMib myMib, |
|
SnmpStandardObjectServer objserv) { |
|
super(myMib,objserv); |
|
} |
|
|
|
// Returns a pointer to the JvmMemManager meta node - we're going |
|
// to reuse its SnmpTableHandler by filtering out all that is |
|
|
|
private final JvmMemManagerTableMetaImpl getManagers(SnmpMib mib) { |
|
if (managers == null) { |
|
managers = (JvmMemManagerTableMetaImpl) |
|
mib.getRegisteredTableMeta("JvmMemManagerTable"); |
|
} |
|
return managers; |
|
} |
|
|
|
|
|
|
|
**/ |
|
protected SnmpTableHandler getHandler(Object userData) { |
|
JvmMemManagerTableMetaImpl managerTable= getManagers(theMib); |
|
return managerTable.getHandler(userData); |
|
} |
|
|
|
|
|
protected SnmpOid getNextOid(Object userData) |
|
throws SnmpStatusException { |
|
|
|
return getNextOid(null,userData); |
|
} |
|
|
|
|
|
protected SnmpOid getNextOid(SnmpOid oid, Object userData) |
|
throws SnmpStatusException { |
|
final boolean dbg = log.isDebugOn(); |
|
try { |
|
if (dbg) log.debug("getNextOid", "previous=" + oid); |
|
|
|
// Get the data handler. |
|
|
|
SnmpTableHandler handler = getHandler(userData); |
|
if (handler == null) { |
|
// This should never happen. |
|
// If we get here it's a bug. |
|
|
|
if (dbg) log.debug("getNextOid", "handler is null!"); |
|
throw new |
|
SnmpStatusException(SnmpStatusException.noSuchInstance); |
|
} |
|
|
|
|
|
// Get the next oid, using the GC filter. |
|
|
|
final SnmpOid next = filter.getNext(handler,oid); |
|
if (dbg) log.debug("getNextOid", "next=" + next); |
|
|
|
// if next is null: we reached the end of the table. |
|
|
|
if (next == null) |
|
throw new |
|
SnmpStatusException(SnmpStatusException.noSuchInstance); |
|
|
|
return next; |
|
} catch (RuntimeException x) { |
|
// debug. This should never happen. |
|
|
|
if (dbg) log.debug("getNextOid",x); |
|
throw x; |
|
} |
|
} |
|
|
|
|
|
|
|
protected boolean contains(SnmpOid oid, Object userData) { |
|
// Get the handler. |
|
|
|
SnmpTableHandler handler = getHandler(userData); |
|
|
|
// handler should never be null. |
|
|
|
if (handler == null) |
|
return false; |
|
return filter.contains(handler,oid); |
|
} |
|
|
|
|
|
public Object getEntry(SnmpOid oid) |
|
throws SnmpStatusException { |
|
|
|
if (oid == null) |
|
throw new SnmpStatusException(SnmpStatusException.noSuchInstance); |
|
|
|
// Get the request contextual cache (userData). |
|
|
|
final Map<Object, Object> m = JvmContextFactory.getUserData(); |
|
|
|
// First look in the request contextual cache: maybe we've already |
|
// created this entry... |
|
// |
|
|
|
// We know in the case of this table that the index is an integer, |
|
// it is thus the first OID arc of the index OID. |
|
|
|
final long index = oid.getOidArc(0); |
|
|
|
// We're going to use this name to store/retrieve the entry in |
|
// the request contextual cache. |
|
// |
|
// Revisit: Probably better programming to put all these strings |
|
// in some interface. |
|
|
|
final String entryTag = ((m==null)?null:("JvmMemGCTable.entry." + |
|
index)); |
|
|
|
// If the entry is in the cache, simply return it. |
|
|
|
if (m != null) { |
|
final Object entry = m.get(entryTag); |
|
if (entry != null) return entry; |
|
} |
|
|
|
// Entry was not in request cache. Make a new one. |
|
// |
|
// Get the data hanler. |
|
|
|
SnmpTableHandler handler = getHandler(m); |
|
|
|
// handler should never be null. |
|
|
|
if (handler == null) |
|
throw new SnmpStatusException(SnmpStatusException.noSuchInstance); |
|
|
|
// Use the filter to retrieve only GarabageCollectorMBean data. |
|
|
|
final Object data = filter.getData(handler,oid); |
|
|
|
// data may be null if the OID we were given is not valid. |
|
// (e.g. it identifies a MemoryManager which is not a |
|
// GarbageCollector) |
|
|
|
if (data == null) |
|
throw new SnmpStatusException(SnmpStatusException.noSuchInstance); |
|
|
|
// Make a new entryy (transient object that will be kept only |
|
// for the duration of the request. |
|
|
|
final Object entry = |
|
new JvmMemGCEntryImpl((GarbageCollectorMXBean)data,(int)index); |
|
|
|
// Put the entry in the request cache in case we need it later |
|
// in the processing of the request. Note that we could have |
|
// optimized this by making JvmMemGCEntryImpl extend |
|
// JvmMemManagerEntryImpl, and then make sure that |
|
// JvmMemManagerTableMetaImpl creates an instance of JvmMemGCEntryImpl |
|
// instead of JvmMemManagerEntryImpl when the associated data is |
|
// an instance of GarbageCollectorMXBean. This would have made it |
|
// possible to share the transient entry object. |
|
// As it is, we may have two transient objects that points to |
|
// the same underlying MemoryManagerMXBean (which is definitely |
|
// not a problem - but is only a small dysatisfaction) |
|
|
|
if (m != null && entry != null) { |
|
m.put(entryTag,entry); |
|
} |
|
|
|
return entry; |
|
} |
|
|
|
static final MibLogger log = new MibLogger(JvmMemGCTableMetaImpl.class); |
|
} |