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

/**
 * The class is used for implementing the "JvmMemGCTable" table.
 */
public class JvmMemGCTableMetaImpl extends  JvmMemGCTableMeta {

    /**
     * This class acts as a filter over the SnmpTableHandler
     * used for the JvmMemoryManagerTable. It filters out
     * (skip) all MemoryManagerMXBean that are not instances of
     * GarbageCollectorMXBean so that only Garbage Collectors are
     * seen. This is a better solution than relying on
     * ManagementFactory.getGarbageCollectorMXBeans() because it makes it
     * possible to guarantee the consistency betwen the MemoryManager table
     * and the GCTable since both will be sharing the same cache.
     **/
    protected static class GCTableFilter {

        /**
         * Returns the index that immediately follows the given
         * <var>index</var>. The returned index is strictly greater
         * than the given <var>index</var>, and is contained in the table.
         * <br>If the given <var>index</var> is null, returns the first
         * index in the table.
         * <br>If there are no index after the given <var>index</var>,
         * returns null.
         * This method is an optimization for the case where the
         * SnmpTableHandler is in fact an instance of SnmpCachedData.
         **/
        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) {
                    // That's the next: return it.
                    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;
        }

        /**
         * Returns the index that immediately follows the given
         * <var>index</var>. The returned index is strictly greater
         * than the given <var>index</var>, and is contained in the table.
         * <br>If the given <var>index</var> is null, returns the first
         * index in the table.
         * <br>If there are no index after the given <var>index</var>,
         * returns null.
         **/
        public SnmpOid getNext(SnmpTableHandler handler, SnmpOid index) {

            // try to call the optimized method
            if (handler instanceof SnmpCachedData)
                return getNext((SnmpCachedData)handler, index);

            // too bad - revert to non-optimized generic algorithm
            SnmpOid next = index;
            do {
                next = handler.getNext(next);
                final Object value = handler.getData(next);
                if (value instanceof GarbageCollectorMXBean)
                    // That's the next! return it
                    return next;
                // skip to next index...
            } while (next != null);
            return null;
        }

        /**
         * Returns the data associated with the given index.
         * If the given index is not found, null is returned.
         * Note that returning null does not necessarily means that
         * the index was not found.
         **/
        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;
        }

        /**
         * Returns true if the given <var>index</var> is present.
         **/
        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();


    /**
     * Constructor for the table. Initialize metadata for "JvmMemGCTableMeta".
     */
    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
    // not a GarbageCollectorMXBean.
    private final JvmMemManagerTableMetaImpl getManagers(SnmpMib mib) {
        if (managers == null) {
            managers = (JvmMemManagerTableMetaImpl)
                mib.getRegisteredTableMeta("JvmMemManagerTable");
        }
        return managers;
    }

    /**
     * Returns the JvmMemManagerTable SnmpTableHandler
     **/
    protected SnmpTableHandler getHandler(Object userData) {
        JvmMemManagerTableMetaImpl managerTable= getManagers(theMib);
        return managerTable.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();
        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;
        }
    }


    // 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 filter.contains(handler,oid);
    }

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