001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: * The Original Software is NetBeans. The Initial Developer of the Original
026: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
027: * Microsystems, Inc. All Rights Reserved.
028: *
029: * If you wish your version of this file to be governed by only the CDDL
030: * or only the GPL Version 2, indicate your decision by adding
031: * "[Contributor] elects to include this software in this distribution
032: * under the [CDDL or GPL Version 2] license." If you do not indicate a
033: * single choice of license, a recipient has the option to distribute
034: * your version of this file under either the CDDL, the GPL Version 2 or
035: * to extend the choice of license to its licensees as provided above.
036: * However, if you add GPL Version 2 code and therefore, elected the GPL
037: * Version 2 license, then the option applies only if the new code is
038: * made subject to such option by the copyright holder.
039: */
040:
041: package org.netbeans.lib.profiler.results.cpu;
042:
043: import org.netbeans.lib.profiler.results.CCTNode;
044: import org.netbeans.lib.profiler.utils.formatting.MethodNameFormatterFactory;
045: import java.text.MessageFormat;
046: import java.util.ResourceBundle;
047:
048: /**
049: * Base Presentation-Time CPU Profiling Calling Context Tree (CCT) Node class.
050: * Subclasses provide an implementation that is backed by the flattened tree data array in CPUCCTContainer
051: * (PrestimeCPUCCTNodeBacked) and the one that contains all the data in the node itself (PrestimeCPUCCTNodeFree).
052: *
053: * @author Misha Dmitriev
054: */
055: public abstract class PrestimeCPUCCTNode implements CCTNode, Cloneable {
056: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
057:
058: // -----
059: // I18N String constants
060: private static final ResourceBundle messages = ResourceBundle
061: .getBundle("org.netbeans.lib.profiler.results.cpu.Bundle"); // NOI18N
062: private static final String SELF_TIME_STRING = messages
063: .getString("PrestimeCPUCCTNode_SelfTimeString"); // NOI18N
064: private static final String FROM_MSG = messages
065: .getString("PrestimeCPUCCTNode_FromMsg"); // NOI18N
066: // -----
067: protected static final char MASK_SELF_TIME_NODE = 0x1;
068: protected static final char MASK_CONTEXT_CALLS_NODE = 0x2;
069: protected static final char MASK_THREAD_NODE = 0x4;
070: public static final int SORT_BY_NAME = 1;
071: public static final int SORT_BY_TIME_0 = 2;
072: public static final int SORT_BY_TIME_1 = 3;
073: public static final int SORT_BY_INVOCATIONS = 4;
074:
075: //~ Instance fields ----------------------------------------------------------------------------------------------------------
076:
077: protected CPUCCTContainer container;
078: protected PrestimeCPUCCTNode parent;
079: protected PrestimeCPUCCTNode[] children;
080: protected char flags; // Non-zero for several special kinds of nodes, per MASK_* bit constants above
081:
082: //~ Constructors -------------------------------------------------------------------------------------------------------------
083:
084: protected PrestimeCPUCCTNode() {
085: }
086:
087: /**
088: * Constructor for creating normal nodes representing methods
089: */
090: protected PrestimeCPUCCTNode(CPUCCTContainer container,
091: PrestimeCPUCCTNode parent) {
092: this .container = container;
093: this .parent = parent;
094: }
095:
096: //~ Methods ------------------------------------------------------------------------------------------------------------------
097:
098: public abstract CCTNode getChild(int index);
099:
100: public abstract CCTNode[] getChildren();
101:
102: public CPUCCTContainer getContainer() {
103: return container;
104: }
105:
106: public void setContextCallsNode() {
107: flags = MASK_CONTEXT_CALLS_NODE;
108: }
109:
110: public boolean isContextCallsNode() {
111: return (flags & MASK_CONTEXT_CALLS_NODE) != 0;
112: }
113:
114: public String[] getMethodClassNameAndSig() {
115: if (!isThreadNode()) {
116: return container.getMethodClassNameAndSig(getMethodId());
117: } else {
118: return new String[] { container.getThreadName(), "", "" }; // NOI18N
119: }
120: }
121:
122: public abstract int getMethodId();
123:
124: public abstract int getNCalls();
125:
126: public abstract int getNChildren();
127:
128: public String getNodeName() {
129: if (isSelfTimeNode()) {
130: return SELF_TIME_STRING;
131: } else if (isThreadNode()) {
132: return container.getThreadName();
133: }
134:
135: int methodId = getMethodId();
136: String[] methodClassNameAndSig = container
137: .getMethodClassNameAndSig(methodId);
138:
139: // PlainFormattableMethodName format = new PlainFormattableMethodName(
140: // methodClassNameAndSig[0], methodClassNameAndSig[1], methodClassNameAndSig[2]
141: // );
142: // String res = format.getFormattedClassAndMethod();
143: String res = MethodNameFormatterFactory.getDefault()
144: .getFormatter().formatMethodName(
145: methodClassNameAndSig[0],
146: methodClassNameAndSig[1],
147: methodClassNameAndSig[2]).toFormatted();
148:
149: if (isContextCallsNode()) {
150: return MessageFormat.format(FROM_MSG, new Object[] { res });
151: } else {
152: return res;
153: }
154: }
155:
156: public CCTNode getParent() {
157: return parent;
158: }
159:
160: public abstract long getSleepTime0();
161:
162: public abstract int getThreadId();
163:
164: public void setSelfTimeNode() {
165: flags = MASK_SELF_TIME_NODE;
166: }
167:
168: public boolean isSelfTimeNode() {
169: return (flags & MASK_SELF_TIME_NODE) != 0;
170: }
171:
172: public void setThreadNode() {
173: flags = MASK_THREAD_NODE;
174: }
175:
176: public boolean isThreadNode() {
177: return (flags & MASK_THREAD_NODE) != 0;
178: }
179:
180: public abstract long getTotalTime0();
181:
182: public abstract float getTotalTime0InPerCent();
183:
184: public abstract long getTotalTime1();
185:
186: public abstract float getTotalTime1InPerCent();
187:
188: public abstract long getWaitTime0();
189:
190: public int getIndexOfChild(Object child) {
191: for (int i = 0; i < children.length; i++) {
192: if ((PrestimeCPUCCTNode) child == children[i]) {
193: return i;
194: }
195: }
196:
197: return -1;
198: }
199:
200: /**
201: * This is not equal to doSortChildren below, because the real implementation of sortChildren may need to do some
202: * more things, such as generating the children, or deciding to return immediately.
203: */
204: public abstract void sortChildren(int sortBy, boolean sortOrder);
205:
206: public String toString() {
207: return getNodeName();
208: }
209:
210: protected void doSortChildren(int sortBy, boolean sortOrder) {
211: int len = children.length;
212:
213: for (int i = 0; i < len; i++) {
214: children[i].sortChildren(sortBy, sortOrder);
215: }
216:
217: if (len > 1) {
218: switch (sortBy) {
219: case SORT_BY_NAME:
220: sortChildrenByName(sortOrder);
221:
222: break;
223: case SORT_BY_TIME_0:
224: sortChildrenByTime0(sortOrder);
225:
226: break;
227: case SORT_BY_TIME_1:
228: sortChildrenByTime1(sortOrder);
229:
230: break;
231: case SORT_BY_INVOCATIONS:
232: sortChildrenByInvocations(sortOrder);
233:
234: break;
235: }
236: }
237: }
238:
239: protected void sortChildrenByInvocations(boolean sortOrder) {
240: int len = children.length;
241: int[] values = new int[len];
242:
243: for (int i = 0; i < len; i++) {
244: values[i] = children[i].getNCalls();
245: }
246:
247: sortInts(values, sortOrder);
248: }
249:
250: protected void sortChildrenByName(boolean sortOrder) {
251: int len = children.length;
252: String[] values = new String[len];
253:
254: for (int i = 0; i < len; i++) {
255: values[i] = children[i].getNodeName();
256: }
257:
258: sortStrings(values, sortOrder);
259: }
260:
261: protected void sortChildrenByTime0(boolean sortOrder) {
262: int len = children.length;
263: long[] values = new long[len];
264:
265: for (int i = 0; i < len; i++) {
266: values[i] = children[i].getTotalTime0();
267: }
268:
269: sortLongs(values, sortOrder);
270: }
271:
272: protected void sortChildrenByTime1(boolean sortOrder) {
273: int len = children.length;
274: long[] values = new long[len];
275:
276: for (int i = 0; i < len; i++) {
277: values[i] = children[i].getTotalTime1();
278: }
279:
280: sortLongs(values, sortOrder);
281: }
282:
283: protected void sortInts(int[] values, boolean sortOrder) {
284: int len = values.length;
285:
286: // Just the insertion sort - we will never get really large arrays here
287: for (int i = 0; i < len; i++) {
288: for (int j = i; (j > 0)
289: && ((sortOrder == false) ? (values[j - 1] < values[j])
290: : (values[j - 1] > values[j])); j--) {
291: int tmp = values[j];
292: values[j] = values[j - 1];
293: values[j - 1] = tmp;
294:
295: PrestimeCPUCCTNode tmpCh = children[j];
296: children[j] = children[j - 1];
297: children[j - 1] = tmpCh;
298: }
299: }
300: }
301:
302: protected void sortLongs(long[] values, boolean sortOrder) {
303: int len = values.length;
304:
305: // Just the insertion sort - we will never get really large arrays here
306: for (int i = 0; i < len; i++) {
307: for (int j = i; (j > 0)
308: && ((sortOrder == false) ? (values[j - 1] < values[j])
309: : (values[j - 1] > values[j])); j--) {
310: long tmp = values[j];
311: values[j] = values[j - 1];
312: values[j - 1] = tmp;
313:
314: PrestimeCPUCCTNode tmpCh = children[j];
315: children[j] = children[j - 1];
316: children[j - 1] = tmpCh;
317: }
318: }
319: }
320:
321: protected void sortStrings(String[] values, boolean sortOrder) {
322: int len = values.length;
323:
324: // Just the insertion sort - we will never get really large arrays here
325: for (int i = 0; i < len; i++) {
326: for (int j = i; (j > 0)
327: && ((sortOrder == false) ? (values[j - 1]
328: .compareTo(values[j]) < 0) : (values[j - 1]
329: .compareTo(values[j]) > 0)); j--) {
330: String tmp = values[j];
331: values[j] = values[j - 1];
332: values[j - 1] = tmp;
333:
334: PrestimeCPUCCTNode tmpCh = children[j];
335: children[j] = children[j - 1];
336: children[j - 1] = tmpCh;
337: }
338: }
339: }
340: }
|