1 /*
2  * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.jvmstat.perfdata.monitor.v2_0;
27 
28 import sun.jvmstat.monitor.*;
29 import sun.jvmstat.perfdata.monitor.*;
30 import java.nio.*;
31 
32 /**
33  * Class representing the 2.0 version of the HotSpot PerfData instrumentation
34  * buffer header.
35  * <p>
36  * The PerfDataBufferPrologue class supports parsing of the version
37  * specific portions of the PerfDataPrologue C structure:
38  * <pre>
39  * typedef struct {
40  *   ...                      // handled by superclass
41  *   jint used;               // number of PerfData memory bytes used
42  *   jint overflow;           // number of bytes of overflow
43  *   jlong mod_time_stamp;    // time stamp of the last structural modification
44  *   jint entry_offset;       // offset of the first PerfDataEntry
45  *   jint num_entries;        // number of allocated PerfData entries
46  * } PerfDataPrologue
47  * </pre>
48  *
49  * @author Brian Doherty
50  * @since 1.5
51  */
52 public class PerfDataBufferPrologue extends AbstractPerfDataBufferPrologue {
53 
54     private final static int SUPPORTED_MAJOR_VERSION = 2;
55     private final static int SUPPORTED_MINOR_VERSION = 0;
56 
57     /*
58      * the following constants must match the field offsets and sizes
59      * in the PerfDataPrologue structure in perfMemory.hpp. offsets are
60      * relative to the start of the PerfDataPrologue structure.
61      *
62      * note that PERFDATA_PROLOG_ACCESSIBLE_OFFSET redefines
63      * PERFDATA_PROLOG_RESERVEDB1_OFFSET from AbstractPerfDataBufferPrologue.
64      */
65     final static int PERFDATA_PROLOG_ACCESSIBLE_OFFSET=7;
66     final static int PERFDATA_PROLOG_ACCESSIBLE_SIZE=1;        // sizeof(byte)
67     final static int PERFDATA_PROLOG_USED_OFFSET=8;
68     final static int PERFDATA_PROLOG_USED_SIZE=4;              // sizeof(int)
69     final static int PERFDATA_PROLOG_OVERFLOW_OFFSET=12;
70     final static int PERFDATA_PROLOG_OVERFLOW_SIZE=4;          // sizeof(int)
71     final static int PERFDATA_PROLOG_MODTIMESTAMP_OFFSET=16;
72     final static int PERFDATA_PROLOG_MODTIMESTAMP_SIZE=8;      // sizeof(long)
73     final static int PERFDATA_PROLOG_ENTRYOFFSET_OFFSET=24;
74     final static int PERFDATA_PROLOG_ENTRYOFFSET_SIZE=4;       // sizeof(int)
75     final static int PERFDATA_PROLOG_NUMENTRIES_OFFSET=28;
76     final static int PERFDATA_PROLOG_NUMENTRIES_SIZE=4;        // sizeof(int)
77 
78     final static int PERFDATA_PROLOG_SIZE=32;  // sizeof(struct PerfDataProlog)
79 
80     // names for counters that expose prologue fields
81     final static String PERFDATA_BUFFER_SIZE_NAME  = "sun.perfdata.size";
82     final static String PERFDATA_BUFFER_USED_NAME  = "sun.perfdata.used";
83     final static String PERFDATA_OVERFLOW_NAME     = "sun.perfdata.overflow";
84     final static String PERFDATA_MODTIMESTAMP_NAME = "sun.perfdata.timestamp";
85     final static String PERFDATA_NUMENTRIES_NAME   = "sun.perfdata.entries";
86 
87     /**
88      * Create an instance of PerfDataBufferPrologue from the given
89      * ByteBuffer object.
90      *
91      * @param byteBuffer the buffer containing the binary header data
92      */
PerfDataBufferPrologue(ByteBuffer byteBuffer)93     public PerfDataBufferPrologue(ByteBuffer byteBuffer)
94            throws MonitorException  {
95         super(byteBuffer);
96         assert ((getMajorVersion() == 2) && (getMinorVersion() == 0));
97     }
98 
99     /**
100      * {@inheritDoc}
101      */
supportsAccessible()102     public boolean supportsAccessible() {
103         return true;
104     }
105 
106     /**
107      * {@inheritDoc}
108      */
isAccessible()109     public boolean isAccessible() {
110         assert supportsAccessible();
111         byteBuffer.position(PERFDATA_PROLOG_ACCESSIBLE_OFFSET);
112         byte value = byteBuffer.get();
113         return value != 0;
114     }
115 
116     /**
117      * Get the utilization of the instrumentation memory buffer.
118      *
119      * @return int - the utilization of the buffer
120      */
getUsed()121     public int getUsed() {
122         byteBuffer.position(PERFDATA_PROLOG_USED_OFFSET);
123         return byteBuffer.getInt();
124     }
125 
126     /**
127      * Get the size of the instrumentation memory buffer.
128      *
129      * @return int - the size of the buffer
130      */
getBufferSize()131     public int getBufferSize() {
132         return byteBuffer.capacity();
133     }
134 
135     /**
136      * Get the buffer overflow amount. This value is non-zero if the
137      * HotSpot JVM has overflowed the instrumentation memory buffer.
138      * The target JVM can be restarted with -XX:PerfDataMemSize=X to
139      * create a larger memory buffer.
140      *
141      * @return int - the size of the buffer
142      */
getOverflow()143     public int getOverflow() {
144         byteBuffer.position(PERFDATA_PROLOG_OVERFLOW_OFFSET);
145         return byteBuffer.getInt();
146     }
147 
148     /**
149      * Get the time of last modification for the instrumentation
150      * memory buffer. This method returns the time, as ticks since the
151      * start of the target JVM, of the last structural modification to
152      * the instrumentation buffer. Structural modifications correspond to
153      * the addition or deletion of instrumentation objects. Updates to
154      * counter values are not structural modifications.
155      */
getModificationTimeStamp()156     public long getModificationTimeStamp() {
157         byteBuffer.position(PERFDATA_PROLOG_MODTIMESTAMP_OFFSET);
158         return byteBuffer.getLong();
159     }
160 
161     /**
162      * Get the offset of the first PerfDataEntry.
163      */
getEntryOffset()164     public int getEntryOffset() {
165         byteBuffer.position(PERFDATA_PROLOG_ENTRYOFFSET_OFFSET);
166         return byteBuffer.getInt();
167     }
168 
169     /**
170      * Get the offset of the first PerfDataEntry.
171      */
getNumEntries()172     public int getNumEntries() {
173         byteBuffer.position(PERFDATA_PROLOG_NUMENTRIES_OFFSET);
174         return byteBuffer.getInt();
175     }
176 
177     /**
178      * {@inheritDoc}
179      */
getSize()180     public int getSize() {
181         return PERFDATA_PROLOG_SIZE;  // sizeof(struct PerfDataProlog)
182     }
183 
184     /**
185      * Return an IntBuffer that accesses the used value. This is used
186      * to create a Monitor object for this value.
187      *
188      * @return IntBuffer - a ByteBuffer that accesses the used value
189      *                     in the instrumentation buffer header.
190      * @see #getUsed()
191      */
usedBuffer()192     IntBuffer usedBuffer() {
193         byteBuffer.position(PERFDATA_PROLOG_USED_OFFSET);
194         IntBuffer ib = byteBuffer.asIntBuffer();
195         ib.limit(1);
196         return ib;
197     }
198 
199     /**
200      * Return an IntBuffer that accesses the size value. This is used
201      * to create a Monitor object for this value.
202      *
203      * @return IntBuffer - a ByteBuffer that accesses the size value
204      *                     in the instrumentation buffer header.
205      * @see #getBufferSize()
206      */
sizeBuffer()207     IntBuffer sizeBuffer() {
208         IntBuffer ib = IntBuffer.allocate(1);
209         ib.put(byteBuffer.capacity());
210         return ib;
211     }
212 
213     /**
214      * Return an IntBuffer that accesses the overflow value. This is used
215      * to create a Monitor object for this value.
216      *
217      * @return IntBuffer - a ByteBuffer that accesses the overflow value
218      *                     in the instrumentation buffer header.
219      * @see #getOverflow()
220      */
overflowBuffer()221     IntBuffer overflowBuffer() {
222         byteBuffer.position(PERFDATA_PROLOG_OVERFLOW_OFFSET);
223         IntBuffer ib = byteBuffer.asIntBuffer();
224         ib.limit(1);
225         return ib;
226     }
227 
228     /**
229      * Return a LongBuffer that accesses the modification timestamp value.
230      * This is used to create a Monitor object for this value.
231      *
232      * @return LongBuffer - a ByteBuffer that accesses the modification time
233      *                      stamp value in the instrumentation buffer header.
234      * @see #getModificationTimeStamp()
235      */
modificationTimeStampBuffer()236     LongBuffer modificationTimeStampBuffer() {
237         byteBuffer.position(PERFDATA_PROLOG_MODTIMESTAMP_OFFSET);
238         LongBuffer lb = byteBuffer.asLongBuffer();
239         lb.limit(1);
240         return lb;
241     }
242 
243     /**
244      * Return an IntBuffer that accesses the number of entries value.
245      * This is used to create a Monitor object for this value.
246      *
247      * @return LongBuffer - a ByteBuffer that accesses the num_entries
248      *                      value in the instrumentation buffer header.
249      * @see #getNumEntries()
250      */
numEntriesBuffer()251     IntBuffer numEntriesBuffer() {
252         byteBuffer.position(PERFDATA_PROLOG_NUMENTRIES_OFFSET);
253         IntBuffer ib = byteBuffer.asIntBuffer();
254         ib.limit(1);
255         return ib;
256     }
257 }
258