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

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

/**
 * The concrete implementation of version 2.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.
 * <p>
 * The structure of the 2.0 entry is defined in struct PerfDataEnry
 * as decsribed in perfMemory.hpp. This structure looks like:
 * <pre>
 * typedef struct {
 *   jint entry_length;         // entry length in bytes
 *   jint name_offset;          // offset to entry name, relative to start
 *                              // of entry
 *   jint vector_length;        // length of the vector. If 0, then scalar.
 *   jbyte data_type;           // JNI field descriptor type
 *   jbyte flags;               // miscellaneous attribute flags
 *                              // 0x01 - supported
 *   jbyte data_units;          // unit of measure attribute
 *   jbyte data_variability;    // variability attribute
 *   jbyte data_offset;         // offset to data item, relative to start
 *                              // of entry.
 * } PerfDataEntry;
 * </pre>
 *
 * @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);

    /*
     * These are primarily for documentary purposes and the match up
     * with the PerfDataEntry structure in perfMemory.hpp. They are
     * generally unused in this code, but they are kept consistent with
     * the data structure just in case some unforseen need arrises.
     */
    private final static int PERFDATA_ENTRYLENGTH_OFFSET=0;
    private final static int PERFDATA_ENTRYLENGTH_SIZE=4;   // sizeof(int)
    private final static int PERFDATA_NAMEOFFSET_OFFSET=4;
    private final static int PERFDATA_NAMEOFFSET_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_DATAVAR_OFFSET=15;
    private final static int PERFDATA_DATAVAR_SIZE=1;       // sizeof(byte)
    private final static int PERFDATA_DATAOFFSET_OFFSET=16;
    private final static int PERFDATA_DATAOFFSET_SIZE=4;    // sizeof(int)

    PerfDataBufferPrologue prologue;
    int nextEntry;
    long lastNumEntries;
    IntegerMonitor overflow;
    ArrayList<Monitor> insertedMonitors;

    /**
     * Construct a PerfDataBuffer 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);

        // wait for the target JVM to indicate that it's intrumentation
        // buffer is safely accessible
        synchWithTarget();

        // parse the currently defined entries starting at the first entry.
        nextEntry = prologue.getEntryOffset();

        // record the number of entries before parsing the structure
        int numEntries = prologue.getNumEntries();

        // start parsing
        Monitor monitor = getNextMonitorEntry();
        while (monitor != null) {
            map.put(monitor.getName(), monitor);
            monitor = getNextMonitorEntry();
        }

        /*
         * keep track of the current number of entries in the shared
         * memory for new entry detection purposes. It's possible for
         * the data structure to be modified while the Map is being
         * built and the entry count in the header might change while
         * we are parsing it. The map will contain all the counters
         * found, but the number recorded in numEntries might be small
         * than what than the number we actually parsed (due to asynchronous
         * updates). This discrepency is handled by ignoring any re-parsed
         * entries when updating the Map in getNewMonitors().
         */
        lastNumEntries = numEntries;

        // keep track of the monitors just added.
        insertedMonitors = new ArrayList<Monitor>(map.values());
    }

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

        int numEntries = prologue.getNumEntries();

        if (numEntries > lastNumEntries) {
            lastNumEntries = numEntries;
            Monitor monitor = getNextMonitorEntry();

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

                // guard against re-parsed entries
                if (!map.containsKey(name)) {
                    map.put(name, monitor);
                    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 of 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 that waits until the target jvm indicates that
     * its shared memory is safe to access.
     */
    protected void synchWithTarget() 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;

        // loop waiting for the accessible indicater to be non-zero
        log("synchWithTarget: " + lvmid + " ");
        while (!prologue.isAccessible()) {

            log(".");

            // give the target jvm a chance to complete initializatoin
            try { Thread.sleep(20); } catch (InterruptedException e) { }

            if (System.currentTimeMillis() > timeLimit) {
                logln("failed: " + lvmid);
                throw new MonitorException("Could not synchronize with target");
            }
        }
        logln("success: " + lvmid);
    }

    /**
     * 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(
                    "Misaligned entry index: "
                    + Integer.toHexString(nextEntry));
        }

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

        // check for end of the buffer
        if (nextEntry == buffer.limit()) {
            logln("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
                    + " (0x" + Integer.toHexString(entryLength) + ")");
        }

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

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

        // we can safely read this entry
        int nameOffset = buffer.getInt();
        int vectorLength = buffer.getInt();
        byte typeCodeByte = buffer.get();
        byte flags = buffer.get();
        byte unitsByte = buffer.get();
        byte varByte = buffer.get();
        int dataOffset = buffer.getInt();

        dump_entry_fixed(entryStart, nameOffset, vectorLength, typeCodeByte,
                         flags, unitsByte, varByte, dataOffset);

        // convert common attributes to their object types
        Units units = Units.toUnits(unitsByte);
        Variability variability = Variability.toVariability(varByte);
        TypeCode typeCode = null;
        boolean supported = (flags & 0x01) != 0;

        try {
            typeCode = TypeCode.toTypeCode(typeCodeByte);

        } catch (IllegalArgumentException e) {
            throw new MonitorStructureException(
                    "Illegal type code encountered:"
                    + " entry_offset = 0x" + Integer.toHexString(nextEntry)
                    + ", type_code = " + Integer.toHexString(typeCodeByte));
        }

        // verify that the name_offset is contained within the entry bounds
        if (nameOffset > entryLength) {
            throw new MonitorStructureException(
                    "Field extends beyond entry bounds"
                    + " entry_offset = 0x" + Integer.toHexString(nextEntry)
                    + ", name_offset = 0x" + Integer.toHexString(nameOffset));
        }

        // verify that the data_offset is contained within the entry bounds
        if (dataOffset > entryLength) {
            throw new MonitorStructureException(
                    "Field extends beyond entry bounds:"
                    + " entry_offset = 0x" + Integer.toHexString(nextEntry)
                    + ", data_offset = 0x" + Integer.toHexString(dataOffset));
        }

        // validate the variability and units fields
        if (variability == Variability.INVALID) {
            throw new MonitorDataException(
                    "Invalid variability attribute:"
                    + " entry_offset = 0x" + Integer.toHexString(nextEntry)
                    + ", variability = 0x" + Integer.toHexString(varByte));
        }

        if (units == Units.INVALID) {
            throw new MonitorDataException(
                    "Invalid units attribute: entry_offset = 0x"
                    + Integer.toHexString(nextEntry)
                    + ", units = 0x" + Integer.toHexString(unitsByte));
        }

        // the entry looks good - parse the variable length components

        /*
         * The name starts at nameOffset and continues up to the first null
         * byte. however, we don't know the length, but we can approximate it
         * without searching for the null by using the offset for the data
         * field, which follows the name field.
         */
        assert (buffer.position() == (entryStart + nameOffset));
        assert (dataOffset > nameOffset);

        // include possible pad space
        int maxNameLength = dataOffset-nameOffset;

        // maxNameLength better be less than the total entry length
        assert (maxNameLength < entryLength);

        // collect the characters, but do not collect the null byte,
        // as the String(byte[]) constructor does not ignore it!
        byte[] nameBytes = new byte[maxNameLength];
        int nameLength = 0;
        byte b;
        while (((b = buffer.get()) != 0) && (nameLength < maxNameLength)) {
             nameBytes[nameLength++] = b;
        }

        assert (nameLength < maxNameLength);

        // we should before or at the start of the data field
        assert (buffer.position() <= (entryStart + dataOffset));

        // convert the name bytes into a String
        String name = new String(nameBytes, 0, nameLength);

        /*
         * compute the size of the data item - this includes pad
         * characters used to align the next entry.
         */
        int dataSize = entryLength - dataOffset;

        // set the position to the start of the data item
        buffer.position(entryStart + dataOffset);

        dump_entry_variable(name, buffer, dataSize);

        if (vectorLength == 0) {
            // create a scalar Monitor object
            if (typeCode == TypeCode.LONG) {
                LongBuffer lb = buffer.asLongBuffer();
                lb.limit(1);  // limit buffer size to one long value.
                monitor = new PerfLongMonitor(name, units, variability,
                                              supported, lb);
            } else {
                /*
                 * unexpected type code - coding error or uncoordinated
                 * JVM change
                 */
                throw new MonitorTypeException(
                        "Unexpected type code encountered:"
                        + " entry_offset = 0x" + Integer.toHexString(nextEntry)
                        + ", name = " + name
                        + ", type_code = " + typeCode
                        + " (0x" + Integer.toHexString(typeCodeByte) + ")");
            }
        } else {
            // create a vector Monitor object
            if (typeCode == TypeCode.BYTE) {
                if (units != Units.STRING) {
                    // only byte arrays of type STRING are currently supported
                    throw new MonitorTypeException(
                            "Unexpected vector type encounterd:"
                            + " entry_offset = "
                            + Integer.toHexString(nextEntry)
                            + ", name = " + name
                            + ", type_code = " + typeCode + " (0x"
                            + Integer.toHexString(typeCodeByte) + ")"
                            + ", units = " + units + " (0x"
                            + Integer.toHexString(unitsByte) + ")");
                }

                ByteBuffer bb = buffer.slice();
                bb.limit(vectorLength); // limit buffer length to # of chars

                if (variability == Variability.CONSTANT) {
                    monitor = new PerfStringConstantMonitor(name, supported,
                                                            bb);
                } else if (variability == Variability.VARIABLE) {
                    monitor = new PerfStringVariableMonitor(name, supported,
                                                            bb, vectorLength-1);
                } else if (variability == Variability.MONOTONIC) {
                    // Monotonically increasing byte arrays are not supported
                    throw new MonitorDataException(
                            "Unexpected variability attribute:"
                            + " entry_offset = 0x"
                            + Integer.toHexString(nextEntry)
                            + " name = " + name
                            + ", variability = " + variability + " (0x"
                            + Integer.toHexString(varByte) + ")");
                } else {
                    // variability was validated above, so this unexpected
                    assert false;
                }
            } else {
                // coding error or uncoordinated JVM change
                throw new MonitorTypeException(
                        "Unexpected type code encountered:"
                        + " entry_offset = 0x"
                        + Integer.toHexString(nextEntry)
                        + ", name = " + name
                        + ", type_code = " + typeCode + " (0x"
                        + Integer.toHexString(typeCodeByte) + ")");
            }
        }

        // 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<String, Monitor> map, int lvmid) {
        if (DEBUG) {
            Set<String> keys = map.keySet();

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

    /**
     * Method to dump the fixed portion of an entry.
     */
    private void dump_entry_fixed(int entry_start, int nameOffset,
                                  int vectorLength, byte typeCodeByte,
                                  byte flags, byte unitsByte, byte varByte,
                                  int dataOffset) {
        if (DEBUG) {
            System.err.println("Entry at offset: 0x"
                               + Integer.toHexString(entry_start));
            System.err.println("\tname_offset = 0x"
                               + Integer.toHexString(nameOffset));
            System.err.println("\tvector_length = 0x"
                               + Integer.toHexString(vectorLength));
            System.err.println("\tdata_type = 0x"
                               + Integer.toHexString(typeCodeByte));
            System.err.println("\tflags = 0x"
                               + Integer.toHexString(flags));
            System.err.println("\tdata_units = 0x"
                               + Integer.toHexString(unitsByte));
            System.err.println("\tdata_variability = 0x"
                               + Integer.toHexString(varByte));
            System.err.println("\tdata_offset = 0x"
                               + Integer.toHexString(dataOffset));
        }
    }

    private void dump_entry_variable(String name, ByteBuffer bb, int size) {
        if (DEBUG) {
            char[] toHex = new char[] { '0', '1', '2', '3',
                                        '4', '5', '6', '7',
                                        '8', '9', 'a', 'b',
                                        'c', 'd', 'e', 'f' };

            ByteBuffer data = bb.slice();
            data.limit(size);

            System.err.println("\tname = " + name);
            System.err.println("\tdata = ");

            int count=0;
            while (data.hasRemaining()) {
                byte b = data.get();
                byte high = (byte)((b >> 8) & 0x0f);
                byte low = (byte)(b & 0x0f);

                if (count % 16 == 0) {
                    System.err.print("\t\t" + Integer.toHexString(count / 16)
                                     + ": ");
                }

                System.err.print(String.valueOf(toHex[high])
                                 + String.valueOf(toHex[low]));

                count++;
                if (count % 16 == 0) {
                    System.err.println();
                } else {
                    System.err.print(" ");
                }
            }
            if (count % 16 != 0) {
                System.err.println();
            }
        }
    }

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

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