| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
package sun.management.snmp.jvminstr;  | 
 | 
 | 
 | 
// java imports  | 
 | 
 | 
 | 
import com.sun.jmx.mbeanserver.Util;  | 
 | 
import java.io.Serializable;  | 
 | 
import java.util.List;  | 
 | 
import java.util.Iterator;  | 
 | 
import java.util.Map;  | 
 | 
import java.util.HashMap;  | 
 | 
import java.util.TreeMap;  | 
 | 
import java.util.Collections;  | 
 | 
 | 
 | 
// jmx imports  | 
 | 
 | 
 | 
import javax.management.MBeanServer;  | 
 | 
import javax.management.ObjectName;  | 
 | 
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 com.sun.jmx.snmp.agent.SnmpMibTable;  | 
 | 
 | 
 | 
import java.lang.management.MemoryManagerMXBean;  | 
 | 
import java.lang.management.MemoryPoolMXBean;  | 
 | 
 | 
 | 
import sun.management.snmp.jvmmib.JvmMemMgrPoolRelTableMeta;  | 
 | 
import sun.management.snmp.util.SnmpTableCache;  | 
 | 
import sun.management.snmp.util.SnmpCachedData;  | 
 | 
import sun.management.snmp.util.SnmpTableHandler;  | 
 | 
import sun.management.snmp.util.MibLogger;  | 
 | 
