~ubuntu-branches/ubuntu/trusty/eclipse-linuxtools/trusty

« back to all changes in this revision

Viewing changes to oprofile/org.eclipse.linuxtools.oprofile.core/src/org/eclipse/linuxtools/internal/oprofile/core/linux/LinuxOpcontrolProvider.java

  • Committer: Package Import Robot
  • Author(s): Jakub Adam
  • Date: 2012-06-29 12:07:30 UTC
  • Revision ID: package-import@ubuntu.com-20120629120730-bfri1xys1i71dpn6
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
7
 *
 
8
 * Contributors:
 
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;
 
13
 
 
14
import java.io.BufferedReader;
 
15
import java.io.File;
 
16
import java.io.FileNotFoundException;
 
17
import java.io.IOException;
 
18
import java.io.InputStreamReader;
 
19
import java.net.URL;
 
20
import java.util.ArrayList;
 
21
 
 
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;
 
35
 
 
36
/**
 
37
 * A class which encapsulates running opcontrol.
 
38
 */
 
39
public class LinuxOpcontrolProvider implements IOpcontrolProvider {
 
40
        private static final String OPCONTROL_EXECUTABLE = "opcontrol";
 
41
        
 
42
        // Location of opcontrol security wrapper
 
43
        private static final String OPCONTROL_REL_PATH = "natives/linux/scripts/" + OPCONTROL_EXECUTABLE; //$NON-NLS-1$
 
44
        
 
45
        private final String opcontrolProgram;
 
46
 
 
47
        // Initialize the Oprofile kernel module and oprofilefs
 
48
        private static final String OPD_INIT_MODULE = "--init"; //$NON-NLS-1$
 
49
        
 
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$
 
60
 
 
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$
 
66
 
 
67
        private static final String OPD_SETUP_IMAGE = "--image="; //$NON-NLS-1$
 
68
 
 
69
        private static final String OPD_CALLGRAPH_DEPTH = "--callgraph="; //$NON-NLS-1$
 
70
 
 
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$
 
74
        
 
75
        // Start the daemon process without starting data collection
 
76
        private static final String OPD_START_DAEMON = "--start-daemon"; //$NON-NLS-1$
 
77
        
 
78
        // Start collecting profiling data
 
79
        private static final String OPD_START_COLLECTION = "--start"; //$NON-NLS-1$
 
80
        
 
81
        // Flush the collected profiling data to disk
 
82
        private static final String OPD_DUMP = "--dump"; //$NON-NLS-1$
 
83
        
 
84
        // Stop data collection
 
85
        private static final String OPD_STOP_COLLECTION = "--stop"; //$NON-NLS-1$
 
86
        
 
87
        // Stop data collection and stop daemon
 
88
        private static final String OPD_SHUTDOWN = "--shutdown"; //$NON-NLS-1$
 
89
        
 
90
        // Clear out data from current session
 
91
        private static final String OPD_RESET = "--reset"; //$NON-NLS-1$
 
92
        
 
93
        // Unload the oprofile kernel module and oprofilefs
 
94
        private static final String OPD_DEINIT_MODULE = "--deinit"; //$NON-NLS-1$
 
95
        
 
96
        // Logging verbosity. Specified with setupDaemon.
 
97
        //--verbosity=all generates WAY too much stuff in the log
 
98
        private String verbosity = ""; //$NON-NLS-1$
 
99
        
 
100
        
 
101
        public LinuxOpcontrolProvider() throws OpcontrolException {
 
102
                opcontrolProgram = findOpcontrol();
 
103
        }
 
104
 
 
105
        /**
 
106
         * Unload the kernel module and oprofilefs
 
107
         * @throws OpcontrolException
 
108
         */
 
109
        public void deinitModule() throws OpcontrolException {
 
110
                runOpcontrol(OPD_DEINIT_MODULE);
 
111
        }
 
112
        
 
113
        /**
 
114
         * Dump collected profiling data
 
115
         * @throws OpcontrolException
 
116
         */
 
117
        public void dumpSamples() throws OpcontrolException {
 
118
                runOpcontrol(OPD_DUMP);
 
119
        }
 
120
        
 
121
        /**
 
122
         * Loads the kernel module and oprofilefs
 
123
         * @throws OpcontrolException
 
124
         */
 
125
        public void initModule() throws OpcontrolException {
 
126
                runOpcontrol(OPD_INIT_MODULE);
 
127
        }
 
128
        
 
129
        /**
 
130
         * Clears out data from current session
 
131
         * @throws OpcontrolException
 
132
         */
 
133
        public void reset() throws OpcontrolException {
 
134
                runOpcontrol(OPD_RESET);
 
135
        }
 
136
        
 
137
        /**
 
138
         * Saves the current ("default") session
 
139
         * @param name  the name to which to save the session
 
140
         * @throws OpcontrolException
 
141
         */
 
142
        public void saveSession(String name) throws OpcontrolException {
 
143
                SessionManager sessMan;
 
144
                try {
 
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);
 
151
                                p.waitFor();
 
152
                        }
 
153
                        sessMan.write();
 
154
                } catch (FileNotFoundException e) {
 
155
                        //intentionally blank
 
156
                        //during a save, the session file will exist
 
157
                } catch (IOException e) {
 
158
                        e.printStackTrace();
 
159
                } catch (InterruptedException e) {
 
160
                        e.printStackTrace();
 
161
                }
 
