1 /* |
|
2 * Copyright (c) 2004, 2014, 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.v1_0; |
|
27 |
|
28 import sun.jvmstat.monitor.*; |
|
29 import sun.jvmstat.perfdata.monitor.*; |
|
30 import java.util.*; |
|
31 import java.util.regex.*; |
|
32 import java.nio.*; |
|
33 |
|
34 /** |
|
35 * The concrete implementation of version 1.0 of the HotSpot PerfData |
|
36 * Instrumentation buffer. This class is responsible for parsing the |
|
37 * instrumentation memory and constructing the necessary objects to |
|
38 * represent and access the instrumentation objects contained in the |
|
39 * memory buffer. |
|
40 * |
|
41 * @author Brian Doherty |
|
42 * @since 1.5 |
|
43 * @see AbstractPerfDataBuffer |
|
44 */ |
|
45 public class PerfDataBuffer extends PerfDataBufferImpl { |
|
46 |
|
47 // 8028357 removed old, inefficient debug logging |
|
48 |
|
49 private static final int syncWaitMs = |
|
50 Integer.getInteger("sun.jvmstat.perdata.syncWaitMs", 5000); |
|
51 private static final ArrayList<Monitor> EMPTY_LIST = new ArrayList<Monitor>(0); |
|
52 |
|
53 /* |
|
54 * the following constants must be kept in sync with struct |
|
55 * PerfDataEntry in perfMemory.hpp |
|
56 */ |
|
57 private final static int PERFDATA_ENTRYLENGTH_OFFSET=0; |
|
58 private final static int PERFDATA_ENTRYLENGTH_SIZE=4; // sizeof(int) |
|
59 private final static int PERFDATA_NAMELENGTH_OFFSET=4; |
|
60 private final static int PERFDATA_NAMELENGTH_SIZE=4; // sizeof(int) |
|
61 private final static int PERFDATA_VECTORLENGTH_OFFSET=8; |
|
62 private final static int PERFDATA_VECTORLENGTH_SIZE=4; // sizeof(int) |
|
63 private final static int PERFDATA_DATATYPE_OFFSET=12; |
|
64 private final static int PERFDATA_DATATYPE_SIZE=1; // sizeof(byte) |
|
65 private final static int PERFDATA_FLAGS_OFFSET=13; |
|
66 private final static int PERFDATA_FLAGS_SIZE=1; // sizeof(byte) |
|
67 private final static int PERFDATA_DATAUNITS_OFFSET=14; |
|
68 private final static int PERFDATA_DATAUNITS_SIZE=1; // sizeof(byte) |
|
69 private final static int PERFDATA_DATAATTR_OFFSET=15; |
|
70 private final static int PERFDATA_DATAATTR_SIZE=1; // sizeof(byte) |
|
71 private final static int PERFDATA_NAME_OFFSET=16; |
|
72 |
|
73 PerfDataBufferPrologue prologue; |
|
74 int nextEntry; |
|
75 int pollForEntry; |
|
76 int perfDataItem; |
|
77 long lastModificationTime; |
|
78 int lastUsed; |
|
79 IntegerMonitor overflow; |
|
80 ArrayList<Monitor> insertedMonitors; |
|
81 |
|
82 /** |
|
83 * Construct a PerfDataBufferImpl instance. |
|
84 * <p> |
|
85 * This class is dynamically loaded by |
|
86 * {@link AbstractPerfDataBuffer#createPerfDataBuffer}, and this |
|
87 * constructor is called to instantiate the instance. |
|
88 * |
|
89 * @param buffer the buffer containing the instrumentation data |
|
90 * @param lvmid the Local Java Virtual Machine Identifier for this |
|
91 * instrumentation buffer. |
|
92 */ |
|
93 public PerfDataBuffer(ByteBuffer buffer, int lvmid) |
|
94 throws MonitorException { |
|
95 super(buffer, lvmid); |
|
96 prologue = new PerfDataBufferPrologue(buffer); |
|
97 this.buffer.order(prologue.getByteOrder()); |
|
98 } |
|
99 |
|
100 /** |
|
101 * {@inheritDoc} |
|
102 */ |
|
103 protected void buildMonitorMap(Map<String, Monitor> map) throws MonitorException { |
|
104 assert Thread.holdsLock(this); |
|
105 |
|
106 // start at the beginning of the buffer |
|
107 buffer.rewind(); |
|
108 |
|
109 // create pseudo monitors |
|
110 buildPseudoMonitors(map); |
|
111 |
|
112 // position buffer to start of the data section |
|
113 buffer.position(prologue.getSize()); |
|
114 nextEntry = buffer.position(); |
|
115 perfDataItem = 0; |
|
116 |
|
117 int used = prologue.getUsed(); |
|
118 long modificationTime = prologue.getModificationTimeStamp(); |
|
119 |
|
120 Monitor m = getNextMonitorEntry(); |
|
121 while (m != null) { |
|
122 map.put(m.getName(), m); |
|
123 m = getNextMonitorEntry(); |
|
124 } |
|
125 |
|
126 /* |
|
127 * set the last modification data. These are set to the values |
|
128 * recorded before parsing the data structure. This allows the |
|
129 * the data structure to be modified while the Map is being built. |
|
130 * The Map may contain more entries than indicated based on the |
|
131 * time stamp, but this is handled by ignoring duplicate entries |
|
132 * when the Map is updated in getNewMonitors(). |
|
133 */ |
|
134 lastUsed = used; |
|
135 lastModificationTime = modificationTime; |
|
136 |
|
137 // synchronize with the target jvm |
|
138 synchWithTarget(map); |
|
139 |
|
140 // work around 1.4.2 counter inititization bugs |
|
141 kludge(map); |
|
142 |
|
143 insertedMonitors = new ArrayList<Monitor>(map.values()); |
|
144 } |
|
145 |
|
146 /** |
|
147 * {@inheritDoc} |
|
148 */ |
|
149 protected void getNewMonitors(Map<String, Monitor> map) throws MonitorException { |
|
150 assert Thread.holdsLock(this); |
|
151 |
|
152 int used = prologue.getUsed(); |
|
153 long modificationTime = prologue.getModificationTimeStamp(); |
|
154 |
|
155 if ((used > lastUsed) || (lastModificationTime > modificationTime)) { |
|
156 |
|
157 lastUsed = used; |
|
158 lastModificationTime = modificationTime; |
|
159 |
|
160 Monitor monitor = getNextMonitorEntry(); |
|
161 while (monitor != null) { |
|
162 String name = monitor.getName(); |
|
163 |
|
164 // guard against duplicate entries |
|
165 if (!map.containsKey(name)) { |
|
166 map.put(name, monitor); |
|
167 |
|
168 /* |
|
169 * insertedMonitors is null when called from pollFor() |
|
170 * via buildMonitorMap(). Since we update insertedMonitors |
|
171 * at the end of buildMonitorMap(), it's ok to skip the |
|
172 * add here. |
|
173 */ |
|
174 if (insertedMonitors != null) { |
|
175 insertedMonitors.add(monitor); |
|
176 } |
|
177 } |
|
178 monitor = getNextMonitorEntry(); |
|
179 } |
|
180 } |
|
181 } |
|
182 |
|
183 /** |
|
184 * {@inheritDoc} |
|
185 */ |
|
186 protected MonitorStatus getMonitorStatus(Map<String, Monitor> map) throws MonitorException { |
|
187 assert Thread.holdsLock(this); |
|
188 assert insertedMonitors != null; |
|
189 |
|
190 // load any new monitors |
|
191 getNewMonitors(map); |
|
192 |
|
193 // current implementation doesn't support deletion or reuse of entries |
|
194 ArrayList<Monitor> removed = EMPTY_LIST; |
|
195 ArrayList<Monitor> inserted = insertedMonitors; |
|
196 |
|
197 insertedMonitors = new ArrayList<Monitor>(); |
|
198 return new MonitorStatus(inserted, removed); |
|
199 } |
|
200 |
|
201 /** |
|
202 * Build the pseudo monitors used to map the prolog data into counters. |
|
203 */ |
|
204 protected void buildPseudoMonitors(Map<String, Monitor> map) { |
|
205 Monitor monitor = null; |
|
206 String name = null; |
|
207 IntBuffer ib = null; |
|
208 |
|
209 name = PerfDataBufferPrologue.PERFDATA_MAJOR_NAME; |
|
210 ib = prologue.majorVersionBuffer(); |
|
211 monitor = new PerfIntegerMonitor(name, Units.NONE, |
|
212 Variability.CONSTANT, false, ib); |
|
213 map.put(name, monitor); |
|
214 |
|
215 name = PerfDataBufferPrologue.PERFDATA_MINOR_NAME; |
|
216 ib = prologue.minorVersionBuffer(); |
|
217 monitor = new PerfIntegerMonitor(name, Units.NONE, |
|
218 Variability.CONSTANT, false, ib); |
|
219 map.put(name, monitor); |
|
220 |
|
221 name = PerfDataBufferPrologue.PERFDATA_BUFFER_SIZE_NAME; |
|
222 ib = prologue.sizeBuffer(); |
|
223 monitor = new PerfIntegerMonitor(name, Units.BYTES, |
|
224 Variability.MONOTONIC, false, ib); |
|
225 map.put(name, monitor); |
|
226 |
|
227 name = PerfDataBufferPrologue.PERFDATA_BUFFER_USED_NAME; |
|
228 ib = prologue.usedBuffer(); |
|
229 monitor = new PerfIntegerMonitor(name, Units.BYTES, |
|
230 Variability.MONOTONIC, false, ib); |
|
231 map.put(name, monitor); |
|
232 |
|
233 name = PerfDataBufferPrologue.PERFDATA_OVERFLOW_NAME; |
|
234 ib = prologue.overflowBuffer(); |
|
235 monitor = new PerfIntegerMonitor(name, Units.BYTES, |
|
236 Variability.MONOTONIC, false, ib); |
|
237 map.put(name, monitor); |
|
238 this.overflow = (IntegerMonitor)monitor; |
|
239 |
|
240 name = PerfDataBufferPrologue.PERFDATA_MODTIMESTAMP_NAME; |
|
241 LongBuffer lb = prologue.modificationTimeStampBuffer(); |
|
242 monitor = new PerfLongMonitor(name, Units.TICKS, |
|
243 Variability.MONOTONIC, false, lb); |
|
244 map.put(name, monitor); |
|
245 } |
|
246 |
|
247 /** |
|
248 * Method to provide a gross level of synchronization with the |
|
249 * target monitored jvm. |
|
250 * |
|
251 * gross synchronization works by polling for the hotspot.rt.hrt.ticks |
|
252 * counter, which is the last counter created by the StatSampler |
|
253 * initialization code. The counter is updated when the watcher thread |
|
254 * starts scheduling tasks, which is the last thing done in vm |
|
255 * initialization. |
|
256 */ |
|
257 protected void synchWithTarget(Map<String, Monitor> map) throws MonitorException { |
|
258 /* |
|
259 * synch must happen with syncWaitMs from now. Default is 5 seconds, |
|
260 * which is reasonabally generous and should provide for extreme |
|
261 * situations like startup delays due to allocation of large ISM heaps. |
|
262 */ |
|
263 long timeLimit = System.currentTimeMillis() + syncWaitMs; |
|
264 |
|
265 String name = "hotspot.rt.hrt.ticks"; |
|
266 LongMonitor ticks = (LongMonitor)pollFor(map, name, timeLimit); |
|
267 |
|
268 /* |
|
269 * loop waiting for the ticks counter to be non zero. This is |
|
270 * an indication that the jvm is initialized. |
|
271 */ |
|
272 while (ticks.longValue() == 0) { |
|
273 try { Thread.sleep(20); } catch (InterruptedException e) { } |
|
274 |
|
275 if (System.currentTimeMillis() > timeLimit) { |
|
276 throw new MonitorException("Could Not Synchronize with target"); |
|
277 } |
|
278 } |
|
279 } |
|
280 |
|
281 /** |
|
282 * Method to poll the instrumentation memory for a counter with |
|
283 * the given name. The polling period is bounded by the timeLimit |
|
284 * argument. |
|
285 */ |
|
286 protected Monitor pollFor(Map<String, Monitor> map, String name, long timeLimit) |
|
287 throws MonitorException { |
|
288 Monitor monitor = null; |
|
289 |
|
290 pollForEntry = nextEntry; |
|
291 while ((monitor = map.get(name)) == null) { |
|
292 |
|
293 try { Thread.sleep(20); } catch (InterruptedException e) { } |
|
294 |
|
295 long t = System.currentTimeMillis(); |
|
296 if ((t > timeLimit) || (overflow.intValue() > 0)) { |
|
297 throw new MonitorException("Could not find expected counter"); |
|
298 } |
|
299 |
|
300 getNewMonitors(map); |
|
301 } |
|
302 return monitor; |
|
303 } |
|
304 |
|
305 /** |
|
306 * method to make adjustments for known counter problems. This |
|
307 * method depends on the availability of certain counters, which |
|
308 * is generally guaranteed by the synchWithTarget() method. |
|
309 */ |
|
310 protected void kludge(Map<String, Monitor> map) { |
|
311 if (Boolean.getBoolean("sun.jvmstat.perfdata.disableKludge")) { |
|
312 // bypass all kludges |
|
313 return; |
|
314 } |
|
315 |
|
316 String name = "java.vm.version"; |
|
317 StringMonitor jvm_version = (StringMonitor)map.get(name); |
|
318 if (jvm_version == null) { |
|
319 jvm_version = (StringMonitor)findByAlias(name); |
|
320 } |
|
321 |
|
322 name = "java.vm.name"; |
|
323 StringMonitor jvm_name = (StringMonitor)map.get(name); |
|
324 if (jvm_name == null) { |
|
325 jvm_name = (StringMonitor)findByAlias(name); |
|
326 } |
|
327 |
|
328 name = "hotspot.vm.args"; |
|
329 StringMonitor args = (StringMonitor)map.get(name); |
|
330 if (args == null) { |
|
331 args = (StringMonitor)findByAlias(name); |
|
332 } |
|
333 |
|
334 assert ((jvm_name != null) && (jvm_version != null) && (args != null)); |
|
335 |
|
336 if (jvm_name.stringValue().indexOf("HotSpot") >= 0) { |
|
337 if (jvm_version.stringValue().startsWith("1.4.2")) { |
|
338 kludgeMantis(map, args); |
|
339 } |
|
340 } |
|
341 } |
|
342 |
|
343 /** |
|
344 * method to repair the 1.4.2 parallel scavenge counters that are |
|
345 * incorrectly initialized by the JVM when UseAdaptiveSizePolicy |
|
346 * is set. This bug couldn't be fixed for 1.4.2 FCS due to putback |
|
347 * restrictions. |
|
348 */ |
|
349 private void kludgeMantis(Map<String, Monitor> map, StringMonitor args) { |
|
350 /* |
|
351 * the HotSpot 1.4.2 JVM with the +UseParallelGC option along |
|
352 * with its default +UseAdaptiveSizePolicy option has a bug with |
|
353 * the initialization of the sizes of the eden and survivor spaces. |
|
354 * See bugid 4890736. |
|
355 * |
|
356 * note - use explicit 1.4.2 counter names here - don't update |
|
357 * to latest counter names or attempt to find aliases. |
|
358 */ |
|
359 |
|
360 String cname = "hotspot.gc.collector.0.name"; |
|
361 StringMonitor collector = (StringMonitor)map.get(cname); |
|
362 |
|
363 if (collector.stringValue().compareTo("PSScavenge") == 0) { |
|
364 boolean adaptiveSizePolicy = true; |
|
365 |
|
366 /* |
|
367 * HotSpot processes the -XX:Flags/.hotspotrc arguments prior to |
|
368 * processing the command line arguments. This allows the command |
|
369 * line arguments to override any defaults set in .hotspotrc |
|
370 */ |
|
371 cname = "hotspot.vm.flags"; |
|
372 StringMonitor flags = (StringMonitor)map.get(cname); |
|
373 String allArgs = flags.stringValue() + " " + args.stringValue(); |
|
374 |
|
375 /* |
|
376 * ignore the -XX: prefix as it only applies to the arguments |
|
377 * passed from the command line (i.e. the invocation api). |
|
378 * arguments passed through .hotspotrc omit the -XX: prefix. |
|
379 */ |
|
380 int ahi = allArgs.lastIndexOf("+AggressiveHeap"); |
|
381 int aspi = allArgs.lastIndexOf("-UseAdaptiveSizePolicy"); |
|
382 |
|
383 if (ahi != -1) { |
|
384 /* |
|
385 * +AggressiveHeap was set, check if -UseAdaptiveSizePolicy |
|
386 * is set after +AggressiveHeap. |
|
387 */ |
|
388 // |
|
389 if ((aspi != -1) && (aspi > ahi)) { |
|
390 adaptiveSizePolicy = false; |
|
391 } |
|
392 } else { |
|
393 /* |
|
394 * +AggressiveHeap not set, must be +UseParallelGC. The |
|
395 * relative position of -UseAdaptiveSizePolicy is not |
|
396 * important in this case, as it will override the |
|
397 * UseParallelGC default (+UseAdaptiveSizePolicy) if it |
|
398 * appears anywhere in the JVM arguments. |
|
399 */ |
|
400 if (aspi != -1) { |
|
401 adaptiveSizePolicy = false; |
|
402 } |
|
403 } |
|
404 |
|
405 if (adaptiveSizePolicy) { |
|
406 // adjust the buggy AdaptiveSizePolicy size counters. |
|
407 |
|
408 // first remove the real counters. |
|
409 String eden_size = "hotspot.gc.generation.0.space.0.size"; |
|
410 String s0_size = "hotspot.gc.generation.0.space.1.size"; |
|
411 String s1_size = "hotspot.gc.generation.0.space.2.size"; |
|
412 map.remove(eden_size); |
|
413 map.remove(s0_size); |
|
414 map.remove(s1_size); |
|
415 |
|
416 // get the maximum new generation size |
|
417 String new_max_name = "hotspot.gc.generation.0.capacity.max"; |
|
418 LongMonitor new_max = (LongMonitor)map.get(new_max_name); |
|
419 |
|
420 /* |
|
421 * replace the real counters with pseudo counters that are |
|
422 * initialized to the correct values. The maximum size of |
|
423 * the eden and survivor spaces are supposed to be: |
|
424 * max_eden_size = new_size - (2*alignment). |
|
425 * max_survivor_size = new_size - (2*alignment). |
|
426 * since we don't know the alignment value used, and because |
|
427 * of other parallel scavenge bugs that result in oversized |
|
428 * spaces, we just set the maximum size of each space to the |
|
429 * full new gen size. |
|
430 */ |
|
431 Monitor monitor = null; |
|
432 |
|
433 LongBuffer lb = LongBuffer.allocate(1); |
|
434 lb.put(new_max.longValue()); |
|
435 monitor = new PerfLongMonitor(eden_size, Units.BYTES, |
|
436 Variability.CONSTANT, false, lb); |
|
437 map.put(eden_size, monitor); |
|
438 |
|
439 monitor = new PerfLongMonitor(s0_size, Units.BYTES, |
|
440 Variability.CONSTANT, false, lb); |
|
441 map.put(s0_size, monitor); |
|
442 |
|
443 monitor = new PerfLongMonitor(s1_size, Units.BYTES, |
|
444 Variability.CONSTANT, false, lb); |
|
445 map.put(s1_size, monitor); |
|
446 } |
|
447 } |
|
448 } |
|
449 |
|
450 /** |
|
451 * method to extract the next monitor entry from the instrumentation memory. |
|
452 * assumes that nextEntry is the offset into the byte array |
|
453 * at which to start the search for the next entry. method leaves |
|
454 * next entry pointing to the next entry or to the end of data. |
|
455 */ |
|
456 protected Monitor getNextMonitorEntry() throws MonitorException { |
|
457 Monitor monitor = null; |
|
458 |
|
459 // entries are always 4 byte aligned. |
|
460 if ((nextEntry % 4) != 0) { |
|
461 throw new MonitorStructureException( |
|
462 "Entry index not properly aligned: " + nextEntry); |
|
463 } |
|
464 |
|
465 // protect against a corrupted shared memory region. |
|
466 if ((nextEntry < 0) || (nextEntry > buffer.limit())) { |
|
467 throw new MonitorStructureException( |
|
468 "Entry index out of bounds: nextEntry = " + nextEntry |
|
469 + ", limit = " + buffer.limit()); |
|
470 } |
|
471 |
|
472 // check for the end of the buffer |
|
473 if (nextEntry == buffer.limit()) { |
|
474 return null; |
|
475 } |
|
476 |
|
477 buffer.position(nextEntry); |
|
478 |
|
479 int entryStart = buffer.position(); |
|
480 int entryLength = buffer.getInt(); |
|
481 |
|
482 // check for valid entry length |
|
483 if ((entryLength < 0) || (entryLength > buffer.limit())) { |
|
484 throw new MonitorStructureException( |
|
485 "Invalid entry length: entryLength = " + entryLength); |
|
486 } |
|
487 |
|
488 // check if last entry occurs before the eof. |
|
489 if ((entryStart + entryLength) > buffer.limit()) { |
|
490 throw new MonitorStructureException( |
|
491 "Entry extends beyond end of buffer: " |
|
492 + " entryStart = " + entryStart |
|
493 + " entryLength = " + entryLength |
|
494 + " buffer limit = " + buffer.limit()); |
|
495 } |
|
496 |
|
497 if (entryLength == 0) { |
|
498 // end of data |
|
499 return null; |
|
500 } |
|
501 |
|
502 int nameLength = buffer.getInt(); |
|
503 int vectorLength = buffer.getInt(); |
|
504 byte dataType = buffer.get(); |
|
505 byte flags = buffer.get(); |
|
506 Units u = Units.toUnits(buffer.get()); |
|
507 Variability v = Variability.toVariability(buffer.get()); |
|
508 boolean supported = (flags & 0x01) != 0; |
|
509 |
|
510 // defend against corrupt entries |
|
511 if ((nameLength <= 0) || (nameLength > entryLength)) { |
|
512 throw new MonitorStructureException( |
|
513 "Invalid Monitor name length: " + nameLength); |
|
514 } |
|
515 |
|
516 if ((vectorLength < 0) || (vectorLength > entryLength)) { |
|
517 throw new MonitorStructureException( |
|
518 "Invalid Monitor vector length: " + vectorLength); |
|
519 } |
|
520 |
|
521 // read in the perfData item name, casting bytes to chars. skip the |
|
522 // null terminator |
|
523 // |
|
524 byte[] nameBytes = new byte[nameLength-1]; |
|
525 for (int i = 0; i < nameLength-1; i++) { |
|
526 nameBytes[i] = buffer.get(); |
|
527 } |
|
528 |
|
529 // convert name into a String |
|
530 String name = new String(nameBytes, 0, nameLength-1); |
|
531 |
|
532 if (v == Variability.INVALID) { |
|
533 throw new MonitorDataException("Invalid variability attribute:" |
|
534 + " entry index = " + perfDataItem |
|
535 + " name = " + name); |
|
536 } |
|
537 if (u == Units.INVALID) { |
|
538 throw new MonitorDataException("Invalid units attribute: " |
|
539 + " entry index = " + perfDataItem |
|
540 + " name = " + name); |
|
541 } |
|
542 |
|
543 int offset; |
|
544 if (vectorLength == 0) { |
|
545 // scalar Types |
|
546 if (dataType == BasicType.LONG.intValue()) { |
|
547 offset = entryStart + entryLength - 8; /* 8 = sizeof(long) */ |
|
548 buffer.position(offset); |
|
549 LongBuffer lb = buffer.asLongBuffer(); |
|
550 lb.limit(1); |
|
551 monitor = new PerfLongMonitor(name, u, v, supported, lb); |
|
552 perfDataItem++; |
|
553 } else { |
|
554 // bad data types. |
|
555 throw new MonitorTypeException("Invalid Monitor type:" |
|
556 + " entry index = " + perfDataItem |
|
557 + " name = " + name |
|
558 + " type = " + dataType); |
|
559 } |
|
560 } else { |
|
561 // vector types |
|
562 if (dataType == BasicType.BYTE.intValue()) { |
|
563 if (u != Units.STRING) { |
|
564 // only byte arrays of type STRING are currently supported |
|
565 throw new MonitorTypeException("Invalid Monitor type:" |
|
566 + " entry index = " + perfDataItem |
|
567 + " name = " + name |
|
568 + " type = " + dataType); |
|
569 } |
|
570 |
|
571 offset = entryStart + PERFDATA_NAME_OFFSET + nameLength; |
|
572 buffer.position(offset); |
|
573 ByteBuffer bb = buffer.slice(); |
|
574 bb.limit(vectorLength); |
|
575 bb.position(0); |
|
576 |
|
577 if (v == Variability.CONSTANT) { |
|
578 monitor = new PerfStringConstantMonitor(name, supported, |
|
579 bb); |
|
580 } else if (v == Variability.VARIABLE) { |
|
581 monitor = new PerfStringVariableMonitor(name, supported, |
|
582 bb, vectorLength-1); |
|
583 } else { |
|
584 // Monotonically increasing byte arrays are not supported |
|
585 throw new MonitorDataException( |
|
586 "Invalid variability attribute:" |
|
587 + " entry index = " + perfDataItem |
|
588 + " name = " + name |
|
589 + " variability = " + v); |
|
590 } |
|
591 perfDataItem++; |
|
592 } else { |
|
593 // bad data types. |
|
594 throw new MonitorTypeException( |
|
595 "Invalid Monitor type:" + " entry index = " |
|
596 + perfDataItem + " name = " + name |
|
597 + " type = " + dataType); |
|
598 } |
|
599 } |
|
600 |
|
601 // setup index to next entry for next iteration of the loop. |
|
602 nextEntry = entryStart + entryLength; |
|
603 return monitor; |
|
604 } |
|
605 } |
|