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