| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
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);  | 
 | 
}  |