162
        }
 
163
        
 
164
        /**
 
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
 
169
         */
 
170
        public void deleteSession (String sessionName, String eventName) throws OpcontrolException {
 
171
                File file = new File (SessionManager.OPXML_PREFIX + SessionManager.MODEL_DATA + eventName + sessionName);
 
172
                file.delete();
 
173
                SessionManager sessMan = new SessionManager(SessionManager.SESSION_LOCATION);
 
174
                sessMan.removeSession(sessionName, eventName);
 
175
                sessMan.write();
 
176
        }
 
177
 
 
178
        /**
 
179
         * Give setup aruments
 
180
         * @param args  list of parameters for daemon
 
181
         * @throws OpcontrolException
 
182
         */
 
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>();
 
186
                args.add(OPD_SETUP);
 
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);
 
191
                        } else {
 
192
                                for (int i = 0; i < events.length; ++i) {
 
193
                                        eventToArguments(args, events[i]);
 
194
                                }
 
195
                        }
 
196
                }
 
197
                runOpcontrol(args);
 
198
        }
 
199
        
 
200
        /**
 
201
         * Stop data collection and remove daemon
 
202
         * @throws OpcontrolException
 
203
         */
 
204
        public void shutdownDaemon() throws OpcontrolException {
 
205
                runOpcontrol(OPD_SHUTDOWN);
 
206
        }
 
207
        
 
208
        /**
 
209
         * Start data collection (will start daemon if necessary)
 
210
         * @throws OpcontrolException
 
211
         */
 
212
        public void startCollection() throws OpcontrolException {
 
213
                runOpcontrol(OPD_START_COLLECTION);
 
214
        }
 
215
        
 
216
        /**
 
217
         * Start daemon without starting profiling
 
218
         * @throws OpcontrolException
 
219
         */
 
220
        public void startDaemon() throws OpcontrolException {
 
221
                runOpcontrol(OPD_START_DAEMON);
 
222
        }
 
223
        
 
224
        /**
 
225
         * Stop data collection
 
226
         * @throws OpcontrolException
 
227
         */
 
228
        public void stopCollection() throws OpcontrolException {
 
229
                runOpcontrol(OPD_STOP_COLLECTION);
 
230
        }
 
231
 
 
232
        /**
 
233
         * Check status. returns true if any status was returned
 
234
         * @throws OpcontrolException
 
235
         */
 
236
        public boolean status() throws OpcontrolException {
 
237
                return runOpcontrol(OPD_HELP);
 
238
        }
 
239
        
 
240
        // Convenience function
 
241
        private boolean runOpcontrol(String cmd) throws OpcontrolException {
 
242
                ArrayList<String> list = new ArrayList<String>();
 
243
                list.add(cmd);
 
244
                return runOpcontrol(list);
 
245
        }
 
246
        
 
247
        // Will add opcontrol program to beginning of args
 
248
        // args: list of opcontrol arguments (not including opcontrol program itself)
 
249
        /**
 
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
 
253
         */
 
254
        private boolean runOpcontrol(ArrayList<String> args) throws OpcontrolException {        
 
255
                IProject project = Oprofile.getCurrentProject();
 
256
                
 
257
                
 
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);
 
