gdbtrace: Build with Java 7
[deliverable/tracecompass.git] / org.eclipse.linuxtools.gdbtrace.core / src / org / eclipse / linuxtools / internal / gdbtrace / core / 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
ce800780 13 * Bernd Hufmann - Fixed deadlock during shutdown
6de2f761
PT
14 *******************************************************************************/
15
8343b1f5 16package org.eclipse.linuxtools.internal.gdbtrace.core.trace;
6de2f761
PT
17
18import java.util.HashMap;
19import java.util.Hashtable;
20import java.util.List;
21import java.util.Map;
22import java.util.concurrent.ExecutionException;
23import java.util.concurrent.RejectedExecutionException;
24
25import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
26import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
27import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
28import org.eclipse.cdt.dsf.concurrent.Query;
29import org.eclipse.cdt.dsf.datamodel.DMContexts;
30import org.eclipse.cdt.dsf.datamodel.IDMContext;
31import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
32import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
33import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
34import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
35import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
36import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
6de2f761
PT
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;
8343b1f5
PT
78import org.eclipse.linuxtools.internal.gdbtrace.core.GdbTraceCorePlugin;
79import org.eclipse.linuxtools.internal.gdbtrace.core.event.GdbTraceEvent;
80import org.eclipse.linuxtools.internal.gdbtrace.core.event.GdbTraceEventContent;
6de2f761
PT
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)
76faccfa 134 private Map<Integer, MIBreakpointDMData> fTpInfo = new HashMap<>();
6de2f761
PT
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;
ce800780
BH
321 try {
322 fLaunch.terminate();
323 } catch (DebugException e) {
324 e.printStackTrace();
325 }
326 fLaunch = null;
6de2f761
PT
327 }
328 }
329
330 /**
331 * This method will try (once per call) to get the number of GDB tracepoint
332 * frames for the current session, from DSF-GDB, until it succeeds at
333 * getting an amount different than zero.
334 *
335 * @return The number of frames in current session or zero if unsuccessful
336 */
337 public int getNumberOfFrames() {
338 if (fNumberOfFrames == 0) {
339 fNumberOfFrames = findNumFrames();
340 }
341 return fNumberOfFrames;
342 }
343
344
345 /**
346 * Wrapper around the selecting of a frame and the reading of its
347 * information. this is a work-around for the potential problem of
348 * concurrent access to these functions by more than one thread,
349 * where two clients might interfere with each other.
350 * <p>
351 * Note: We also try to get the tracepoint info here, if it's not
352 * already filled-in.
353 *
354 * @param rank a long corresponding to the number of the frame to be
355 * selected and read
356 * @return A GdbTraceEvent object, or null in case of failure.
357 */
358 public synchronized GdbTraceEvent selectAndReadFrame(final long rank) {
359 // lazy init of tracepoints info
360 if(fTpInfo.isEmpty()) {
361 getTracepointInfo();
362 }
363 if (selectDataFrame(rank, false)) {
364 GdbTraceEvent event = getTraceFrameData(rank);
365 long ts = event.getTimestamp().getValue();
366 if (ts == rank) {
367 return event;
368 }
369 }
370 return null;
371 }
372
373
374 /**
375 * This class implements a best-effort look-up of the detailed tracepoint
376 * information (source code filename, line number, etc...).
377 */
378 private void getTracepointInfo() {
379
380 // Get the latest executor/service tracker
381 final DsfExecutor executor = DsfSession.getSession(fSessionId).getExecutor();
382 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
383
384 Query<Object> selectRecordQuery = new Query<Object>() {
385 @Override
386 public void execute(final DataRequestMonitor<Object> drm) {
387
388 // A breakpoint is no longer GDB-global but tied to a specific process
389 // So we need to find our process and the ask for its breakpoints
390 IMIProcesses procService = tracker.getService(IMIProcesses.class);
391 final ICommandControlService cmdControl = tracker.getService(ICommandControlService.class);
392 if (procService == null || cmdControl == null) {
393 drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
394 drm.done();
395 return;
396 }
397
398 ITraceTargetDMContext context = (ITraceTargetDMContext) cmdControl.getContext();
399 ICommandControlDMContext cmdControlDMC = DMContexts.getAncestorOfType(context, ICommandControlDMContext.class);
400
401 procService.getProcessesBeingDebugged(
402 cmdControlDMC,
403 new DataRequestMonitor<IDMContext[]>(executor, drm) {
404 @Override
405 protected void handleSuccess() {
406 assert getData() != null;
407 assert getData().length == 1;
408 if (getData() == null || getData().length < 1) {
409 drm.done();
410 return;
411 }
412
413 // Choose the first process for now, until gdb can tell
414 // us which process the trace record is associated with.
415 IContainerDMContext containerDMC = (IContainerDMContext)(getData()[0]);
416 IBreakpointsTargetDMContext bpTargetDMC = DMContexts.getAncestorOfType(containerDMC , IBreakpointsTargetDMContext.class);
417
418 CommandFactory cmdFactory = tracker.getService(IMICommandControl.class).getCommandFactory();
419 IBreakpoints bpService = tracker.getService(MIBreakpoints.class);
420 if (cmdFactory == null || bpService == null) {
421 drm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Could not find necessary services", null)); //$NON-NLS-1$
422 drm.done();
423 return;
424 }
425
426 // Execute the command
427 cmdControl.queueCommand(cmdFactory.createMIBreakList(bpTargetDMC),
428 new DataRequestMonitor<MIBreakListInfo>(executor, drm) {
429 @Override
430 protected void handleSuccess() {
431 MIBreakpoint[] breakpoints = getData().getMIBreakpoints();
432 for (int i = 0; i < breakpoints.length; i++) {
433 MIBreakpointDMData breakpoint = new MIBreakpointDMData(breakpoints[i]);
434 String type = breakpoint.getBreakpointType();
435 // Only save info if the current breakpoint is of type tracepoint
436 if(type.compareTo(MIBreakpoints.TRACEPOINT) == 0 ) {
437 fTpInfo.put(new Integer(breakpoint.getReference()), breakpoint);
438 }
439 }
440 drm.done();
441 }
442 });
443 }
444 });
445 }
446 };
447 try {
448 executor.execute(selectRecordQuery);
449 selectRecordQuery.get(); // blocks
450 } catch (RejectedExecutionException e) {
451
452 } catch (InterruptedException e) {
453 // TODO Auto-generated catch block
454 e.printStackTrace();
455 } catch (ExecutionException e) {
456 // TODO Auto-generated catch block
457 e.printStackTrace();
458 } finally {
459 tracker.dispose();
460 }
461 }
462
463 /**
464 * Returns the number of frames contained in currently loaded tracepoint GDB
465 * session.
466 * <p>
467 * Note: A postmortem GDB session must be started before calling
468 * this method
469 *
470 * @return the number of frames contained in currently loaded tracepoint GDB
471 * session or zero in case of error
472 */
473 private synchronized int findNumFrames() {
474 int frameNum = 0;
475
476 if (DsfSession.getSession(fSessionId) == null) {
477 return 0;
478 }
479
480 final DsfExecutor executor = DsfSession.getSession(fSessionId)
481 .getExecutor();
482 final DsfServicesTracker tracker = new DsfServicesTracker(
483 GdbTraceCorePlugin.getBundleContext(), fSessionId);
484
485 Query<ITraceStatusDMData> selectRecordQuery = new Query<ITraceStatusDMData>() {
486 @Override
487 public void execute(
488 final DataRequestMonitor<ITraceStatusDMData> queryRm) {
489 final IGDBTraceControl traceControl = tracker
490 .getService(IGDBTraceControl.class);
491
492 final ICommandControlService commandControl = tracker
493 .getService(ICommandControlService.class);
494 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl
495 .getContext();
496
497 if (traceControl != null) {
498 traceControl.getTraceStatus(dmc, queryRm);
499 } else {
500 queryRm.done();
501 }
502 }
503 };
504 try {
505 executor.execute(selectRecordQuery);
506 ITraceStatusDMData data = selectRecordQuery.get(); // blocks
507 frameNum = data.getNumberOfCollectedFrame();
508 } catch (InterruptedException e) {
509
510 } catch (java.util.concurrent.ExecutionException e) {
511
512 } catch (RejectedExecutionException e) {
513
514 } finally {
515 tracker.dispose();
516 }
517 return frameNum;
518 }
519
520 /**
521 * This method uses the DSF-GDB interface to select a given frame number
522 * in the current GDB tracepoint session.
523 *
524 * @param rank the rank of the tracepoint frame to select.
525 * @param update true if visualization should be updated
526 * @return boolean true if select worked.
527 */
528 public boolean selectDataFrame(final long rank, final boolean update) {
529 boolean status = true;
530
531 final DsfSession dsfSession = DsfSession.getSession(fSessionId);
532 if (dsfSession == null) {
533 return false;
534 }
535
536 if (update) {
537 /*
538 * Clear the selection to ensure that the new selection is not
539 * prevented from overriding the current selection by the DSF
540 * selection policy. This could be removed when DSF provides
541 * an API to force the trace record selection in the Debug view.
542 */
543 Display.getDefault().syncExec(new Runnable() {
544 @Override
545 public void run() {
546 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
547 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
548 IViewPart vp = wbPage.findView(IDebugUIConstants.ID_DEBUG_VIEW);
549 if (vp instanceof AbstractDebugView) {
550 Viewer viewer = ((AbstractDebugView) vp).getViewer();
551 if (viewer instanceof ITreeModelViewer) {
552 ((ITreeModelViewer) viewer).setSelection(StructuredSelection.EMPTY, false, true);
553 }
554 }
555 }
556 }
557 }
558 });
559 }
560
561 final DsfExecutor executor = dsfSession.getExecutor();
562 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
563
564 Query<Object> selectRecordQuery = new Query<Object>() {
565 @Override
566 public void execute(final DataRequestMonitor<Object> queryRm) {
567 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
568
569 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
570 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl.getContext();
571
572 if (traceControl != null) {
573 ITraceRecordDMContext newCtx = traceControl.createTraceRecordContext(dmc, Integer.toString((int) rank));
574 if (update) {
575 dsfSession.dispatchEvent(new TraceRecordSelectedChangedEvent(newCtx), new Hashtable<String, String>());
576 }
577 traceControl.selectTraceRecord(newCtx, queryRm);
578 } else {
579 queryRm.done();
580 }
581 }
582 };
583 try {
584 executor.execute(selectRecordQuery);
585 selectRecordQuery.get(); // blocks
586 } catch (InterruptedException e) {
587 status = false;
588 } catch (java.util.concurrent.ExecutionException e) {
589 status = false;
590 } catch (RejectedExecutionException e) {
591 status = false;
592 } finally {
593 tracker.dispose();
594 }
595 return status;
596 }
597
598 /**
599 * This method uses DSF-GDB to read the currently selected GDB tracepoint
600 * data frame. An object of type GdbTraceEvent is build based on the
601 * information contained in the data frame and returned to the caller.
602 * <p>
603 * NOTE : A frame must be selected before calling this method!
604 *
605 * @param rank for internal purposes - does <b>not</b> control which
606 * frame will be read!
607 * @return parsed tp frame, in the form of a GdbTraceEvent
608 */
609 private GdbTraceEvent getTraceFrameData(final long rank) {
610
611 if (DsfSession.getSession(fSessionId) == null) {
612 return null;
613 }
614
615 final DsfExecutor executor = DsfSession.getSession(fSessionId).getExecutor();
616 final DsfServicesTracker tracker = new DsfServicesTracker(GdbTraceCorePlugin.getBundleContext(), fSessionId);
617
618 Query<ITraceRecordDMData> getFrameDataQuery = new Query<ITraceRecordDMData>() {
619 @Override
620 public void execute(final DataRequestMonitor<ITraceRecordDMData> rm) {
621 final IGDBTraceControl traceControl = tracker.getService(IGDBTraceControl.class);
622
623 final ICommandControlService commandControl = tracker.getService(ICommandControlService.class);
624 final ITraceTargetDMContext dmc = (ITraceTargetDMContext) commandControl.getContext();
625
626 if (traceControl != null) {
627 traceControl.getCurrentTraceRecordContext(dmc,
628 new DataRequestMonitor<ITraceRecordDMContext>(executor, rm) {
629 @Override
630 protected void handleSuccess() {
631 traceControl.getTraceRecordData(getData(), rm);
632 }
633 });
634 } else {
635 rm.done();
636 }
637 }
638 };
639 try {
640 // Execute the above query
641 executor.execute(getFrameDataQuery);
642 ITraceRecordDMData data = getFrameDataQuery.get(); // blocking call
643
644 if (data == null) {
645 return null;
646 }
647
648 String ts = data.getTimestamp();
649 if (ts == null) {
650 ts = "0"; //$NON-NLS-1$
651 }
652
653 // get corresponding TP data
654 String tmfEventRef;
655 MIBreakpointDMData bp = fTpInfo.get(Integer.valueOf(data.getTracepointNumber()));
656 if (bp != null) {
657 tmfEventRef = bp.getFileName() + ":" + bp.getLineNumber() + " :: " + bp.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
658 }
659 else {
660 tmfEventRef = tracedExecutable;
661 }
662
663 GdbTraceEventContent evContent = new GdbTraceEventContent(
664 data.getContent(),
665 Integer.parseInt(data.getTracepointNumber()),
666 Integer.parseInt(data.getRecordId()));
667
668 GdbTraceEvent ev = new GdbTraceEvent(fGdbTrace,
669 new TmfTimestamp(Integer.parseInt(data.getRecordId())),
670 "Tracepoint: " + data.getTracepointNumber() + ", Frame: " + data.getRecordId(), //$NON-NLS-1$ //$NON-NLS-2$
671 tmfEventType,
672 evContent,
673 tmfEventRef);
674
675 return ev;
676
677 } catch (InterruptedException e) {
678 return createExceptionEvent(rank, "Interruption exception"); //$NON-NLS-1$
679 } catch (java.util.concurrent.ExecutionException e) {
680 return createExceptionEvent(rank, "GDB exception"); //$NON-NLS-1$
681 } catch (RejectedExecutionException e) {
682 return createExceptionEvent(rank, "Request rejected exception"); //$NON-NLS-1$
683 } catch (Exception e) {
684 return createExceptionEvent(rank, "General exception"); //$NON-NLS-1$
685 }
686
687 finally {
688 tracker.dispose();
689 }
690 }
691
692 /**
693 * This is a helper method for getTraceFrameData, to create for it a
694 * "best effort" GdbTraceEvent when a problem occurs during the reading.
695 *
696 * @param rank long containing the number of the frame where the problem occurred
697 * @param message String containing a brief explanation of problem.
698 * @return a GdbTraceEvent object, filled as best as possible
699 */
700 private GdbTraceEvent createExceptionEvent(final long rank, final String message) {
701 // get corresponding TP data
702 String tmfEventRef;
703 String tmfEventSrc;
704 MIBreakpointDMData bp = fTpInfo.get(rank);
705 if (bp != null) {
706 tmfEventRef = bp.getFileName() + ":" + bp.getLineNumber() + " :: " + bp.getFunctionName(); //$NON-NLS-1$ //$NON-NLS-2$
707 tmfEventSrc = bp.getFileName() + " :: " + bp.getFunctionName() + ", line: " + bp.getLineNumber(); //$NON-NLS-1$ //$NON-NLS-2$
708 }
709 else {
710 tmfEventRef = tracedExecutable;
711 tmfEventSrc = "Tracepoint: n/a"; //$NON-NLS-1$
712 }
713
714 GdbTraceEventContent evContent = new GdbTraceEventContent("ERROR: " + message, 0, 0); //$NON-NLS-1$
715
716 GdbTraceEvent ev = new GdbTraceEvent(fGdbTrace,
717 new TmfTimestamp(rank),
718 tmfEventSrc,
719 tmfEventType,
720 evContent,
721 tmfEventRef);
722
723 return ev;
724 }
725
726 /**
727 * @return DSF-GDB session id of the current session.
728 */
729 public String getSessionId() {
730 return fSessionId;
731 }
732
733 /**
734 * Handler method that catches the DSF "record selected changed" event.
735 * It in turn creates a TMF "time sync" signal.
736 * @param event TraceRecordSelectedChangedEvent: The DSF event.
737 */
738 @DsfServiceEventHandler
739 public void handleDSFRecordSelectedEvents(final ITraceRecordSelectedChangedDMEvent event) {
740 if (event instanceof TraceRecordSelectedChangedEvent) {
741 TraceRecordSelectedChangedEvent traceEvent = (TraceRecordSelectedChangedEvent) event;
742 ITraceRecordDMContext context = traceEvent.getDMContext();
743 final String reference = context.getRecordId();
744 if (reference != null) {
745 int recordId = Integer.parseInt(reference);
746 selectGdbTraceEditor(context.getSessionId(), recordId);
747 }
748 }
749 }
750
751 private static void closeGdbTraceEditor(final String sessionId) {
752 Display.getDefault().asyncExec(new Runnable() {
753 @Override
754 public void run() {
755 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
756 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
757 for (IEditorReference editorReference : wbPage.getEditorReferences()) {
758 IEditorPart editor = editorReference.getEditor(false);
759 if (editor instanceof ITmfTraceEditor) {
760 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
761 if (trace instanceof GdbTrace) {
762 if (((GdbTrace) trace).getDsfSessionId().equals(sessionId)) {
763 wbPage.closeEditor(editor, false);
764 }
765 }
766 }
767 }
768 }
769 }
770 }
771 });
772 }
773
774 private static void selectGdbTraceEditor(final String sessionId, final int recordId) {
775 Display.getDefault().asyncExec(new Runnable() {
776 @Override
777 public void run() {
778 for (IWorkbenchWindow wbWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
779 for (IWorkbenchPage wbPage : wbWindow.getPages()) {
780 for (IEditorReference editorReference : wbPage.getEditorReferences()) {
781 IEditorPart editor = editorReference.getEditor(false);
782 if (editor instanceof ITmfTraceEditor) {
783 ITmfTrace trace = ((ITmfTraceEditor) editor).getTrace();
784 if (trace instanceof GdbTrace) {
785 if (((GdbTrace) trace).getDsfSessionId().equals(sessionId)) {
786 wbPage.bringToTop(editor);
787 if (recordId != -1) {
788 gotoRank(editor, recordId);
789 }
790 return;
791 }
792 } else if (trace instanceof TmfExperiment) {
793 TmfExperiment experiment = (TmfExperiment) trace;
794 int nbTraces = experiment.getTraces().length;
795 for (int i = 0; i < nbTraces; i++) {
796 GdbTrace gdbTrace = (GdbTrace) experiment.getTraces()[i];
797 if (gdbTrace.getDsfSessionId().equals(sessionId)) {
798 wbPage.bringToTop(editor);
799 if (recordId != -1) {
800 int rank = recordId * nbTraces + i;
801 gotoRank(editor, rank);
802 }
803 return;
804 }
805 }
806 }
807 }
808 }
809 }
810 }
811 }
812 });
813 }
814
815 private static void gotoRank(IEditorPart editor, int rank) {
816 IEditorInput editorInput = editor.getEditorInput();
817 if (editorInput instanceof IFileEditorInput) {
818 IFile file = ((IFileEditorInput) editorInput).getFile();
819 try {
820 final IMarker marker = file.createMarker(IMarker.MARKER);
821 marker.setAttribute(IMarker.LOCATION, (Integer) rank);
822 IDE.gotoMarker(editor, marker);
823 marker.delete();
824 } catch (CoreException e) {
825 e.printStackTrace();
826 }
827 }
828 }
829}
This page took 0.057951 seconds and 5 git commands to generate.