diff options
author | Marc Khouzam | 2010-01-27 19:05:47 +0000 |
---|---|---|
committer | Marc Khouzam | 2010-01-27 19:05:47 +0000 |
commit | 6764511b39d631ac4b487645993b3a443af72992 (patch) | |
tree | 86ec1dec9e47aaddd6e4e310d5d54b59d05816d4 | |
parent | 9524c4671f2b6ae6871bdd4cbfb95c20658bc134 (diff) | |
download | org.eclipse.cdt-6764511b39d631ac4b487645993b3a443af72992.tar.gz org.eclipse.cdt-6764511b39d631ac4b487645993b3a443af72992.tar.xz org.eclipse.cdt-6764511b39d631ac4b487645993b3a443af72992.zip |
[284286] New Trace Control View to allow to start/stop/status a tracing experiment. Support for Trace State Variables. Support for Saving trace data to a file.
38 files changed, 3473 insertions, 17 deletions
diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/ISaveTraceDataHandler.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/ISaveTraceDataHandler.java new file mode 100644 index 00000000000..2e6324c8175 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/ISaveTraceDataHandler.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.model; + +import org.eclipse.debug.core.commands.IDebugCommandHandler; + +/** + * Handler interface to save trace data. + * @since 7.0 + */ +public interface ISaveTraceDataHandler extends IDebugCommandHandler { +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IStartTracingHandler.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IStartTracingHandler.java new file mode 100644 index 00000000000..66958e5391a --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IStartTracingHandler.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.model; + +import org.eclipse.debug.core.commands.IDebugCommandHandler; + +/** + * Handler interface to request the start of tracing. + * @since 7.0 + */ +public interface IStartTracingHandler extends IDebugCommandHandler { +} diff --git a/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IStopTracingHandler.java b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IStopTracingHandler.java new file mode 100644 index 00000000000..f4329fffa6a --- /dev/null +++ b/debug/org.eclipse.cdt.debug.core/src/org/eclipse/cdt/debug/core/model/IStopTracingHandler.java @@ -0,0 +1,20 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.core.model; + +import org.eclipse.debug.core.commands.IDebugCommandHandler; + +/** + * Handler interface to request the stop of tracing. + * @since 7.0 + */ +public interface IStopTracingHandler extends IDebugCommandHandler { +} diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.properties b/debug/org.eclipse.cdt.debug.ui/plugin.properties index 4779c044db0..09a835265e9 100644 --- a/debug/org.eclipse.cdt.debug.ui/plugin.properties +++ b/debug/org.eclipse.cdt.debug.ui/plugin.properties @@ -222,4 +222,12 @@ Uncall.label = Uncall BreakpointTypes.label=B&reakpoint Types # Tracepoints -TracepointActionSet.label=Tracepoints +TracepointActionSet.label=C/C++ Tracepoints +TracingCategory.description=Category for Tracing Commands +TracingCategory.name=Tracing Commands +StartTracing.description=Start Tracing Experiment +StartTracing.name=Start Tracing +StopTracing.description=Stop Tracing Experiment +StopTracing.name=Stop Tracing +SaveTraceData.description=Save Trace Data to File +SaveTraceData.name=Save Trace Data diff --git a/debug/org.eclipse.cdt.debug.ui/plugin.xml b/debug/org.eclipse.cdt.debug.ui/plugin.xml index d5577da1295..ad584e03084 100644 --- a/debug/org.eclipse.cdt.debug.ui/plugin.xml +++ b/debug/org.eclipse.cdt.debug.ui/plugin.xml @@ -2021,6 +2021,29 @@ id="org.eclipse.cdt.debug.ui.command.uncall" name="%Uncall.name"> </command> + <category + description="%TracingCategory.description" + id="org.eclipse.cdt.debug.ui.category.tracing" + name="%TracingCategory.name"> + </category> + <command + categoryId="org.eclipse.cdt.debug.ui.category.tracing" + description="%StartTracing.description" + id="org.eclipse.cdt.debug.ui.command.startTracing" + name="%StartTracing.name"> + </command> + <command + categoryId="org.eclipse.cdt.debug.ui.category.tracing" + description="%StopTracing.description" + id="org.eclipse.cdt.debug.ui.command.stopTracing" + name="%StopTracing.name"> + </command> + <command + categoryId="org.eclipse.cdt.debug.ui.category.tracing" + description="%SaveTraceData.description" + id="org.eclipse.cdt.debug.ui.command.saveTraceData" + name="%SaveTraceData.name"> + </command> </extension> <extension point="org.eclipse.ui.handlers"> @@ -2044,6 +2067,18 @@ class="org.eclipse.cdt.debug.internal.ui.commands.UncallCommandHandler" commandId="org.eclipse.cdt.debug.ui.command.uncall"> </handler> + <handler + class="org.eclipse.cdt.debug.internal.ui.commands.StartTracingCommandHandler" + commandId="org.eclipse.cdt.debug.ui.command.startTracing"> + </handler> + <handler + class="org.eclipse.cdt.debug.internal.ui.commands.StopTracingCommandHandler" + commandId="org.eclipse.cdt.debug.ui.command.stopTracing"> + </handler> + <handler + class="org.eclipse.cdt.debug.internal.ui.commands.SaveTraceDataCommandHandler" + commandId="org.eclipse.cdt.debug.ui.command.saveTraceData"> + </handler> </extension> <extension point="org.eclipse.core.expressions.definitions"> @@ -2344,6 +2379,33 @@ </visibleWhen> </command> </menuContribution> + <menuContribution + locationURI="popup:org.eclipse.debug.ui.DebugView?before=renderGroup"> + <command + commandId="org.eclipse.cdt.debug.ui.command.startTracing" + icon="icons/obj16/start_tracing_obj.gif" + label="%StartTracing.name" + style="push"> + <visibleWhen + checkEnabled="false"> + <reference + definitionId="org.eclipse.cdt.debug.ui.testIsTracepointActionSetActive"> + </reference> + </visibleWhen> + </command> + <command + commandId="org.eclipse.cdt.debug.ui.command.stopTracing" + icon="icons/obj16/stop_tracing_obj.gif" + label="%StopTracing.name" + style="push"> + <visibleWhen + checkEnabled="false"> + <reference + definitionId="org.eclipse.cdt.debug.ui.testIsTracepointActionSetActive"> + </reference> + </visibleWhen> + </command> + </menuContribution> </extension> <extension point="org.eclipse.ui.popupMenus"> diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/SaveTraceDataCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/SaveTraceDataCommandHandler.java new file mode 100644 index 00000000000..1ec7c31c52d --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/SaveTraceDataCommandHandler.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.ui.commands; + +import org.eclipse.cdt.debug.core.model.ISaveTraceDataHandler; +import org.eclipse.debug.ui.actions.DebugCommandHandler; + +/** + * Command handler to save the trace data to a file + * + * @since 7.0 + */ +public class SaveTraceDataCommandHandler extends DebugCommandHandler { + @Override + protected Class<?> getCommandType() { + return ISaveTraceDataHandler.class; + } +} diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/StartTracingCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/StartTracingCommandHandler.java new file mode 100644 index 00000000000..ec420386a3a --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/StartTracingCommandHandler.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.ui.commands; + +import org.eclipse.cdt.debug.core.model.IStartTracingHandler; +import org.eclipse.debug.ui.actions.DebugCommandHandler; + +/** + * Command handler to request the start of tracing + * + * @since 7.0 + */ +public class StartTracingCommandHandler extends DebugCommandHandler { + @Override + protected Class<?> getCommandType() { + return IStartTracingHandler.class; + } +} diff --git a/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/StopTracingCommandHandler.java b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/StopTracingCommandHandler.java new file mode 100644 index 00000000000..62a39eb0ee3 --- /dev/null +++ b/debug/org.eclipse.cdt.debug.ui/src/org/eclipse/cdt/debug/internal/ui/commands/StopTracingCommandHandler.java @@ -0,0 +1,26 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.debug.internal.ui.commands; + +import org.eclipse.cdt.debug.core.model.IStopTracingHandler; +import org.eclipse.debug.ui.actions.DebugCommandHandler; + +/** + * Command handler to request the stop of tracing + * + * @since 7.0 + */ +public class StopTracingCommandHandler extends DebugCommandHandler { + @Override + protected Class<?> getCommandType() { + return IStopTracingHandler.class; + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties index 3b671d0714c..33b424837b2 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.properties @@ -29,3 +29,9 @@ editorTextHover.description=Shows formatted value in debugger hover breakpoints.property.filter=Filter tracepoints.property.common=Common tracepoints.property.actions=Actions + +# Tracepoints +view.traceControl.name=Trace Control +toolbar.startTracing.name=Start Tracing +toolbar.stopTracing.name=Stop Tracing +toolbar.saveTracing.name=Save Trace Data diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml index 42f4bf9b040..655fa49925e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/plugin.xml @@ -355,5 +355,56 @@ debugModelId="org.eclipse.cdt.dsf.gdb"> </modelContextBinding> </extension> - + <extension + point="org.eclipse.ui.views"> + <view + category="org.eclipse.debug.ui" + class="org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints.TraceControlView" + icon="icons/full/view16/tracecontrol_view.gif" + id="org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view" + name="%view.traceControl.name"> + </view> + </extension> + <extension + point="org.eclipse.ui.perspectiveExtensions"> + <perspectiveExtension + targetID="org.eclipse.debug.ui.DebugPerspective"> + <view + relative="org.eclipse.ui.views.ContentOutline" + visible="false" + relationship="stack" + id="org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view"> + </view> + <viewShortcut + id="org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view"> + </viewShortcut> + </perspectiveExtension> + </extension> + <extension + point="org.eclipse.ui.menus"> + <menuContribution + locationURI="toolbar:org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view?after=additions"> + <command + commandId="org.eclipse.cdt.debug.ui.command.startTracing" + icon="icons/full/obj16/starttracing.gif" + label="%toolbar.startTracing.name" + style="push"> + </command> + <command + commandId="org.eclipse.cdt.debug.ui.command.stopTracing" + icon="icons/full/obj16/stoptracing.gif" + label="%toolbar.stopTracing.name" + style="push"> + </command> + </menuContribution> + <menuContribution + locationURI="menu:org.eclipse.cdt.dsf.gdb.ui.tracecontrol.view?after=additions"> + <command + commandId="org.eclipse.cdt.debug.ui.command.saveTraceData" + icon="icons/full/obj16/savetrace.gif" + label="%toolbar.saveTracing.name" + style="push"> + </command> + </menuContribution> + </extension> </plugin> diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java index 018c5a329fe..fa3c3b8e93f 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/GdbAdapterFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems and others. + * Copyright (c) 2010 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -20,7 +20,10 @@ import org.eclipse.cdt.debug.core.model.IReverseResumeHandler; import org.eclipse.cdt.debug.core.model.IReverseStepIntoHandler; import org.eclipse.cdt.debug.core.model.IReverseStepOverHandler; import org.eclipse.cdt.debug.core.model.IReverseToggleHandler; +import org.eclipse.cdt.debug.core.model.ISaveTraceDataHandler; +import org.eclipse.cdt.debug.core.model.IStartTracingHandler; import org.eclipse.cdt.debug.core.model.ISteppingModeTarget; +import org.eclipse.cdt.debug.core.model.IStopTracingHandler; import org.eclipse.cdt.debug.core.model.IUncallHandler; import org.eclipse.cdt.dsf.concurrent.Immutable; import org.eclipse.cdt.dsf.concurrent.ThreadSafe; @@ -44,6 +47,9 @@ import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseResumeCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseStepIntoCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseStepOverCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbReverseToggleCommand; +import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbSaveTraceDataCommand; +import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbStartTracingCommand; +import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbStopTracingCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.commands.GdbUncallCommand; import org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.GdbViewModelAdapter; import org.eclipse.cdt.dsf.gdb.launching.GdbLaunch; @@ -104,6 +110,9 @@ public class GdbAdapterFactory final SteppingController fSteppingController; final DefaultRefreshAllTarget fRefreshAllTarget; final GdbReverseToggleCommand fReverseToggleTarget; + final GdbStartTracingCommand fStartTracingTarget; + final GdbStopTracingCommand fStopTracingTarget; + final GdbSaveTraceDataCommand fSaveTraceDataTarget; SessionAdapterSet(GdbLaunch launch) { fLaunch = launch; @@ -140,7 +149,10 @@ public class GdbAdapterFactory fModelSelectionPolicyFactory = new DefaultDsfModelSelectionPolicyFactory(); fRefreshAllTarget = new DefaultRefreshAllTarget(); fReverseToggleTarget = new GdbReverseToggleCommand(session); - + fStartTracingTarget = new GdbStartTracingCommand(session); + fStopTracingTarget = new GdbStopTracingCommand(session); + fSaveTraceDataTarget = new GdbSaveTraceDataCommand(session); + session.registerModelAdapter(ISteppingModeTarget.class, fSteppingModeTarget); session.registerModelAdapter(IStepIntoHandler.class, fStepIntoCommand); session.registerModelAdapter(IReverseStepIntoHandler.class, fReverseStepIntoCommand); @@ -158,6 +170,9 @@ public class GdbAdapterFactory session.registerModelAdapter(IModelSelectionPolicyFactory.class, fModelSelectionPolicyFactory); session.registerModelAdapter(IRefreshAllTarget.class, fRefreshAllTarget); session.registerModelAdapter(IReverseToggleHandler.class, fReverseToggleTarget); + session.registerModelAdapter(IStartTracingHandler.class, fStartTracingTarget); + session.registerModelAdapter(IStopTracingHandler.class, fStopTracingTarget); + session.registerModelAdapter(ISaveTraceDataHandler.class, fSaveTraceDataTarget); fDebugModelProvider = new IDebugModelProvider() { // @see org.eclipse.debug.core.model.IDebugModelProvider#getModelIdentifiers() @@ -203,6 +218,9 @@ public class GdbAdapterFactory session.unregisterModelAdapter(IModelSelectionPolicyFactory.class); session.unregisterModelAdapter(IRefreshAllTarget.class); session.unregisterModelAdapter(IReverseToggleHandler.class); + session.unregisterModelAdapter(IStartTracingHandler.class); + session.unregisterModelAdapter(IStopTracingHandler.class); + session.unregisterModelAdapter(ISaveTraceDataHandler.class); fSteppingModeTarget.dispose(); fStepIntoCommand.dispose(); @@ -220,6 +238,9 @@ public class GdbAdapterFactory fDisconnectCommand.dispose(); fSuspendTrigger.dispose(); fReverseToggleTarget.dispose(); + fStartTracingTarget.dispose(); + fStopTracingTarget.dispose(); + fSaveTraceDataTarget.dispose(); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbSaveTraceDataCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbSaveTraceDataCommand.java new file mode 100644 index 00000000000..d534bf15f68 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbSaveTraceDataCommand.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.commands; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; + +import org.eclipse.cdt.debug.core.model.ISaveTraceDataHandler; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DsfExecutor; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.debug.core.IRequest; +import org.eclipse.debug.core.commands.AbstractDebugCommand; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IEnabledStateRequest; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.FileDialog; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.PlatformUI; + +/** + * Command to save the trace data to file + * + * @since 2.1 + */ +public class GdbSaveTraceDataCommand extends AbstractDebugCommand implements ISaveTraceDataHandler { + + private final DsfExecutor fExecutor; + private final DsfServicesTracker fTracker; + + public GdbSaveTraceDataCommand(DsfSession session) { + fExecutor = session.getExecutor(); + fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId()); + } + + public void dispose() { + fTracker.dispose(); + } + + @Override + protected void doExecute(Object[] targets, IProgressMonitor monitor, IRequest request) + throws CoreException { + if (targets.length != 1) { + return; + } + + final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class); + if (dmc == null) { + return; + } + + final String[] fileName = new String[1]; + PlatformUI.getWorkbench().getDisplay().syncExec(new Runnable() { + public void run() { + fileName[0] = promptForFileName(); + }; + }); + + if (fileName[0] != null) { + Query<Object> saveTraceDataQuery = new Query<Object>() { + @Override + public void execute(final DataRequestMonitor<Object> rm) { + IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); + + if (traceControl != null) { + traceControl.saveTraceData(dmc, fileName[0], false, rm); + } else { + rm.done(); + } + } + }; + try { + fExecutor.execute(saveTraceDataQuery); + saveTraceDataQuery.get(); + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } catch (RejectedExecutionException e) { + // Can be thrown if the session is shutdown + } + } + } + + @Override + protected boolean isExecutable(Object[] targets, IProgressMonitor monitor, IEnabledStateRequest request) + throws CoreException { + if (targets.length != 1) { + return false; + } + + final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class); + if (dmc == null) { + return false; + } + + Query<Boolean> canSaveQuery = new Query<Boolean>() { + @Override + public void execute(DataRequestMonitor<Boolean> rm) { + IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); + + if (traceControl != null) { + traceControl.canSaveTraceData(dmc, rm); + } else { + rm.setData(false); + rm.done(); + } + } + }; + try { + fExecutor.execute(canSaveQuery); + return canSaveQuery.get(); + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } catch (RejectedExecutionException e) { + // Can be thrown if the session is shutdown + } + + return false; + } + + @Override + protected Object getTarget(Object element) { + if (element instanceof IDMVMContext) { + return element; + } + return null; + } + + /* + * Keep the command enabled since there is no automatic re-selection of the debug + * context for this command. If not, it will remain disabled until something causes + * the debug context to change. + * + * (non-Javadoc) + * @see org.eclipse.debug.core.commands.AbstractDebugCommand#isRemainEnabled(org.eclipse.debug.core.commands.IDebugCommandRequest) + */ + @Override + protected boolean isRemainEnabled(IDebugCommandRequest request) { + return true; + } + + private String promptForFileName() { + Shell shell = Display.getDefault().getActiveShell(); + if (shell == null) { + return null; + } + + FileDialog fd = new FileDialog(shell, SWT.SAVE); + return fd.open(); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStartTracingCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStartTracingCommand.java new file mode 100644 index 00000000000..5ca46d2f65a --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStartTracingCommand.java @@ -0,0 +1,143 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.commands; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; + +import org.eclipse.cdt.debug.core.model.IStartTracingHandler; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DsfExecutor; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.debug.core.IRequest; +import org.eclipse.debug.core.commands.AbstractDebugCommand; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IEnabledStateRequest; + +/** + * Command to start the tracing experiment + * + * @since 2.1 + */ +public class GdbStartTracingCommand extends AbstractDebugCommand implements IStartTracingHandler { + private final DsfExecutor fExecutor; + private final DsfServicesTracker fTracker; + + public GdbStartTracingCommand(DsfSession session) { + fExecutor = session.getExecutor(); + fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId()); + } + + public void dispose() { + fTracker.dispose(); + } + + @Override + protected void doExecute(Object[] targets, IProgressMonitor monitor, IRequest request) + throws CoreException { + if (targets.length != 1) { + return; + } + + final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class); + if (dmc == null) { + return; + } + + Query<Object> startTracingQuery = new Query<Object>() { + @Override + public void execute(DataRequestMonitor<Object> rm) { + IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); + + if (traceControl != null) { + traceControl.startTracing(dmc, rm); + } else { + rm.done(); + } + } + }; + try { + fExecutor.execute(startTracingQuery); + startTracingQuery.get(); + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } catch (RejectedExecutionException e) { + // Can be thrown if the session is shutdown + } + } + + @Override + protected boolean isExecutable(Object[] targets, IProgressMonitor monitor, IEnabledStateRequest request) + throws CoreException { + if (targets.length != 1) { + return false; + } + + final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class); + if (dmc == null) { + return false; + } + + Query<Boolean> canStartTracingQuery = new Query<Boolean>() { + @Override + public void execute(DataRequestMonitor<Boolean> rm) { + IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); + + if (traceControl != null) { + traceControl.canStartTracing(dmc, rm); + } else { + rm.setData(false); + rm.done(); + } + } + }; + try { + fExecutor.execute(canStartTracingQuery); + return canStartTracingQuery.get(); + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } catch (RejectedExecutionException e) { + // Can be thrown if the session is shutdown + } + + return false; + } + + @Override + protected Object getTarget(Object element) { + if (element instanceof IDMVMContext) { + return element; + } + return null; + } + + /* + * Re-selection of the debug context will be forced by the Debug Model through a StartTracing event. + * Therefore, the enablement of this command will be refreshed, so we don't need to keep it enabled. + * In fact, it is better to have it disabled right after selection to avoid a double-click + * + * (non-Javadoc) + * @see org.eclipse.debug.core.commands.AbstractDebugCommand#isRemainEnabled(org.eclipse.debug.core.commands.IDebugCommandRequest) + */ + @Override + protected boolean isRemainEnabled(IDebugCommandRequest request) { + return false; + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStopTracingCommand.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStopTracingCommand.java new file mode 100644 index 00000000000..b232b2070b7 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/commands/GdbStopTracingCommand.java @@ -0,0 +1,142 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.commands; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; + +import org.eclipse.cdt.debug.core.model.IStopTracingHandler; +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DsfExecutor; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.debug.core.IRequest; +import org.eclipse.debug.core.commands.AbstractDebugCommand; +import org.eclipse.debug.core.commands.IDebugCommandRequest; +import org.eclipse.debug.core.commands.IEnabledStateRequest; + +/** + * Command to stop the tracing experiment + * + * @since 2.1 + */ +public class GdbStopTracingCommand extends AbstractDebugCommand implements IStopTracingHandler { + private final DsfExecutor fExecutor; + private final DsfServicesTracker fTracker; + + public GdbStopTracingCommand(DsfSession session) { + fExecutor = session.getExecutor(); + fTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), session.getId()); + } + + public void dispose() { + fTracker.dispose(); + } + + @Override + protected void doExecute(Object[] targets, IProgressMonitor monitor, IRequest request) + throws CoreException { + if (targets.length != 1) { + return; + } + + final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class); + if (dmc == null) { + return; + } + + Query<Object> stopTracingQuery = new Query<Object>() { + @Override + public void execute(final DataRequestMonitor<Object> rm) { + IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); + + if (traceControl != null) { + traceControl.stopTracing(dmc, rm); + } else { + rm.done(); + } + } + }; + try { + fExecutor.execute(stopTracingQuery); + stopTracingQuery.get(); + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } catch (RejectedExecutionException e) { + // Can be thrown if the session is shutdown + } + } + + @Override + protected boolean isExecutable(Object[] targets, IProgressMonitor monitor, IEnabledStateRequest request) + throws CoreException { + if (targets.length != 1) { + return false; + } + + final ITraceTargetDMContext dmc = DMContexts.getAncestorOfType(((IDMVMContext)targets[0]).getDMContext(), ITraceTargetDMContext.class); + if (dmc == null) { + return false; + } + + Query<Boolean> canStopTracingQuery = new Query<Boolean>() { + @Override + public void execute(DataRequestMonitor<Boolean> rm) { + IGDBTraceControl traceControl = fTracker.getService(IGDBTraceControl.class); + + if (traceControl != null) { + traceControl.canStopTracing(dmc, rm); + } else { + rm.setData(false); + rm.done(); + } + } + }; + try { + fExecutor.execute(canStopTracingQuery); + return canStopTracingQuery.get(); + } catch (InterruptedException e) { + } catch (ExecutionException e) { + } catch (RejectedExecutionException e) { + // Can be thrown if the session is shutdown + } + + return false; + } + + @Override + protected Object getTarget(Object element) { + if (element instanceof IDMVMContext) { + return element; + } + return null; + } + + /* + * Re-selection of the debug context will be forced by the Debug Model through a StopTracing event. + * Therefore, the enablement of this command will be refreshed, so we don't need to keep it enabled. + * In fact, it is better to have it disabled right after selection to avoid a double-click + * (non-Javadoc) + * @see org.eclipse.debug.core.commands.AbstractDebugCommand#isRemainEnabled(org.eclipse.debug.core.commands.IDebugCommandRequest) + */ + @Override + protected boolean isRemainEnabled(IDebugCommandRequest request) { + return false; + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/AbstractImageRegistry.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/AbstractImageRegistry.java new file mode 100644 index 00000000000..413e9148822 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/AbstractImageRegistry.java @@ -0,0 +1,145 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashMap; + +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.swt.SWTException; +import org.eclipse.swt.graphics.Image; +import org.osgi.framework.Bundle; + +/** + * Abstract image registry that allows for defining fallback paths for images. + * This is copy of <code>org.eclipse.cdt.dsf.debug.internal.ui.disassembly.AbstractImageRegistry</code> + * + * @since 2.1 + */ +public abstract class AbstractImageRegistry extends ImageRegistry { + private HashMap<String, String> fPlugins = new HashMap<String, String>(); + private HashMap<String, String[]> fLocations = new HashMap<String, String[]>(); + private URL fBaseUrl; + + protected AbstractImageRegistry(Plugin plugin) { + fBaseUrl = plugin.getBundle().getEntry("/"); //$NON-NLS-1$ + } + + /** + * Defines the key for a local image, that must be found below the icons directory + * in the plugin. + * @param key Key by which the image can be referred by. + * @param dir Directory relative to icons/ + * @param name The name of the file defining the icon. The name will be used as + * key. + */ + protected void localImage(String key, String dir, String name) { + if (dir== null || dir.equals(""))//$NON-NLS-1$ + fLocations.put(key, new String[] {"icons/" + name}); //$NON-NLS-1$ + else + fLocations.put(key, new String[] {"icons/" + dir + "/" + name}); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Defines the key for a non-local image, that must be found below the icons directory + * of some plugin. + * @param key Key by which the image can be referred by. + * @param plugin The plugin id, where the icon is searched. + * @param dirs A couple of directories below icons/ in the plugin. If loading fails, + * the next dir will be taken as fallback. + * @param name The name of the file defining the icon. The name will be used as + * key. + */ + protected void externalImage(String key, String plugin, String[] dirs, String name) { + if (plugin != null) { + fPlugins.put(key, plugin); + } + String[] locations = new String[dirs.length]; + for (int i = 0; i < dirs.length; i++) { + String dir = dirs[i]; + if (dir== null || dir.equals(""))//$NON-NLS-1$ + locations[i] = "icons/" + name; //$NON-NLS-1$ + else + locations[i] = "icons/" + dir + "/" + name; //$NON-NLS-1$ //$NON-NLS-2$ + } + fLocations.put(key, locations); + } + + // overrider + @Override + final public Image get(String key) { + Image i = super.get(key); + if (i != null) { + return i; + } + + ImageDescriptor d = createFileImageDescriptor(key); + if (d != null) { + put(key, d); + return super.get(key); + } + return null; + } + + // overrider + @Override + final public ImageDescriptor getDescriptor(String key) { + ImageDescriptor d = super.getDescriptor(key); + if (d != null) { + return d; + } + + d = createFileImageDescriptor(key); + if (d != null) { + put(key, d); + return d; + } + return null; + } + + private ImageDescriptor createFileImageDescriptor(String key) { + URL url = fBaseUrl; + String pluginId = fPlugins.get(key); + if (pluginId != null) { + Bundle bundle= Platform.getBundle(pluginId); + if (bundle != null) { + url = bundle.getEntry("/"); //$NON-NLS-1$ + } + } + String[] locations= fLocations.get(key); + if (locations != null) { + for (int i = 0; i < locations.length; i++) { + String loc = locations[i]; + URL full; + try { + full = new URL(url, loc); + ImageDescriptor candidate = ImageDescriptor.createFromURL(full); + if (candidate != null && candidate.getImageData() != null) { + return candidate; + } + } catch (MalformedURLException e) { + GdbUIPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, "Malformed Icon URL", e)); //$NON-NLS-1$ + } catch (SWTException e) { + // try the next one. + } + } + } + return null; + } + +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlView.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlView.java new file mode 100644 index 00000000000..6dc7d96e77d --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceControlView.java @@ -0,0 +1,511 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; + +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.RejectedExecutionException; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.DsfRunnable; +import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; +import org.eclipse.cdt.dsf.concurrent.Query; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.DMContexts; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent; +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceStatusDMData; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceVariableDMData; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingStartedDMEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingStoppedDMEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingSupportedChangeDMEvent; +import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; +import org.eclipse.cdt.dsf.service.DsfServicesTracker; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.cdt.dsf.service.DsfSession.SessionEndedListener; +import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.ui.DebugUITools; +import org.eclipse.debug.ui.IDebugUIConstants; +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.custom.StyledText; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IMemento; +import org.eclipse.ui.ISelectionListener; +import org.eclipse.ui.IViewPart; +import org.eclipse.ui.IViewSite; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.PartInitException; +import org.eclipse.ui.actions.ActionFactory; +import org.eclipse.ui.part.ViewPart; + +/** + * TraceControlView Part + * + * This view is used to control Tracing. + * + * @since 2.1 + */ +public class TraceControlView extends ViewPart implements IViewPart, SessionEndedListener { + + private static final String EMPTY_STRING = ""; //$NON-NLS-1$ + + public class FailedTraceVariableCreationException extends Exception { + private static final long serialVersionUID = -3042693455630687285L; + + FailedTraceVariableCreationException() {} + + FailedTraceVariableCreationException(String errorMessage) { + super(errorMessage); + } + } + + /** + * Action to refresh the content of the view. + */ + private final class ActionRefreshView extends Action { + public ActionRefreshView() { + setText(TracepointsMessages.TraceControlView_action_Refresh_label); + setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Refresh_enabled)); + setDisabledImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Refresh_disabled)); + } + @Override + public void run() { + updateContent(); + } + } + + private final class ActionOpenTraceVarDetails extends Action { + public ActionOpenTraceVarDetails() { + setText(TracepointsMessages.TraceControlView_action_trace_variable_details); + setImageDescriptor(TracepointImageRegistry.getImageDescriptor(TracepointImageRegistry.ICON_Trace_Variables)); + } + @Override + public void run() { + Shell shell = Display.getDefault().getActiveShell(); + TraceVarDetailsDialog dialog = new TraceVarDetailsDialog(shell, TraceControlView.this); + dialog.open(); + } + } + + private ISelectionListener fDebugViewListener = null; + private String fDebugSessionId = null; + private DsfServicesTracker fServicesTracker = null; + private volatile ITraceTargetDMContext fTargetContext = null; + + private StyledText fStatusText = null; + protected Action fActionRefreshView = null; + protected Action fOpenTraceVarDetails = null; + private boolean fTracingSupported = false; + + public TraceControlView() { + } + + @Override + public void init(IViewSite site) throws PartInitException { + super.init(site); + site.getPage().addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, + fDebugViewListener = new ISelectionListener() { + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + updateDebugContext(); + }}); + } + + @Override + public void init(IViewSite site, IMemento memento) throws PartInitException { + init(site); + } + + @Override + public void createPartControl(Composite parent) { + Composite composite = new Composite(parent, SWT.NONE); + GridLayout layout = new GridLayout(1, false); + composite.setLayout(layout); + + // Let's just create a place to put a text status for now. + // A fancier display would be nicer though + fStatusText = new StyledText(composite, SWT.MULTI); + GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true); + fStatusText.setLayoutData(gd); + fStatusText.setEditable(false); + fStatusText.setCaret(null); + + createActions(); + + if (fDebugSessionId != null) { + debugSessionChanged(); + } else { + updateDebugContext(); + } + DsfSession.addSessionEndedListener(this); + } + + protected void createActions() { + IActionBars bars = getViewSite().getActionBars(); + IToolBarManager manager = bars.getToolBarManager(); + + // Create the action to refresh the view + fActionRefreshView = new ActionRefreshView(); + bars.setGlobalActionHandler(ActionFactory.REFRESH.getId(), fActionRefreshView); + manager.add(fActionRefreshView); + + // Create the action to open the trace variable details + fOpenTraceVarDetails = new ActionOpenTraceVarDetails(); + manager.add(fOpenTraceVarDetails); + + bars.updateActionBars(); + updateActionEnablement(); + } + + @Override + public void dispose() { + getSite().getPage().removeSelectionListener(fDebugViewListener); + setDebugContext(null); + super.dispose(); + } + + protected void updateContent() { + asyncExec(new Runnable() { + public void run() { + String content = ""; //$NON-NLS-1$ + String status = retrieveStatus(); + if (status != null && status.length() > 0) { + Calendar cal = Calendar.getInstance(); + SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$ + + content = TracepointsMessages.TraceControlView_trace_view_content_updated_label + + sdf.format(cal.getTime()) + "\n" + status; //$NON-NLS-1$ + } + fStatusText.setText(content); + updateActionEnablement(); + }}); + } + + protected String retrieveStatus() { + if (fDebugSessionId == null) { + return EMPTY_STRING; + } + + final ITraceTargetDMContext ctx = DMContexts.getAncestorOfType(fTargetContext, ITraceTargetDMContext.class); + if (ctx == null) { + return EMPTY_STRING; + } + + Query<ITraceStatusDMData> query = new Query<ITraceStatusDMData>() { + @Override + protected void execute(DataRequestMonitor<ITraceStatusDMData> rm) { + final IGDBTraceControl traceControl = getService(IGDBTraceControl.class); + if (traceControl != null) { + traceControl.getTraceStatus(ctx, rm); + } else { + rm.setData(null); + rm.done(); + } + } + }; + try { + getSession().getExecutor().execute(query); + ITraceStatusDMData data = query.get(); + if (data != null) { + fTracingSupported = data.isTracingSupported(); + if (fTracingSupported) return data.toString(); + } else { + fTracingSupported = false; + } + } catch (InterruptedException exc) { + } catch (ExecutionException exc) { + } + + return EMPTY_STRING; + } + + protected void updateDebugContext() { + IAdaptable debugContext = DebugUITools.getDebugContext(); + if (debugContext instanceof IDMVMContext) { + setDebugContext((IDMVMContext)debugContext); + } else { + setDebugContext(null); + } + } + + protected void setDebugContext(IDMVMContext vmContext) { + if (vmContext != null) { + IDMContext dmContext = vmContext.getDMContext(); + String sessionId = dmContext.getSessionId(); + fTargetContext = DMContexts.getAncestorOfType(dmContext, ITraceTargetDMContext.class); + if (!sessionId.equals(fDebugSessionId)) { + if (fDebugSessionId != null && getSession() != null) { + try { + final DsfSession session = getSession(); + session.getExecutor().execute(new DsfRunnable() { + public void run() { + session.removeServiceEventListener(TraceControlView.this); + } + }); + } catch (RejectedExecutionException e) { + // Session is shut down. + } + } + fDebugSessionId = sessionId; + if (fServicesTracker != null) { + fServicesTracker.dispose(); + } + fServicesTracker = new DsfServicesTracker(GdbUIPlugin.getBundleContext(), sessionId); + debugSessionChanged(); + } + } else if (fDebugSessionId != null) { + if (getSession() != null) { + try { + final DsfSession session = getSession(); + session.getExecutor().execute(new DsfRunnable() { + public void run() { + session.removeServiceEventListener(TraceControlView.this); + } + }); + } catch (RejectedExecutionException e) { + // Session is shut down. + } + } + fDebugSessionId = null; + fTargetContext = null; + if (fServicesTracker != null) { + fServicesTracker.dispose(); + fServicesTracker = null; + } + debugSessionChanged(); + } + } + + private void debugSessionChanged() { + // When dealing with a new debug session, assume tracing is not supported. + // updateContent() will fix it + fTracingSupported = false; + + if (fDebugSessionId != null) { + try { + final DsfSession session = getSession(); + session.getExecutor().execute(new DsfRunnable() { + public void run() { + session.addServiceEventListener(TraceControlView.this, null); + } + }); + } catch (RejectedExecutionException e) { + // Session is shut down. + } + } + + updateContent(); + } + + protected void updateActionEnablement() { + enableActions(fTracingSupported); + } + + protected void enableActions(boolean enabled) { + fOpenTraceVarDetails.setEnabled(enabled); + fActionRefreshView.setEnabled(enabled); + } + + private void asyncExec(Runnable runnable) { + if (fStatusText != null) { + fStatusText.getDisplay().asyncExec(runnable); + } + } + + public void sessionEnded(DsfSession session) { + if (session.getId().equals(fDebugSessionId)) { + asyncExec(new Runnable() { + public void run() { + setDebugContext(null); + }}); + } + } + + /* + * When tracing starts, we know the status has changed + */ + @DsfServiceEventHandler + public void handleEvent(ITracingStartedDMEvent event) { + updateContent(); + } + + /* + * When tracing stops, we know the status has changed + */ + @DsfServiceEventHandler + public void handleEvent(ITracingStoppedDMEvent event) { + updateContent(); + } + + /* + * Since something suspended, might as well refresh our status + * to show the latest. + */ + @DsfServiceEventHandler + public void handleEvent(ISuspendedDMEvent event) { + updateContent(); + } + + /* + * Tracing support has changed, update view + */ + @DsfServiceEventHandler + public void handleEvent(ITracingSupportedChangeDMEvent event) { + updateContent(); + } + + + @Override + public void setFocus() { + if (fStatusText != null) { + fStatusText.setFocus(); + } + } + + private DsfSession getSession() { + return DsfSession.getSession(fDebugSessionId); + } + + private <V> V getService(Class<V> serviceClass) { + if (fServicesTracker != null) { + return fServicesTracker.getService(serviceClass); + } + return null; + } + + /** + * Get the list of trace variables from the backend. + * + * @return null when the list cannot be obtained. + */ + public ITraceVariableDMData[] getTraceVarList() { + if (fDebugSessionId == null) { + return null; + } + + final ITraceTargetDMContext ctx = DMContexts.getAncestorOfType(fTargetContext, ITraceTargetDMContext.class); + if (ctx == null) { + return null; + } + + Query<ITraceVariableDMData[]> query = new Query<ITraceVariableDMData[]>() { + @Override + protected void execute(final DataRequestMonitor<ITraceVariableDMData[]> rm) { + final IGDBTraceControl traceControl = getService(IGDBTraceControl.class); + + if (traceControl != null) { + traceControl.getTraceVariables(ctx, + new DataRequestMonitor<ITraceVariableDMData[]>(getSession().getExecutor(), rm) { + @Override + protected void handleCompleted() { + if (isSuccess()) { + rm.setData(getData()); + } else { + rm.setData(null); + } + rm.done(); + }; + + }); + } else { + rm.setData(null); + rm.done(); + } + } + }; + try { + getSession().getExecutor().execute(query); + return query.get(); + } catch (InterruptedException exc) { + } catch (ExecutionException exc) { + } + + return null; + } + + /** + * Create a new trace variable in the backend. + * + * @throws FailedTraceVariableCreationException when the creation fails. The exception + * will contain the error message to display to the user. + */ + protected void createVariable(final String name, final String value) throws FailedTraceVariableCreationException { + if (fDebugSessionId == null) { + throw new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_create_variable_error); + } + + final ITraceTargetDMContext ctx = DMContexts.getAncestorOfType(fTargetContext, ITraceTargetDMContext.class); + if (ctx == null) { + throw new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_create_variable_error); + } + + Query<String> query = new Query<String>() { + @Override + protected void execute(final DataRequestMonitor<String> rm) { + final IGDBTraceControl traceControl = getService(IGDBTraceControl.class); + + if (traceControl != null) { + traceControl.createTraceVariable(ctx, name, value, + new RequestMonitor(getSession().getExecutor(), rm) { + @Override + protected void handleFailure() { + String message = TracepointsMessages.TraceControlView_create_variable_error; + Throwable t = getStatus().getException(); + if (t != null) { + message = t.getMessage(); + } + FailedTraceVariableCreationException e = + new FailedTraceVariableCreationException(message); + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Backend error", e)); + rm.done(); + }; + }); + } else { + FailedTraceVariableCreationException e = + new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_trace_variable_tracing_unavailable); + rm.setStatus(new Status(IStatus.ERROR, GdbUIPlugin.PLUGIN_ID, IDsfStatusConstants.INVALID_STATE, "Tracing unavailable", e)); + rm.done(); + } + } + }; + try { + getSession().getExecutor().execute(query); + query.get(); + } catch (InterruptedException e) { + // Session terminated + } catch (ExecutionException e) { + Throwable t = e.getCause(); + if (t instanceof CoreException) { + t = ((CoreException)t).getStatus().getException(); + if (t instanceof FailedTraceVariableCreationException) { + throw (FailedTraceVariableCreationException)t; + } + } + throw new FailedTraceVariableCreationException(TracepointsMessages.TraceControlView_create_variable_error); + } + } +} + diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceVarDetailsDialog.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceVarDetailsDialog.java new file mode 100644 index 00000000000..0e2ddc00679 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TraceVarDetailsDialog.java @@ -0,0 +1,311 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; + +import java.text.Collator; +import java.util.Locale; + +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints.TraceControlView.FailedTraceVariableCreationException; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceVariableDMData; +import org.eclipse.jface.dialogs.Dialog; +import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; +import org.eclipse.swt.events.FocusEvent; +import org.eclipse.swt.events.FocusListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.graphics.Image; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Button; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.swt.widgets.TableItem; +import org.eclipse.swt.widgets.Text; +import org.eclipse.ui.plugin.AbstractUIPlugin; + +public final class TraceVarDetailsDialog extends Dialog { + + private Button createButton = null; + private Button refreshButton = null; + private Table table = null; + private TraceControlView fView = null; + private Text nameInput = null; + private Text valueInput = null; + private Image warningImage = null; + private Label warningIconLabel = null; + private Label warningTextLabel = null; + + public TraceVarDetailsDialog(Shell shell, TraceControlView view) { + super(shell); + setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX); + fView = view; + } + + @Override + protected Control createDialogArea(Composite parent) { + getShell().setText(TracepointsMessages.TraceControlView_trace_variable_details_dialog_title); + + Composite composite = new Composite(parent, SWT.NONE); + GridLayout gridLayout = new GridLayout(1, false); + composite.setLayout(gridLayout); + composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + // Create the table to show the existing variables and their values + Composite tableComposite = new Composite(composite, SWT.NONE); + gridLayout = new GridLayout(1, false); + tableComposite.setLayout(gridLayout); + tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); + + table = new Table(tableComposite, SWT.BORDER | SWT.HIDE_SELECTION); + + final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); + gridData.heightHint = 6 * table.getItemHeight(); + table.setLayoutData(gridData); + table.setLinesVisible(true); + table.setHeaderVisible(true); + + final TableColumn nameTableColumn = new TableColumn(table, SWT.NONE); + nameTableColumn.setWidth(150); + nameTableColumn.setText(TracepointsMessages.TraceControlView_trace_variable_details_column_name); + nameTableColumn.setAlignment(SWT.LEFT); + + final TableColumn initValTableColumn = new TableColumn(table, SWT.NONE); + initValTableColumn.setWidth(120); + initValTableColumn.setText(TracepointsMessages.TraceControlView_trace_variable_details_column_init_value); + initValTableColumn.setAlignment(SWT.RIGHT); + + final TableColumn currentValTableColumn = new TableColumn(table, SWT.NONE); + currentValTableColumn.setWidth(120); + currentValTableColumn.setText(TracepointsMessages.TraceControlView_trace_variable_details_column_curr_value); + currentValTableColumn.setAlignment(SWT.RIGHT); + + refreshButton = new Button(tableComposite, SWT.NONE); + refreshButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false, 2, 1)); + refreshButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + handleRefresh(); + } + }); + refreshButton.setText(TracepointsMessages.TraceControlView_trace_variable_details_refresh_button); + refreshButton.setEnabled(true); + + Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); + separator.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + // Create the section to create a new variable + Composite createComposite = new Composite(composite, SWT.NONE); + gridLayout = new GridLayout(1, false); + createComposite.setLayout(gridLayout); + createComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + // Now a composite just for the input + Composite inputComposite = new Composite(createComposite, SWT.NONE); + gridLayout = new GridLayout(2, false); + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + inputComposite.setLayout(gridLayout); + inputComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); + + Label nameLabel = new Label(inputComposite, SWT.NONE); + nameLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); + nameLabel.setText(TracepointsMessages.TraceControlView_trace_variable_details_name_label); + nameInput = new Text(inputComposite, SWT.BORDER); + nameInput.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + Label valueLabel = new Label(inputComposite, SWT.NONE); + valueLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); + valueLabel.setText(TracepointsMessages.TraceControlView_trace_variable_details_value_label); + valueInput = new Text(inputComposite, SWT.BORDER); + valueInput.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + // And a composite for the create button and its warning icon and text + Composite createButtonComposite = new Composite(createComposite, SWT.NONE); + gridLayout = new GridLayout(3, false); + gridLayout.marginWidth = 0; + gridLayout.marginHeight = 0; + createButtonComposite.setLayout(gridLayout); + createButtonComposite.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + + createButton = new Button(createButtonComposite, SWT.NONE); + createButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); + createButton.addSelectionListener(new SelectionAdapter() { + @Override + public void widgetSelected(SelectionEvent e) { + handleCreate(); + } + }); + createButton.setText(TracepointsMessages.TraceControlView_trace_variable_details_create_button); + createButton.setEnabled(true); + + warningIconLabel = new Label(createButtonComposite, SWT.NONE); + warningIconLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false)); + + warningImage = AbstractUIPlugin + .imageDescriptorFromPlugin( + GdbUIPlugin.PLUGIN_ID, "icons/full/obj16/warning.gif").createImage(); //$NON-NLS-1$ + warningIconLabel.setImage(warningImage); + warningIconLabel.setVisible(false); + + warningTextLabel = new Label(createButtonComposite, SWT.NONE); + warningTextLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + if (warningImage != null) + warningImage.dispose(); + } + }); + + // When the user goes into either input field, then pressing return + // should try to create the command + FocusListener clearWarningFocusListener = new FocusListener() { + public void focusGained(FocusEvent e) { + getShell().setDefaultButton(createButton); + } + public void focusLost(FocusEvent e) { + } + }; + + nameInput.addFocusListener(clearWarningFocusListener); + valueInput.addFocusListener(clearWarningFocusListener); + + // When the user modifies any entry in the input, we should clear any warning + ModifyListener clearWarningListener = new ModifyListener() { + public void modifyText(ModifyEvent e) { + setWarningVisible(false); + } + }; + + nameInput.addModifyListener(clearWarningListener); + valueInput.addModifyListener(clearWarningListener); + + resetInputFields(); + handleRefresh(); + + return composite; + } + + /** + * Set the visibility of the warning. Should be set to true when there + * is a problem creating the specific variable; false otherwise + * + * @param visible + * True for visible, false for hidden. + */ + public void setWarningVisible(boolean visible) { + if (warningIconLabel == null) + return; + warningIconLabel.setVisible(visible); + + if (visible == false) { + if (warningTextLabel != null) { + warningTextLabel.setText(""); //$NON-NLS-1$ + } + } + } + + /** + * Set the visibility of the warning icon to true and set its + * text to the parameter message. + */ + public void setWarningVisible(String message) { + if (warningIconLabel == null || warningTextLabel == null) + return; + warningTextLabel.setText(message); + warningIconLabel.setVisible(true); + nameInput.setFocus(); + } + + @Override + protected void createButtonsForButtonBar(Composite parent) { + // create Close button only + createButton(parent, IDialogConstants.CLOSE_ID, IDialogConstants.CLOSE_LABEL, + true); + } + + @Override + protected void buttonPressed(int buttonId) { + if (IDialogConstants.CLOSE_ID == buttonId) { + close(); + } + } + + protected void handleRefresh() { + ITraceVariableDMData[] vars = fView.getTraceVarList(); + table.removeAll(); + for (ITraceVariableDMData var : vars) { + String currentVal = var.getValue(); + if (currentVal == null) { + currentVal = ""; //$NON-NLS-1$ + } + addTableItem(var.getName(), var.getInitialValue(), currentVal); + } + } + + private void addTableItem(String name, String initVal, String currentVal) { + // Find where to insert the new element + int index = -1; + TableItem[] items = table.getItems(); + Collator collator = Collator.getInstance(Locale.getDefault()); + for (int i = 0; i < items.length; i++) { + String rowName = items[i].getText(0); + if (collator.compare(name, rowName) < 0) { + index = i; + break; + } + } + + if (index == -1) { + index = items.length; + } + + TableItem tableItem = new TableItem(table, SWT.NONE, index); + tableItem.setText(0, name); + tableItem.setText(1, initVal); + tableItem.setText(2, currentVal); + } + + protected void resetInputFields() { + nameInput.setText(""); //$NON-NLS-1$ + valueInput.setText("0"); //$NON-NLS-1$ + } + + protected void handleCreate() { + String name = nameInput.getText(); + if (name != null && name.length() > 0) { + String value = valueInput.getText(); + if (value != null && value.length() == 0) { + value = null; // No value specified + } + + try { + fView.createVariable(name, value); + resetInputFields(); + nameInput.setFocus(); + handleRefresh(); + } catch (FailedTraceVariableCreationException e) { + setWarningVisible(e.getMessage()); + } + } else { + setWarningVisible(TracepointsMessages.TraceControlView_create_variable_empty_name_error); + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointImageRegistry.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointImageRegistry.java new file mode 100644 index 00000000000..a3c338597c9 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointImageRegistry.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.core.runtime.Plugin; +import org.eclipse.jface.resource.ImageDescriptor; + +/** + * @since 2.1 + */ +public class TracepointImageRegistry extends AbstractImageRegistry { + private static List<Object[]> fStore = new ArrayList<Object[]>(); + + private static String add(String plugin, String[] dirs, String name) { + String key = plugin+'/'+dirs[0]+'/'+name; + fStore.add(new Object[] {key, plugin, dirs, name}); + return key; + } + + private static final String ORG_ECLIPSE_UI_PLUGIN_ID = "org.eclipse.ui"; //$NON-NLS-1$ + private static final String ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID = "org.eclipse.cdt.dsf.gdb.ui"; //$NON-NLS-1$ + + public static final String ICON_Refresh_enabled = add(ORG_ECLIPSE_UI_PLUGIN_ID, new String[] {"full/elcl16"}, "refresh_nav.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Refresh_disabled = add(ORG_ECLIPSE_UI_PLUGIN_ID, new String[] {"full/dlcl16"}, "refresh_nav.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + public static final String ICON_Trace_Variables = add(ORG_ECLIPSE_CDT_DSF_GDB_UI_PLUGIN_ID, new String[] {"full/obj16"}, "tracevariables.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + private static TracepointImageRegistry INSTANCE= new TracepointImageRegistry(GdbUIPlugin.getDefault()); + + TracepointImageRegistry(Plugin plugin) { + super(plugin); + initialize(); + } + + void initialize() { + for (Iterator<Object[]> iter = fStore.iterator(); iter.hasNext();) { + Object[] element = iter.next(); + if (element.length == 2) { + String dir= (String) element[0]; + String name= (String) element[1]; + localImage(name, dir, name); + } else { + String key = (String) element[0]; + String plugin= (String) element[1]; + String[] dirs= (String[]) element[2]; + String name= (String) element[3]; + externalImage(key, plugin, dirs, name); + } + } + } + + public static ImageDescriptor getImageDescriptor(String key) { + return INSTANCE.getDescriptor(key); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.java new file mode 100644 index 00000000000..899e479fd44 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * Copyright (c) 2010 Wind River Systems and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Wind River Systems - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints; + +import org.eclipse.osgi.util.NLS; + +/** + * @since 2.1 + */ +public final class TracepointsMessages extends NLS { + + private static final String BUNDLE_NAME = "org.eclipse.cdt.dsf.gdb.internal.ui.tracepoints.TracepointsMessages";//$NON-NLS-1$ + + private TracepointsMessages() { + // Do not instantiate + } + + public static String TraceControlView_action_Refresh_label; + public static String TraceControlView_trace_view_content_updated_label; + public static String TraceControlView_action_trace_variable_details; + public static String TraceControlView_trace_variable_invalid_value; + public static String TraceControlView_trace_variable_tracing_unavailable; + public static String TraceControlView_trace_variable_details_dialog_title; + public static String TraceControlView_trace_variable_details_column_name; + public static String TraceControlView_trace_variable_details_column_init_value; + public static String TraceControlView_trace_variable_details_column_curr_value; + public static String TraceControlView_trace_variable_details_refresh_button; + public static String TraceControlView_trace_variable_details_create_button; + public static String TraceControlView_trace_variable_details_name_label; + public static String TraceControlView_trace_variable_details_value_label; + public static String TraceControlView_create_variable_error; + public static String TraceControlView_create_variable_empty_name_error; + + static { + NLS.initializeMessages(BUNDLE_NAME, TracepointsMessages.class); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.properties b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.properties new file mode 100644 index 00000000000..1973ad04244 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/tracepoints/TracepointsMessages.properties @@ -0,0 +1,26 @@ +########################################################################## +# Copyright (c) 2010 Ericsson and others. +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Eclipse Public License v1.0 +# which accompanies this distribution, and is available at +# http://www.eclipse.org/legal/epl-v10.html +# +# Contributors: +# Ericsson - initial API and implementation +########################################################################## + +TraceControlView_action_Refresh_label=Refresh +TraceControlView_trace_view_content_updated_label=Last updated at: +TraceControlView_action_trace_variable_details=Manage Trace Variables +TraceControlView_trace_variable_invalid_value=Initial value must be an integer +TraceControlView_trace_variable_tracing_unavailable=Tracing unavailable +TraceControlView_trace_variable_details_dialog_title=Trace Variable Details +TraceControlView_trace_variable_details_column_name=Name +TraceControlView_trace_variable_details_column_init_value=Initial Value +TraceControlView_trace_variable_details_column_curr_value=Current Value +TraceControlView_trace_variable_details_refresh_button=Refresh +TraceControlView_trace_variable_details_create_button=Create +TraceControlView_trace_variable_details_name_label=Name: +TraceControlView_trace_variable_details_value_label=Value: +TraceControlView_create_variable_error=Error creating trace variable +TraceControlView_create_variable_empty_name_error=Cannot create variable with empty name
\ No newline at end of file diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMProvider.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMProvider.java index a038d4748db..4dbe31966ce 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMProvider.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb.ui/src/org/eclipse/cdt/dsf/gdb/internal/ui/viewmodel/launch/LaunchVMProvider.java @@ -14,6 +14,7 @@ package org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch; import java.util.concurrent.RejectedExecutionException; import org.eclipse.cdt.dsf.concurrent.DsfRunnable; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.ThreadSafe; import org.eclipse.cdt.dsf.debug.service.ICachingService; import org.eclipse.cdt.dsf.debug.service.IProcesses; @@ -26,6 +27,9 @@ import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.LaunchRootVMNode; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.StackFramesVMNode; import org.eclipse.cdt.dsf.debug.ui.viewmodel.launch.StandardProcessVMNode; import org.eclipse.cdt.dsf.gdb.internal.ui.GdbUIPlugin; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingStartedDMEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingStoppedDMEvent; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITracingSupportedChangeDMEvent; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.DsfSession; import org.eclipse.cdt.dsf.ui.viewmodel.AbstractVMAdapter; @@ -70,8 +74,42 @@ public class LaunchVMProvider extends AbstractLaunchVMProvider { return false; } + + if (eventToSkip instanceof ITracingStartedDMEvent || + eventToSkip instanceof ITracingStoppedDMEvent) + { + if (newEvent instanceof ITracingStartedDMEvent || + newEvent instanceof ITracingStoppedDMEvent) + { + return true; + } + } + + if (eventToSkip instanceof ITracingSupportedChangeDMEvent) + { + if (newEvent instanceof ITracingSupportedChangeDMEvent) + { + return true; + } + } return super.canSkipHandlingEvent(newEvent, eventToSkip); } + + @Override + public void handleEvent(Object event, RequestMonitor rm) { + if (event instanceof ITracingStartedDMEvent || + event instanceof ITracingStoppedDMEvent || + event instanceof ITracingSupportedChangeDMEvent) + { + // Refresh the view to trigger a context change, which + // will cause command enablement to be refreshed + refresh(); + rm.done(); + return; + } + + super.handleEvent(event, rm); + } @Override public void refresh() { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java index e57a2366bc9..dddadf2dc0e 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ServicesLaunchSequence.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2009 Wind River Systems and others. + * Copyright (c) 2010 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -9,6 +9,7 @@ * Wind River Systems - initial API and implementation * Nokia - created GDBBackend service. Sep. 2008 * IBM Corporation + * Ericsson - Support for Tracing Control service *******************************************************************************/ package org.eclipse.cdt.dsf.gdb.launching; @@ -27,6 +28,7 @@ import org.eclipse.cdt.dsf.debug.service.ISourceLookup; import org.eclipse.cdt.dsf.debug.service.IStack; import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext; import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; import org.eclipse.cdt.dsf.mi.service.CSourceLookup; import org.eclipse.cdt.dsf.mi.service.IMIBackend; import org.eclipse.cdt.dsf.mi.service.IMIProcesses; @@ -111,6 +113,16 @@ public class ServicesLaunchSequence extends Sequence { public void execute(RequestMonitor requestMonitor) { fLaunch.getServiceFactory().createService(IDisassembly.class, fSession).initialize(requestMonitor); }}, + new Step() { @Override + public void execute(RequestMonitor requestMonitor) { + IGDBTraceControl traceService = fLaunch.getServiceFactory().createService(IGDBTraceControl.class, fSession, fLaunch.getLaunchConfiguration()); + // Note that for older versions of GDB, we don't support tracing, so there is no trace service. + if (traceService != null) { + traceService.initialize(requestMonitor); + } else { + requestMonitor.done(); + } + }}, }; DsfSession fSession; diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ShutdownSequence.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ShutdownSequence.java index e89f4607f9a..6962aeaf8b1 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ShutdownSequence.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/launching/ShutdownSequence.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2006, 2008 Wind River Systems and others. + * Copyright (c) 2010 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,7 +11,6 @@ package org.eclipse.cdt.dsf.gdb.launching; import org.eclipse.cdt.dsf.concurrent.DsfExecutor; -import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants; import org.eclipse.cdt.dsf.concurrent.RequestMonitor; import org.eclipse.cdt.dsf.concurrent.Sequence; import org.eclipse.cdt.dsf.debug.service.IBreakpoints; @@ -26,12 +25,11 @@ import org.eclipse.cdt.dsf.debug.service.ISourceLookup; import org.eclipse.cdt.dsf.debug.service.IStack; import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl; import org.eclipse.cdt.dsf.mi.service.IMIBackend; import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager; import org.eclipse.cdt.dsf.service.DsfServicesTracker; import org.eclipse.cdt.dsf.service.IDsfService; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; public class ShutdownSequence extends Sequence { @@ -70,6 +68,11 @@ public class ShutdownSequence extends Sequence { }, new Step() { @Override public void execute(RequestMonitor requestMonitor) { + shutdownService(IGDBTraceControl.class, requestMonitor); + } + }, new Step() { + @Override + public void execute(RequestMonitor requestMonitor) { shutdownService(IDisassembly.class, requestMonitor); } }, new Step() { @@ -155,8 +158,8 @@ public class ShutdownSequence extends Sequence { } }); } else { - requestMonitor.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, - "Service '" + clazz.getName() + "' not found.", null)); //$NON-NLS-1$//$NON-NLS-2$ + // It is possible that a particular service was not instantiated at all + // depending on our backend requestMonitor.done(); } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_1.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_1.java new file mode 100644 index 00000000000..6bc9fdc7b03 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GDBTraceControl_7_1.java @@ -0,0 +1,773 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.service; + +import java.util.Hashtable; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.debug.service.ICachingService; +import org.eclipse.cdt.dsf.debug.service.command.CommandCache; +import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService; +import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; +import org.eclipse.cdt.dsf.mi.service.command.commands.MITargetSelectTFile; +import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceDefineVariable; +import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceListVariables; +import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceSave; +import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceStart; +import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceStatus; +import org.eclipse.cdt.dsf.mi.service.command.commands.MITraceStop; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStatusInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStopInfo; +import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo.MITraceVariableInfo; +import org.eclipse.cdt.dsf.service.AbstractDsfService; +import org.eclipse.cdt.dsf.service.DsfSession; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.osgi.framework.BundleContext; + +/** + * This class implements the ITraceControl interface which gives access + * to the debugger's tracing functionality. + * + * @since 2.1 + */ +public class GDBTraceControl_7_1 extends AbstractDsfService implements IGDBTraceControl, ICachingService { + +// @Immutable +// private static final class MITraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext { +// +// // The trace record reference +// private final int fReference; +// +// /** +// * @param session the DsfSession for this service +// * @param parents the parent contexts +// * @param reference the trace record reference +// */ +// public MITraceRecordDMContext(DsfSession session, IDMContext[] parents, int reference) { +// super(session.getId(), parents); +// fReference = reference; +// } +// +// public int getReference() { +// return fReference; +// } +// +// /* (non-Javadoc) +// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object) +// */ +// @Override +// public boolean equals(Object obj) { +// return baseEquals(obj) && (fReference == ((MITraceRecordDMContext) obj).fReference); +// } +// +// /* (non-Javadoc) +// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode() +// */ +// @Override +// public int hashCode() { +// return baseHashCode() + fReference; +// } +// +// /* (non-Javadoc) +// * @see java.lang.Object#toString() +// */ +// @Override +// public String toString() { +// return baseToString() + ".reference(" + fReference + ")"; //$NON-NLS-1$//$NON-NLS-2$ +// } +// } +// +// /** +// * Trace record context used to indicate that there is no current trace record selected. +// */ +// @Immutable +// private static final class InvalidTraceRecordDMContext extends AbstractDMContext implements ITraceRecordDMContext { +// +// /** +// * @param session the DsfSession for this service +// * @param parents the parent contexts +// * @param reference the trace record reference +// */ +// public InvalidTraceRecordDMContext(DsfSession session, IDMContext[] parents) { +// super(session.getId(), parents); +// } +// +// +// /* (non-Javadoc) +// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#equals(java.lang.Object) +// */ +// @Override +// public boolean equals(Object obj) { +// return baseEquals(obj); +// } +// +// /* (non-Javadoc) +// * @see org.eclipse.cdt.dsf.datamodel.AbstractDMContext#hashCode() +// */ +// @Override +// public int hashCode() { +// return baseHashCode(); +// } +// +// /* (non-Javadoc) +// * @see java.lang.Object#toString() +// */ +// @Override +// public String toString() { +// return baseToString() + ".noTraceRecord"; //$NON-NLS-1$ +// } +// } +// +// @Immutable +// private static class MITraceRecordDMData implements ITraceRecordDMData { +// private final String fData; +// +// public MITraceRecordDMData(String data) { +// fData = data; +// } +// +// public String getData() { return fData; } +// } + + private class TraceVariableDMData implements ITraceVariableDMData { + private String fName; + private String fValue; + private String fInitialValue; + + public TraceVariableDMData(String name, String value) { + this(name, value, null); + } + + public TraceVariableDMData(String name, String initial, String value) { + fName = name; + fInitialValue = initial; + fValue = value; + } + + public String getName() { + return fName; + } + + public String getValue() { + return fValue; + } + + public String getInitialValue() { + return fInitialValue; + } + } + + private class TraceStatusDMData implements ITraceStatusDMData { + private int fFreeBufferSize; + private int fTotalBufferSize; + private int fNumberOfCollectedFrames; + private boolean fTracingActive; + private boolean fTracingSupported; + private STOP_REASON_ENUM fStopReason; + private Integer fStoppingTracepoint; + + /** + * Create a status when tracing is supported + */ + public TraceStatusDMData(boolean active, int free, int total, int frames, + STOP_REASON_ENUM reason, Integer tracepoint) { + fFreeBufferSize = free; + fTotalBufferSize = total; + fNumberOfCollectedFrames = frames; + fTracingActive = active; + fTracingSupported = true; + fStopReason = reason; + fStoppingTracepoint = tracepoint; + } + + /** + * Status without a Stop reason + */ + public TraceStatusDMData(boolean active, int free, int total, int frames) { + this(active, free, total, frames, null, null); + } + + /** + * Create a status when tracing is not supported + */ + public TraceStatusDMData() { + this(false, 0, 0, 0); + fTracingSupported = false; + } + + public int getFreeBufferSize() { + return fFreeBufferSize; + } + + public int getNumberOfCollectedFrame() { + return fNumberOfCollectedFrames; + } + + public int getTotalBufferSize() { + return fTotalBufferSize; + } + + public boolean isTracingActive() { + return fTracingActive; + } + + public boolean isTracingSupported() { + return fTracingSupported; + } + + public STOP_REASON_ENUM getStopReason() { + return fStopReason; + } + + public Integer getStoppingTracepoint() { + if (fStopReason == null) { + return null; + } + return fStoppingTracepoint; + } + + @SuppressWarnings("nls") + @Override + public String toString() { + String str = "\n"; + + if (!fTracingSupported) { + return "\nTracing is not supported\n"; + } + + str += "Tracing is currently" + (!fTracingActive ? " not":"") + " active\n"; + str += "Buffer contains " + fNumberOfCollectedFrames + " trace frame" + + (fNumberOfCollectedFrames>1?"s":"") + "\n";//" (out of ? created in total)\n"; + str += "Currently using " + (fTotalBufferSize - fFreeBufferSize) + + " bytes out of " + fTotalBufferSize + "\n"; + + if (fStopReason != null) { + assert !fTracingActive; + str += "Tracing stopped because of"; + if (fStopReason == STOP_REASON_ENUM.REQUEST) { + str += " user request"; + } else if (fStopReason == STOP_REASON_ENUM.PASSCOUNT) { + str += " passcount"; + if (fStoppingTracepoint != null) { + str += " of tracepoint number " + fStoppingTracepoint; + } + } else if (fStopReason == STOP_REASON_ENUM.OVERFLOW) { + str += " buffer full"; + } else if (fStopReason == STOP_REASON_ENUM.DISCONNECTION) { + str += " disconnection"; + } else if (fStopReason == STOP_REASON_ENUM.ERROR) { + str += " error"; + } else { + str += " unknow reason"; + } + } + + return str; + } + } + + private static class TracingSupportedChangeEvent extends AbstractDMEvent<ITraceTargetDMContext> + implements ITracingSupportedChangeDMEvent { + private final boolean fTracingSupported; + + public TracingSupportedChangeEvent(ITraceTargetDMContext context, boolean supported) { + super(context); + fTracingSupported = supported; + } + + public boolean isTracingSupported() { + return fTracingSupported; + } + } + + private static class TracingStartedEvent extends AbstractDMEvent<ITraceTargetDMContext> + implements ITracingStartedDMEvent { + public TracingStartedEvent(ITraceTargetDMContext context) { + super(context); + } + } + + private static class TracingStoppedEvent extends AbstractDMEvent<ITraceTargetDMContext> + implements ITracingStoppedDMEvent { + public TracingStoppedEvent(ITraceTargetDMContext context) { + super(context); + } + } + +// private static class TraceRecordSelectedChangedEvent extends AbstractDMEvent<ITraceRecordDMContext> +// implements ITraceRecordSelectedChangedDMEvent { +// public TraceRecordSelectedChangedEvent(ITraceRecordDMContext context) { +// super(context); +// } +// } + + private CommandCache fTraceCache; + private ICommandControlService fConnection; +// private ITraceRecordDMContext fCurrentRecordDmc = null; + + private boolean fIsTracingActive = false; + private boolean fIsTracingSupported = false; + private int fTraceRecordsStored = 0; + + + public GDBTraceControl_7_1(DsfSession session, ILaunchConfiguration config) { + super(session); + } + + /** + * This method initializes this service. + * + * @param requestMonitor + * The request monitor indicating the operation is finished + */ + @Override + public void initialize(final RequestMonitor requestMonitor) { + super.initialize(new RequestMonitor(getExecutor(), requestMonitor) { + @Override + protected void handleSuccess() { + doInitialize(requestMonitor); + } + }); + } + + /** + * This method initializes this service after our superclass's initialize() + * method succeeds. + * + * @param requestMonitor + * The call-back object to notify when this service's + * initialization is done. + */ + private void doInitialize(RequestMonitor requestMonitor) { + + // Register to receive service events for this session. +// getSession().addServiceEventListener(this, null); + + // Register this service. + register(new String[] {IGDBTraceControl.class.getName()}, + new Hashtable<String, String>()); + + + fConnection = getServicesTracker().getService(ICommandControlService.class); + fTraceCache = new CommandCache(getSession(), fConnection); + fTraceCache.setContextAvailable(fConnection.getContext(), true); + + requestMonitor.done(); + } + + /** + * This method shuts down this service. It unregisters the service, stops + * receiving service events, and calls the superclass shutdown() method to + * finish the shutdown process. + * + * @return void + */ + @Override + public void shutdown(RequestMonitor requestMonitor) { + unregister(); +// getSession().removeServiceEventListener(this); + super.shutdown(requestMonitor); + } + + /** + * @return The bundle context of the plug-in to which this service belongs. + */ + @Override + protected BundleContext getBundleContext() { + return GdbPlugin.getBundleContext(); + } + + public void canStartTracing(ITraceTargetDMContext context, final DataRequestMonitor<Boolean> rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + rm.setData(fIsTracingSupported); + rm.done(); + } + + public void startTracing(final ITraceTargetDMContext context, final RequestMonitor rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + canStartTracing(context, new DataRequestMonitor<Boolean>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + if (!getData()) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Cannot start tracing", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + fConnection.queueCommand( + new MITraceStart(context), + new DataRequestMonitor<MIInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + fIsTracingActive = true; + getSession().dispatchEvent(new TracingStartedEvent(context), getProperties()); + rm.done(); + } + }); + } + }); + } + + public void canStopTracing(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + isTracing(context, rm); + } + + public void stopTracing(final ITraceTargetDMContext context, final RequestMonitor rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + canStopTracing(context, new DataRequestMonitor<Boolean>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + if (!getData()) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Cannot stop tracing", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + fConnection.queueCommand( + new MITraceStop(context), + new DataRequestMonitor<MITraceStopInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + MITraceStopInfo info = getData(); + + // Update the tracing state in case it was stopped by the backend + if (fIsTracingActive != info.isTracingActive()) { + fIsTracingActive = info.isTracingActive(); + if (!fIsTracingActive) { + getSession().dispatchEvent(new TracingStoppedEvent(context), getProperties()); + } + } + + fTraceRecordsStored = info.getNumberOfCollectedFrame(); + rm.done(); + } + }); + } + }); + } + + public void isTracing(ITraceTargetDMContext context, final DataRequestMonitor<Boolean> rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // Although tracing can be automatically stopped on the target, we + // don't go to the backend for this call, or we would make too many calls + // Instead, we can use our buffered state; we simply won't know about an + // automatic stop until a forced refresh. (Note that the MI notification + // about automatic stops, is not available until GDB 7.1 is released) + rm.setData(fIsTracingActive); + rm.done(); + } + + public void canSaveTraceData(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + rm.setData(fTraceRecordsStored > 0); + rm.done(); + } + + public void saveTraceData(ITraceTargetDMContext context, String file, boolean remoteSave, RequestMonitor rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + fConnection.queueCommand( + new MITraceSave(context, file, remoteSave), + new DataRequestMonitor<MIInfo>(getExecutor(), rm)); + } + + public void canLoadTraceData(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + rm.setData(true); + rm.done(); + } + + public void loadTraceData(ITraceTargetDMContext context, String file, RequestMonitor rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + fConnection.queueCommand( + new MITargetSelectTFile(context, file), + new DataRequestMonitor<MIInfo>(getExecutor(), rm)); + } + + public void getTraceStatus(final ITraceTargetDMContext context, final DataRequestMonitor<ITraceStatusDMData> rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + fConnection.queueCommand( + new MITraceStatus(context), + new DataRequestMonitor<MITraceStatusInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + MITraceStatusInfo info = getData(); + + if (fIsTracingSupported != info.isTracingSupported()) { + fIsTracingSupported = info.isTracingSupported(); + getSession().dispatchEvent(new TracingSupportedChangeEvent(context, fIsTracingSupported), getProperties()); + } + + if (fIsTracingSupported) { + // Update the tracing state in case it was stopped by the backend + if (fIsTracingActive != info.isTracingActive()) { + fIsTracingActive = info.isTracingActive(); + if (fIsTracingActive) { + getSession().dispatchEvent(new TracingStartedEvent(context), getProperties()); + } else { + getSession().dispatchEvent(new TracingStoppedEvent(context), getProperties()); + } + } + + fTraceRecordsStored = info.getNumberOfCollectedFrame(); + + STOP_REASON_ENUM stopReason = info.getStopReason(); + if (stopReason == null) { + rm.setData(new TraceStatusDMData(info.isTracingActive(), + info.getFreeBufferSize(), + info.getTotalBufferSize(), + info.getNumberOfCollectedFrame())); + } else { + rm.setData(new TraceStatusDMData(info.isTracingActive(), + info.getFreeBufferSize(), + info.getTotalBufferSize(), + info.getNumberOfCollectedFrame(), + stopReason, + info.getStopTracepoint())); + } + } else { + fTraceRecordsStored = 0; + fIsTracingActive = false; + rm.setData(new TraceStatusDMData()); + } + rm.done(); + } + }); + } + + public void createTraceVariable(ITraceTargetDMContext context, + String varName, + String varValue, + RequestMonitor rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + if (varValue == null) { + fConnection.queueCommand( + new MITraceDefineVariable(context, varName), + new DataRequestMonitor<MIInfo>(getExecutor(), rm)); + } else { + fConnection.queueCommand( + new MITraceDefineVariable(context, varName, varValue), + new DataRequestMonitor<MIInfo>(getExecutor(), rm)); + } + } + + + public void getTraceVariables(ITraceTargetDMContext context, final DataRequestMonitor<ITraceVariableDMData[]> rm) { + if (context == null) { + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, "Invalid context", null)); //$NON-NLS-1$ + rm.done(); + return; + } + + // It may be possible to cache this call, if we can figure out that all the cases + // where to data can change, to clear the cache in those cases + fConnection.queueCommand( + new MITraceListVariables(context), + new DataRequestMonitor<MITraceListVariablesInfo>(getExecutor(), rm) { + @Override + protected void handleSuccess() { + MITraceVariableInfo[] vars = getData().getTraceVariables(); + TraceVariableDMData[] varDataArray = new TraceVariableDMData[vars.length]; + for (int i = 0; i < vars.length; i++) { + varDataArray[i] = new TraceVariableDMData(vars[i].getName(), + vars[i].getInitialValue(), + vars[i].getCurrentValue()); + } + + rm.setData(varDataArray); + rm.done(); + } + }); + } +// +// /** +// * Create a trace record context +// */ +// public ITraceRecordDMContext createTraceRecordContext(IDMContext ctx, int index) { +// return new MITraceRecordDMContext(getSession(), new IDMContext[] { ctx }, index); +// } +// +// public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx) { +// if (ctx instanceof InvalidTraceRecordDMContext) { +// // No specified context, so we return the first record context +// return new MITraceRecordDMContext(getSession(), new IDMContext[] { ctx }, 0); +// } +// if (ctx instanceof MITraceRecordDMContext) { +// return new MITraceRecordDMContext(getSession(), +// ctx.getParents(), +// ((MITraceRecordDMContext)ctx).getReference() + 1); +// } +// return null; +// } +// +// public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx) { +// if (ctx instanceof MITraceRecordDMContext) { +// return new MITraceRecordDMContext(getSession(), +// ctx.getParents(), +// ((MITraceRecordDMContext)ctx).getReference() - 1); +// } +// return null; +// } +// +// +// public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm) { +// if (fCurrentRecordDmc == null) { +// drm.setData(new InvalidTraceRecordDMContext(getSession(), new IDMContext[] { context })); +// } else { +// drm.setData(fCurrentRecordDmc); +// } +// drm.done(); +// } +// +// public void selectTraceRecord(final ITraceRecordDMContext context, final RequestMonitor rm) { +// if (context instanceof MITraceRecordDMContext) { +// ITraceTargetDMContext targetDmc = DMContexts.getAncestorOfType(context, ITraceTargetDMContext.class); +// fConnection.queueCommand( +// new MITraceFind(targetDmc, ((MITraceRecordDMContext)context).getReference()), +// new DataRequestMonitor<MITraceFindInfo>(getExecutor(), rm) { +// @Override +// protected void handleSuccess() { +// if (getData().isFound() == false) { +// rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Could not find trace record", null)); //$NON-NLS-1$ +// } else { +// fCurrentRecordDmc = context; +// getSession().dispatchEvent(new TraceRecordSelectedChangedEvent(context), getProperties()); +// } +// rm.done(); +// } +// }); +// } else { +// rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid trace record context.", null)); //$NON-NLS-1$ +// rm.done(); +// } +// } +// +// public void setDefaultCollect(ITraceTargetDMContext context, String[] expressions, RequestMonitor rm) { +// fConnection.queueCommand( +// new MIGDBSetDefaultCollect(context, expressions), +// new DataRequestMonitor<MIInfo>(getExecutor(), rm)); +// } +// +// public void getDefaultCollect(ITraceTargetDMContext context, final DataRequestMonitor<String> rm) { +// // should use a cache and have it reset in setDefaultCommands +// fConnection.queueCommand( +// new MIGDBShowDefaultCollect(context), +// new DataRequestMonitor<MIGDBShowInfo>(getExecutor(), rm) { +// @Override +// protected void handleSuccess() { +// rm.setData(getData().getValue()); +// rm.done(); +// } +// }); +// } +// +// +// public void getTraceRecordData(ITraceRecordDMContext context, +// DataRequestMonitor<ITraceRecordDMData> rm) { +// assert false; +// } +// +// public void saveTracepoints(ITraceTargetDMContext context, +// String file, +// RequestMonitor rm) { +// assert false; +// } +// +// public void loadTracepoints(ITraceTargetDMContext context, +// String file, +// RequestMonitor rm) { +// assert false; +// } +// +// public void saveTraceData(ITraceTargetDMContext context, +// String file, +// RequestMonitor rm) { +// assert false; +// } +// +// public void loadTraceData(ITraceTargetDMContext context, +// String file, +// RequestMonitor rm) { +// assert false; +// } +// +// public void createTraceVariable(IExecutionDMContext context, +// RequestMonitor rm) { +// assert false; +// } + + public void flushCache(IDMContext context) { + fTraceCache.reset(context); + } + +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java index b55c3aa77d5..35b1501b2bc 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/GdbDebugServicesFactory.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2008 Ericsson and others. + * Copyright (c) 2010 Ericsson and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -27,11 +27,11 @@ import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; import org.eclipse.cdt.dsf.gdb.service.command.GDBControl; import org.eclipse.cdt.dsf.gdb.service.command.GDBControl_7_0; import org.eclipse.cdt.dsf.mi.service.CSourceLookup; -import org.eclipse.cdt.dsf.mi.service.MIExpressions; import org.eclipse.cdt.dsf.mi.service.IMIBackend; import org.eclipse.cdt.dsf.mi.service.MIBreakpoints; import org.eclipse.cdt.dsf.mi.service.MIBreakpointsManager; import org.eclipse.cdt.dsf.mi.service.MIDisassembly; +import org.eclipse.cdt.dsf.mi.service.MIExpressions; import org.eclipse.cdt.dsf.mi.service.MIMemory; import org.eclipse.cdt.dsf.mi.service.MIModules; import org.eclipse.cdt.dsf.mi.service.MIRegisters; @@ -71,9 +71,14 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { return (V)createBackendGDBService(session, (ILaunchConfiguration)arg); } } + } else if (IGDBTraceControl.class.isAssignableFrom(clazz)) { + for (Object arg : optionalArguments) { + if (arg instanceof ILaunchConfiguration) { + return (V)createTraceControlService(session, (ILaunchConfiguration)arg); + } + } } - return super.createService(clazz, session); } @@ -154,4 +159,15 @@ public class GdbDebugServicesFactory extends AbstractDsfDebugServicesFactory { protected IStack createStackService(DsfSession session) { return new MIStack(session); } + + /** @since 2.1 */ + protected IGDBTraceControl createTraceControlService(DsfSession session, ILaunchConfiguration config) { + // This service is available for GDB 7.1. But until that GDB is itself available + // there is a pre-release that has a version of 6.8.50.20090414 + if ("6.8.50.20090414".compareTo(fVersion) <= 0) { + return new GDBTraceControl_7_1(session, config); + } + // There is no implementation of the TraceControl service before GDB 7.1 + return null; + } } diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl.java new file mode 100644 index 00000000000..5526e734adb --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/IGDBTraceControl.java @@ -0,0 +1,190 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.gdb.service; + +import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; +import org.eclipse.cdt.dsf.concurrent.Immutable; +import org.eclipse.cdt.dsf.concurrent.RequestMonitor; +import org.eclipse.cdt.dsf.datamodel.IDMContext; +import org.eclipse.cdt.dsf.datamodel.IDMData; +import org.eclipse.cdt.dsf.datamodel.IDMEvent; +import org.eclipse.cdt.dsf.service.IDsfService; + +/** + * The TraceControl service provides access to the debugger Tracing functionality. + * It is used to do such things as start and stop tracing. + * + * @since 2.1 + */ +public interface IGDBTraceControl extends IDsfService { + + /** + * Marker interface for a context on which trace operations can be performed + */ + public interface ITraceTargetDMContext extends IDMContext {} + + /** + * Specific Trace Record context. It describes tracing data. + */ + @Immutable + public interface ITraceRecordDMContext extends IDMContext {} + + /** + * This is the model data interface that corresponds to ITraceRecordDMContext. + * The content of the data is backend-specific and therefore is not specified here. + */ + public interface ITraceRecordDMData extends IDMData { + } + + /** + * Trace events + */ + public interface ITracingSupportedChangeDMEvent extends IDMEvent<ITraceTargetDMContext> { + boolean isTracingSupported(); + } + public interface ITracingStartedDMEvent extends IDMEvent<ITraceTargetDMContext> {} + public interface ITracingStoppedDMEvent extends IDMEvent<ITraceTargetDMContext> {} + public interface ITraceRecordSelectedChangedDMEvent extends IDMEvent<ITraceRecordDMContext> {} + + /** + * Returns whether tracing can be started on the specified trace target + */ + public void canStartTracing(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm); + /** + * Start tracing on the specified trace target + */ + public void startTracing(ITraceTargetDMContext context, RequestMonitor rm); + /** + * Returns whether tracing can be stopped on the specified trace target + */ + public void canStopTracing(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm); + /** + * Stop tracing on the specified trace target + */ + public void stopTracing(ITraceTargetDMContext context, RequestMonitor rm); + /** + * Returns true if tracing is ongoing. + */ + public void isTracing(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm); + + /** + * Returns true if trace data can be saved to file + */ + public void canSaveTraceData(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm); + + /** + * Save trace data (all trace records) to the specified file in a format suitable for {@link loadTraceData} + * If 'remoteSave' is true, the storage will be done on the target. + */ + public void saveTraceData(ITraceTargetDMContext context, + String file, boolean remoteSave, + RequestMonitor rm); + + /** + * Returns true if trace data can be loaded from a file + */ + public void canLoadTraceData(ITraceTargetDMContext context, DataRequestMonitor<Boolean> rm); + + /** + * Load trace data (all trace records) from the specified file. A file created from a call to + * {@link saveTraceData} should have the correct format to be loaded by this call. + */ + public void loadTraceData(ITraceTargetDMContext context, + String file, + RequestMonitor rm); + + +// /** +// * Request that the backend use the specified trace record. +// */ +// public void selectTraceRecord(ITraceRecordDMContext context, RequestMonitor rm); +// /** +// * Returns the trace record data of the specified trace record. +// */ +// public void getTraceRecordData(ITraceRecordDMContext context, +// DataRequestMonitor<ITraceRecordDMData> rm); +// +// /** +// * Save all tracepoint definitions to the specified file in a +// * format suitable for {@link loadTracepoints}. +// */ +// // This should probably be part of the GDB Breakpoints service +// public void saveTracepoints(ITraceTargetDMContext context, +// String file, +// RequestMonitor rm); +// +// /** +// * Load all tracepoint definitions from the specified file. +// * A file created from a call to {@link saveTracepoints} should have +// * the correct format to be loaded by this call. +// */ +// // This should probably be part of the GDB Breakpoints service +// public void loadTracepoints(ITraceTargetDMContext context, +// String file, +// RequestMonitor rm); +// + + + ///////////////////////////////////////////////// + // GDB specific part + ///////////////////////////////////////////////// + + public static enum STOP_REASON_ENUM { REQUEST, PASSCOUNT, OVERFLOW, DISCONNECTION, ERROR, UNKNOWN }; + + public interface ITraceStatusDMData extends IDMData { + boolean isTracingSupported(); + boolean isTracingActive(); + int getNumberOfCollectedFrame(); + int getTotalBufferSize(); + int getFreeBufferSize(); + + STOP_REASON_ENUM getStopReason(); + + /** + * Returns the id of the tracepoint that caused the stop. + * Should be null if getStopReason is null + */ + Integer getStoppingTracepoint(); + } + + public interface ITraceVariableDMData extends IDMData { + String getName(); + String getValue(); + String getInitialValue(); + } + + /** + * Request the tracing status of the specified trace target + */ + public void getTraceStatus(ITraceTargetDMContext context, DataRequestMonitor<ITraceStatusDMData> rm); + + /** + * Create a new trace state variable with an optional value + */ + public void createTraceVariable(ITraceTargetDMContext context, + String varName, + String varValue, + RequestMonitor rm); + + /** + * Get a list of all trace state variables and their values + */ + public void getTraceVariables(ITraceTargetDMContext context, DataRequestMonitor<ITraceVariableDMData[]> rm); + +// public ITraceRecordDMContext createTraceRecordContext(IDMContext ctx, int index); +// public void getCurrentTraceRecordContext(ITraceTargetDMContext context, DataRequestMonitor<ITraceRecordDMContext> drm); +// public ITraceRecordDMContext createNextRecordContext(ITraceRecordDMContext ctx); +// public ITraceRecordDMContext createPrevRecordContext(ITraceRecordDMContext ctx); +// +// public void setDefaultCollect(ITraceTargetDMContext context, String[] expressions, RequestMonitor rm); +// public void getDefaultCollect(ITraceTargetDMContext context, DataRequestMonitor<String> rm); + +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControlDMContext.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControlDMContext.java index 19657a111e6..3569044face 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControlDMContext.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/gdb/service/command/GDBControlDMContext.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2007, 2008 Wind River Systems and others. + * Copyright (c) 2010 Wind River Systems and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,6 +15,7 @@ import org.eclipse.cdt.dsf.debug.service.IDisassembly.IDisassemblyDMContext; import org.eclipse.cdt.dsf.debug.service.IModules.ISymbolDMContext; import org.eclipse.cdt.dsf.debug.service.ISignals.ISignalsDMContext; import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext; +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext; /** @@ -22,7 +23,7 @@ import org.eclipse.cdt.dsf.mi.service.command.MIControlDMContext; */ public class GDBControlDMContext extends MIControlDMContext implements ISymbolDMContext, IBreakpointsTargetDMContext, ISourceLookupDMContext, - ISignalsDMContext, IDisassemblyDMContext + ISignalsDMContext, IDisassemblyDMContext, ITraceTargetDMContext { public GDBControlDMContext(String sessionId, String commandControlId) { diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java index 2e6b158fcdd..5506b929e32 100644 --- a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/AbstractMIControl.java @@ -704,6 +704,57 @@ public abstract class AbstractMIControl extends AbstractDsfService return clientMsg.toString(); } + private String getBackendMessage(MIOutput response) { + + // Attempt to extract a message from the result record: + String message = null; + String[] parameters = null; + if (response != null && response.getMIResultRecord() != null) { + MIResult[] results = response.getMIResultRecord().getMIResults(); + + // Extract the parameters + MIResult paramsRes = findResultRecord(results, "parameters"); //$NON-NLS-1$ + if (paramsRes != null && paramsRes.getMIValue() instanceof MIList) { + MIValue[] paramValues = ((MIList)paramsRes.getMIValue()).getMIValues(); + parameters = new String[paramValues.length]; + for (int i = 0; i < paramValues.length; i++) { + if (paramValues[i] instanceof MIConst) { + parameters[i] = ((MIConst)paramValues[i]).getString(); + } else { + parameters[i] = ""; //$NON-NLS-1$ + } + } + } + MIResult messageRes = findResultRecord(results, "message"); //$NON-NLS-1$ + if (messageRes != null && messageRes.getMIValue() instanceof MIConst) { + message = ((MIConst)messageRes.getMIValue()).getString(); + } + // FRCH: I believe that the actual string is "msg" ... + // FRCH: (at least for the version of gdb I'm using) + else { + messageRes = findResultRecord(results, "msg"); //$NON-NLS-1$ + if (messageRes != null && messageRes.getMIValue() instanceof MIConst) { + message = ((MIConst)messageRes.getMIValue()).getString(); + } + } + } + StringBuilder clientMsg = new StringBuilder(); + if (message != null) { + if (parameters != null) { + try { + clientMsg.append(MessageFormat.format(message, parameters)); + } catch(IllegalArgumentException e2) { + // Message format string invalid. Fallback to just appending the strings. + clientMsg.append(message); + clientMsg.append(parameters); + } + } else { + clientMsg.append(message); + } + } + return clientMsg.toString(); + } + void processMIOutput(String line) { MIParser.RecordType recordType = fMiParser.getRecordType(line); @@ -740,7 +791,9 @@ public abstract class AbstractMIControl extends AbstractDsfService if ( errorResult.equals(MIResultRecord.ERROR) ) { String status = getStatusString(commandHandle.getCommand(),response); - rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, status, null)); + String message = getBackendMessage(response); + Exception exception = new Exception(message); + rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, status, exception)); } /* diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITargetSelectTFile.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITargetSelectTFile.java new file mode 100644 index 00000000000..c2dcc797dae --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITargetSelectTFile.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.datamodel.IDMContext; + +/** + * This command sets up a connection with a trace data file. + * + * Available with GDB 7.1 + * + * @since 2.1 + */ +public class MITargetSelectTFile extends MITargetSelect { + + public MITargetSelectTFile(IDMContext ctx, String traceFilePath) { + super(ctx, new String[] { "tfile", traceFilePath}); //$NON-NLS-1$ + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceDefineVariable.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceDefineVariable.java new file mode 100644 index 00000000000..e8d8a6f5b31 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceDefineVariable.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; + +/** + * -trace-define-variable + * + * Creates trace variable name if it does not exist. If value is specified, + * sets the initial value of the specified trace variable to that value. + * Note that the name should start with the `$' character. + * + * Available with GDB 7.1 + * + * @since 2.1 + */ +public class MITraceDefineVariable extends MICommand<MIInfo> { + public MITraceDefineVariable(ITraceTargetDMContext ctx, String varName) { + this(ctx, varName, ""); //$NON-NLS-1$ + } + + public MITraceDefineVariable(ITraceTargetDMContext ctx, String varName, String varValue) { + super(ctx, "-trace-define-variable", new String[] { varName, varValue }); //$NON-NLS-1$ + } + +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceListVariables.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceListVariables.java new file mode 100644 index 00000000000..e5faf1f995f --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceListVariables.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; +import org.eclipse.cdt.dsf.mi.service.command.output.MITraceListVariablesInfo; + +/** + * -trace-list-variables + * + * Return a table of all defined trace variables. Each element of the table has the + * following fields: + * 'name' The name of the trace variable. This field is always present. + * 'initial' The initial value. This is a 64-bit signed integer. This field is always present. + * 'current' The value the trace variable has at the moment. This is a 64-bit signed integer. + * This field may is absent if the current value is not defined, for example if + * the trace was never run, or is presently running. + * + * Available with GDB 7.1 + * + * @since 2.1 + */ +public class MITraceListVariables extends MICommand<MITraceListVariablesInfo> { + + public MITraceListVariables(ITraceTargetDMContext ctx) { + super(ctx, "-trace-list-variables"); //$NON-NLS-1$ + } + + @Override + public MITraceListVariablesInfo getResult(MIOutput out) { + return new MITraceListVariablesInfo(out); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceSave.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceSave.java new file mode 100644 index 00000000000..eb4b852933d --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceSave.java @@ -0,0 +1,36 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; + +/** + * -trace-save [-r] FILENAME + * + * Saves the collected trace data to FILENAME. Without the '-r' option, the data is downloaded + * from the target and saved in a local file. With the '-r' option the target is asked to perform + * the save. + * + * Available with GDB 7.1 + * + * @since 2.1 + */ +public class MITraceSave extends MICommand<MIInfo> { + + public MITraceSave(ITraceTargetDMContext ctx, String file, boolean remoteSave) { + super(ctx, "-trace-save", null, new String[] { file }); //$NON-NLS-1$ + if (remoteSave) { + setOptions(new String[] { "-r" }); //$NON-NLS-1$ + } + } + +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStart.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStart.java new file mode 100644 index 00000000000..ecdf458270c --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStart.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; + +/** + * -trace-start + * + * Starts a tracing experiment. The result of this command does not have any fields. + * + * Available with GDB 7.1 + * + * @since 2.1 + */ +public class MITraceStart extends MICommand<MIInfo> { + public MITraceStart(ITraceTargetDMContext ctx) { + super(ctx, "-trace-start"); //$NON-NLS-1$ + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStatus.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStatus.java new file mode 100644 index 00000000000..c591b86231c --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStatus.java @@ -0,0 +1,34 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; +import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStatusInfo; + +/** + * -trace-status + * + * Gets the status of tracing. + * + * Available with GDB 7.1 + * + * @since 2.1 + */ +public class MITraceStatus extends MICommand<MITraceStatusInfo> { + public MITraceStatus(ITraceTargetDMContext ctx) { + super(ctx, "-trace-status"); //$NON-NLS-1$ + } + @Override + public MITraceStatusInfo getResult(MIOutput out) { + return new MITraceStatusInfo(out); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStop.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStop.java new file mode 100644 index 00000000000..a6180093273 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/commands/MITraceStop.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.commands; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.ITraceTargetDMContext; +import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput; +import org.eclipse.cdt.dsf.mi.service.command.output.MITraceStopInfo; + +/** + * -trace-stop + * + * Stops a tracing experiment. The result of this command has the same fields + * as -trace-status, except that the 'supported' and 'running' fields are not output. + * + * Available with GDB 7.1 + * + * @since 2.1 + */ +public class MITraceStop extends MICommand<MITraceStopInfo> { + public MITraceStop(ITraceTargetDMContext ctx) { + super(ctx, "-trace-stop"); //$NON-NLS-1$ + } + @Override + public MITraceStopInfo getResult(MIOutput out) { + return new MITraceStopInfo(out); + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceListVariablesInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceListVariablesInfo.java new file mode 100644 index 00000000000..42287d25fe2 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceListVariablesInfo.java @@ -0,0 +1,124 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.output; + +import java.util.ArrayList; +import java.util.List; + +/** + * -trace-list-variables + * + * ^done,trace-variables={nr_rows="1",nr_cols="3", + * hdr=[{width="15",alignment="-1",col_name="name",colhdr="Name"}, + * {width="11",alignment="-1",col_name="initial",colhdr="Initial"}, + * {width="11",alignment="-1",col_name="current",colhdr="Current"}], + * body=[variable={name="$trace_timestamp",initial="0"} + * variable={name="$foo",initial="10",current="15"}]} + * + * @since 2.1 + */ +public class MITraceListVariablesInfo extends MIInfo { + + public class MITraceVariableInfo { + private String fName; + private String fInitialValue; + private String fCurrentValue; + + public String getName() { + return fName; + } + + public String getCurrentValue() { + return fCurrentValue; + } + + public String getInitialValue() { + return fInitialValue; + } + } + + private MITraceVariableInfo[] fVariables; + + public MITraceListVariablesInfo(MIOutput out) { + super(out); + parse(); + } + + public MITraceVariableInfo[] getTraceVariables() { + return fVariables; + } + + private void parse() { + List<MITraceVariableInfo> aList = new ArrayList<MITraceVariableInfo>(1); + if (isDone()) { + MIOutput out = getMIOutput(); + MIResultRecord rr = out.getMIResultRecord(); + if (rr != null) { + MIResult[] results = rr.getMIResults(); + for (int i = 0; i < results.length; i++) { + String var = results[i].getVariable(); + if (var.equals("trace-variables")) { //$NON-NLS-1$ + parseTable(results[i].getMIValue(), aList); + } + } + } + } + fVariables = aList.toArray(new MITraceVariableInfo[aList.size()]); + } + + private void parseTable(MIValue val, List<MITraceVariableInfo> aList) { + if (val instanceof MITuple) { + MIResult[] table = ((MITuple)val).getMIResults(); + for (int i = 0; i < table.length; i++) { + String variable = table[i].getVariable(); + if (variable.equals("body")) { //$NON-NLS-1$ + parseBody(table[i].getMIValue(), aList); + } + } + } + } + + private void parseBody(MIValue body, List<MITraceVariableInfo> aList) { + if (body instanceof MIList) { + MIResult[] vars = ((MIList)body).getMIResults(); + for (int i = 0; i < vars.length; i++) { + String variable = vars[i].getVariable(); + if (variable.equals("variable")) { //$NON-NLS-1$ + parseVariable(vars[i].getMIValue(), aList); + } + } + } + } + + private void parseVariable(MIValue variable, List<MITraceVariableInfo> aList) { + if (variable instanceof MITuple) { + MIResult[] results = ((MITuple)variable).getMIResults(); + MITraceVariableInfo info = new MITraceVariableInfo(); + for (int i = 0; i < results.length; i++) { + String var = results[i].getVariable(); + MIValue value = results[i].getMIValue(); + String str = ""; //$NON-NLS-1$ + if (value != null && value instanceof MIConst) { + str = ((MIConst)value).getCString(); + } + + if (var.equals("name")) { //$NON-NLS-1$ + info.fName = str; + } else if (var.equals("initial")) { //$NON-NLS-1$ + info.fInitialValue = str; + } else if (var.equals("current")) { //$NON-NLS-1$ + info.fCurrentValue = str; + } + } + aList.add(info); + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStatusInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStatusInfo.java new file mode 100644 index 00000000000..ea634208829 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStatusInfo.java @@ -0,0 +1,136 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.output; + +import org.eclipse.cdt.dsf.gdb.service.IGDBTraceControl.STOP_REASON_ENUM; + +/** + * -trace-status result. + * + * ^done,supported="1",running="1",frames="0",buffer-size="5242880",buffer-free="5242880" + * ^done,supported="1",running="0",stop-reason="request",frames="0",buffer-size="5242880",buffer-free="5242880" + * ^done,supported="1",running="0",stop-reason="passcount",stopping-tracepoint="7",frames="3",buffer-size="5242880",buffer-free="5242862" + * + * @since 2.1 + */ +public class MITraceStatusInfo extends MIInfo { + + private int fFreeBufferSize = 0; + private int fTotalBufferSize = 0; + private int fNumberOfCollectedFrames = 0; + private boolean fIsTracingActive = false; + private boolean fIsTracingSupported = false; + private STOP_REASON_ENUM fStopReason = null; + private Integer fStoppingTracepoint = null; + + public MITraceStatusInfo(MIOutput out) { + super(out); + parse(); + } + + public int getFreeBufferSize() { + return fFreeBufferSize; + } + + public int getNumberOfCollectedFrame() { + return fNumberOfCollectedFrames; + } + + public int getTotalBufferSize() { + return fTotalBufferSize; + } + + public boolean isTracingActive() { + return fIsTracingActive; + } + + public boolean isTracingSupported() { + return fIsTracingSupported; + } + + public STOP_REASON_ENUM getStopReason() { + return fStopReason; + } + + public Integer getStopTracepoint() { + return fStoppingTracepoint; + } + + private void parse() { + if (isDone()) { + MIOutput out = getMIOutput(); + MIResultRecord rr = out.getMIResultRecord(); + if (rr != null) { + MIResult[] results = rr.getMIResults(); + for (int i = 0; i < results.length; i++) { + String var = results[i].getVariable(); + if (var.equals("supported")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fIsTracingSupported = ((MIConst)val).getString().equals("0") ? false : true;; //$NON-NLS-1$ + } + } else if (var.equals("running")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + fIsTracingActive = ((MIConst)val).getString().equals("0") ? false : true;; //$NON-NLS-1$ + } + } else if (var.equals("frames")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + try { + fNumberOfCollectedFrames = Integer.parseInt(((MIConst)val).getString()); + } catch (NumberFormatException e) {} + } + } else if (var.equals("buffer-size")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + try { + fTotalBufferSize = Integer.parseInt(((MIConst)val).getString()); + } catch (NumberFormatException e) {} + } + } else if (var.equals("buffer-free")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + try { + fFreeBufferSize = Integer.parseInt(((MIConst)val).getString()); + } catch (NumberFormatException e) {} + } + } else if (var.equals("stop-reason")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + String reason = ((MIConst)val).getString().trim(); + if (reason.equalsIgnoreCase("request")) { //$NON-NLS-1$ + fStopReason = STOP_REASON_ENUM.REQUEST; + } else if (reason.equalsIgnoreCase("overflow")) { //$NON-NLS-1$ + fStopReason = STOP_REASON_ENUM.OVERFLOW; + } else if (reason.equalsIgnoreCase("disconnection")) { //$NON-NLS-1$ + fStopReason = STOP_REASON_ENUM.DISCONNECTION; + } else if (reason.equalsIgnoreCase("passcount")) { //$NON-NLS-1$ + fStopReason = STOP_REASON_ENUM.PASSCOUNT; + } else if (reason.equalsIgnoreCase("error")) { //$NON-NLS-1$ + fStopReason = STOP_REASON_ENUM.ERROR; + } else { + fStopReason = STOP_REASON_ENUM.UNKNOWN; + } + } + } else if (var.equals("stopping-tracepoint")) { //$NON-NLS-1$ + MIValue val = results[i].getMIValue(); + if (val instanceof MIConst) { + try { + fStoppingTracepoint = Integer.parseInt(((MIConst)val).getString()); + } catch (NumberFormatException e) {} + } + } + } + } + } + } +} diff --git a/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStopInfo.java b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStopInfo.java new file mode 100644 index 00000000000..b4aa30540b5 --- /dev/null +++ b/dsf-gdb/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/command/output/MITraceStopInfo.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2010 Ericsson and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Ericsson - Initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.dsf.mi.service.command.output; + + +/** + * -trace-stop result. + * + * The result of this command has the same fields as -trace-status, except that the + * 'supported' and 'running' fields are not output. + * The output is therefore a subset of the output of the -trace-status command. + * The way MI fields are optional allows us to simply re-use the MITraceStatusInfo class + * + * @since 2.1 + */ +public class MITraceStopInfo extends MITraceStatusInfo { + public MITraceStopInfo(MIOutput out) { + super(out); + } +} |