1
/*******************************************************************************
2
* Copyright (c) 2004, 2008, 2009 Red Hat, Inc.
3
* All rights reserved. This program and the accompanying materials
4
* are made available under the terms of the Eclipse Public License v1.0
5
* which accompanies this distribution, and is available at
6
* http://www.eclipse.org/legal/epl-v10.html
9
* Keith Seitz <keiths@redhat.com> - initial API and implementation
10
* Kent Sebastian <ksebasti@redhat.com>
11
*******************************************************************************/
12
package org.eclipse.linuxtools.internal.oprofile.core.linux;
14
import java.io.BufferedReader;
16
import java.io.FileNotFoundException;
17
import java.io.IOException;
18
import java.io.InputStreamReader;
20
import java.util.ArrayList;
22
import org.eclipse.core.resources.IProject;
23
import org.eclipse.core.runtime.FileLocator;
24
import org.eclipse.core.runtime.Path;
25
import org.eclipse.core.runtime.Platform;
26
import org.eclipse.linuxtools.internal.oprofile.core.IOpcontrolProvider;
27
import org.eclipse.linuxtools.internal.oprofile.core.OpcontrolException;
28
import org.eclipse.linuxtools.internal.oprofile.core.Oprofile;
29
import org.eclipse.linuxtools.internal.oprofile.core.OprofileCorePlugin;
30
import org.eclipse.linuxtools.internal.oprofile.core.daemon.OprofileDaemonEvent;
31
import org.eclipse.linuxtools.internal.oprofile.core.daemon.OprofileDaemonOptions;
32
import org.eclipse.linuxtools.internal.oprofile.core.opxml.sessions.SessionManager;
33
import org.eclipse.linuxtools.tools.launch.core.factory.RuntimeProcessFactory;
34
import org.eclipse.linuxtools.tools.launch.core.properties.LinuxtoolsPathProperty;
37
* A class which encapsulates running opcontrol.
39
public class LinuxOpcontrolProvider implements IOpcontrolProvider {
40
private static final String OPCONTROL_EXECUTABLE = "opcontrol";
42
// Location of opcontrol security wrapper
43
private static final String OPCONTROL_REL_PATH = "natives/linux/scripts/" + OPCONTROL_EXECUTABLE; //$NON-NLS-1$
45
private final String opcontrolProgram;
47
// Initialize the Oprofile kernel module and oprofilefs
48
private static final String OPD_INIT_MODULE = "--init"; //$NON-NLS-1$
50
// Setup daemon collection arguments
51
private static final String OPD_SETUP = "--setup"; //$NON-NLS-1$
52
private static final String OPD_HELP = "--help"; //$NON-NLS-1$
53
private static final String OPD_SETUP_SEPARATE = "--separate="; //$NON-NLS-1$
54
private static final String OPD_SETUP_SEPARATE_SEPARATOR = ","; //$NON-NLS-1$
55
private static final String OPD_SETUP_SEPARATE_NONE = "none"; //$NON-NLS-1$
56
private static final String OPD_SETUP_SEPARATE_LIBRARY = "library"; //$NON-NLS-1$
57
private static final String OPD_SETUP_SEPARATE_KERNEL = "kernel"; //$NON-NLS-1$
58
private static final String OPD_SETUP_SEPARATE_THREAD = "thread"; //$NON-NLS-1$
59
private static final String OPD_SETUP_SEPARATE_CPU = "cpu"; //$NON-NLS-1$
61
private static final String OPD_SETUP_EVENT = "--event="; //$NON-NLS-1$
62
private static final String OPD_SETUP_EVENT_SEPARATOR = ":"; //$NON-NLS-1$
63
private static final String OPD_SETUP_EVENT_TRUE = "1"; //$NON-NLS-1$
64
private static final String OPD_SETUP_EVENT_FALSE = "0"; //$NON-NLS-1$
65
private static final String OPD_SETUP_EVENT_DEFAULT = "default"; //$NON-NLS-1$
67
private static final String OPD_SETUP_IMAGE = "--image="; //$NON-NLS-1$
69
private static final String OPD_CALLGRAPH_DEPTH = "--callgraph="; //$NON-NLS-1$
71
// Kernel image file options
72
private static final String OPD_KERNEL_NONE = "--no-vmlinux"; //$NON-NLS-1$
73
private static final String OPD_KERNEL_FILE = "--vmlinux="; //$NON-NLS-1$
75
// Start the daemon process without starting data collection
76
private static final String OPD_START_DAEMON = "--start-daemon"; //$NON-NLS-1$
78
// Start collecting profiling data
79
private static final String OPD_START_COLLECTION = "--start"; //$NON-NLS-1$
81
// Flush the collected profiling data to disk
82
private static final String OPD_DUMP = "--dump"; //$NON-NLS-1$
84
// Stop data collection
85
private static final String OPD_STOP_COLLECTION = "--stop"; //$NON-NLS-1$
87
// Stop data collection and stop daemon
88
private static final String OPD_SHUTDOWN = "--shutdown"; //$NON-NLS-1$
90
// Clear out data from current session
91
private static final String OPD_RESET = "--reset"; //$NON-NLS-1$
93
// Unload the oprofile kernel module and oprofilefs
94
private static final String OPD_DEINIT_MODULE = "--deinit"; //$NON-NLS-1$
96
// Logging verbosity. Specified with setupDaemon.
97
//--verbosity=all generates WAY too much stuff in the log
98
private String verbosity = ""; //$NON-NLS-1$
101
public LinuxOpcontrolProvider() throws OpcontrolException {
102
opcontrolProgram = findOpcontrol();
106
* Unload the kernel module and oprofilefs
107
* @throws OpcontrolException
109
public void deinitModule() throws OpcontrolException {
110
runOpcontrol(OPD_DEINIT_MODULE);
114
* Dump collected profiling data
115
* @throws OpcontrolException
117
public void dumpSamples() throws OpcontrolException {
118
runOpcontrol(OPD_DUMP);
122
* Loads the kernel module and oprofilefs
123
* @throws OpcontrolException
125
public void initModule() throws OpcontrolException {
126
runOpcontrol(OPD_INIT_MODULE);
130
* Clears out data from current session
131
* @throws OpcontrolException
133
public void reset() throws OpcontrolException {
134
runOpcontrol(OPD_RESET);
138
* Saves the current ("default") session
139
* @param name the name to which to save the session
140
* @throws OpcontrolException
142
public void saveSession(String name) throws OpcontrolException {
143
SessionManager sessMan;
145
sessMan = new SessionManager(SessionManager.SESSION_LOCATION);
146
for (String event : sessMan.getSessionEvents(SessionManager.CURRENT)){
147
sessMan.addSession(name, event);
148
String oldFile = SessionManager.OPXML_PREFIX + SessionManager.MODEL_DATA + event + SessionManager.CURRENT;
149
String newFile = SessionManager.OPXML_PREFIX + SessionManager.MODEL_DATA + event + name;
150
Process p = Runtime.getRuntime().exec("cp " + oldFile + " " + newFile);
154
} catch (FileNotFoundException e) {
155
//intentionally blank
156
//during a save, the session file will exist
157
} catch (IOException e) {
159
} catch (InterruptedException e) {
165
* Delete the session with the specified name for the specified event
166
* @param sessionName The name of the session to delete
167
* @param eventName The name of the event containing the session
168
* @throws OpcontrolException
170
public void deleteSession (String sessionName, String eventName) throws OpcontrolException {
171
File file = new File (SessionManager.OPXML_PREFIX + SessionManager.MODEL_DATA + eventName + sessionName);
173
SessionManager sessMan = new SessionManager(SessionManager.SESSION_LOCATION);
174
sessMan.removeSession(sessionName, eventName);
179
* Give setup aruments
180
* @param args list of parameters for daemon
181
* @throws OpcontrolException
183
public void setupDaemon(OprofileDaemonOptions options, OprofileDaemonEvent[] events) throws OpcontrolException {
184
// Convert options & events to arguments for opcontrol
185
ArrayList<String> args = new ArrayList<String>();
187
optionsToArguments(args, options);
188
if (!Oprofile.getTimerMode()) {
189
if (events == null || events.length == 0) {
190
args.add(OPD_SETUP_EVENT + OPD_SETUP_EVENT_DEFAULT);
192
for (int i = 0; i < events.length; ++i) {
193
eventToArguments(args, events[i]);
201
* Stop data collection and remove daemon
202
* @throws OpcontrolException
204
public void shutdownDaemon() throws OpcontrolException {
205
runOpcontrol(OPD_SHUTDOWN);
209
* Start data collection (will start daemon if necessary)
210
* @throws OpcontrolException
212
public void startCollection() throws OpcontrolException {
213
runOpcontrol(OPD_START_COLLECTION);
217
* Start daemon without starting profiling
218
* @throws OpcontrolException
220
public void startDaemon() throws OpcontrolException {
221
runOpcontrol(OPD_START_DAEMON);
225
* Stop data collection
226
* @throws OpcontrolException
228
public void stopCollection() throws OpcontrolException {
229
runOpcontrol(OPD_STOP_COLLECTION);
233
* Check status. returns true if any status was returned
234
* @throws OpcontrolException
236
public boolean status() throws OpcontrolException {
237
return runOpcontrol(OPD_HELP);
240
// Convenience function
241
private boolean runOpcontrol(String cmd) throws OpcontrolException {
242
ArrayList<String> list = new ArrayList<String>();
244
return runOpcontrol(list);
247
// Will add opcontrol program to beginning of args
248
// args: list of opcontrol arguments (not including opcontrol program itself)
250
* @return true if any output was produced on the error stream. Unfortunately
251
* this appears to currently be the only way we can tell if user correctly
252
* entered the password
254
private boolean runOpcontrol(ArrayList<String> args) throws OpcontrolException {
255
IProject project = Oprofile.getCurrentProject();
258
// If no linuxtools' toolchain is defined for this project, use the path for the
259
// link created by the installation script
260
if(project == null || LinuxtoolsPathProperty.getInstance().getLinuxtoolsPath(project).equals("")){
261
args.add(0, opcontrolProgram);
263
args.add(0, OPCONTROL_EXECUTABLE);
266
// Verbosity hack. If --start or --start-daemon, add verbosity, if set
267
String cmd = args.get(1);
268
if (verbosity.length() > 0 && (cmd.equals (OPD_START_COLLECTION) || cmd.equals(OPD_START_DAEMON))) {
272
String[] cmdArray = new String[args.size()];
273
args.toArray(cmdArray);
275
// Print what is passed on to opcontrol
276
if (OprofileCorePlugin.isDebugMode()) {
277
printOpcontrolCmd(cmdArray);
282
if(project == null || LinuxtoolsPathProperty.getInstance().getLinuxtoolsPath(project).equals("")){
283
p = Runtime.getRuntime().exec(cmdArray);
285
p = RuntimeProcessFactory.getFactory().sudoExec(cmdArray, project);
287
} catch (IOException ioe) {
288
throw new OpcontrolException(OprofileCorePlugin.createErrorStatus("opcontrolRun", ioe)); //$NON-NLS-1$
292
BufferedReader errout = new BufferedReader(new InputStreamReader(p.getErrorStream()));
293
BufferedReader stdout = new BufferedReader(new InputStreamReader(p.getInputStream()));
294
String errOutput = ""; //$NON-NLS-1$
295
String output = "", s; //$NON-NLS-1$
297
while ((s = errout.readLine()) != null) {
298
errOutput += s + "\n"; //$NON-NLS-1$
300
// Unfortunately, when piped through consolehelper stderr output
301
// is redirected to stdout. Need to read stdout and do some
302
// string matching in order to give some better advice as to how to
303
// alleviate the nmi_watchdog problem. See RH BZ #694631
304
while ((s = stdout.readLine()) != null) {
305
output += s + "\n"; //$NON-NLS-1$
310
int ret = p.waitFor();
312
OpControlErrorHandler errHandler = OpControlErrorHandler.getInstance();
313
OpcontrolException ex = errHandler.handleError(output, errOutput);
317
if (errOutput.length() != 0) {
321
} catch (IOException ioe) {
322
ioe.printStackTrace();
323
} catch (InterruptedException e) {
331
* Print to stdout what is passed on to opcontrol.
335
private void printOpcontrolCmd(String[] cmdArray) {
336
StringBuffer buf = new StringBuffer();
337
for (String token: cmdArray) {
341
System.out.println(OprofileCorePlugin.DEBUG_PRINT_PREFIX + buf.toString());
344
private static String findOpcontrol() throws OpcontrolException {
345
IProject project = Oprofile.getCurrentProject();
346
URL url = FileLocator.find(Platform.getBundle(OprofileCorePlugin
347
.getId()), new Path(OPCONTROL_REL_PATH), null);
351
return FileLocator.toFileURL(url).getPath();
352
} catch (IOException ignore) {
354
// If no linuxtools' toolchain is defined for this project and oprofile is not
355
// installed, throw exception
356
} else if(project == null || LinuxtoolsPathProperty.getInstance().getLinuxtoolsPath(project).equals("")){
357
throw new OpcontrolException(OprofileCorePlugin.createErrorStatus(
358
"opcontrolProvider", null)); //$NON-NLS-1$
364
// Convert the event into arguments for opcontrol
365
private void eventToArguments(ArrayList<String> args, OprofileDaemonEvent event) {
366
// Event spec: "EVENT:count:mask:profileKernel:profileUser"
367
String spec = new String(OPD_SETUP_EVENT);
368
spec += event.getEvent().getText();
369
spec += OPD_SETUP_EVENT_SEPARATOR;
370
spec += event.getResetCount();
371
spec += OPD_SETUP_EVENT_SEPARATOR;
372
spec += event.getEvent().getUnitMask().getMaskValue();
373
spec += OPD_SETUP_EVENT_SEPARATOR;
374
spec += (event.getProfileKernel() ? OPD_SETUP_EVENT_TRUE : OPD_SETUP_EVENT_FALSE);
375
spec += OPD_SETUP_EVENT_SEPARATOR;
376
spec += (event.getProfileUser() ? OPD_SETUP_EVENT_TRUE : OPD_SETUP_EVENT_FALSE);
380
// Convert the options into arguments for opcontrol
381
private void optionsToArguments(ArrayList<String> args, OprofileDaemonOptions options) {
382
// Add separate flags
383
int mask = options.getSeparateProfilesMask();
385
String separate = new String(OPD_SETUP_SEPARATE);
387
if (mask == OprofileDaemonOptions.SEPARATE_NONE) {
388
separate += OPD_SETUP_SEPARATE_NONE;
390
//note that opcontrol will nicely ignore the trailing comma
391
if ((mask & OprofileDaemonOptions.SEPARATE_LIBRARY) != 0)
392
separate += OPD_SETUP_SEPARATE_LIBRARY + OPD_SETUP_SEPARATE_SEPARATOR;
393
if ((mask & OprofileDaemonOptions.SEPARATE_KERNEL) != 0)
394
separate += OPD_SETUP_SEPARATE_KERNEL + OPD_SETUP_SEPARATE_SEPARATOR;
395
if ((mask & OprofileDaemonOptions.SEPARATE_THREAD) != 0)
396
separate += OPD_SETUP_SEPARATE_THREAD + OPD_SETUP_SEPARATE_SEPARATOR;
397
if ((mask & OprofileDaemonOptions.SEPARATE_CPU) != 0)
398
separate += OPD_SETUP_SEPARATE_CPU + OPD_SETUP_SEPARATE_SEPARATOR;
403
if (options.getKernelImageFile() == null || options.getKernelImageFile().length() == 0) {
404
args.add(OPD_KERNEL_NONE);
406
args.add(OPD_KERNEL_FILE + options.getKernelImageFile());
409
//image filter -- always non-null
410
args.add(OPD_SETUP_IMAGE + options.getBinaryImage());
413
args.add(OPD_CALLGRAPH_DEPTH + options.getCallgraphDepth());