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;
042:
043: import org.netbeans.lib.profiler.ProfilerClient;
044: import org.netbeans.lib.profiler.ProfilerLogger;
045: import org.netbeans.lib.profiler.global.CommonConstants;
046: import org.netbeans.lib.profiler.results.cpu.*;
047: import org.netbeans.lib.profiler.results.memory.MemoryDataFrameProcessor;
048: import org.netbeans.lib.profiler.results.memory.MemoryProfilingResultsListener;
049: import java.util.Collections;
050: import java.util.LinkedList;
051: import java.util.List;
052: import java.util.concurrent.ExecutorService;
053: import java.util.concurrent.Executors;
054: import java.util.logging.Logger;
055:
056: /**
057: *
058: * @author Jaroslav Bachorik
059: */
060: public final class ProfilingResultsDispatcher implements
061: ProfilingResultsProvider.Dispatcher {
062: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
063:
064: private static final Logger LOGGER = Logger
065: .getLogger(ProfilingResultsDispatcher.class.getName()); // NOI18N
066: private static final int QLengthLowerBound = 13;
067: private static final int QLengthUpperBound = 15;
068: private static ProfilingResultsDispatcher instance;
069:
070: //~ Instance fields ----------------------------------------------------------------------------------------------------------
071:
072: private final CPUDataFrameProcessor cpuDataProcessor = new CPUDataFrameProcessor();
073: private final MemoryDataFrameProcessor memoryDataProcessor = new MemoryDataFrameProcessor();
074: private final Object cpuDataProcessorQLengthLock = new Object();
075: private final Object memDataProcessorQLengthLock = new Object();
076: private ExecutorService queueProcessor;
077: private volatile boolean pauseFlag = true;
078:
079: // @GuardedBy cpuDataProcessorQLengthLock
080: private int cpuDataProcessorQLength = 0;
081:
082: // @GuardedBy memDataProcessorQLengthLock
083: private int memDataProcessorQLength = 0;
084:
085: //~ Methods ------------------------------------------------------------------------------------------------------------------
086:
087: public static synchronized ProfilingResultsDispatcher getDefault() {
088: if (instance == null) {
089: instance = new ProfilingResultsDispatcher();
090: }
091:
092: return instance;
093: }
094:
095: public void addListener(final CPUProfilingResultListener listener) {
096: if (cpuDataProcessor != null) {
097: cpuDataProcessor.addListener(listener);
098: }
099: }
100:
101: public void addListener(
102: final MemoryProfilingResultsListener listener) {
103: if (memoryDataProcessor != null) {
104: memoryDataProcessor.addListener(listener);
105: }
106: }
107:
108: public synchronized void dataFrameReceived(final byte[] buffer,
109: final int instrumentationType) {
110: if (!cpuDataProcessor.hasListeners()
111: && !memoryDataProcessor.hasListeners()) {
112: return; // no consumers
113: }
114:
115: switch (instrumentationType) {
116: case CommonConstants.INSTR_RECURSIVE_FULL:
117: case CommonConstants.INSTR_RECURSIVE_SAMPLED: {
118: synchronized (cpuDataProcessorQLengthLock) {
119: cpuDataProcessorQLength++;
120:
121: if (cpuDataProcessorQLength > QLengthUpperBound) {
122: try {
123: cpuDataProcessorQLengthLock.wait();
124: } catch (InterruptedException e) {
125: Thread.currentThread().interrupt();
126: }
127: }
128:
129: getExecutor().submit(new Runnable() {
130: public void run() {
131: try {
132: cpuDataProcessor.processDataFrame(buffer);
133: } finally {
134: synchronized (cpuDataProcessorQLengthLock) {
135: cpuDataProcessorQLength--;
136:
137: if (cpuDataProcessorQLength < QLengthLowerBound) {
138: cpuDataProcessorQLengthLock
139: .notifyAll();
140: }
141: }
142: }
143: }
144: });
145: }
146:
147: break;
148: }
149: case CommonConstants.INSTR_OBJECT_ALLOCATIONS:
150: case CommonConstants.INSTR_OBJECT_LIVENESS: {
151: synchronized (memDataProcessorQLengthLock) {
152: memDataProcessorQLength++;
153:
154: if (memDataProcessorQLength > QLengthUpperBound) {
155: try {
156: memDataProcessorQLengthLock.wait();
157: } catch (InterruptedException e) {
158: Thread.currentThread().interrupt();
159: }
160: }
161:
162: getExecutor().submit(new Runnable() {
163: public void run() {
164: try {
165: memoryDataProcessor
166: .processDataFrame(buffer);
167: } finally {
168: synchronized (memDataProcessorQLengthLock) {
169: memDataProcessorQLength--;
170:
171: if (memDataProcessorQLength < QLengthLowerBound) {
172: memDataProcessorQLengthLock
173: .notifyAll();
174: }
175: }
176: }
177: }
178: });
179: }
180:
181: break;
182: }
183: default:
184: ProfilerLogger.warning("Unknown instrumentation type ("
185: + instrumentationType + ") in dataframe"); // NOI18N
186: }
187: }
188:
189: public void pause(boolean flush) {
190: pauseFlag = true;
191: }
192:
193: public void removeAllListeners() {
194: if (cpuDataProcessor != null) {
195: cpuDataProcessor.removeAllListeners();
196: }
197:
198: if (memoryDataProcessor != null) {
199: memoryDataProcessor.removeAllListeners();
200: }
201: }
202:
203: public void removeListener(final CPUProfilingResultListener listener) {
204: if (cpuDataProcessor != null) {
205: cpuDataProcessor.removeListener(listener);
206: }
207: }
208:
209: public void removeListener(
210: final MemoryProfilingResultsListener listener) {
211: if (memoryDataProcessor != null) {
212: memoryDataProcessor.removeListener(listener);
213: }
214: }
215:
216: public void reset() {
217: fireReset();
218: }
219:
220: public void resume() {
221: pauseFlag = false;
222: }
223:
224: public synchronized void shutdown() {
225: // queueProcessor.shutdownNow();
226: fireShutdown(); // signalize shutdown
227: removeAllListeners();
228: }
229:
230: public synchronized void startup(ProfilerClient client) {
231: fireStartup(client);
232: resume();
233: }
234:
235: private synchronized ExecutorService getExecutor() {
236: if (queueProcessor == null) {
237: queueProcessor = Executors.newSingleThreadExecutor();
238: }
239:
240: return queueProcessor;
241: }
242:
243: private synchronized void fireReset() {
244: cpuDataProcessor.reset();
245: memoryDataProcessor.reset();
246: }
247:
248: private synchronized void fireShutdown() {
249: if (cpuDataProcessor != null) {
250: cpuDataProcessor.shutdown();
251: }
252:
253: if (memoryDataProcessor != null) {
254: memoryDataProcessor.shutdown();
255: }
256: }
257:
258: private synchronized void fireStartup(ProfilerClient client) {
259: cpuDataProcessor.startup(client);
260: memoryDataProcessor.startup(client);
261: }
262: }
|