/*
 * Copyright (c) 2004, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.jvmstat.perfdata.monitor.v1_0;

import sun.management.counter.Units;
import sun.management.counter.Variability;
import sun.jvmstat.monitor.*;
import sun.jvmstat.perfdata.monitor.*;
import java.util.*;
import java.util.regex.*;
import java.nio.*;

/**
 * The concrete implementation of version 1.0 of the HotSpot PerfData
 * Instrumentation buffer. This class is responsible for parsing the
 * instrumentation memory and constructing the necessary objects to
 * represent and access the instrumentation objects contained in the
 * memory buffer.
 *
 * @author Brian Doherty
 * @since 1.5
 * @see AbstractPerfDataBuffer
 */
public class PerfDataBuffer extends PerfDataBufferImpl {

    private static final boolean DEBUG = false;
    private static final int syncWaitMs =
            Integer.getInteger("sun.jvmstat.perdata.syncWaitMs", 5000);
    private static final ArrayList EMPTY_LIST = new ArrayList(0);

    /*
     * the following constants must be kept in sync with struct
     * PerfDataEntry in perfMemory.hpp
     */
    private final static int PERFDATA_ENTRYLENGTH_OFFSET=0;
    private final static int PERFDATA_ENTRYLENGTH_SIZE=4;   // sizeof(int)
    private final static int PERFDATA_NAMELENGTH_OFFSET=4;
    private final static int PERFDATA_NAMELENGTH_SIZE=4;    // sizeof(int)
    private final static int PERFDATA_VECTORLENGTH_OFFSET=8;
    private final static int PERFDATA_VECTORLENGTH_SIZE=4;  // sizeof(int)
    private final static int PERFDATA_DATATYPE_OFFSET=12;
    private final static int PERFDATA_DATATYPE_SIZE=1;      // sizeof(byte)
    private final static int PERFDATA_FLAGS_OFFSET=13;
    private final static int PERFDATA_FLAGS_SIZE=1;        // sizeof(byte)
    private final static int PERFDATA_DATAUNITS_OFFSET=14;
    private final static int PERFDATA_DATAUNITS_SIZE=1;     // sizeof(byte)
    private final static int PERFDATA_DATAATTR_OFFSET=15;
    private final static int PERFDATA_DATAATTR_SIZE=1;      // sizeof(byte)
    private final static int PERFDATA_NAME_OFFSET=16;

    PerfDataBufferPrologue prologue;
    int nextEntry;
    int pollForEntry;
    int perfDataItem;
    long lastModificationTime;
    int lastUsed;
    IntegerMonitor overflow;
    ArrayList<Monitor> insertedMonitors;

    /**
     * Construct a PerfDataBufferImpl instance.
     * <p>
     * This class is dynamically loaded by
     * {@link AbstractPerfDataBuffer#createPerfDataBuffer}, and this
     * constructor is called to instantiate the instance.
     *
     * @param buffer the buffer containing the instrumentation data
     * @param lvmid the Local Java Virtual Machine Identifier for this
     *              instrumentation buffer.
     */
    public PerfDataBuffer(ByteBuffer buffer, int lvmid)
           throws MonitorException {
        super(buffer, lvmid);
        prologue = new PerfDataBufferPrologue(buffer);
        this.buffer.order(prologue.getByteOrder());
    }

    /**
     * {@inheritDoc}
     */
    protected void buildMonitorMap(Map<String, Monitor> map) throws MonitorException {
        assert Thread.holdsLock(this);

        // start at the beginning of the buffer
        buffer.rewind();

        // create pseudo monitors
        buildPseudoMonitors(map);

        // position buffer to start of the data section
        buffer.position(prologue.getSize());
        nextEntry = buffer.position();
        perfDataItem = 0;

        int used = prologue.getUsed();
        long modificationTime = prologue.getModificationTimeStamp();

        Monitor m = getNextMonitorEntry();
        while (m != null) {
            map.put(m.getName(), m);
            m = getNextMonitorEntry();
        }

        /*
         * set the last modification data. These are set to the values
         * recorded before parsing the data structure. This allows the
         * the data structure to be modified while the Map is being built.
         * The Map may contain more entries than indicated based on the
         * time stamp, but this is handled by ignoring duplicate entries
         * when the Map is updated in getNewMonitors().
         */
        lastUsed = used;
        lastModificationTime = modificationTime;

        // synchronize with the target jvm
        synchWithTarget(map);

        // work around 1.4.2 counter inititization bugs
        kludge(map);

        insertedMonitors = new ArrayList<Monitor>(map.values());
    }