262
                } else{
 
263
                        args.add(0, OPCONTROL_EXECUTABLE);
 
264
                }
 
265
 
 
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))) {
 
269
                        args.add(verbosity);
 
270
                }
 
271
                
 
272
                String[] cmdArray = new String[args.size()];
 
273
                args.toArray(cmdArray);
 
274
                
 
275
                // Print what is passed on to opcontrol
 
276
                if (OprofileCorePlugin.isDebugMode()) {
 
277
                        printOpcontrolCmd(cmdArray);
 
278
                }
 
279
                
 
280
                Process p = null;
 
281
                try {
 
282
                        if(project == null || LinuxtoolsPathProperty.getInstance().getLinuxtoolsPath(project).equals("")){
 
283
                                p = Runtime.getRuntime().exec(cmdArray);
 
284
                        } else{
 
285
                                p = RuntimeProcessFactory.getFactory().sudoExec(cmdArray, project);
 
286
                        }
 
287
                } catch (IOException ioe) {                     
 
288
                        throw new OpcontrolException(OprofileCorePlugin.createErrorStatus("opcontrolRun", ioe)); //$NON-NLS-1$
 
289
                }
 
290
                
 
291
                if (p != null) {
 
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$
 
296
                        try {
 
297
                                while ((s = errout.readLine()) != null) {
 
298
                                        errOutput += s + "\n"; //$NON-NLS-1$
 
299
                                }
 
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$
 
306
                                }
 
307
                                stdout.close();
 
308
                                errout.close();
 
309
 
 
310
                                int ret = p.waitFor();
 
311
                                if (ret != 0) {
 
312
                                        OpControlErrorHandler errHandler = OpControlErrorHandler.getInstance();
 
313
                                        OpcontrolException ex = errHandler.handleError(output, errOutput);
 
314
                                        throw ex;
 
315
                                }
 
316
                                
 
317
                                if (errOutput.length() != 0) {
 
318
                                        return true;
 
319
                                }
 
320
                                
 
321
                        } catch (IOException ioe) { 
 
322
                                ioe.printStackTrace();
 
323
                        } catch (InterruptedException e) {
 
324
                                e.printStackTrace();
 
325
                        }
 
326
                }
 
327
                return false;
 
328
        }
 
329
 
 
330
        /**
 
331
         * Print to stdout what is passed on to opcontrol.
 
332
         * 
 
333
         * @param cmdArray
 
334
         */
 
335
        private void printOpcontrolCmd(String[] cmdArray) {
 
336
                StringBuffer buf = new StringBuffer();
 
337
                for (String token: cmdArray) {
 
338
                        buf.append(token);
 
339
                        buf.append(" ");
 
340
                }
 
341
                System.out.println(OprofileCorePlugin.DEBUG_PRINT_PREFIX + buf.toString());
 
342
        }
 
343
        
 
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);
 
348
 
 
349
                if (url != null) {
 
350
                        try {
 
351
                                return FileLocator.toFileURL(url).getPath();
 
352
                        } catch (IOException ignore) {
 
353
                        }
 
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$
 
359
                }
 
360
 
 
361
                return null;
 
362
        }      
 
363
 
 
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);
 
377
                args.add(spec);
 
378
        }
 
379
        
 
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();
 
384
 
 
385
                String separate = new String(OPD_SETUP_SEPARATE);
 
386
                
 
387
                if (mask == OprofileDaemonOptions.SEPARATE_NONE) {
 
388
                        separate += OPD_SETUP_SEPARATE_NONE;
 
389
                } else {
 
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;
 
399
                }
 
400
                args.add(separate);
 
401
                
 
402
                // Add kernel image
 
403
                if (options.getKernelImageFile() == null || options.getKernelImageFile().length() == 0) {
 
404
                        args.add(OPD_KERNEL_NONE);
 
405
                } else {
 
406
                        args.add(OPD_KERNEL_FILE + options.getKernelImageFile());
 
407
                }
 
408
 
 
409
                //image filter -- always non-null
 
410
                args.add(OPD_SETUP_IMAGE + options.getBinaryImage());
 
411
                
 
412
                //callgraph depth
 
413
                args.add(OPD_CALLGRAPH_DEPTH + options.getCallgraphDepth());
 
414
        }
 
415
 
 
416
}