1/* 2 * Copyright (c) 2003, 2011, 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 26package sun.management.counter.perf; 27 28import sun.management.counter.*; 29import java.nio.*; 30import java.io.UnsupportedEncodingException; 31 32class PerfDataEntry { 33 private class EntryFieldOffset { 34 private final static int SIZEOF_BYTE = 1; 35 private final static int SIZEOF_INT = 4; 36 private final static int SIZEOF_LONG = 8; 37 38 private final static int ENTRY_LENGTH_SIZE = SIZEOF_INT; 39 private final static int NAME_OFFSET_SIZE = SIZEOF_INT; 40 private final static int VECTOR_LENGTH_SIZE = SIZEOF_INT; 41 private final static int DATA_TYPE_SIZE = SIZEOF_BYTE; 42 private final static int FLAGS_SIZE = SIZEOF_BYTE; 43 private final static int DATA_UNIT_SIZE = SIZEOF_BYTE; 44 private final static int DATA_VAR_SIZE = SIZEOF_BYTE; 45 private final static int DATA_OFFSET_SIZE = SIZEOF_INT; 46 47 final static int ENTRY_LENGTH = 0; 48 final static int NAME_OFFSET = ENTRY_LENGTH + ENTRY_LENGTH_SIZE; 49 final static int VECTOR_LENGTH = NAME_OFFSET + NAME_OFFSET_SIZE;; 50 final static int DATA_TYPE = VECTOR_LENGTH + VECTOR_LENGTH_SIZE; 51 final static int FLAGS = DATA_TYPE + DATA_TYPE_SIZE; 52 final static int DATA_UNIT = FLAGS + FLAGS_SIZE; 53 final static int DATA_VAR = DATA_UNIT + DATA_UNIT_SIZE; 54 final static int DATA_OFFSET = DATA_VAR + DATA_VAR_SIZE; 55 } 56 57 private String name; 58 private int entryStart; 59 private int entryLength; 60 private int vectorLength; 61 private PerfDataType dataType; 62 private int flags; 63 private Units unit; 64 private Variability variability; 65 private int dataOffset; 66 private int dataSize; 67 private ByteBuffer data; 68 69 PerfDataEntry(ByteBuffer b) { 70 entryStart = b.position(); 71 entryLength = b.getInt(); 72 73 // check for valid entry length 74 if (entryLength <= 0 || entryLength > b.limit()) { 75 throw new InstrumentationException("Invalid entry length: " + 76 " entryLength = " + entryLength); 77 } 78 // check if last entry occurs before the eof. 79 if ((entryStart + entryLength) > b.limit()) { 80 throw new InstrumentationException("Entry extends beyond end of buffer: " + 81 " entryStart = " + entryStart + 82 " entryLength = " + entryLength + 83 " buffer limit = " + b.limit()); 84 } 85 86 b.position(entryStart + EntryFieldOffset.NAME_OFFSET); 87 int nameOffset = b.getInt(); 88 89 if ((entryStart + nameOffset) > b.limit()) { 90 throw new InstrumentationException("Invalid name offset: " + 91 " entryStart = " + entryStart + 92 " nameOffset = " + nameOffset + 93 " buffer limit = " + b.limit()); 94 } 95 96 97 b.position(entryStart + EntryFieldOffset.VECTOR_LENGTH); 98 vectorLength = b.getInt(); 99 100 b.position(entryStart + EntryFieldOffset.DATA_TYPE); 101 dataType = PerfDataType.toPerfDataType(b.get()); 102 103 b.position(entryStart + EntryFieldOffset.FLAGS); 104 flags = b.get(); 105 106 b.position(entryStart + EntryFieldOffset.DATA_UNIT); 107 unit = Units.toUnits(b.get()); 108 109 b.position(entryStart + EntryFieldOffset.DATA_VAR); 110 variability = Variability.toVariability(b.get()); 111 112 b.position(entryStart + EntryFieldOffset.DATA_OFFSET); 113 dataOffset = b.getInt(); 114 115 // read in the perfData item name, casting bytes to chars. skip the 116 // null terminator 117 b.position(entryStart + nameOffset); 118 // calculate the length of the name 119 int nameLength = 0; 120 byte c; 121 for (; (c = b.get()) != (byte)0; nameLength++); 122 123 byte[] symbolBytes = new byte[nameLength]; 124 b.position(entryStart + nameOffset); 125 for (int i = 0; i < nameLength; i++) { 126 symbolBytes[i] = b.get(); 127 } 128 129 // convert name into a String 130 try { 131 name = new String(symbolBytes, "UTF-8"); 132 } 133 catch (UnsupportedEncodingException e) { 134 // should not reach here 135 // "UTF-8" is always a known encoding 136 throw new InternalError(e.getMessage(), e); 137 } 138 139 if (variability == Variability.INVALID) { 140 throw new InstrumentationException("Invalid variability attribute:" + 141 " name = " + name); 142 } 143 if (unit == Units.INVALID) { 144 throw new InstrumentationException("Invalid units attribute: " + 145 " name = " + name); 146 } 147 148 if (vectorLength > 0) { 149 dataSize = vectorLength * dataType.size(); 150 } else { 151 dataSize = dataType.size(); 152 } 153 154 // check if data beyond the eof. 155 if ((entryStart + dataOffset + dataSize) > b.limit()) { 156 throw new InstrumentationException("Data extends beyond end of buffer: " + 157 " entryStart = " + entryStart + 158 " dataOffset = " + dataOffset+ 159 " dataSize = " + dataSize + 160 " buffer limit = " + b.limit()); 161 } 162 // Construct a ByteBuffer for the data 163 b.position(entryStart + dataOffset); 164 data = b.slice(); 165 data.order(b.order()); 166 data.limit(dataSize); 167 } 168 169 170 public int size() { 171 return entryLength; 172 } 173 174 public String name() { 175 return name; 176 } 177 178 public PerfDataType type() { 179 return dataType; 180 } 181 182 public Units units() { 183 return unit; 184 } 185 186 public int flags() { 187 return flags; 188 } 189 190 /** 191 * Returns the number of elements in the data. 192 */ 193 public int vectorLength() { 194 return vectorLength; 195 } 196 197 public Variability variability() { 198 return variability; 199 } 200 201 public ByteBuffer byteData() { 202 data.position(0); 203 assert data.remaining() == vectorLength(); 204 return data.duplicate(); 205 } 206 207 public LongBuffer longData() { 208 LongBuffer lb = data.asLongBuffer(); 209 return lb; 210 } 211} 212