1
0
Fork 0
mirror of https://github.com/eclipse-cdt/cdt synced 2025-07-24 09:25:31 +02:00

Bug 336876 - [multicore] Grouping of Execution Elements for DSF debugger feature

This commit is contained in:
Patrick Chuong 2011-03-10 20:38:23 +00:00
parent ceb221e714
commit e9ccc03be3
20 changed files with 1048 additions and 15 deletions

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
********************************************************************************/
package org.eclipse.cdt.debug.core.model;
import org.eclipse.debug.core.commands.IDebugCommandHandler;
/**
* Handler interface to perform grouping of debug contexts.
*
* @since 7.1
*/
public interface IGroupDebugContextsHandler extends IDebugCommandHandler {
}

View file

@ -0,0 +1,22 @@
/*******************************************************************************
* Copyright (c) 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
********************************************************************************/
package org.eclipse.cdt.debug.core.model;
import org.eclipse.debug.core.commands.IDebugCommandHandler;
/**
* Handler interface to perform ungrouping of debug contexts.
*
* @since 7.1
*/
public interface IUngroupDebugContextsHandler extends IDebugCommandHandler {
}

View file

@ -9,6 +9,7 @@
# QNX Software Systems - Initial API and implementation
# IBM Corporation
# Patrick Chuong (Texas Instruments) - Pin and Clone Supports (Bug 331781)
# Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
###############################################################################
pluginName=C/C++ Development Tools Debugger UI
@ -195,6 +196,15 @@ Uncall.name = Uncall
Uncall.description = Perform Uncall
Uncall.label = Uncall
# Debug View layout
DebugViewLayoutActionSet.label = Debug View Layout
DebugViewLayoutCategory.name = Debug View Layout Commands
DebugViewLayoutCategory.description = Set of commands for controlling the Debug View Layout
GroupDebugContexts.name = Group
GroupDebugContexts.description = Groups the selected debug contexts
UngroupDebugContexts.name = Ungroup
UngroupDebugContexts.description = Ungroups the selected debug contexts
# Menu for selecting breakpoint toggle type
BreakpointTypes.label=B&reakpoint Types

View file

@ -1818,6 +1818,11 @@
label="%TracepointActionSet.label"
visible="false">
</actionSet>
<actionSet
id="org.eclipse.cdt.debug.ui.debugViewLayoutActionSet"
label="%DebugViewLayoutActionSet.label"
visible="false">
</actionSet>
</extension>
<extension
point="org.eclipse.ui.commands">
@ -1897,6 +1902,23 @@
helpContextId="view_memory_context"
name="%command.viewMemory.name">
</command>
<category
description="%DebugViewLayoutCategory.description"
id="org.eclipse.cdt.debug.ui.category.debugViewLayout"
name="%DebugViewLayoutCategory.name">
</category>
<command
categoryId="org.eclipse.cdt.debug.ui.category.debugViewLayout"
description="%GroupDebugContexts.description"
id="org.eclipse.cdt.debug.ui.command.groupDebugContexts"
name="%GroupDebugContexts.name">
</command>
<command
categoryId="org.eclipse.cdt.debug.ui.category.debugViewLayout"
description="%UngroupDebugContexts.description"
id="org.eclipse.cdt.debug.ui.command.ungroupDebugContexts"
name="%UngroupDebugContexts.name">
</command>
</extension>
<extension
point="org.eclipse.ui.handlers">
@ -1951,6 +1973,14 @@
</with>
</activeWhen>
</handler>
<handler
class="org.eclipse.cdt.debug.internal.ui.commands.GroupDebugContextsCommandHandler"
commandId="org.eclipse.cdt.debug.ui.command.groupDebugContexts">
</handler>
<handler
class="org.eclipse.cdt.debug.internal.ui.commands.UngroupDebugContextsCommandHandler"
commandId="org.eclipse.cdt.debug.ui.command.ungroupDebugContexts">
</handler>
</extension>
<extension
point="org.eclipse.core.expressions.definitions">
@ -2004,6 +2034,18 @@
</iterate>
</with>
</definition>
<definition
id="org.eclipse.cdt.debug.ui.testDebugViewLayoutActionSetActive">
<with
variable="activeContexts">
<iterate
operator="or">
<equals
value="org.eclipse.cdt.debug.ui.debugViewLayoutActionSet">
</equals>
</iterate>
</with>
</definition>
</extension>
<extension
point="org.eclipse.ui.bindings">
@ -2297,6 +2339,53 @@
</visibleWhen>
</command>
</menuContribution>
<menuContribution
locationURI="popup:org.eclipse.debug.ui.DebugView?after=emptyStepGroup">
<command
commandId="org.eclipse.cdt.debug.ui.command.groupDebugContexts"
label="%GroupDebugContexts.name">
<visibleWhen
checkEnabled="false">
<and>
<reference
definitionId="org.eclipse.cdt.debug.ui.testDebugViewLayoutActionSetActive">
</reference>
<with
variable="debugContext">
<iterate
ifEmpty="false"
operator="and">
<test
property="org.eclipse.cdt.debug.ui.isGroupDebugContextsVisible">
</test>
</iterate>
</with>
</and>
</visibleWhen>
</command>
<command
commandId="org.eclipse.cdt.debug.ui.command.ungroupDebugContexts"
label="%UngroupDebugContexts.name">
<visibleWhen
checkEnabled="false">
<and>
<reference
definitionId="org.eclipse.cdt.debug.ui.testDebugViewLayoutActionSetActive">
</reference>
<with
variable="debugContext">
<iterate
ifEmpty="false"
operator="and">
<test
property="org.eclipse.cdt.debug.ui.isUngroupDebugContextsVisible">
</test>
</iterate>
</with>
</and>
</visibleWhen>
</command>
</menuContribution>
</extension>
<!-- Cast to Type / Display as Array -->

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
********************************************************************************/
package org.eclipse.cdt.debug.internal.ui.commands;
import org.eclipse.cdt.debug.core.model.IGroupDebugContextsHandler;
import org.eclipse.debug.ui.actions.DebugCommandHandler;
/**
* Command handler to trigger grouping of debug contexts operation.
*
* @since 7.1
*/
public class GroupDebugContextsCommandHandler extends DebugCommandHandler {
@Override
protected Class<?> getCommandType() {
return IGroupDebugContextsHandler.class;
}
}

