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.server;
042:
043: import org.netbeans.lib.profiler.global.CommonConstants;
044: import org.netbeans.lib.profiler.global.Platform;
045: import java.io.*;
046: import java.nio.MappedByteBuffer;
047: import java.nio.channels.FileChannel;
048:
049: /**
050: * Target VM-side management of the shared-memory event buffer file, through which rough profiling data
051: * is transmitted to the client.
052: *
053: * @author Tomas Hurka
054: * @author Misha Dmitriev
055: */
056: public class EventBufferManager implements CommonConstants {
057: //~ Static fields/initializers -----------------------------------------------------------------------------------------------
058:
059: private static final boolean DEBUG = System
060: .getProperty("org.netbeans.lib.profiler.server.EventBufferManager") != null; // NOI18N
061:
062: //~ Instance fields ----------------------------------------------------------------------------------------------------------
063:
064: private File bufFile;
065: private FileChannel bufFileChannel;
066: private MappedByteBuffer mapByteBuf;
067: private ProfilerServer profilerServer;
068: private RandomAccessFile raFile;
069: private String bufFileName;
070: private boolean bufFileOk;
071: private boolean remoteProfiling;
072:
073: //~ Constructors -------------------------------------------------------------------------------------------------------------
074:
075: public EventBufferManager(ProfilerServer server) {
076: profilerServer = server;
077: remoteProfiling = server.getProfilingSessionStatus().remoteProfiling;
078: }
079:
080: //~ Methods ------------------------------------------------------------------------------------------------------------------
081:
082: public String getBufferFileName() {
083: if (remoteProfiling) {
084: return ""; // NOI18N
085: } else {
086: return bufFileName;
087: }
088: }
089:
090: public void eventBufferDumpHook(byte[] eventBuffer, int startPos,
091: int curPtrPos) {
092: int length = curPtrPos - startPos;
093:
094: if (!remoteProfiling) {
095: if (!bufFileOk) {
096: return;
097: }
098:
099: if (DEBUG) {
100: System.err
101: .println("EventBufferManager.DEBUG: Dumping to file: startPos:"
102: + startPos + ", length:" + length); // NOI18N
103: }
104:
105: mapByteBuf.reset();
106: mapByteBuf.put(eventBuffer, startPos, length);
107: bufFileOk = profilerServer.sendEventBufferDumpedCommand(
108: length, true); // This will wait for response as well
109: } else {
110: synchronized (profilerServer) {
111: profilerServer.sendEventBufferDumpedCommand(length,
112: false); // This will not wait for response
113:
114: ObjectOutputStream os = profilerServer
115: .getSocketOutputStream();
116:
117: try {
118: if (DEBUG) {
119: System.err
120: .println("EventBufferManager.DEBUG: Dumping to wire: startPos:"
121: + startPos
122: + ", curPtrPos:"
123: + curPtrPos
124: + ", length:"
125: + (curPtrPos - startPos)); // NOI18N
126: }
127:
128: os.write(eventBuffer, startPos, curPtrPos
129: - startPos);
130: os.flush();
131: } catch (IOException ex) {
132: System.err
133: .println("Profiler Agent Error: error writing collected data to the socket: "
134: + ex.getMessage()); // NOI18N
135: }
136: }
137:
138: bufFileOk = profilerServer.getAndCheckLastResponse();
139: }
140: }
141:
142: public void freeBufferFile() {
143: if (remoteProfiling) {
144: return;
145: }
146:
147: try {
148: if (bufFileChannel != null) {
149: mapByteBuf = null;
150: bufFileChannel.close();
151: raFile.close();
152: System.gc(); // GCing mapBuf is the only way to free the buffer file.
153: bufFileOk = false;
154: }
155: } catch (IOException ex) {
156: System.err
157: .println("Profiler Agent Error: internal error when closing temporary memory-mapped communication file"); // NOI18N
158: }
159: }
160:
161: public void openBufferFile(int sizeInBytes) throws IOException {
162: if (remoteProfiling) {
163: return;
164: }
165:
166: if (bufFileOk) {
167: return;
168: }
169:
170: try {
171: bufFile = File.createTempFile("jfluidbuf", null); // NOI18N
172: bufFileName = bufFile.getCanonicalPath();
173:
174: // Bugfix: http://profiler.netbeans.org/issues/show_bug.cgi?id=59166
175: // Summary: Temporary communication file should be accessible for all users
176: // Bugfix details: As it does not seem to be possible to set the file permissions using Java code
177: // we explicitely invoke chmod on the newly created buffer file if we are on UNIX
178: if (Platform.isUnix()) {
179: try {
180: Runtime.getRuntime()
181: .exec(
182: new String[] { "chmod", "666",
183: bufFileName }); // NOI18N
184: } catch (Exception e) {
185: System.err
186: .println("*** JFluid Warning: Failed to set access permissions on temporary buffer file, you may not be able to attach as a different user: "
187: + e.getMessage()); // NOI18N
188: }
189: }
190:
191: raFile = new RandomAccessFile(bufFile, "rw"); // NOI18N
192: bufFileChannel = raFile.getChannel();
193: mapByteBuf = bufFileChannel.map(
194: FileChannel.MapMode.READ_WRITE, 0, sizeInBytes);
195: mapByteBuf.rewind();
196: mapByteBuf.mark();
197: bufFileOk = true;
198: } catch (FileNotFoundException ex1) {
199: System.err
200: .println("Profiler Agent Error: FileNotFoundException in EventBufferManager.openBufferFile - should not happen!"); // NOI18N
201:
202: return;
203: } catch (IOException ex2) {
204: System.err
205: .println("Profiler Agent Error: Could not create temporary buffer file in the default temporary directory: "
206: + ex2.getMessage()
207: + ": "
208: + System.getProperty("java.io.tmpdir")); // NOI18N
209: throw new IOException(
210: "Could not create temporary buffer file in the default temporary directory: "
211: + ex2.getMessage() + ": "
212: + System.getProperty("java.io.tmpdir")); // NOI18N
213: }
214: }
215: }
|