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

import sun.jvmstat.monitor.*;
import java.nio.ByteOrder;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

/**
 * Abstraction representing the HotSpot PerfData instrumentation buffer
 * header. This class represents only the fixed portion of the header.
 * Version specific classes represent the portion of the header that
 * may change from release to release.
 * <p>
 * The PerfDataBufferProlog class supports parsing of the following
 * C structure:
 * <pre>
 * typedef struct {
 *   jint magic;             // magic number - 0xcafec0c0
 *   jbyte byte_order;       // byte order of the buffer
 *   jbyte major_version;    // major and minor version numbers
 *   jbyte minor_version;
 *   jbyte reserved_byte1;   // reserved - see concrete implementations for
 *                           // possible definition.
 *   ...                     // remainder is handled by the subclasses.
 * } PerfDataPrologue
 * </pre>
 *
 * @author Brian Doherty
 * @since 1.5
 */
public abstract class AbstractPerfDataBufferPrologue {

    protected ByteBuffer byteBuffer;

    /*
     * the following constants must match the field offsets and sizes
     * in the PerfDataPrologue structure in perfMemory.hpp
     */
    final static int PERFDATA_PROLOG_OFFSET=0;
    final static int PERFDATA_PROLOG_MAGIC_OFFSET=0;
    final static int PERFDATA_PROLOG_BYTEORDER_OFFSET=4;
    final static int PERFDATA_PROLOG_BYTEORDER_SIZE=1;         // sizeof(byte)
    final static int PERFDATA_PROLOG_MAJOR_OFFSET=5;
    final static int PERFDATA_PROLOG_MAJOR_SIZE=1;             // sizeof(byte)
    final static int PERFDATA_PROLOG_MINOR_OFFSET=6;
    final static int PERFDATA_PROLOG_MINOR_SIZE=1;             // sizeof(byte)
    final static int PERFDATA_PROLOG_RESERVEDB1_OFFSET=7;
    final static int PERFDATA_PROLOG_RESERVEDB1_SIZE=1;        // sizeof(byte)

    final static int PERFDATA_PROLOG_SIZE=8;   // sizeof(struct PerfDataProlog)

    // these constants should match their #define counterparts in perfMemory.hpp
    final static byte PERFDATA_BIG_ENDIAN=0;
    final static byte PERFDATA_LITTLE_ENDIAN=1;
    final static int  PERFDATA_MAGIC = 0xcafec0c0;

    // names for counters that expose the prolog fields
    public final static String PERFDATA_MAJOR_NAME =
            "sun.perfdata.majorVersion";
    public final static String PERFDATA_MINOR_NAME =
            "sun.perfdata.minorVersion";

    /**
     * Construct a PerfDataBufferPrologue instance.
     *
     * @param byteBuffer buffer containing the instrumentation data
     */
    public AbstractPerfDataBufferPrologue(ByteBuffer byteBuffer)
           throws MonitorException  {
        this.byteBuffer = byteBuffer.duplicate();

        // the magic number is always stored in big-endian format
        if (getMagic() != PERFDATA_MAGIC) {
            throw new MonitorVersionException(
                    "Bad Magic: " + Integer.toHexString(getMagic()));
        }

        // set the byte order
        this.byteBuffer.order(getByteOrder());
    }

    /**
     * Get the magic number.
     *
     * @return int - the magic number
     */
    public int getMagic() {
        // the magic number is always stored in big-endian format
        ByteOrder order = byteBuffer.order();
        byteBuffer.order(ByteOrder.BIG_ENDIAN);

        // get the magic number
        byteBuffer.position(PERFDATA_PROLOG_MAGIC_OFFSET);
        int magic = byteBuffer.getInt();

        // restore the byte order
        byteBuffer.order(order);
        return magic;
    }

    /**
     * Get the byte order.
     *
     * @return int - the byte order of the instrumentation buffer
     */
    public ByteOrder getByteOrder() {
        // byte order field is byte order independent
        byteBuffer.position(PERFDATA_PROLOG_BYTEORDER_OFFSET);

        byte byte_order = byteBuffer.get();

        if (byte_order == PERFDATA_BIG_ENDIAN) {
            return ByteOrder.BIG_ENDIAN;
        } else {
            return ByteOrder.LITTLE_ENDIAN;
        }
    }