View file

@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
********************************************************************************/
package org.eclipse.cdt.debug.internal.ui.commands;
import org.eclipse.cdt.debug.core.model.IUngroupDebugContextsHandler;
import org.eclipse.debug.ui.actions.DebugCommandHandler;
/**
* Command handler to trigger ungrouping of debug contexts operation.
*
* @since 7.1
*/
public class UngroupDebugContextsCommandHandler extends DebugCommandHandler {
@Override
protected Class<?> getCommandType() {
return IUngroupDebugContextsHandler.class;
}
}

View file

@ -22,6 +22,8 @@ Require-Bundle: org.eclipse.ui;bundle-version="3.5.0",
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.dsf.debug.internal.ui;x-internal:=true,
org.eclipse.cdt.dsf.debug.internal.ui.actions;x-internal:=true,
org.eclipse.cdt.dsf.debug.internal.ui.debugview.layout;x-internal:=true,
org.eclipse.cdt.dsf.debug.internal.ui.debugview.layout.actions,
org.eclipse.cdt.dsf.debug.internal.ui.disassembly;x-internal:=true,
org.eclipse.cdt.dsf.debug.internal.ui.disassembly.actions;x-internal:=true,
org.eclipse.cdt.dsf.debug.internal.ui.disassembly.model;x-internal:=true,

View file

@ -450,8 +450,14 @@
properties="areNumberFormatsSupported,isNumberFormatAvailable,isNumberFormatActive"
type="org.eclipse.debug.ui.IDebugView">
</propertyTester>
<propertyTester
class="org.eclipse.cdt.dsf.debug.internal.ui.debugview.layout.DebugViewLayoutTester"
id="org.eclipse.cdt.dsf.ui.debug.view.layout.DebugViewLayoutTester"
namespace="org.eclipse.cdt.debug.ui"
properties="isGroupDebugContextsVisible,isUngroupDebugContextsVisible"
type="org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext">
</propertyTester>
</extension>
<extension
point="org.eclipse.debug.ui.detailPaneFactories">
<detailFactories
@ -790,4 +796,5 @@
</editor>
</extension>
</plugin>

View file

@ -0,0 +1,45 @@
/*******************************************************************************
* Copyright (c) 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
********************************************************************************/
package org.eclipse.cdt.dsf.debug.internal.ui.debugview.layout;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.core.expressions.PropertyTester;
/**
* Property tester for debug view related commands - group, ungroup, hide, etc.
*
* @since 2.2
*/
public class DebugViewLayoutTester extends PropertyTester{
public DebugViewLayoutTester() {
}
protected static final String IS_GROUP_VISIBLE = "isGroupDebugContextsVisible"; //$NON-NLS-1$
protected static final String IS_UNGROUP_VISIBLE = "isUngroupDebugContextsVisible"; //$NON-NLS-1$
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
if( IS_GROUP_VISIBLE.equals(property) || IS_UNGROUP_VISIBLE.equals(property)) {
if (receiver instanceof IDMVMContext) {
return test((IDMVMContext)receiver);
}
}
return false;
}
private boolean test(IDMVMContext dmContext) {
String sessionId = dmContext.getDMContext().getSessionId();
return DsfSession.isSessionActive(sessionId);
}
}