import sun.management.snmp.util.JvmContextFactory;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta  | 
 | 
    implements Serializable { | 
 | 
 | 
 | 
    static final long serialVersionUID = 1896509775012355443L;  | 
 | 
 | 
 | 
    /**  | 
 | 
     * A concrete implementation of {@link SnmpTableCache}, for the | 
 | 
     * jvmMemMgrPoolRelTable.  | 
 | 
     **/  | 
 | 
 | 
 | 
    private static class JvmMemMgrPoolRelTableCache  | 
 | 
        extends SnmpTableCache { | 
 | 
 | 
 | 
        static final long serialVersionUID = 6059937161990659184L;  | 
 | 
        final private JvmMemMgrPoolRelTableMetaImpl meta;  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         **/  | 
 | 
        JvmMemMgrPoolRelTableCache(JvmMemMgrPoolRelTableMetaImpl meta,  | 
 | 
                                   long validity) { | 
 | 
            this.validity = validity;  | 
 | 
            this.meta     = meta;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
         **/  | 
 | 
        public SnmpTableHandler getTableHandler() { | 
 | 
            final Map<Object,Object> userData = JvmContextFactory.getUserData();  | 
 | 
            return getTableDatas(userData);  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         **/  | 
 | 
        private static Map<String, SnmpOid> buildPoolIndexMap(SnmpTableHandler handler) { | 
 | 
              | 
 | 
            if (handler instanceof SnmpCachedData)  | 
 | 
                return buildPoolIndexMap((SnmpCachedData)handler);  | 
 | 
 | 
 | 
              | 
 | 
            final Map<String, SnmpOid> m = new HashMap<>();  | 
 | 
            SnmpOid index=null;  | 
 | 
            while ((index = handler.getNext(index))!=null) { | 
 | 
                final MemoryPoolMXBean mpm =  | 
 | 
                    (MemoryPoolMXBean)handler.getData(index);  | 
 | 
                if (mpm == null) continue;  | 
 | 
                final String name = mpm.getName();  | 
 | 
                if (name == null) continue;  | 
 | 
                m.put(name,index);  | 
 | 
            }  | 
 | 
            return m;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         **/  | 
 | 
        private static Map<String, SnmpOid> buildPoolIndexMap(SnmpCachedData cached) { | 
 | 
            if (cached == null) return Collections.emptyMap();  | 
 | 
            final SnmpOid[] indexes = cached.indexes;  | 
 | 
            final Object[]  datas   = cached.datas;  | 
 | 
            final int len = indexes.length;  | 
 | 
            final Map<String, SnmpOid> m = new HashMap<>(len);  | 
 | 
            for (int i=0; i<len; i++) { | 
 | 
                final SnmpOid index = indexes[i];  | 
 | 
                if (index == null) continue;  | 
 | 
                final MemoryPoolMXBean mpm =  | 
 | 
                    (MemoryPoolMXBean)datas[i];  | 
 | 
                if (mpm == null) continue;  | 
 | 
                final String name = mpm.getName();  | 
 | 
                if (name == null) continue;  | 
 | 
                m.put(name,index);  | 
 | 
            }  | 
 | 
            return m;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         **/  | 
 | 
        protected SnmpCachedData updateCachedDatas(Object userData) { | 
 | 
              | 
 | 
            final SnmpTableHandler mmHandler =  | 
 | 
                meta.getManagerHandler(userData);  | 
 | 
 | 
 | 
              | 
 | 
            final SnmpTableHandler mpHandler =  | 
 | 
                meta.getPoolHandler(userData);  | 
 | 
 | 
 | 
              | 
 | 
            final long time = System.currentTimeMillis();  | 
 | 
 | 
 | 
              | 
 | 
            final Map<String,SnmpOid> poolIndexMap = buildPoolIndexMap(mpHandler);  | 
 | 
 | 
 | 
            // For each memory manager, get the list of memory pools  | 
 | 
            // For each memory pool, find its index in the memory pool table  | 
 | 
              | 
 | 
            final TreeMap<SnmpOid, Object> table =  | 
 | 
                    new TreeMap<>(SnmpCachedData.oidComparator);  | 
 | 
            updateTreeMap(table,userData,mmHandler,mpHandler,poolIndexMap);  | 
 | 
 | 
 | 
            return new SnmpCachedData(time,table);  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
         **/  | 
 | 
        protected String[] getMemoryPools(Object userData,  | 
 | 
                                      MemoryManagerMXBean mmm, long mmarc) { | 
 | 
            final String listTag =  | 
 | 
                "JvmMemManager." + mmarc + ".getMemoryPools";  | 
 | 
 | 
 | 
            String[] result=null;  | 
 | 
            if (userData instanceof Map) { | 
 | 
                result = (String[])((Map)userData).get(listTag);  | 
 | 
                if (result != null) return result;  | 
 | 
            }  | 
 | 
 | 
 | 
            if (mmm!=null) { | 
 | 
                result = mmm.getMemoryPoolNames();  | 
 | 
            }  | 
 | 
            if ((result!=null)&&(userData instanceof Map)) { | 
 | 
                Map<Object, Object> map = Util.cast(userData);  | 
 | 
                map.put(listTag,result);  | 
 | 
            }  | 
 | 
 | 
 | 
            return result;  | 
 | 
        }  | 
 | 
 | 
 | 
        protected void updateTreeMap(TreeMap<SnmpOid, Object> table, Object userData,  | 
 | 
                                     MemoryManagerMXBean mmm,  | 
 | 
                                     SnmpOid mmIndex,  | 
 | 
                                     Map<String, SnmpOid> poolIndexMap) { | 
 | 
 | 
 | 
            // The MemoryManager index is an int, so it's the first  | 
 | 
              | 
 | 
            final long mmarc;  | 
 | 
            try { | 
 | 
                mmarc = mmIndex.getOidArc(0);  | 
 | 
            } catch (SnmpStatusException x) { | 
 | 
                log.debug("updateTreeMap", | 
 | 
                          "Bad MemoryManager OID index: "+mmIndex);  | 
 | 
                log.debug("updateTreeMap",x); | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
 | 
 | 
              | 
 | 
            final String[] mpList = getMemoryPools(userData,mmm,mmarc);  | 
 | 
            if (mpList == null || mpList.length < 1) return;  | 
 | 
 | 
 | 
            final String mmmName = mmm.getName();  | 
 | 
            for (int i = 0; i < mpList.length; i++) { | 
 | 
                final String mpmName = mpList[i];  | 
 | 
                if (mpmName == null) continue;  | 
 | 
                final SnmpOid mpIndex = poolIndexMap.get(mpmName);  | 
 | 
                if (mpIndex == null) continue;  | 
 | 
 | 
 | 
                // The MemoryPool index is an int, so it's the first  | 
 | 
                  | 
 | 
                final long mparc;  | 
 | 
                try { | 
 | 
                    mparc  = mpIndex.getOidArc(0);  | 
 | 
                } catch (SnmpStatusException x) { | 
 | 
                    log.debug("updateTreeMap","Bad MemoryPool OID index: " + | 
 | 
                          mpIndex);  | 
 | 
                    log.debug("updateTreeMap",x); | 
 | 
                    continue;  | 
 | 
                }  | 
 | 
                // The MemoryMgrPoolRel table indexed is composed  | 
 | 
                // of the MemoryManager index, to which the MemoryPool  | 
 | 
                  | 
 | 
                final long[] arcs = { mmarc, mparc }; | 
 | 
 | 
 | 
                final SnmpOid index = new SnmpOid(arcs);  | 
 | 
 | 
 | 
                table.put(index, new JvmMemMgrPoolRelEntryImpl(mmmName,  | 
 | 
                                                               mpmName,  | 
 | 
                                                               (int)mmarc,  | 
 | 
                                                               (int)mparc));  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        protected void updateTreeMap(TreeMap<SnmpOid, Object> table, Object userData,  | 
 | 
                                     SnmpTableHandler mmHandler,  | 
 | 
                                     SnmpTableHandler mpHandler,  | 
 | 
                                     Map<String, SnmpOid> poolIndexMap) { | 
 | 
            if (mmHandler instanceof SnmpCachedData) { | 
 | 
                updateTreeMap(table,userData,(SnmpCachedData)mmHandler,  | 
 | 
                              mpHandler,poolIndexMap);  | 
 | 
                return;  | 
 | 
            }  | 
 | 
 | 
 | 
            SnmpOid mmIndex=null;  | 
 | 
            while ((mmIndex = mmHandler.getNext(mmIndex))!=null) { | 
 | 
                final MemoryManagerMXBean mmm =  | 
 | 
                    (MemoryManagerMXBean)mmHandler.getData(mmIndex);  | 
 | 
                if (mmm == null) continue;  | 
 | 
                updateTreeMap(table,userData,mmm,mmIndex,poolIndexMap);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        protected void updateTreeMap(TreeMap<SnmpOid, Object> table, Object userData,  | 
 | 
                                     SnmpCachedData mmHandler,  | 
 | 
                                     SnmpTableHandler mpHandler,  | 
 | 
                                     Map<String, SnmpOid> poolIndexMap) { | 
 | 
 | 
 | 
            final SnmpOid[] indexes = mmHandler.indexes;  | 
 | 
            final Object[]  datas   = mmHandler.datas;  | 
 | 
            final int size = indexes.length;  | 
 | 
            for (int i=size-1; i>-1; i--) { | 
 | 
                final MemoryManagerMXBean mmm =  | 
 | 
                    (MemoryManagerMXBean)datas[i];  | 
 | 
                if (mmm == null) continue;  | 
 | 
                updateTreeMap(table,userData,mmm,indexes[i],poolIndexMap);  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    protected SnmpTableCache cache;  | 
 | 
 | 
 | 
    private transient JvmMemManagerTableMetaImpl managers = null;  | 
 | 
    private transient JvmMemPoolTableMetaImpl    pools    = null;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public JvmMemMgrPoolRelTableMetaImpl(SnmpMib myMib,  | 
 | 
                                      SnmpStandardObjectServer objserv) { | 
 | 
        super(myMib,objserv);  | 
 | 
        this.cache = new  | 
 | 
            JvmMemMgrPoolRelTableCache(this,((JVM_MANAGEMENT_MIB_IMPL)myMib).  | 
 | 
                                       validity());  | 
 | 
    }  | 
 | 
 | 
 | 
    // Returns a pointer to the JvmMemManager meta node - we're going  | 
 | 
    // to reuse its SnmpTableHandler in order to implement the  | 
 | 
      | 
 | 
    private final JvmMemManagerTableMetaImpl getManagers(SnmpMib mib) { | 
 | 
        if (managers == null) { | 
 | 
            managers = (JvmMemManagerTableMetaImpl)  | 
 | 
                mib.getRegisteredTableMeta("JvmMemManagerTable"); | 
 | 
        }  | 
 | 
        return managers;  | 
 | 
    }  | 
 | 
 | 
 | 
    // Returns a pointer to the JvmMemPool meta node - we're going  | 
 | 
    // to reuse its SnmpTableHandler in order to implement the  | 
 | 
      | 
 | 
    private final JvmMemPoolTableMetaImpl getPools(SnmpMib mib) { | 
 | 
        if (pools == null) { | 
 | 
            pools = (JvmMemPoolTableMetaImpl)  | 
 | 
                mib.getRegisteredTableMeta("JvmMemPoolTable"); | 
 | 
        }  | 
 | 
        return pools;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     **/  | 
 | 
    protected SnmpTableHandler getManagerHandler(Object userData) { | 
 | 
        final JvmMemManagerTableMetaImpl managerTable = getManagers(theMib);  | 
 | 
        return managerTable.getHandler(userData);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     **/  | 
 | 
    protected SnmpTableHandler getPoolHandler(Object userData) { | 
 | 
        final JvmMemPoolTableMetaImpl poolTable = getPools(theMib);  | 
 | 
        return poolTable.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();  | 
 | 
        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  | 
 | 
          | 
 | 
        final SnmpOid next = handler.getNext(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;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
    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 handler.contains(oid);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    public Object getEntry(SnmpOid oid)  | 
 | 
        throws SnmpStatusException { | 
 | 
 | 
 | 
        if (oid == null || oid.getLength() < 2)  | 
 | 
            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);  | 
 | 
 | 
 | 
        // Get the request contextual cache (userData).  | 
 | 
          | 
 | 
        final Map<Object, Object> m = JvmContextFactory.getUserData();  | 
 | 
 | 
 | 
        // We know in the case of this table that the index is composed  | 
 | 
        // of two integers,  | 
 | 
        //  o The MemoryManager is the first  OID arc of the index OID.  | 
 | 
        //  o The MemoryPool    is the second OID arc of the index OID.  | 
 | 
          | 
 | 
        final long   mgrIndex     = oid.getOidArc(0);  | 
 | 
        final long   poolIndex    = oid.getOidArc(1);  | 
 | 
 | 
 | 
        // 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:  | 
 | 
                                 ("JvmMemMgrPoolRelTable.entry." + | 
 | 
                                  mgrIndex + "." + poolIndex));  | 
 | 
 | 
 | 
        // If the entry is in the cache, simply return it.  | 
 | 
          | 
 | 
        if (m != null) { | 
 | 
            final Object entry = m.get(entryTag);  | 
 | 
            if (entry != null) return entry;  | 
 | 
        }  | 
 | 
 | 
 | 
        // The entry was not in the 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);  | 
 | 
 | 
 | 
        // Get the data associated with our entry.  | 
 | 
          | 
 | 
        final Object data = handler.getData(oid);  | 
 | 
 | 
 | 
        // data may be null if the OID we were given is not valid.  | 
 | 
          | 
 | 
        if (!(data instanceof JvmMemMgrPoolRelEntryImpl))  | 
 | 
            throw new SnmpStatusException(SnmpStatusException.noSuchInstance);  | 
 | 
 | 
 | 
        // make the new entry (transient object that will be kept only  | 
 | 
        // for the duration of the request.  | 
 | 
          | 
 | 
        final Object entry = (JvmMemMgrPoolRelEntryImpl)data;  | 
 | 
        // XXXXX Revisit  | 
 | 
        // new JvmMemMgrPoolRelEntryImpl((MemoryManagerMXBean)data,  | 
 | 
        //                                (int)mgrIndex,(int)poolIndex);  | 
 | 
 | 
 | 
        // Put the entry in the cache in case we need it later while processing  | 
 | 
        // the request.  | 
 | 
          | 
 | 
        if (m != null && entry != null) { | 
 | 
            m.put(entryTag,entry);  | 
 | 
        }  | 
 | 
 | 
 | 
        return entry;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     **/  | 
 | 
    protected SnmpTableHandler getHandler(Object userData) { | 
 | 
        final Map<Object, Object> m;  | 
 | 
        if (userData instanceof Map) m=Util.cast(userData);  | 
 | 
        else m=null;  | 
 | 
 | 
 | 
          | 
 | 
        if (m != null) { | 
 | 
            final SnmpTableHandler handler =  | 
 | 
                (SnmpTableHandler)m.get("JvmMemMgrPoolRelTable.handler"); | 
 | 
            if (handler != null) return handler;  | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        final SnmpTableHandler handler = cache.getTableHandler();  | 
 | 
 | 
 | 
        if (m != null && handler != null )  | 
 | 
            m.put("JvmMemMgrPoolRelTable.handler",handler); | 
 | 
 | 
 | 
        return handler;  | 
 | 
    }  | 
 | 
 | 
 | 
    static final MibLogger log =  | 
 | 
        new MibLogger(JvmMemMgrPoolRelTableMetaImpl.class);  | 
 | 
}  |