001: /*
002: * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
003: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004: *
005: * This code is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU General Public License version 2 only, as
007: * published by the Free Software Foundation. Sun designates this
008: * particular file as subject to the "Classpath" exception as provided
009: * by Sun in the LICENSE file that accompanied this code.
010: *
011: * This code is distributed in the hope that it will be useful, but WITHOUT
012: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014: * version 2 for more details (a copy is included in the LICENSE file that
015: * accompanied this code).
016: *
017: * You should have received a copy of the GNU General Public License version
018: * 2 along with this work; if not, write to the Free Software Foundation,
019: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020: *
021: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022: * CA 95054 USA or visit www.sun.com if you need additional information or
023: * have any questions.
024: */
025:
026: package sun.jvmstat.perfdata.monitor;
027:
028: import sun.jvmstat.monitor.*;
029: import java.nio.ByteOrder;
030: import java.nio.ByteBuffer;
031: import java.nio.IntBuffer;
032:
033: /**
034: * Abstraction representing the HotSpot PerfData instrumentation buffer
035: * header. This class represents only the fixed portion of the header.
036: * Version specific classes represent the portion of the header that
037: * may change from release to release.
038: * <p>
039: * The PerfDataBufferProlog class supports parsing of the following
040: * C structure:
041: * <pre>
042: * typedef struct {
043: * jint magic; // magic number - 0xcafec0c0
044: * jbyte byte_order; // byte order of the buffer
045: * jbyte major_version; // major and minor version numbers
046: * jbyte minor_version;
047: * jbyte reserved_byte1; // reserved - see concrete implementations for
048: * // possible definition.
049: * ... // remainder is handled by the subclasses.
050: * } PerfDataPrologue
051: * </pre>
052: *
053: * @author Brian Doherty
054: * @version 1.8, 05/05/07
055: * @since 1.5
056: */
057: public abstract class AbstractPerfDataBufferPrologue {
058:
059: protected ByteBuffer byteBuffer;
060:
061: /*
062: * the following constants must match the field offsets and sizes
063: * in the PerfDataPrologue structure in perfMemory.hpp
064: */
065: final static int PERFDATA_PROLOG_OFFSET = 0;
066: final static int PERFDATA_PROLOG_MAGIC_OFFSET = 0;
067: final static int PERFDATA_PROLOG_BYTEORDER_OFFSET = 4;
068: final static int PERFDATA_PROLOG_BYTEORDER_SIZE = 1; // sizeof(byte)
069: final static int PERFDATA_PROLOG_MAJOR_OFFSET = 5;
070: final static int PERFDATA_PROLOG_MAJOR_SIZE = 1; // sizeof(byte)
071: final static int PERFDATA_PROLOG_MINOR_OFFSET = 6;
072: final static int PERFDATA_PROLOG_MINOR_SIZE = 1; // sizeof(byte)
073: final static int PERFDATA_PROLOG_RESERVEDB1_OFFSET = 7;
074: final static int PERFDATA_PROLOG_RESERVEDB1_SIZE = 1; // sizeof(byte)
075:
076: final static int PERFDATA_PROLOG_SIZE = 8; // sizeof(struct PerfDataProlog)
077:
078: // these constants should match their #define counterparts in perfMemory.hpp
079: final static byte PERFDATA_BIG_ENDIAN = 0;
080: final static byte PERFDATA_LITTLE_ENDIAN = 1;
081: final static int PERFDATA_MAGIC = 0xcafec0c0;
082:
083: // names for counters that expose the prolog fields
084: public final static String PERFDATA_MAJOR_NAME = "sun.perfdata.majorVersion";
085: public final static String PERFDATA_MINOR_NAME = "sun.perfdata.minorVersion";
086:
087: /**
088: * Construct a PerfDataBufferPrologue instance.
089: *
090: * @param byteBuffer buffer containing the instrumentation data
091: */
092: public AbstractPerfDataBufferPrologue(ByteBuffer byteBuffer)
093: throws MonitorException {
094: this .byteBuffer = byteBuffer.duplicate();
095:
096: // the magic number is always stored in big-endian format
097: if (getMagic() != PERFDATA_MAGIC) {
098: throw new MonitorVersionException("Bad Magic: "
099: + Integer.toHexString(getMagic()));
100: }
101:
102: // set the byte order
103: this .byteBuffer.order(getByteOrder());
104: }
105:
106: /**
107: * Get the magic number.
108: *
109: * @return int - the magic number
110: */
111: public int getMagic() {
112: // the magic number is always stored in big-endian format
113: ByteOrder order = byteBuffer.order();
114: byteBuffer.order(ByteOrder.BIG_ENDIAN);
115:
116: // get the magic number
117: byteBuffer.position(PERFDATA_PROLOG_MAGIC_OFFSET);
118: int magic = byteBuffer.getInt();
119:
120: // restore the byte order
121: byteBuffer.order(order);
122: return magic;
123: }
124:
125: /**
126: * Get the byte order.
127: *
128: * @return int - the byte order of the instrumentation buffer
129: */
130: public ByteOrder getByteOrder() {
131: // byte order field is byte order independent
132: byteBuffer.position(PERFDATA_PROLOG_BYTEORDER_OFFSET);
133:
134: byte byte_order = byteBuffer.get();
135:
136: if (byte_order == PERFDATA_BIG_ENDIAN) {
137: return ByteOrder.BIG_ENDIAN;
138: } else {
139: return ByteOrder.LITTLE_ENDIAN;
140: }
141: }
142:
143: /**
144: * Get the major version.
145: *
146: * @return int - the major version
147: */
148: public int getMajorVersion() {
149: // major version field is byte order independent
150: byteBuffer.position(PERFDATA_PROLOG_MAJOR_OFFSET);
151: return (int) byteBuffer.get();
152: }
153:
154: /**
155: * Get the minor version.
156: *
157: * @return int - the minor version
158: */
159: public int getMinorVersion() {
160: // minor version field is byte order independent
161: byteBuffer.position(PERFDATA_PROLOG_MINOR_OFFSET);
162: return (int) byteBuffer.get();
163: }
164:
165: /**
166: * Get the accessible flag. If supported, it indicates that the shared
167: * memory region is sufficiently initialized for client acccess.
168: *
169: * @return boolean - the initialized status
170: * @see #supportsAccessible()
171: */
172: public abstract boolean isAccessible();
173:
174: /**
175: * Test if the accessible flag is supported by this version of
176: * the PerfDataBufferPrologue. Although not an abstract method, this
177: * method should be overridden by version specific subclasses.
178: *
179: * @return boolean - the initialized flag support status.
180: * @see #isAccessible()
181: */
182: public abstract boolean supportsAccessible();
183:
184: /**
185: * Get the size of the header portion of the instrumentation buffer.
186: *
187: * @return int - the size of the header
188: */
189: public int getSize() {
190: return PERFDATA_PROLOG_SIZE; // sizeof(struct PerfDataProlog)
191: }
192:
193: /**
194: * Return an IntBuffer that accesses the major version number.
195: * This is used to create a Monitor object for this value.
196: *
197: * @return IntBuffer - a ByteBuffer that accesses the major version number
198: * in the instrumentation buffer header.
199: */
200: public IntBuffer majorVersionBuffer() {
201: int[] holder = new int[1];
202: holder[0] = getMajorVersion();
203: IntBuffer ib = IntBuffer.wrap(holder);
204: ib.limit(1);
205: return ib;
206: }
207:
208: /**
209: * Return an IntBuffer that accesses the minor version number.
210: * This is used to create a Monitor object for this value.
211: *
212: * @return IntBuffer - a ByteBuffer that accesses the minor version number
213: * in the instrumentation buffer header.
214: */
215: public IntBuffer minorVersionBuffer() {
216: int[] holder = new int[1];
217: holder[0] = getMinorVersion();
218: IntBuffer ib = IntBuffer.wrap(holder);
219: ib.limit(1);
220: return ib;
221: }
222:
223: /**
224: * Get the magic number from the given byteBuffer.
225: *
226: * @return int - the magic number
227: */
228: public static int getMagic(ByteBuffer bb) {
229: // save buffer state
230: int position = bb.position();
231: ByteOrder order = bb.order();
232:
233: // the magic number is always stored in big-endian format
234: bb.order(ByteOrder.BIG_ENDIAN);
235: bb.position(PERFDATA_PROLOG_MAGIC_OFFSET);
236: int magic = bb.getInt();
237:
238: // restore buffer state.
239: bb.order(order);
240: bb.position(position);
241:
242: return magic;
243: }
244:
245: /**
246: * Get the major version number from the given ByteBuffer.
247: *
248: * @return int - the major version
249: */
250: public static int getMajorVersion(ByteBuffer bb) {
251: // save buffer state
252: int position = bb.position();
253:
254: bb.position(PERFDATA_PROLOG_MAJOR_OFFSET);
255: int major = (int) bb.get();
256:
257: // restore buffer state.
258: bb.position(position);
259:
260: return major;
261: }
262:
263: /**
264: * Get the minor version number from the given ByteBuffer.
265: *
266: * @return int - the minor version
267: */
268: public static int getMinorVersion(ByteBuffer bb) {
269: // save buffer state
270: int position = bb.position();
271:
272: bb.position(PERFDATA_PROLOG_MINOR_OFFSET);
273: int minor = (int) bb.get();
274:
275: // restore buffer state.
276: bb.position(position);
277:
278: return minor;
279: }
280:
281: /**
282: * Get the byte order for the given ByteBuffer.
283: *
284: * @return int - the byte order of the instrumentation buffer
285: */
286: public static ByteOrder getByteOrder(ByteBuffer bb) {
287: // save buffer state
288: int position = bb.position();
289:
290: bb.position(PERFDATA_PROLOG_BYTEORDER_OFFSET);
291: ByteOrder order = (bb.get() == PERFDATA_BIG_ENDIAN) ? ByteOrder.BIG_ENDIAN
292: : ByteOrder.LITTLE_ENDIAN;
293:
294: // restore buffer state.
295: bb.position(position);
296: return order;
297: }
298: }
|