View file

@ -0,0 +1,144 @@
/*******************************************************************************
* Copyright (c) 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
********************************************************************************/
package org.eclipse.cdt.dsf.debug.internal.ui.debugview.layout.actions;
import java.util.HashSet;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
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.internal.provisional.service.IExecutionContextTranslator;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.internal.ui.DsfUIPlugin;
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.debug.core.commands.IDebugCommandHandler;
import org.eclipse.debug.core.commands.IDebugCommandRequest;
import org.eclipse.debug.core.commands.IEnabledStateRequest;
/**
* @since 2.2
*/
@SuppressWarnings("restriction")
public abstract class DsfDebugViewLayoutCommand implements IDebugCommandHandler{
protected final DsfExecutor fExecutor;
protected final DsfServicesTracker fTracker;
protected static IExecutionDMContext[] EMPTY_ARRAY = new IExecutionDMContext[0];
public DsfDebugViewLayoutCommand(DsfSession session) {
fExecutor = session.getExecutor();
fTracker = new DsfServicesTracker(DsfUIPlugin.getBundleContext(), session.getId());
}
public void dispose() {
fTracker.dispose();
}
/**
*
* @param request
* @return set of IExecutionDMContext if:
* - all elements are from a DSF session.
* - all elements are from the same DSF session.
*/
protected IExecutionDMContext[] getDMContexts( IDebugCommandRequest request) {
HashSet<IExecutionDMContext> ret = new HashSet<IExecutionDMContext>();
String sessionId = null;
for( Object obj : request.getElements()) {
if(!( obj instanceof IDMVMContext ))
return EMPTY_ARRAY;
IDMContext dmContext = ((IDMVMContext)obj).getDMContext();
IExecutionDMContext exeContext = DMContexts.getAncestorOfType(dmContext, IExecutionDMContext.class);
if( exeContext == null)
return EMPTY_ARRAY;
// make sure all elements are from the same DSF session.
if( sessionId == null) {
sessionId = dmContext.getSessionId();
}
else {
if( !sessionId.equals(dmContext.getSessionId()))
return EMPTY_ARRAY;
}
ret.add(exeContext);
}
return ret.toArray(new IExecutionDMContext[0]);
}
public void canExecute(final IEnabledStateRequest request) {
final IExecutionDMContext[] executionContexts = getDMContexts( request);
if( executionContexts.length > 0 && !fExecutor.isTerminated()) {
fExecutor.submit(new DsfRunnable() {
public void run() {
IExecutionContextTranslator translator = fTracker.getService(IExecutionContextTranslator.class);
if( translator != null) {
canExecuteOnDsfThread(translator, executionContexts,
new DataRequestMonitor<Boolean>(fExecutor, null) {
@Override
protected void handleCompleted() {
boolean canExecute = isSuccess() && getData();
request.setEnabled(canExecute);
request.done();
}
});
} else {
request.setEnabled(false);
request.done();
}
}
});
}
else {
request.setEnabled(false);
request.done();
}
}
public boolean execute(final IDebugCommandRequest request) {
final IExecutionDMContext[] executionContexts = getDMContexts( request);
if( executionContexts.length > 0 && !fExecutor.isTerminated()) {
fExecutor.submit(new DsfRunnable() {
public void run() {
IExecutionContextTranslator translator = fTracker.getService(IExecutionContextTranslator.class);
if( translator != null) {
executeOnDsfThread(translator, executionContexts,
new RequestMonitor(fExecutor, null) {
@Override
protected void handleCompleted() {
request.done();
}
});
}
else
request.done();
}
});
return false;
}
request.done();
return true;
}
abstract void executeOnDsfThread( IExecutionContextTranslator translator, IExecutionDMContext[] contexts, RequestMonitor requestMonitor);
abstract void canExecuteOnDsfThread( IExecutionContextTranslator translator, IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
}

View file

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
********************************************************************************/
package org.eclipse.cdt.dsf.debug.internal.ui.debugview.layout.actions;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.debug.internal.provisional.service.IExecutionContextTranslator;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.debug.core.commands.IDebugCommandHandler;
/**
* @since 2.2
*/
@SuppressWarnings("restriction")
public class DsfGroupDebugContextsCommand extends DsfDebugViewLayoutCommand implements IDebugCommandHandler{
@Override
void executeOnDsfThread( IExecutionContextTranslator translator, IExecutionDMContext[] contexts, RequestMonitor requestMonitor) {
translator.group(contexts, requestMonitor);
}
@Override
void canExecuteOnDsfThread( IExecutionContextTranslator translator, IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
translator.canGroup(contexts, rm);
}
public DsfGroupDebugContextsCommand(DsfSession session) {
super( session);
}
}

View file

@ -0,0 +1,39 @@
/*******************************************************************************
* Copyright (c) 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 336876)
********************************************************************************/
package org.eclipse.cdt.dsf.debug.internal.ui.debugview.layout.actions;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.debug.internal.provisional.service.IExecutionContextTranslator;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.debug.core.commands.IDebugCommandHandler;
/**
* @since 2.2
*/
@SuppressWarnings("restriction")
public class DsfUngroupDebugContextsCommand extends DsfDebugViewLayoutCommand implements IDebugCommandHandler{
public DsfUngroupDebugContextsCommand(DsfSession session) {
super( session);
}
@Override
void executeOnDsfThread(IExecutionContextTranslator translator, IExecutionDMContext[] contexts, RequestMonitor requestMonitor) {
translator.ungroup(contexts, requestMonitor);
}
@Override
void canExecuteOnDsfThread(IExecutionContextTranslator translator, IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm) {
translator.canUngroup(contexts, rm);
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2009 Wind River Systems, Inc. and others.
* Copyright (c) 2008, 2011 Wind River Systems, Inc. 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
@ -8,6 +8,7 @@
* Contributors:
* Wind River Systems - initial API and implementation
* Patrick Chuong (Texas Instruments) - Add support for icon overlay in the debug view (Bug 334566)
* Dobrin Alexiev (Texas Instruments) - user groups support (bug 240208)
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch;
@ -41,7 +42,6 @@ import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
import org.eclipse.cdt.dsf.ui.viewmodel.ModelProxyInstalledEvent;
import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate;
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
@ -65,7 +65,7 @@ import org.eclipse.debug.ui.IDebugUIConstants;
*
* @since 1.1
*/
public abstract class AbstractContainerVMNode extends AbstractDMVMNode
public abstract class AbstractContainerVMNode extends AbstractExecutionContextVMNode
implements IElementLabelProvider, IElementPropertiesProvider
{
/**

View file

@ -0,0 +1,344 @@
/*******************************************************************************
* Copyright (c) 2010, 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 240208)
********************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch;
import java.util.ArrayList;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
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.datamodel.IDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerResumedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IResumedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.SteppingController.SteppingTimedOutEvent;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
import org.eclipse.cdt.dsf.ui.viewmodel.IVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
/**
* This class is a base class of AbstractThreadVMNode and AbstractContainerVMNode.
* It contains common functionality between these classes.
*
* The main reason this class is introduce is to allow the debug view to
* show multiple levels of execution containers and properly handle the delta generation.
*
* Longer term we would like to merge the classes AbstractContainerVMNode and
* AbstractThreadVMNode. That will make the implementation of both classes
* more generic and robust in the case of recursive containers.
*
* Having this class as a base for both AbstractContainerVMNode and
* AbstractThreadVMNode enables us to merge them in the future.
*
* Originally DefaultVMModelProxyStrategy didn't accept recursive container for
* generating deltas, even though they are accepted and supported by
* AbstractDMVMProvider for viewing.
* The approach I took to support recursive container in delta generation is to have
* the VMNodes to generate level by level its deltas instead of one the whole delta at once.
* That required changes in identifying which is the correct context for each of the events.
*
* See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=240208
*
* @since 2.2
* @experimental
*/
public abstract class AbstractExecutionContextVMNode extends AbstractDMVMNode
{
/**
* List that keeps track of which events are considered leave events for
* delta creation.
*/
protected ArrayList<Class<?>> leafEventTypes = new ArrayList<Class<?>>();
/**
* List that keeps track of which events are considered container events for
* delta creation.
*/
protected ArrayList<Class<?>> containerEventTypes = new ArrayList<Class<?>>();
/**
* Constructor.
* Pass the parameter to the base class's constructor.
*
* @param session
* @param dmcClassType
*
* @see #setChildNodes(IVMNode[])
*/
public AbstractExecutionContextVMNode(AbstractDMVMProvider provider,
DsfSession session, Class<? extends IDMContext> dmcClassType) {
super(provider, session, dmcClassType);
}
/**
* Adds the events that common DSF classes relay on.
*/
protected void addCommonEventTypes() {
// non container events.
addEventType(ISuspendedDMEvent.class,false);
addEventType(IResumedDMEvent.class, false);
addEventType(FullStackRefreshEvent.class, false);
addEventType(SteppingTimedOutEvent.class, false);
addEventType(ExpandStackEvent.class, false);
// container events.
addEventType(IContainerSuspendedDMEvent.class,true);
addEventType(IContainerResumedDMEvent.class, true);
}
/**
* When DSF debugger define custom events for which the containers and threads
* nodes needs to be update they can need to register these events using this
* function, so the proper recursive deltas are being created.
*
* @param eventClass
*/
protected void addEventType( Class<? extends IDMEvent<?>> eventClass, boolean containerEvent)
{
if( containerEvent)
containerEventTypes.add( eventClass);
else
leafEventTypes.add( eventClass);
}
/**
* If DSF debuggers overrides the behavior of the AbstractThreadVMNode
* or AbstractContainerVMNode, some event are no longer needed the derived
* VMNdoe can call this method to remove some events.
*
* @param eventClass
* @param containerEvent
*/
protected void removeEventType( Class<?> eventClass, boolean containerEvent) {
if( containerEvent)
containerEventTypes.remove( eventClass);
else
leafEventTypes.remove( eventClass);
}
/**
* When we support recursive containers we want to make sure the immediate parent is returned only.
*
* @param parentDelta
* @param e
* @param rm - request monitor
* @return true if the context is set by the method.
*/
protected boolean getContextsForRecursiveVMNode(VMDelta parentDelta, Object e, final DataRequestMonitor<IVMContext[]> rm) {
IExecutionDMContext leafContext = null;
if( isExecutionContainerEvent(e)) {
leafContext = getLeafContextForContainerEvent( e);
}
else if( isExecutionLeafEvent(e)) {
leafContext = getLeafContextForLeafEvent( e);
}
if( leafContext != null) {
setImmediateParentAsContexts(leafContext,parentDelta,rm);
return true;
}
return false;
}
/**
* Make sure we build the delta for the recursive containers one level at a time.
*
* @param e - the events.
* @param parentDelta
* @param nodeOffset
* @param requestMonitor
* @return true if the delta is built by this method.
*/
protected boolean buildDeltaForRecursiveVMNode(Object e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) {
IExecutionDMContext leafContext = null;
if( isExecutionContainerEvent(e)) {
leafContext = getLeafContextForContainerEvent( e);
}
else if( isExecutionLeafEvent(e)) {
leafContext = getLeafContextForLeafEvent( e);
}
if( leafContext != null) {
addOneLevelToDelta( leafContext, parentDelta, requestMonitor);
return true;
}
return false;
}
/**
* When the deltas are generated one level at a time we needs to distinguish
* between container and regular event to return the proper context for the event.
*
* @param event
* @return
*/
protected IExecutionDMContext getLeafContextForContainerEvent( Object event) {
IExecutionDMContext leafEC = null;
IExecutionDMContext[] triggeringContext = null;
if( isExecutionContainerEvent(event)) {
if( event instanceof IContainerSuspendedDMEvent) {
IContainerSuspendedDMEvent typedEvent = (IContainerSuspendedDMEvent)event;
triggeringContext = typedEvent.getTriggeringContexts();
}
if( event instanceof IContainerResumedDMEvent) {
IContainerResumedDMEvent typedEvent = (IContainerResumedDMEvent)event;
triggeringContext = typedEvent.getTriggeringContexts();
}
}
if( triggeringContext != null && triggeringContext.length > 0){
leafEC = triggeringContext[0];
}
return leafEC;
}
/**
* When the deltas are generated one level at a time we needs to distinguish
* between container and regular event to return the proper context for the event.
*
* @param event
* @return
*/
protected IExecutionDMContext getLeafContextForLeafEvent( Object event) {
IExecutionDMContext leafEC = null;
if( event instanceof IDMEvent<?>)
if( isExecutionLeafEvent( event)) {
IDMEvent<?> typedEvent = (IDMEvent<?>)event;
IDMContext dmContext = typedEvent.getDMContext();
if( dmContext instanceof IExecutionDMContext)
leafEC = (IExecutionDMContext)dmContext;
}
return leafEC;
}
/**
* Considers the parent delta when we construct the next level.
*
* @param leafContext
* @param parentDelta
* @param requestMonitor
*/
protected void addOneLevelToDelta( IExecutionDMContext leafContext, VMDelta parentDelta, RequestMonitor requestMonitor) {
assert leafContext != null;
if( parentDelta.getElement() instanceof ILaunch) {
IContainerDMContext topContainer =
DMContexts.getTopMostAncestorOfType( leafContext, IContainerDMContext.class);
// It is possible for a thread node to be an immediate child of a launch node
// with no container node in between.
if( topContainer != null)
parentDelta.addNode(createVMContext(topContainer), 0, IModelDelta.NO_CHANGE);
}
else if( parentDelta.getElement() instanceof IDMVMContext) {
IDMVMContext vmContext = (IDMVMContext)parentDelta.getElement();
IDMContext dmContext = vmContext.getDMContext();
IExecutionDMContext current = DMContexts.getParentOfType(leafContext, IContainerDMContext.class);
while( current != null) {
IContainerDMContext parent = DMContexts.getParentOfType(current, IContainerDMContext.class);
if( dmContext.equals(parent)) {
parentDelta.addNode(createVMContext(current), 0, IModelDelta.NO_CHANGE);
break;
}
current = parent;
}
}
requestMonitor.done();
}
/**
* Based on the event (container or not) set the proper context that is the immediate
* parent one level at a time.
*
* @param leafContext
* @param parentDelta
* @param rm
*/
protected void setImmediateParentAsContexts( IExecutionDMContext leafContext,
VMDelta parentDelta, DataRequestMonitor<IVMContext[]> rm){
assert leafContext != null;
IVMContext[] all = null;
if( parentDelta.getElement() instanceof ILaunch) {
IContainerDMContext topContainer =
DMContexts.getTopMostAncestorOfType( leafContext, IContainerDMContext.class);
if( topContainer != null) {
all = new IVMContext[] { createVMContext(topContainer) };
}
else {
// the thread is directly a child node of the launch node (no container in the middle).
all = new IVMContext[] { createVMContext(leafContext) };
}
}
else if( parentDelta.getElement() instanceof IDMVMContext) {
IDMVMContext vmContext = (IDMVMContext)parentDelta.getElement();
IDMContext dmContext = vmContext.getDMContext();
IExecutionDMContext current = leafContext;
while( current != null) {
IContainerDMContext parent = DMContexts.getParentOfType(current, IContainerDMContext.class);
if( dmContext.equals(parent)) {
all = new IVMContext[] { createVMContext(current)};
break;
}
current = parent;
}
}
if( all == null)
all = new IVMContext[0];
rm.setData( all );
rm.done();
}
/**
* Returns whether the event should be considered a container event or not.
*
* @param event
* @return
*/
protected boolean isExecutionContainerEvent( Object event) {
if( event != null)
for( Class<?> clazz : containerEventTypes)
if( clazz.isAssignableFrom(event.getClass()))
return true;
return false;
}
/**
* Returns whether the event should be use to generate delta for each of the levels.
*
* @param event
* @return
*/
protected boolean isExecutionLeafEvent( Object event) {
if( event != null)
for( Class<?> clazz : leafEventTypes)
if( clazz.isAssignableFrom(event.getClass()))
return true;
return false;
}
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2010 Wind River Systems and others.
* Copyright (c) 2006, 2011 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
* Ericsson - Modified for multi threaded functionality
* Patrick Chuong (Texas Instruments) - Add support for icon overlay in the debug view (Bug 334566)
* Dobrin Alexiev (Texas Instruments) - user groups support (bug 240208)
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.ui.viewmodel.launch;
@ -42,7 +43,6 @@ import org.eclipse.cdt.dsf.ui.viewmodel.IVMContext;
import org.eclipse.cdt.dsf.ui.viewmodel.ModelProxyInstalledEvent;
import org.eclipse.cdt.dsf.ui.viewmodel.VMChildrenUpdate;
import org.eclipse.cdt.dsf.ui.viewmodel.VMDelta;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMNode;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.IElementPropertiesProvider;
@ -68,7 +68,7 @@ import org.eclipse.debug.ui.IDebugUIConstants;
*
* @since 1.1
*/
public abstract class AbstractThreadVMNode extends AbstractDMVMNode
public abstract class AbstractThreadVMNode extends AbstractExecutionContextVMNode
implements IElementLabelProvider, IElementPropertiesProvider
{
/**

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2005, 2010 IBM Corporation and others.
* Copyright (c) 2005, 2011 IBM Corporation 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
@ -8,6 +8,7 @@
* Contributors:
* IBM Corporation - initial API and implementation
* Wind River Systems - adapted to use with DSF
* Dobrin Alexiev (Texas Instruments) - user groups support (bug 240208)
*******************************************************************************/
package org.eclipse.cdt.dsf.ui.viewmodel;
@ -21,6 +22,7 @@ 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.RequestMonitor;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.IDMVMContext;
import org.eclipse.core.runtime.ISafeRunnable;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.SafeRunner;
@ -63,6 +65,7 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
private boolean fDisposed = false;
private ListenerList fListeners = new ListenerList();
private IDoubleClickListener fDoubleClickListener;
private boolean fAllowRecursiveVMNodes = false;
/**
* Creates this model proxy strategy for the given provider.
@ -337,7 +340,7 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
// of the viewer. Get the root node of the chain--i.e.,
// the delta for the root element of the entire viewer.
final IModelDelta viewRootDelta = getRootDelta(getData());
// Find the child nodes that (may) have deltas for the given event.
final Map<IVMNode,Integer> childNodesWithDeltaFlags = getChildNodesWithDeltaFlags(rootNode, getData(), event);
@ -695,8 +698,36 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
delta.setChildCount(getData().get(null));
for (final IVMNode childNode : childNodes.keySet()) {
// Avoid descending into recursive node hierarchy's when calculating the delta.
if (node.equals(childNode)) continue;
if (node.equals(childNode)) {
// Avoid descending into recursive node hierarchy's when calculating the delta.
// if recursive nodes are not allowed.
if( !allowRecursiveVMNodes())
continue;
// get into recursion to build the delta only if the recursive context is added.
//
// We user current assumption that recursive container can be added as first children
// if the list of VMNodes. If we decide to make the patch more generic ( allow recursive
// node to be at different index) we need to remove this simplification.
//
if( isDeltaElementOfType(delta, childNode)) {
childNode.buildDelta(
event, delta, 0,
new RequestMonitor(getVMProvider().getExecutor(), multiRm) {
@Override
protected void handleSuccess() {
buildChildDeltas(
childNode, event, delta, 0,
new RequestMonitor(getVMProvider().getExecutor(), multiRm) );
}
});
multiRmCount++;
}
continue;
}
final int nodeOffset = getData().get(childNode);
childNode.buildDelta(
@ -793,7 +824,7 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
protected Map<IVMNode, Integer> getChildNodesWithDeltaFlags(IVMNode node, ModelDelta parentDelta, Object e) {
Map<IVMNode, Integer> nodes = new HashMap<IVMNode, Integer>();
for (final IVMNode childNode : getVMProvider().getChildVMNodes(node)) {
if (!childNode.equals(node)) {
if (!childNode.equals(node) || allowRecursiveVMNodes()) {
int delta = getDeltaFlags(childNode, parentDelta, e);
if (delta != IModelDelta.NO_CHANGE) {
nodes.put(childNode, delta);
@ -803,5 +834,57 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy {
return nodes;
}
/**
* Returns whether DefaultVMModelProxyStrategy allows to handles recursive VMNdoes hierarchy.
*
* @see setAllowRecursiveVMNodes()
* @return true if this DefaultVMModelProxyStrategy allows recursive containers.
*/
public boolean allowRecursiveVMNodes() {
return fAllowRecursiveVMNodes;
}
/**
* Allow DefaultVMModelProxyStrategy to handles recursive VMNdoes hierarchy.
*
* For example if the client wants the debug view to display container nodes that
* have containers this flag has to be set.
*
* Launch1
* Container-1
* Container-1.1
* Thread-1
* Container-1.1.1
* Thread-2
* Thread-2
*
* This will allow the client to setup a VMNode to be in the list of its children.
* addChildNodes(containerNode, new IVMNode[] { containerNode, threadsNode });
*
* The client also need to make sure the recursive VMNodes and their immediate children:
* 1. Handles buildDelta() by building one level at a time by examining the delta passed as parameter.
* 2. Returns the correct level container inside getContextsForEvent() based on the delta passed.
*
* See org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.launch.ContainerVMNode for sample implementation.
*
* @param allow - whether to allow or not recursive containment of VMNodes.
*/
public void setAllowRecursiveVMNodes( boolean allow) {
fAllowRecursiveVMNodes = allow;
}
/**
* Compares if the VMNode of element of the provided delta is the same as the provided IVMNode.
*
* @param delta - delta for which to compare the IDMVMContext
* @param node - the IVMNode we want to compare to.
* @return if the VMNode of element of the provided delta is the same as the provided IVMNode.
*/
protected boolean isDeltaElementOfType( VMDelta delta, IVMNode node) {
if( delta.getElement() instanceof IDMVMContext) {
IDMVMContext dmvmContext = (IDMVMContext)delta.getElement();
return dmvmContext.getVMNode().equals(node);
}
return false;
}
}

View file

@ -14,6 +14,7 @@ Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.cdt.dsf.concurrent,
org.eclipse.cdt.dsf.datamodel,
org.eclipse.cdt.dsf.debug.internal.provisional.model;x-friends:="org.eclipse.cdt.dsf.ui",
org.eclipse.cdt.dsf.debug.internal.provisional.service;x-internal:=true,
org.eclipse.cdt.dsf.debug.model,
org.eclipse.cdt.dsf.debug.service,
org.eclipse.cdt.dsf.debug.service.command,

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2006, 2009 Wind River Systems and others.
* Copyright (c) 2006, 2011 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
@ -8,6 +8,7 @@
* Contributors:
* Wind River Systems - initial API and implementation
* Ericsson - Modified for additional features in DSF Reference implementation
* Dobrin Alexiev (Texas Instruments) - added helpers for recursive data model contexts (bug 240208)
*******************************************************************************/
package org.eclipse.cdt.dsf.datamodel;
@ -73,6 +74,63 @@ public class DMContexts {
return null;
}
/**
* Finds the top most ancestor of the specified type.
* It assumes only one immediate parent of the give type exists.
* The search is done until there is no more immediate parents of the given type.
* The method returns the last one found.
*
* @param <V>
* @param ctx DMC to search.
* @param ancestorType Class type of the desired DMC ancestor.
* @return Returns the ancestor if found, null otherwise.
* @since 2.2
*/
@ThreadSafe
@SuppressWarnings("unchecked")
public static <V extends IDMContext> V getTopMostAncestorOfType(IDMContext ctx, Class<V> ancestorType) {
if(ctx == null)
return null;
V topMostAncestor = null;
boolean hasAncestorOfType = false;
IDMContext current = ctx;
do {
hasAncestorOfType = false;
IDMContext[] parents = current.getParents();
for( IDMContext parent : parents) {
if (ancestorType.isAssignableFrom(parent.getClass())) {
hasAncestorOfType = true;
topMostAncestor = (V) parent;
current = parent;
}
}
} while( hasAncestorOfType);
return topMostAncestor;
}
/**
* Finds the immediate parent of the specified type if exists.
*
* @param ctx DMC to search.
* @param ancestorType Class type of the desired DMC ancestor.
* @return Returns the ancestor if found, null otherwise.
* @since 2.2
*/
@ThreadSafe
@SuppressWarnings("unchecked")
public static <V extends IDMContext> V getParentOfType(IDMContext ctx, Class<V> ancestorType) {
if(ctx == null)
return null;
for( IDMContext parent : ctx.getParents())
if (ancestorType.isAssignableFrom(parent.getClass()))
return (V)parent;
return null;
}
/**
* Finds all data model contexts of given type among ancestors of the
* specified context. Ancestors are returned in order of closest to farthest,

View file

@ -0,0 +1,65 @@
/*******************************************************************************
* Copyright (c) 2010, 2011 Texas Instruments, Inc. 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:
* Dobrin Alexiev (Texas Instruments) - initial API and implementation (bug 240208)
********************************************************************************/
package org.eclipse.cdt.dsf.debug.internal.provisional.service;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.service.IDsfService;
/**
* EXPERIMENTAL. This class or interface has been added as part
* of a work in progress. There is no guarantee that this API will work or that
* it will remain the same.
*
* Interface for translating one model of execution context hierarchy to another.
* As the grouping feature is added incrementally this interface will be defined properly.
*
* The reason this interface is proposed at the DSF level is to accommodate requirements from
* multiple DSF debuggers.
*
* @since 2.2
* @experimental
*/
public interface IExecutionContextTranslator extends IDsfService {
/**
* returns true if all DM contexts can be grouped into one container.
*
* @param context
* @param rm
*/
void canGroup(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* returns true if all DM contexts can be ungrouped.
*
* @param context
* @param rm
*/
void canUngroup(IExecutionDMContext[] contexts, DataRequestMonitor<Boolean> rm);
/**
* Groups the specified execution contexts.
*
* @param context
* @param requestMonitor
*/
void group(IExecutionDMContext[] contexts, RequestMonitor requestMonitor);
/**
* Ungroups the specified execution contexts.
*
* @param context
* @param requestMonitor
*/
void ungroup(IExecutionDMContext[] contexts, RequestMonitor requestMonitor);
}

View file

@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2008, 2009 Ericsson and others.
* Copyright (c) 2008, 2011 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
@ -7,9 +7,11 @@
*
* Contributors:
* Ericsson - initial API and implementation
*******************************************************************************/
* Dobrin Alexiev (Texas Instruments) - user groups support (bug 240208)
********************************************************************************/
package org.eclipse.cdt.dsf.debug.service;
import org.eclipse.cdt.dsf.debug.internal.provisional.service.IExecutionContextTranslator;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
import org.eclipse.cdt.dsf.service.DsfSession;
@ -48,6 +50,8 @@ public abstract class AbstractDsfDebugServicesFactory implements IDsfDebugServic
return (V)createStackService(session);
} else if (ISymbols.class.isAssignableFrom(clazz)) {
return (V)createSymbolsService(session);
} else if (IExecutionContextTranslator.class.isAssignableFrom(clazz)) {
return (V)createExecutionContextTranslator(session);
}
return null;
@ -66,5 +70,10 @@ public abstract class AbstractDsfDebugServicesFactory implements IDsfDebugServic
protected ISignals createSignalsService(DsfSession session) { return null; }
protected IStack createStackService(DsfSession session) { return null; }
protected ISymbols createSymbolsService(DsfSession session) { return null; }
/**
* @since 2.2
*/
protected IExecutionContextTranslator createExecutionContextTranslator( DsfSession session) { return null; }
}