    /**
     * Get the major version.
     *
     * @return int - the major version
     */
    public int getMajorVersion() {
        // major version field is byte order independent
        byteBuffer.position(PERFDATA_PROLOG_MAJOR_OFFSET);
        return (int)byteBuffer.get();
    }

    /**
     * Get the minor version.
     *
     * @return int - the minor version
     */
    public int getMinorVersion() {
        // minor version field is byte order independent
        byteBuffer.position(PERFDATA_PROLOG_MINOR_OFFSET);
        return (int)byteBuffer.get();
    }

    /**
     * Get the accessible flag. If supported, it indicates that the shared
     * memory region is sufficiently initialized for client acccess.
     *
     * @return boolean - the initialized status
     * @see #supportsAccessible()
     */
    public abstract boolean isAccessible();

    /**
     * Test if the accessible flag is supported by this version of
     * the PerfDataBufferPrologue. Although not an abstract method, this
     * method should be overridden by version specific subclasses.
     *
     * @return boolean - the initialized flag support status.
     * @see #isAccessible()
     */
    public abstract boolean supportsAccessible();

    /**
     * Get the size of the header portion of the instrumentation buffer.
     *
     * @return int - the size of the header
     */
    public int getSize() {
        return PERFDATA_PROLOG_SIZE;  // sizeof(struct PerfDataProlog)
    }

    /**
     * Return an IntBuffer that accesses the major version number.
     * This is used to create a Monitor object for this value.
     *
     * @return IntBuffer - a ByteBuffer that accesses the major version number
     *                     in the instrumentation buffer header.
     */
    public IntBuffer majorVersionBuffer() {
        int[] holder = new int[1];
        holder[0] = getMajorVersion();
        IntBuffer ib = IntBuffer.wrap(holder);
        ib.limit(1);
        return ib;
      }

    /**
     * Return an IntBuffer that accesses the minor version number.
     * This is used to create a Monitor object for this value.
     *
     * @return IntBuffer - a ByteBuffer that accesses the minor version number
     *                     in the instrumentation buffer header.
     */
    public IntBuffer minorVersionBuffer() {
        int[] holder = new int[1];
        holder[0] = getMinorVersion();
        IntBuffer ib = IntBuffer.wrap(holder);
        ib.limit(1);
        return ib;
    }

    /**
     * Get the magic number from the given byteBuffer.
     *
     * @return int - the magic number
     */
    public static int getMagic(ByteBuffer bb) {
        // save buffer state
        int position = bb.position();
        ByteOrder order = bb.order();

        // the magic number is always stored in big-endian format
        bb.order(ByteOrder.BIG_ENDIAN);
        bb.position(PERFDATA_PROLOG_MAGIC_OFFSET);
        int magic = bb.getInt();

        // restore buffer state.
        bb.order(order);
        bb.position(position);

        return magic;
    }

    /**
     * Get the major version number from the given ByteBuffer.
     *
     * @return int - the major version
     */
    public static int getMajorVersion(ByteBuffer bb) {
        // save buffer state
        int position = bb.position();

        bb.position(PERFDATA_PROLOG_MAJOR_OFFSET);
        int major = (int) bb.get();

        // restore buffer state.
        bb.position(position);

        return major;
    }

    /**
     * Get the minor version number from the given ByteBuffer.
     *
     * @return int - the minor version
     */
    public static int getMinorVersion(ByteBuffer bb) {
        // save buffer state
        int position = bb.position();

        bb.position(PERFDATA_PROLOG_MINOR_OFFSET);
        int minor = (int)bb.get();

        // restore buffer state.
        bb.position(position);

        return minor;
    }

    /**
     * Get the byte order for the given ByteBuffer.
     *
     * @return int - the byte order of the instrumentation buffer
     */
    public static ByteOrder getByteOrder(ByteBuffer bb) {
        // save buffer state
        int position = bb.position();

        bb.position(PERFDATA_PROLOG_BYTEORDER_OFFSET);
        ByteOrder order = (bb.get() == PERFDATA_BIG_ENDIAN)
                          ? ByteOrder.BIG_ENDIAN
                          : ByteOrder.LITTLE_ENDIAN;

        // restore buffer state.
        bb.position(position);
        return order;
    }
}