    /**
     * {@inheritDoc}
     */
    protected void getNewMonitors(Map<String, Monitor> map) throws MonitorException {
        assert Thread.holdsLock(this);

        int used = prologue.getUsed();
        long modificationTime = prologue.getModificationTimeStamp();

        if ((used > lastUsed) || (lastModificationTime > modificationTime)) {

            lastUsed = used;
            lastModificationTime = modificationTime;

            Monitor monitor = getNextMonitorEntry();
            while (monitor != null) {
                String name = monitor.getName();

                // guard against duplicate entries
                if (!map.containsKey(name)) {
                    map.put(name, monitor);

                    /*
                     * insertedMonitors is null when called from pollFor()
                     * via buildMonitorMap(). Since we update insertedMonitors
                     * at the end of buildMonitorMap(), it's ok to skip the
                     * add here.
                     */
                    if (insertedMonitors != null) {
                        insertedMonitors.add(monitor);
                    }
                }
                monitor = getNextMonitorEntry();
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    protected MonitorStatus getMonitorStatus(Map<String, Monitor> map) throws MonitorException {
        assert Thread.holdsLock(this);
        assert insertedMonitors != null;

        // load any new monitors
        getNewMonitors(map);

        // current implementation doesn't support deletion or reuse of entries
        ArrayList removed = EMPTY_LIST;
        ArrayList inserted = insertedMonitors;

        insertedMonitors = new ArrayList<Monitor>();
        return new MonitorStatus(inserted, removed);
    }

    /**
     * Build the pseudo monitors used to map the prolog data into counters.
     */
    protected void buildPseudoMonitors(Map<String, Monitor> map) {
        Monitor monitor = null;
        String name = null;
        IntBuffer ib = null;

        name = PerfDataBufferPrologue.PERFDATA_MAJOR_NAME;
        ib = prologue.majorVersionBuffer();
        monitor = new PerfIntegerMonitor(name, Units.NONE,
                                         Variability.CONSTANT, false, ib);
        map.put(name, monitor);

        name = PerfDataBufferPrologue.PERFDATA_MINOR_NAME;
        ib = prologue.minorVersionBuffer();
        monitor = new PerfIntegerMonitor(name, Units.NONE,
                                         Variability.CONSTANT, false, ib);
        map.put(name, monitor);

        name = PerfDataBufferPrologue.PERFDATA_BUFFER_SIZE_NAME;
        ib = prologue.sizeBuffer();
        monitor = new PerfIntegerMonitor(name, Units.BYTES,
                                         Variability.MONOTONIC, false, ib);
        map.put(name, monitor);

        name = PerfDataBufferPrologue.PERFDATA_BUFFER_USED_NAME;
        ib = prologue.usedBuffer();
        monitor = new PerfIntegerMonitor(name, Units.BYTES,
                                         Variability.MONOTONIC, false, ib);
        map.put(name, monitor);

        name = PerfDataBufferPrologue.PERFDATA_OVERFLOW_NAME;
        ib = prologue.overflowBuffer();
        monitor = new PerfIntegerMonitor(name, Units.BYTES,
                                         Variability.MONOTONIC, false, ib);
        map.put(name, monitor);
        this.overflow = (IntegerMonitor)monitor;

        name = PerfDataBufferPrologue.PERFDATA_MODTIMESTAMP_NAME;
        LongBuffer lb = prologue.modificationTimeStampBuffer();
        monitor = new PerfLongMonitor(name, Units.TICKS,
                                      Variability.MONOTONIC, false, lb);
        map.put(name, monitor);
    }

    /**
     * Method to provide a gross level of synchronization with the
     * target monitored jvm.
     *
     * gross synchronization works by polling for the hotspot.rt.hrt.ticks
     * counter, which is the last counter created by the StatSampler
     * initialization code. The counter is updated when the watcher thread
     * starts scheduling tasks, which is the last thing done in vm
     * initialization.
     */
    protected void synchWithTarget(Map<String, Monitor> map) throws MonitorException {
        /*
         * synch must happen with syncWaitMs from now. Default is 5 seconds,
         * which is reasonabally generous and should provide for extreme
         * situations like startup delays due to allocation of large ISM heaps.
         */
        long timeLimit = System.currentTimeMillis() + syncWaitMs;

        String name = "hotspot.rt.hrt.ticks";
        LongMonitor ticks = (LongMonitor)pollFor(map, name, timeLimit);

        /*
         * loop waiting for the ticks counter to be non zero. This is
         * an indication that the jvm is initialized.
         */
        log("synchWithTarget: " + lvmid + " ");
        while (ticks.longValue() == 0) {
            log(".");

            try { Thread.sleep(20); } catch (InterruptedException e) { }

            if (System.currentTimeMillis() > timeLimit) {
                lognl("failed: " + lvmid);
                throw new MonitorException("Could Not Synchronize with target");
            }
        }
        lognl("success: " + lvmid);
    }

    /**
     * Method to poll the instrumentation memory for a counter with
     * the given name. The polling period is bounded by the timeLimit
     * argument.
     */
    protected Monitor pollFor(Map<String, Monitor> map, String name, long timeLimit)
                      throws MonitorException {
        Monitor monitor = null;

        log("polling for: " + lvmid + "," + name + " ");

        pollForEntry = nextEntry;
        while ((monitor = map.get(name)) == null) {
            log(".");

            try { Thread.sleep(20); } catch (InterruptedException e) { }

            long t = System.currentTimeMillis();
            if ((t > timeLimit) || (overflow.intValue() > 0)) {
                lognl("failed: " + lvmid + "," + name);
                dumpAll(map, lvmid);
                throw new MonitorException("Could not find expected counter");
            }

            getNewMonitors(map);
        }
        lognl("success: " + lvmid + "," + name);
        return monitor;
    }

    /**
     * method to make adjustments for known counter problems. This
     * method depends on the availability of certain counters, which
     * is generally guaranteed by the synchWithTarget() method.
     */
    protected void kludge(Map<String, Monitor> map) {
        if (Boolean.getBoolean("sun.jvmstat.perfdata.disableKludge")) {
            // bypass all kludges
            return;
        }

        String name = "java.vm.version";
        StringMonitor jvm_version = (StringMonitor)map.get(name);
        if (jvm_version == null) {
            jvm_version = (StringMonitor)findByAlias(name);
        }

        name = "java.vm.name";
        StringMonitor jvm_name = (StringMonitor)map.get(name);
        if (jvm_name == null) {
            jvm_name = (StringMonitor)findByAlias(name);
        }

        name = "hotspot.vm.args";
        StringMonitor args = (StringMonitor)map.get(name);
        if (args == null) {
            args = (StringMonitor)findByAlias(name);
        }

        assert ((jvm_name != null) && (jvm_version != null) && (args != null));

        if (jvm_name.stringValue().indexOf("HotSpot") >= 0) {
            if (jvm_version.stringValue().startsWith("1.4.2")) {
                kludgeMantis(map, args);
            }
        }
    }

    /**
     * method to repair the 1.4.2 parallel scavenge counters that are
     * incorrectly initialized by the JVM when UseAdaptiveSizePolicy
     * is set. This bug couldn't be fixed for 1.4.2 FCS due to putback
     * restrictions.
     */
    private void kludgeMantis(Map<String, Monitor> map, StringMonitor args) {
        /*
         * the HotSpot 1.4.2 JVM with the +UseParallelGC option along
         * with its default +UseAdaptiveSizePolicy option has a bug with
         * the initialization of the sizes of the eden and survivor spaces.
         * See bugid 4890736.
         *
         * note - use explicit 1.4.2 counter names here - don't update
         * to latest counter names or attempt to find aliases.
         */

        String cname = "hotspot.gc.collector.0.name";
        StringMonitor collector = (StringMonitor)map.get(cname);

        if (collector.stringValue().compareTo("PSScavenge") == 0) {
            boolean adaptiveSizePolicy = true;

            /*
             * HotSpot processes the -XX:Flags/.hotspotrc arguments prior to
             * processing the command line arguments. This allows the command
             * line arguments to override any defaults set in .hotspotrc
             */
            cname = "hotspot.vm.flags";
            StringMonitor flags = (StringMonitor)map.get(cname);
            String allArgs = flags.stringValue() + " " + args.stringValue();

            /*
             * ignore the -XX: prefix as it only applies to the arguments
             * passed from the command line (i.e. the invocation api).
             * arguments passed through .hotspotrc omit the -XX: prefix.
             */
            int ahi = allArgs.lastIndexOf("+AggressiveHeap");
            int aspi = allArgs.lastIndexOf("-UseAdaptiveSizePolicy");

            if (ahi != -1) {
                /*
                 * +AggressiveHeap was set, check if -UseAdaptiveSizePolicy
                 * is set after +AggressiveHeap.
                 */
                //
                if ((aspi != -1) && (aspi > ahi)) {
                    adaptiveSizePolicy = false;
                }
            } else {
                /*
                 * +AggressiveHeap not set, must be +UseParallelGC. The
                 * relative position of -UseAdaptiveSizePolicy is not
                 * important in this case, as it will override the
                 * UseParallelGC default (+UseAdaptiveSizePolicy) if it
                 * appears anywhere in the JVM arguments.
                 */
                if (aspi != -1) {
                    adaptiveSizePolicy = false;
                }
            }

            if (adaptiveSizePolicy) {
                // adjust the buggy AdaptiveSizePolicy size counters.

                // first remove the real counters.
                String eden_size = "hotspot.gc.generation.0.space.0.size";
                String s0_size = "hotspot.gc.generation.0.space.1.size";
                String s1_size = "hotspot.gc.generation.0.space.2.size";
                map.remove(eden_size);
                map.remove(s0_size);
                map.remove(s1_size);

                // get the maximum new generation size
                String new_max_name = "hotspot.gc.generation.0.capacity.max";
                LongMonitor new_max = (LongMonitor)map.get(new_max_name);

                /*
                 * replace the real counters with pseudo counters that are
                 * initialized to to the correct values. The maximum size of
                 * the eden and survivor spaces are supposed to be:
                 *    max_eden_size = new_size - (2*alignment).
                 *    max_survivor_size = new_size - (2*alignment).
                 * since we don't know the alignment value used, and because
                 * of other parallel scavenge bugs that result in oversized
                 * spaces, we just set the maximum size of each space to the
                 * full new gen size.
                 */
                Monitor monitor = null;

                LongBuffer lb = LongBuffer.allocate(1);
                lb.put(new_max.longValue());
                monitor = new PerfLongMonitor(eden_size, Units.BYTES,
                                              Variability.CONSTANT, false, lb);
                map.put(eden_size, monitor);

                monitor = new PerfLongMonitor(s0_size, Units.BYTES,
                                              Variability.CONSTANT, false, lb);
                map.put(s0_size, monitor);

                monitor = new PerfLongMonitor(s1_size, Units.BYTES,
                                              Variability.CONSTANT, false, lb);
                map.put(s1_size, monitor);
            }
        }
    }

    /**
     * method to extract the next monitor entry from the instrumentation memory.
     * assumes that nextEntry is the offset into the byte array
     * at which to start the search for the next entry. method leaves
     * next entry pointing to the next entry or to the end of data.
     */
    protected Monitor getNextMonitorEntry() throws MonitorException {
        Monitor monitor = null;

        // entries are always 4 byte aligned.
        if ((nextEntry % 4) != 0) {
            throw new MonitorStructureException(
                   "Entry index not properly aligned: " + nextEntry);
        }

        // protect against a corrupted shared memory region.
        if ((nextEntry < 0) || (nextEntry > buffer.limit())) {
            throw new MonitorStructureException(
                   "Entry index out of bounds: nextEntry = " + nextEntry
                   + ", limit = " + buffer.limit());
        }

        // check for the end of the buffer
        if (nextEntry == buffer.limit()) {
            lognl("getNextMonitorEntry():"
                  + " nextEntry == buffer.limit(): returning");
            return null;
        }

        buffer.position(nextEntry);

        int entryStart = buffer.position();
        int entryLength = buffer.getInt();

        // check for valid entry length
        if ((entryLength < 0) || (entryLength > buffer.limit())) {
            throw new MonitorStructureException(
                   "Invalid entry length: entryLength = " + entryLength);
        }

        // check if last entry occurs before the eof.
        if ((entryStart + entryLength) > buffer.limit()) {
            throw new MonitorStructureException(
                   "Entry extends beyond end of buffer: "
                   + " entryStart = " + entryStart
                   + " entryLength = " + entryLength
                   + " buffer limit = " + buffer.limit());
        }

        if (entryLength == 0) {
            // end of data
            return null;
        }

        int nameLength = buffer.getInt();
        int vectorLength = buffer.getInt();
        byte dataType = buffer.get();
        byte flags = buffer.get();
        Units u = Units.toUnits(buffer.get());
        Variability v = Variability.toVariability(buffer.get());
        boolean supported = (flags & 0x01) != 0;

        // defend against corrupt entries
        if ((nameLength <= 0) || (nameLength > entryLength)) {
            throw new MonitorStructureException(
                   "Invalid Monitor name length: " + nameLength);
        }

        if ((vectorLength < 0) || (vectorLength > entryLength)) {
            throw new MonitorStructureException(
                   "Invalid Monitor vector length: " + vectorLength);
        }

        // read in the perfData item name, casting bytes to chars. skip the
        // null terminator
        //
        byte[] nameBytes = new byte[nameLength-1];
        for (int i = 0; i < nameLength-1; i++) {
            nameBytes[i] = buffer.get();
        }

        // convert name into a String
        String name = new String(nameBytes, 0, nameLength-1);

        if (v == Variability.INVALID) {
            throw new MonitorDataException("Invalid variability attribute:"
                                           + " entry index = " + perfDataItem
                                           + " name = " + name);
        }
        if (u == Units.INVALID) {
            throw new MonitorDataException("Invalid units attribute: "
                                           + " entry index = " + perfDataItem
                                           + " name = " + name);
        }

        int offset;
        if (vectorLength == 0) {
            // scalar Types
            if (dataType == BasicType.LONG.intValue()) {
                offset = entryStart + entryLength - 8;  /* 8 = sizeof(long) */
                buffer.position(offset);
                LongBuffer lb = buffer.asLongBuffer();
                lb.limit(1);
                monitor = new PerfLongMonitor(name, u, v, supported, lb);
                perfDataItem++;
            } else {
                // bad data types.
                throw new MonitorTypeException("Invalid Monitor type:"
                                    + " entry index = " + perfDataItem
                                    + " name = " + name
                                    + " type = " + dataType);
            }
        } else {
            // vector types
            if (dataType == BasicType.BYTE.intValue()) {
                if (u != Units.STRING) {
                    // only byte arrays of type STRING are currently supported
                    throw new MonitorTypeException("Invalid Monitor type:"
                                      + " entry index = " + perfDataItem
                                      + " name = " + name
                                      + " type = " + dataType);
                }

                offset = entryStart + PERFDATA_NAME_OFFSET + nameLength;
                buffer.position(offset);
                ByteBuffer bb = buffer.slice();
                bb.limit(vectorLength);
                bb.position(0);

                if (v == Variability.CONSTANT) {
                    monitor = new PerfStringConstantMonitor(name, supported,
                                                            bb);
                } else if (v == Variability.VARIABLE) {
                    monitor = new PerfStringVariableMonitor(name, supported,
                                                            bb, vectorLength-1);
                } else {
                    // Monotonically increasing byte arrays are not supported
                    throw new MonitorDataException(
                            "Invalid variability attribute:"
                            + " entry index = " + perfDataItem
                            + " name = " + name
                            + " variability = " + v);
                }
                perfDataItem++;
            } else {
                // bad data types.
                throw new MonitorTypeException(
                        "Invalid Monitor type:" + " entry index = "
                        + perfDataItem + " name = " + name
                        + " type = " + dataType);
            }
        }

        // setup index to next entry for next iteration of the loop.
        nextEntry = entryStart + entryLength;
        return monitor;
    }

    /**
     * Method to dump debugging information
     */
    private void dumpAll(Map map, int lvmid) {
        if (DEBUG) {
            Set keys = map.keySet();

            System.err.println("Dump for " + lvmid);
            int j = 0;
            for (Iterator i = keys.iterator(); i.hasNext(); j++) {
                Monitor monitor = (Monitor)map.get(i.next());
                System.err.println(j + "\t" + monitor.getName()
                                   + "=" + monitor.getValue());
            }
            System.err.println("nextEntry = " + nextEntry
                               + " pollForEntry = " + pollForEntry);
            System.err.println("Buffer info:");
            System.err.println("buffer = " + buffer);
        }
    }

    private void lognl(String s) {
        if (DEBUG) {
            System.err.println(s);
        }
    }

    private void log(String s) {
        if (DEBUG) {
            System.err.print(s);
        }
    }
}
