/*
 * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
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;

/**
 * The class is used for implementing the "JvmMemMgrPoolRelTable" group.
 */
public class JvmMemMgrPoolRelTableMetaImpl extends JvmMemMgrPoolRelTableMeta
    implements Serializable {

    /**
     * A concrete implementation of {@link SnmpTableCache}, for the
     * jvmMemMgrPoolRelTable.
     **/
    private static class JvmMemMgrPoolRelTableCache
        extends SnmpTableCache {

        final private JvmMemMgrPoolRelTableMetaImpl meta;

        /**
         * Create a weak cache for the jvmMemMgrPoolRelTable.
         * @param validity validity of the cached data, in ms.
         **/
        JvmMemMgrPoolRelTableCache(JvmMemMgrPoolRelTableMetaImpl meta,
                                   long validity) {
            this.validity = validity;
            this.meta     = meta;
        }

        /**
         * Call <code>getTableDatas(JvmContextFactory.getUserData())</code>.
         **/
        public SnmpTableHandler getTableHandler() {
            final Map userData = JvmContextFactory.getUserData();
            return getTableDatas(userData);
        }

        /**
         * Builds a map pool-name => pool-index from the SnmpTableHandler
         * of the JvmMemPoolTable.
         **/
        private static Map<String, SnmpOid> buildPoolIndexMap(SnmpTableHandler handler) {
            // optimization...
            if (handler instanceof SnmpCachedData)
                return buildPoolIndexMap((SnmpCachedData)handler);

            // not optimizable... too bad.
            final Map<String, SnmpOid> m = new HashMap<String, SnmpOid>();
            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;
        }

        /**
         * Builds a map pool-name => pool-index from the SnmpTableHandler
         * of the JvmMemPoolTable.
         * Optimized algorithm.
         **/
        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<String, SnmpOid>(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;
        }

        /**
         * Return a table handler that holds the jvmMemManagerTable table data.
         * This method return the cached table data if it is still
         * valid, recompute it and cache the new value if it's not.
         * If it needs to recompute the cached data, it first
         * try to obtain the list of memory managers from the request
         * contextual cache, and if it is not found, it calls
         * <code>ManagementFactory.getMemoryMBean().getMemoryManagers()</code>
         * and caches the value.
         * This ensures that
         * <code>ManagementFactory.getMemoryMBean().getMemoryManagers()</code>
         * is not called more than once per request, thus ensuring a
         * consistent view of the table.
         **/
        protected SnmpCachedData updateCachedDatas(Object userData) {
            // Get the MemoryManager     table
            final SnmpTableHandler mmHandler =
                meta.getManagerHandler(userData);

            // Get the MemoryPool        table
            final SnmpTableHandler mpHandler =
                meta.getPoolHandler(userData);

            // Time stamp for the cache
            final long time = System.currentTimeMillis();

            //     Build a Map poolname -> index
            final Map 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
            // Create a row in the relation table.
            final TreeMap<SnmpOid, Object> table =
                    new TreeMap<SnmpOid, Object>(SnmpCachedData.oidComparator);
            updateTreeMap(table,userData,mmHandler,mpHandler,poolIndexMap);

            return new SnmpCachedData(time,table);
        }


        /**
         * Get the list of memory pool associated with the
         * given MemoryManagerMXBean.
         **/
        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 poolIndexMap) {

            // The MemoryManager index is an int, so it's the first
            // and only subidentifier.
            final long mmarc;
            try {
                mmarc = mmIndex.getOidArc(0);
            } catch (SnmpStatusException x) {
                log.debug("updateTreeMap",
                          "Bad MemoryManager OID index: "+mmIndex);
                log.debug("updateTreeMap",x);
                return;
            }


            // Cache this in userData + get it from cache?
            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 = (SnmpOid)poolIndexMap.get(mpmName);
                if (mpIndex == null) continue;

                // The MemoryPool index is an int, so it's the first
                // and only subidentifier.
                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
                // index is appended.
                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 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 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);
            }
        }
    }

    // The weak cache for this table.
    protected SnmpTableCache cache;

    private transient JvmMemManagerTableMetaImpl managers = null;
    private transient JvmMemPoolTableMetaImpl    pools    = null;

    /**
     * Constructor for the table. Initialize metadata for
     * "JvmMemMgrPoolRelTableMeta".
     * The reference on the MBean server is updated so the entries
     * created through an SNMP SET will be AUTOMATICALLY REGISTERED
     * in Java DMK.
     */
    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
    // relation table.
    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
    // relation table.
    private final JvmMemPoolTableMetaImpl getPools(SnmpMib mib) {
        if (pools == null) {
            pools = (JvmMemPoolTableMetaImpl)
                mib.getRegisteredTableMeta("JvmMemPoolTable");
        }
        return pools;
    }

    /**
     * Returns the JvmMemManagerTable SnmpTableHandler
     **/
    protected SnmpTableHandler getManagerHandler(Object userData) {
        final JvmMemManagerTableMetaImpl managerTable = getManagers(theMib);
        return managerTable.getHandler(userData);
    }

    /**
     * Returns the JvmMemPoolTable SnmpTableHandler
     **/
    protected SnmpTableHandler getPoolHandler(Object userData) {
        final JvmMemPoolTableMetaImpl poolTable = getPools(theMib);
        return poolTable.getHandler(userData);
    }

    // See com.sun.jmx.snmp.agent.SnmpMibTable
    protected SnmpOid getNextOid(Object userData)
        throws SnmpStatusException {
        // null means get the first OID.
        return getNextOid(null,userData);
    }

    // See com.sun.jmx.snmp.agent.SnmpMibTable
    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;
    }


    // See com.sun.jmx.snmp.agent.SnmpMibTable
    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);
    }

    // See com.sun.jmx.snmp.agent.SnmpMibTable
    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;
    }

    /**
     * Get the SnmpTableHandler that holds the jvmMemManagerTable data.
     * First look it up in the request contextual cache, and if it is
     * not found, obtain it from the weak cache.
     * <br>The request contextual cache will be released at the end of the
     * current requests, and is used only to process this request.
     * <br>The weak cache is shared by all requests, and is only
     * recomputed when it is found to be obsolete.
     * <br>Note that the data put in the request contextual cache is
     *     never considered to be obsolete, in order to preserve data
     *     coherency.
     **/
    protected SnmpTableHandler getHandler(Object userData) {
        final Map<Object, Object> m;
        if (userData instanceof Map) m=Util.cast(userData);
        else m=null;

        // Look in the contextual cache.
        if (m != null) {
            final SnmpTableHandler handler =
                (SnmpTableHandler)m.get("JvmMemMgrPoolRelTable.handler");
            if (handler != null) return handler;
        }

        // No handler in contextual cache, make a new one.
        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);
}
