Introduce GDB Tracepoint Analysis feature
[deliverable/tracecompass.git] / org.eclipse.linuxtools.gdbtrace.core / src / org / eclipse / linuxtools / internal / gdbtrace / trace / DsfGdbAdaptor.java
CommitLineData
6de2f761
PT
1/*******************************************************************************
2 * Copyright (c) 2011, 2013 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *
9 * Contributors:
10 * Marc Dumais - Initial implementation
11 * Francois Chouinard - Misc improvements, DSF signal handling, dynamic experiment
12 * Patrick Tasse - Updated for TMF 2.0
13 *******************************************************************************/
14
15package org.eclipse.linuxtools.internal.gdbtrace.trace;
16
17import java.util.HashMap;
18import java.util.Hashtable;
19import java.util.List;
20import java.util.Map;
21import java.util.concurrent.ExecutionException;
22import java.util.concurrent.RejectedExecutionException;
23
24import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
25import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
26import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
27import org.eclipse.cdt.dsf.concurrent.Query;
28import org.eclipse.cdt.dsf.datamodel.DMContexts;
29import org.eclipse.cdt.dsf.datamodel.IDMContext;
30import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
31import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
32import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
33import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
34import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
35import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
36import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin;
37import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch;
38import org.eclipse.cdt.dsf.gdb.service.GDBTraceControl_7_2.TraceRecordSelectedChangedEvent;
39import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl;
40import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMContext;
41import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordDMData;
42import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceRecordSelectedChangedDMEvent;
43import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData;
44import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext;
45import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
46import org.eclipse.cdt.dsf.mi.service.IMIProcesses;
47import org.eclipse.cdt.dsf.mi.service.MIBreakpointDMData;
48import org.eclipse.cdt.dsf.mi.service.MIBreakpoints;
49import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
50import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo;
51import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
52import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
53import org.eclipse.cdt.dsf.service.DsfServicesTracker;
54import org.eclipse.cdt.dsf.service.DsfSession;
55import org.eclipse.core.resources.IFile;
56import org.eclipse.core.resources.IMarker;
57import org.eclipse.core.runtime.CoreException;
58import org.eclipse.core.runtime.IAdaptable;
59import org.eclipse.core.runtime.IPath;
60import org.eclipse.core.runtime.IStatus;
61import org.eclipse.core.runtime.Status;
62import org.eclipse.debug.core.DebugException;
63import org.eclipse.debug.core.DebugPlugin;
64import org.eclipse.debug.core.ILaunch;
65import org.eclipse.debug.core.ILaunchConfigurationType;
66import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
67import org.eclipse.debug.core.ILaunchesListener2;
68import org.eclipse.debug.internal.ui.viewers.model.provisional.ITreeModelViewer;
69import org.eclipse.debug.ui.AbstractDebugView;
70import org.eclipse.debug.ui.DebugUITools;
71import org.eclipse.debug.ui.IDebugUIConstants;
72import org.eclipse.debug.ui.contexts.DebugContextEvent;
73import org.eclipse.debug.ui.contexts.IDebugContextListener;
74import org.eclipse.jface.viewers.ISelection;
75import org.eclipse.jface.viewers.IStructuredSelection;
76import org.eclipse.jface.viewers.StructuredSelection;
77import org.eclipse.jface.viewers.Viewer;
78import org.eclipse.linuxtools.internal.gdbtrace.GdbTraceCorePlugin;
79import org.eclipse.linuxtools.internal.gdbtrace.event.GdbTraceEvent;
80import org.eclipse.linuxtools.internal.gdbtrace.event.GdbTraceEventContent;
81import org.eclipse.linuxtools.tmf.core.event.ITmfEventType;
82import org.eclipse.linuxtools.tmf.core.event.TmfEventField;
83import org.eclipse.linuxtools.tmf.core.event.TmfEventType;
84import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimestamp;
85import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace;
86import org.eclipse.linuxtools.tmf.core.trace.TmfExperiment;
87import org.eclipse.linuxtools.tmf.ui.editors.ITmfTraceEditor;
88import org.eclipse.swt.widgets.Display;
89import org.eclipse.ui.IEditorInput;
90import org.eclipse.ui.IEditorPart;
91import org.eclipse.ui.IEditorReference;
92import org.eclipse.ui.IFileEditorInput;
93import org.eclipse.ui.IViewPart;
94import org.eclipse.ui.IWorkbench;
95import org.eclipse.ui.IWorkbenchPage;
96import org.eclipse.ui.IWorkbenchWindow;
97import org.eclipse.ui.PlatformUI;
98import org.eclipse.ui.ide.IDE;
99
100/**
101 * Adaptor to access GDB Tracepoint frames, previously collected and saved in a
102 * file by GDB. One instance of this maps to a single DSF-GDB session.
103 * <p>
104 * This class offers the functions of starting a post-mortem GDB session with a
105 * tracepoint data file, navigate the data frames and return the data contained
106 * in a given tracepoint frame.
107 * <p>
108 * Note: GDB 7.2 or later is required to handle tracepoints
109 *
110 * @author Marc Dumais
111 * @author Francois Chouinard
112 */
113@SuppressWarnings("restriction")
114public class DsfGdbAdaptor {
115
116 private GdbTrace fGdbTrace;
117
118 private int fNumberOfFrames = 0;
119
120 private ILaunch fLaunch;
121 private boolean isTerminating;
122 private DsfSession fDsfSession = null;
123 private String fSessionId;
124
125 private String tracedExecutable = ""; //$NON-NLS-1$
126
127 private String gdb72Executable = ""; //$NON-NLS-1$
128 private String fTraceFilePath = ""; //$NON-NLS-1$
129 private String fTraceFile = ""; //$NON-NLS-1$
130 private String sourceLocator = ""; //$NON-NLS-1$
131
132 // To save tracepoints detailed info. The key is the rank of the
133 // breakpoint (tracepoint is a kind of breakpoint)
134 private Map<Integer, MIBreakpointDMData> fTpInfo = new HashMap<Integer, MIBreakpointDMData>();
135
136 private TmfEventType tmfEventType = new TmfEventType(ITmfEventType.DEFAULT_CONTEXT_ID, "GDB Tracepoint", TmfEventField.makeRoot(new String[] { "Content" })); //$NON-NLS-1$ //$NON-NLS-2$
137
138 @SuppressWarnings("unused")
139 private static DsfGdbPlatformEventListener fPlatformEventListener = new DsfGdbPlatformEventListener();
140
141 /**
142 * <b><u>DsfGdbPlatformEventListener</u></b>
143 * <p>
144 * Listens to platform and DSF-GDB events that announce important events
145 * about the launchers or a change in debug context that we might need to
146 * react-to.
147 * <p>
148 * @author Francois Chouinard
149 */
150 private static class DsfGdbPlatformEventListener implements
151 ILaunchesListener2, IDebugContextListener {
152
153 /**
154 *
155 */
156 public DsfGdbPlatformEventListener() {
157 Display.getDefault().syncExec(new Runnable() {
158 @Override
159 public void run() {
160 DebugPlugin.getDefault().getLaunchManager().addLaunchListener(DsfGdbPlatformEventListener.this);
161 IWorkbench wb = PlatformUI.getWorkbench();
162 IWorkbenchWindow win = wb.getActiveWorkbenchWindow();
163 DebugUITools.getDebugContextManager().getContextService(win).addDebugContextListener(DsfGdbPlatformEventListener.this);
164 }
165 });
166 }
167
168 @Override
169 public synchronized void launchesRemoved(ILaunch[] launches) {
170 }
171
172 @Override
173 public synchronized void launchesAdded(ILaunch[] launches) {
174 }
175
176 @Override
177 public synchronized void launchesChanged(ILaunch[] launches) {
178 }
179
180 @Override
181 public synchronized void launchesTerminated(ILaunch[] launches) {
182 for (ILaunch launch : launches) {
183 String sessionId = ((GdbLaunch) launch).getSession().getId();
184 closeGdbTraceEditor(sessionId);
185 }
186 }
187
188 private String fCurrentSessionId = ""; //$NON-NLS-1$
189 @Override
190 public void debugContextChanged(DebugContextEvent event) {
191 ISelection selection = event.getContext();
192 if (selection instanceof IStructuredSelection) {
193 List<?> eventContextList = ((IStructuredSelection) selection).toList();
194 for (Object eventContext : eventContextList) {
195 if (eventContext instanceof IAdaptable) {
196 IDMContext context = (IDMContext) ((IAdaptable) eventContext).getAdapter(IDMContext.class);
197 if (context != null) {
198 String sessionId;
199 synchronized(fCurrentSessionId) {
200 sessionId = context.getSessionId();
201 if (sessionId.equals(fCurrentSessionId)) {
202 return;
203 }
204 }
205 fCurrentSessionId = sessionId;
206 // Get the current trace record
207 final DsfExecutor executor = DsfSession.getSession(sessionId).getExecutor();
208 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), sessionId);
209 Query<ITraceRecordDMContext> getCurrentRecordQuery = new Query<ITraceRecordDMContext>() {
210 @Override
211 public void execute(final DataRequestMonitor<ITraceRecordDMContext> queryRm) {
212 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
213 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
214 if (traceControl != null && commandControl != null) {
215 ITraceTargetDMContext traceContext = (ITraceTargetDMContext) commandControl.getContext();
216 traceControl.getCurrentTraceRecordContext(traceContext, queryRm);
217 } else {
218 queryRm.done();
219 }
220 }
221 };
222 try {
223 executor.execute(getCurrentRecordQuery);
224 ITraceRecordDMContext record = getCurrentRecordQuery.get();
225 // If we get a trace record, it means that this can be used
226 if (record != null && record.getRecordId() != null) {
227 int recordId = Integer.parseInt(record.getRecordId());
228 selectGdbTraceEditor(sessionId, recordId);
229 break;
230 }
231 } catch (InterruptedException e) {
232 } catch (java.util.concurrent.ExecutionException e) {
233 } catch (RejectedExecutionException e) {
234 } finally {
235 tracker.dispose();
236 }
237 // else not DSF-GDB or GDB < 7.2
238 }
239 }
240 // else not DSF
241 }
242 }
243 }
244 } // class DsfGdbPlatformEventListener
245
246 /**
247 * Constructor for DsfGdbAdaptor. This is used when we want to launch a
248 * DSF-GDB session and use it as source in our tracing perspective.
249 * i.e. when launching from the Project Explorer
250 *
251 * @param trace the GDB trace
252 * @param gdbExec GDB executable. Must be version 7.2 or later.
253 * @param traceFile previously generated GDB tracepoint file
254 * @param tracedExecutable executable that was used to generate the tracefile
255 * workspace, where the traced executable was taken from.
256 */
257 public DsfGdbAdaptor(GdbTrace trace, String gdbExec, String traceFile, String tracedExecutable) {
258 this.fGdbTrace = trace;
259 this.gdb72Executable = gdbExec;
260 this.fTraceFilePath = traceFile;
261 this.fTraceFile = traceFile.substring(traceFile.lastIndexOf(IPath.SEPARATOR) + 1);
262 this.tracedExecutable = tracedExecutable;
263
264 try {
265 launchDGBPostMortemTrace();
266 } catch (CoreException e) {
267 e.printStackTrace();
268 }
269 }
270
271 /**
272 * Builds a launcher and launches a Post-mortem GDB session, based on a
273 * previously-gathered GDB Tracepoint file. The information used to
274 * create the launcher is provided to the constructor of this class,
275 * at instantiation time.
276 * <p>
277 * Note: Requires GDB 7.2 or later
278 */
279 private void launchDGBPostMortemTrace() throws CoreException {
280
281 ILaunchConfigurationType configType = DebugPlugin
282 .getDefault()
283 .getLaunchManager()
284 .getLaunchConfigurationType("org.eclipse.cdt.launch.postmortemLaunchType"); //$NON-NLS-1$
285 ILaunchConfigurationWorkingCopy wc = configType.newInstance(null, fTraceFile);
286
287 wc.setAttribute("org.eclipse.cdt.dsf.gdb.DEBUG_NAME", gdb72Executable); //$NON-NLS-1$
288 wc.setAttribute("org.eclipse.cdt.dsf.gdb.POST_MORTEM_TYPE", "TRACE_FILE"); //$NON-NLS-1$ //$NON-NLS-2$
289 wc.setAttribute("org.eclipse.cdt.launch.ATTR_BUILD_BEFORE_LAUNCH_ATTR", 0); //$NON-NLS-1$
290 wc.setAttribute("org.eclipse.cdt.launch.COREFILE_PATH", fTraceFilePath); //$NON-NLS-1$
291 wc.setAttribute("org.eclipse.cdt.launch.DEBUGGER_START_MODE", "core"); //$NON-NLS-1$ //$NON-NLS-2$
292 wc.setAttribute("org.eclipse.cdt.launch.PROGRAM_NAME", tracedExecutable); //$NON-NLS-1$
293 // So that the GDB launch is synchronous
294 wc.setAttribute("org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND", false); //$NON-NLS-1$
295
296 if (!sourceLocator.isEmpty()) {
297 wc.setAttribute("org.eclipse.debug.core.source_locator_memento", sourceLocator); //$NON-NLS-1$
298 }
299
300 // Launch GDB session
301 fLaunch = wc.doSave().launch("debug", null); //$NON-NLS-1$
302 isTerminating = false;
303
304 if (fLaunch instanceof GdbLaunch) {
305 fSessionId = ((GdbLaunch) fLaunch).getSession().getId();
306 }
307
308 fDsfSession = ((GdbLaunch) fLaunch).getSession();
309 fDsfSession.addServiceEventListener(this, null);
310
311 // Find the number of frames contained in the tracepoint file
312 fNumberOfFrames = findNumFrames();
313 }
314
315 /**
316 * This method terminates the current DSF-GDB session
317 */
318 public void dispose() {
319 if (fLaunch != null && fLaunch.canTerminate() && !isTerminating) {
320 isTerminating = true;
321 GdbUIPlugin.getShell().getDisplay().asyncExec(new Runnable() {
322 @Override
323 public void run() {
324 try {
325 fLaunch.terminate();
326 } catch (DebugException e) {
327 e.printStackTrace();
328 }
329 fLaunch = null;
330 }
331 });
332 }
333 }
334
335 /**
336 * This method will try (once per call) to get the number of GDB tracepoint
337 * frames for the current session, from DSF-GDB, until it succeeds at
338 * getting an amount different than zero.
339 *
340 * @return The number of frames in current session or zero if unsuccessful
341 */
342 public int getNumberOfFrames() {
343 if (fNumberOfFrames == 0) {
344 fNumberOfFrames = findNumFrames();
345 }
346 return fNumberOfFrames;
347 }
348
349
350 /**
351 * Wrapper around the selecting of a frame and the reading of its
352 * information. this is a work-around for the potential problem of
353 * concurrent access to these functions by more than one thread,
354 * where two clients might interfere with each other.
355 * <p>
356 * Note: We also try to get the tracepoint info here, if it's not
357 * already filled-in.
358 *
359 * @param rank a long corresponding to the number of the frame to be
360 * selected and read
361 * @return A GdbTraceEvent object, or null in case of failure.
362 */
363 public synchronized GdbTraceEvent selectAndReadFrame(final long rank) {
364 // lazy init of tracepoints info
365 if(fTpInfo.isEmpty()) {
366 getTracepointInfo();
367 }
368 if (selectDataFrame(rank, false)) {
369 GdbTraceEvent event = getTraceFrameData(rank);
370 long ts = event.getTimestamp().getValue();
371 if (ts == rank) {
372 return event;
373 }
374 }
375 return null;
376 }
377
378
379 /**
380 * This class implements a best-effort look-up of the detailed tracepoint
381 * information (source code filename, line number, etc...).
382 */
383 private void getTracepointInfo() {
384
385 // Get the latest executor/service tracker
386 final DsfExecutor executor = DsfSession.getSession(fSessionId).getExecutor();
387 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
388
389 Query<Object> selectRecordQuery = new Query<Object>() {
390 @Override
391 public void execute(final DataRequestMonitor<Object> drm) {
392
393 // A breakpoint is no longer GDB-global but tied to a specific process
394 // So we need to find our process and the ask for its breakpoints
395 IMIProcesses procService = tracker.getService(IMIProcesses.class);
396 final ICommandControlService cmdControl = tracker.getService(ICommandControlService.class);
397 if (procService == null || cmdControl == null) {
398 drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
399 drm.done();
400 return;
401 }
402
403 ITraceTargetDMContext context = (ITraceTargetDMContext) cmdControl.getContext();
404 ICommandControlDMContext cmdControlDMC = DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
405
406 procService.getProcessesBeingDebugged(
407 cmdControlDMC,
408 new DataRequestMonitor<IDMContext[]>(executor, drm) {
409 @Override
410 protected void handleSuccess() {
411 assert getData() != null;
412 assert getData().length == 1;
413 if (getData() == null || getData().length < 1) {
414 drm.done();
415 return;
416 }
417
418 // Choose the first process for now, until gdb can tell
419 // us which process the trace record is associated with.
420 IContainerDMContext containerDMC = (IContainerDMContext)(getData()[0]);
421 IBreakpointsTargetDMContext bpTargetDMC = DMContexts.getAncestorOfType(containerDMC , IBreakpointsTargetDMContext.class);
422
423 CommandFactory cmdFactory = tracker.getService(IMICommandControl.class).getCommandFactory();
424 IBreakpoints bpService = tracker.getService(MIBreakpoints.class);
425 if (cmdFactory == null || bpService == null) {
426 drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
427 drm.done();
428 return;
429 }
430
431 // Execute the command
432 cmdControl.queueCommand(cmdFactory.createMIBreakList(bpTargetDMC),
433 new DataRequestMonitor<MIBreakListInfo>(executor, drm) {
434 @Override
435 protected void handleSuccess() {
436 MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
437 for (int i = 0; i < breakpoints.length; i++) {
438 MIBreakpointDMData breakpoint = new MIBreakpointDMData(breakpoints[i]);
439 String type = breakpoint.getBreakpointType();
440 // Only save info if the current breakpoint is of type tracepoint
441 if(type.compareTo(MIBreakpoints.TRACEPOINT) == 0 ) {
442 fTpInfo.put(new Integer(breakpoint.getReference()), breakpoint);
443 }
444 }
445 drm.done();
446 }
447 });
448 }
449 });
450 }
451 };
452 try {
453 executor.execute(selectRecordQuery);
454 selectRecordQuery.get(); // blocks
455 } catch (RejectedExecutionException e) {
456
457 } catch (InterruptedException e) {
458 // TODO Auto-generated catch block
459 e.printStackTrace();
460 } catch (ExecutionException e) {
461 // TODO Auto-generated catch block
462 e.printStackTrace();
463 } finally {
464 tracker.dispose();
465 }
466 }
467
468 /**
469 * Returns the number of frames contained in currently loaded tracepoint GDB
470 * session.
471 * <p>
472 * Note: A postmortem GDB session must be started before calling
473 * this method
474 *
475 * @return the number of frames contained in currently loaded tracepoint GDB
476 * session or zero in case of error
477 */
478 private synchronized int findNumFrames() {
479 int frameNum = 0;
480
481 if (DsfSession.getSession(fSessionId) == null) {
482 return 0;
483 }
484
485 final DsfExecutor executor = DsfSession.getSession(fSessionId)
486 .getExecutor();
487 final DsfServicesTracker tracker = new DsfServicesTracker(
488 GdbTraceCorePlugin.getBundleContext(), fSessionId);
489
490 Query<ITraceStatusDMData> selectRecordQuery = new Query<ITraceStatusDMData>() {
491 @Override
492 public void execute(
493 final DataRequestMonitor<ITraceStatusDMData> queryRm) {
494 final IGDBTraceControl traceControl = tracker
495 .getService(IGDBTraceControl.class);
496
497 final ICommandControlService commandControl = tracker
498 .getService(ICommandControlService.class);
499 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl
500 .getContext();
501
502 if (traceControl != null) {
503 traceControl.getTraceStatus(dmc, queryRm);
504 } else {
505 queryRm.done();
506 }
507 }
508 };
509 try {
510 executor.execute(selectRecordQuery);
511 ITraceStatusDMData data = selectRecordQuery.get(); // blocks
512 frameNum = data.getNumberOfCollectedFrame();
513 } catch (InterruptedException e) {
514
515 } catch (java.util.concurrent.ExecutionException e) {
516
517 } catch (RejectedExecutionException e) {
518
519 } finally {
520 tracker.dispose();
521 }
522 return frameNum;
523 }
524
525 /**
526 * This method uses the DSF-GDB interface to select a given frame number
527 * in the current GDB tracepoint session.
528 *
529 * @param rank the rank of the tracepoint frame to select.
530 * @param update true if visualization should be updated
531 * @return boolean true if select worked.
532 */
533 public boolean selectDataFrame(final long rank, final boolean update) {
534 boolean status = true;
535
536 final DsfSession dsfSession = DsfSession.getSession(fSessionId);
537 if (dsfSession == null) {
538 return false;
539 }
540
541 if (update) {
542 /*
543 * Clear the selection to ensure that the new selection is not
544 * prevented from overriding the current selection by the DSF
545 * selection policy. This could be removed when DSF provides
546 * an API to force the trace record selection in the Debug view.
547 */
548 Display.getDefault().syncExec(new Runnable() {
549 @Override
550 public void run() {
551 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
552 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
553 IViewPart vp = wbPage.findView(IDebugUIConstants.ID_DEBUG_VIEW);
554 if (vp instanceof AbstractDebugView) {
555 Viewer viewer = ((AbstractDebugView) vp).getViewer();
556 if (viewer instanceof ITreeModelViewer) {
557 ((ITreeModelViewer) viewer).setSelection(StructuredSelection.EMPTY, false, true);
558 }
559 }
560 }
561 }
562 }
563 });
564 }
565
566 final DsfExecutor executor = dsfSession.getExecutor();
567 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
568
569 Query<Object> selectRecordQuery = new Query<Object>() {
570 @Override
571 public void execute(final DataRequestMonitor<Object> queryRm) {
572 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
573
574 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
575 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl.getContext();
576
577 if (traceControl != null) {
578 ITraceRecordDMContext newCtx = traceControl.createTraceRecordContext(dmc, Integer.toString((int) rank));
579 if (update) {
580 dsfSession.dispatchEvent(new TraceRecordSelectedChangedEvent(newCtx), new Hashtable<String, String>());
581 }
582 traceControl.selectTraceRecord(newCtx, queryRm);
583 } else {
584 queryRm.done();
585 }
586 }
587 };
588 try {
589 executor.execute(selectRecordQuery);
590 selectRecordQuery.get(); // blocks
591 } catch (InterruptedException e) {
592 status = false;
593 } catch (java.util.concurrent.ExecutionException e) {
594 status = false;
595 } catch (RejectedExecutionException e) {
596 status = false;
597 } finally {
598 tracker.dispose();
599 }
600 return status;
601 }
602
603 /**
604 * This method uses DSF-GDB to read the currently selected GDB tracepoint
605 * data frame. An object of type GdbTraceEvent is build based on the
606 * information contained in the data frame and returned to the caller.
607 * <p>
608 * NOTE : A frame must be selected before calling this method!
609 *
610 * @param rank for internal purposes - does <b>not</b> control which
611 * frame will be read!
612 * @return parsed tp frame, in the form of a GdbTraceEvent
613 */
614 private GdbTraceEvent getTraceFrameData(final long rank) {
615
616 if (DsfSession.getSession(fSessionId) == null) {
617 return null;
618 }
619
620 final DsfExecutor executor = DsfSession.getSession(fSessionId).getExecutor();
621 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
622
623 Query<ITraceRecordDMData> getFrameDataQuery = new Query<ITraceRecordDMData>() {
624 @Override
625 public void execute(final DataRequestMonitor<ITraceRecordDMData> rm) {
626 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
627
628 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
629 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl.getContext();
630
631 if (traceControl != null) {
632 traceControl.getCurrentTraceRecordContext(dmc,
633 new DataRequestMonitor<ITraceRecordDMContext>(executor, rm) {
634 @Override
635 protected void handleSuccess() {
636 traceControl.getTraceRecordData(getData(), rm);
637 }
638 });
639 } else {
640 rm.done();
641 }
642 }
643 };
644 try {
645 // Execute the above query
646 executor.execute(getFrameDataQuery);
647 ITraceRecordDMData data = getFrameDataQuery.get(); // blocking call
648
649 if (data == null) {
650 return null;
651 }
652
653 String ts = data.getTimestamp();
654 if (ts == null) {
655 ts = "0"; //$NON-NLS-1$
656 }
657
658 // get corresponding TP data
659 String tmfEventRef;
660 MIBreakpointDMData bp = fTpInfo.get(Integer.valueOf(data.getTracepointNumber()));
661 if (bp != null) {
662 tmfEventRef = bp.getFileName() + ":" + bp.getLineNumber() + " :: " + bp.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
663 }
664 else {
665 tmfEventRef = tracedExecutable;
666 }
667
668 GdbTraceEventContent evContent = new GdbTraceEventContent(
669 data.getContent(),
670 Integer.parseInt(data.getTracepointNumber()),
671 Integer.parseInt(data.getRecordId()));
672
673 GdbTraceEvent ev = new GdbTraceEvent(fGdbTrace,
674 new TmfTimestamp(Integer.parseInt(data.getRecordId())),
675 "Tracepoint: " + data.getTracepointNumber() + ", Frame: " + data.getRecordId(), //$NON-NLS-1$ //$NON-NLS-2$
676 tmfEventType,
677 evContent,
678 tmfEventRef);
679
680 return ev;
681
682 } catch (InterruptedException e) {
683 return createExceptionEvent(rank, "Interruption exception"); //$NON-NLS-1$
684 } catch (java.util.concurrent.ExecutionException e) {
685 return createExceptionEvent(rank, "GDB exception"); //$NON-NLS-1$
686 } catch (RejectedExecutionException e) {
687 return createExceptionEvent(rank, "Request rejected exception"); //$NON-NLS-1$
688 } catch (Exception e) {
689 return createExceptionEvent(rank, "General exception"); //$NON-NLS-1$
690 }
691
692 finally {
693 tracker.dispose();
694 }
695 }
696
697 /**
698 * This is a helper method for getTraceFrameData, to create for it a
699 * "best effort" GdbTraceEvent when a problem occurs during the reading.
700 *
701 * @param rank long containing the number of the frame where the problem occurred
702 * @param message String containing a brief explanation of problem.
703 * @return a GdbTraceEvent object, filled as best as possible
704 */
705 private GdbTraceEvent createExceptionEvent(final long rank, final String message) {
706 // get corresponding TP data
707 String tmfEventRef;
708 String tmfEventSrc;
709 MIBreakpointDMData bp = fTpInfo.get(rank);
710 if (bp != null) {
711 tmfEventRef = bp.getFileName() + ":" + bp.getLineNumber() + " :: " + bp.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
712 tmfEventSrc = bp.getFileName() + " :: " + bp.getFunctionName() + ", line: " + bp.getLineNumber(); //$NON-NLS-1$ //$NON-NLS-2$
713 }
714 else {
715 tmfEventRef = tracedExecutable;
716 tmfEventSrc = "Tracepoint: n/a"; //$NON-NLS-1$
717 }
718
719 GdbTraceEventContent evContent = new GdbTraceEventContent("ERROR: " + message, 0, 0); //$NON-NLS-1$
720
721 GdbTraceEvent ev = new GdbTraceEvent(fGdbTrace,
722 new TmfTimestamp(rank),
723 tmfEventSrc,
724 tmfEventType,
725 evContent,
726 tmfEventRef);
727
728 return ev;
729 }
730
731 /**
732 * @return DSF-GDB session id of the current session.
733 */
734 public String getSessionId() {
735 return fSessionId;
736 }
737
738 /**
739 * Handler method that catches the DSF "record selected changed" event.
740 * It in turn creates a TMF "time sync" signal.
741 * @param event TraceRecordSelectedChangedEvent: The DSF event.
742 */
743 @DsfServiceEventHandler
744 public void handleDSFRecordSelectedEvents(final ITraceRecordSelectedChangedDMEvent event) {
745 if (event instanceof TraceRecordSelectedChangedEvent) {
746 TraceRecordSelectedChangedEvent traceEvent = (TraceRecordSelectedChangedEvent) event;
747 ITraceRecordDMContext context = traceEvent.getDMContext();
748 final String reference = context.getRecordId();
749 if (reference != null) {
750 int recordId = Integer.parseInt(reference);
751 selectGdbTraceEditor(context.getSessionId(), recordId);
752 }
753 }
754 }
755
756 private static void closeGdbTraceEditor(final String sessionId) {
757 Display.getDefault().asyncExec(new Runnable() {
758 @Override
759 public void run() {
760 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
761 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
762 for (IEditorReference editorReference : wbPage.getEditorReferences()) {
763 IEditorPart editor = editorReference.getEditor(false);
764 if (editor instanceof ITmfTraceEditor) {
765 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
766 if (trace instanceof GdbTrace) {
767 if (((GdbTrace) trace).getDsfSessionId().equals(sessionId)) {
768 wbPage.closeEditor(editor, false);
769 }
770 }
771 }
772 }
773 }
774 }
775 }
776 });
777 }
778
779 private static void selectGdbTraceEditor(final String sessionId, final int recordId) {
780 Display.getDefault().asyncExec(new Runnable() {
781 @Override
782 public void run() {
783 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
784 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
785 for (IEditorReference editorReference : wbPage.getEditorReferences()) {
786 IEditorPart editor = editorReference.getEditor(false);
787 if (editor instanceof ITmfTraceEditor) {
788 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
789 if (trace instanceof GdbTrace) {
790 if (((GdbTrace) trace).getDsfSessionId().equals(sessionId)) {
791 wbPage.bringToTop(editor);
792 if (recordId != -1) {
793 gotoRank(editor, recordId);
794 }
795 return;
796 }
797 } else if (trace instanceof TmfExperiment) {
798 TmfExperiment experiment = (TmfExperiment) trace;
799 int nbTraces = experiment.getTraces().length;
800 for (int i = 0; i < nbTraces; i++) {
801 GdbTrace gdbTrace = (GdbTrace) experiment.getTraces()[i];
802 if (gdbTrace.getDsfSessionId().equals(sessionId)) {
803 wbPage.bringToTop(editor);
804 if (recordId != -1) {
805 int rank = recordId * nbTraces + i;
806 gotoRank(editor, rank);
807 }
808 return;
809 }
810 }
811 }
812 }
813 }
814 }
815 }
816 }
817 });
818 }
819
820 private static void gotoRank(IEditorPart editor, int rank) {
821 IEditorInput editorInput = editor.getEditorInput();
822 if (editorInput instanceof IFileEditorInput) {
823 IFile file = ((IFileEditorInput) editorInput).getFile();
824 try {
825 final IMarker marker = file.createMarker(IMarker.MARKER);
826 marker.setAttribute(IMarker.LOCATION, (Integer) rank);
827 IDE.gotoMarker(editor, marker);
828 marker.delete();
829 } catch (CoreException e) {
830 e.printStackTrace();
831 }
832 }
833 }
834}
This page took 0.096898 seconds and 5 git commands to generate.