From a12a4967e3670c700efb539f7698bdc137fc49cd Mon Sep 17 00:00:00 2001 From: Pawel Piech Date: Tue, 12 Feb 2008 23:13:12 +0000 Subject: [PATCH] [179102] Added logic to handle ModelProxyInstalledEvent. This logic now selects the top stack frame when the debug view is first opened. --- .../ui/viewmodel/launch/LaunchRootVMNode.java | 2 +- .../viewmodel/launch/StackFramesVMNode.java | 115 +++++++--- .../dd/dsf/ui/viewmodel/AbstractVMNode.java | 10 +- .../dsf/ui/viewmodel/AbstractVMProvider.java | 29 ++- .../DefaultVMContentProviderStrategy.java | 61 +++--- .../DefaultVMModelProxyStrategy.java | 205 ++++++++++-------- .../dd/dsf/ui/viewmodel/IVMModelProxy.java | 19 +- .../eclipse/dd/dsf/ui/viewmodel/IVMNode.java | 12 +- .../dd/dsf/ui/viewmodel/IVMProvider.java | 31 ++- .../viewmodel/ModelProxyInstalledEvent.java | 41 ++++ .../dd/dsf/ui/viewmodel/RootVMNode.java | 3 + .../dsf/ui/viewmodel/dm/AbstractDMVMNode.java | 12 +- .../update/AbstractCachingVMProvider.java | 29 +-- 13 files changed, 362 insertions(+), 207 deletions(-) create mode 100644 plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/ModelProxyInstalledEvent.java diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchRootVMNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchRootVMNode.java index 1c0af5b33b5..c6074e21142 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchRootVMNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/LaunchRootVMNode.java @@ -70,7 +70,7 @@ public class LaunchRootVMNode extends RootVMNode return false; } } - return true; + return super.isDeltaEvent(rootObject, e); } @Override diff --git a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java index 2e5f11b5c9e..317a2c584f1 100644 --- a/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java +++ b/plugins/org.eclipse.dd.dsf.debug.ui/src/org/eclipse/dd/dsf/debug/ui/viewmodel/launch/StackFramesVMNode.java @@ -19,7 +19,7 @@ import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.datamodel.DMContexts; import org.eclipse.dd.dsf.debug.service.IRunControl; import org.eclipse.dd.dsf.debug.service.IStack; -import org.eclipse.dd.dsf.debug.service.IStepQueueManager; +import org.eclipse.dd.dsf.debug.service.StepQueueManager; import org.eclipse.dd.dsf.debug.service.IRunControl.IContainerSuspendedDMEvent; import org.eclipse.dd.dsf.debug.service.IRunControl.IExecutionDMContext; import org.eclipse.dd.dsf.debug.service.IRunControl.IResumedDMEvent; @@ -30,6 +30,7 @@ import org.eclipse.dd.dsf.debug.service.IStack.IFrameDMData; import org.eclipse.dd.dsf.service.DsfSession; import org.eclipse.dd.dsf.service.IDsfService; import org.eclipse.dd.dsf.ui.viewmodel.IVMContext; +import org.eclipse.dd.dsf.ui.viewmodel.ModelProxyInstalledEvent; import org.eclipse.dd.dsf.ui.viewmodel.VMChildrenUpdate; import org.eclipse.dd.dsf.ui.viewmodel.VMDelta; import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMNode; @@ -118,31 +119,39 @@ public class StackFramesVMNode extends AbstractDMVMNode return; } - getServicesTracker().getService(IStack.class).getTopFrame( - execDmc, - new DataRequestMonitor(getExecutor(), null) { - @Override - public void handleCompleted() { - if (!getStatus().isOK()) { - handleFailedUpdate(update); - return; - } - - IVMContext topFrameVmc = createVMContext(getData()); - - update.setChild(topFrameVmc, 0); - // If there are old frames cached, use them and only substitute the top frame object. Otherwise, create - // an array of VMCs with just the top frame. - if (fCachedOldFrameVMCs != null && fCachedOldFrameVMCs.length >= 1) { - fCachedOldFrameVMCs[0] = topFrameVmc; - for (int i = 0; i < fCachedOldFrameVMCs.length; i++) - update.setChild(fCachedOldFrameVMCs[i], i); - } else { - update.setChild(topFrameVmc, 0); - } - update.done(); + try { + getSession().getExecutor().execute(new DsfRunnable() { + public void run() { + getServicesTracker().getService(IStack.class).getTopFrame( + execDmc, + new DataRequestMonitor(getExecutor(), null) { + @Override + public void handleCompleted() { + if (!getStatus().isOK()) { + handleFailedUpdate(update); + return; + } + + IVMContext topFrameVmc = createVMContext(getData()); + + update.setChild(topFrameVmc, 0); + // If there are old frames cached, use them and only substitute the top frame object. Otherwise, create + // an array of VMCs with just the top frame. + if (fCachedOldFrameVMCs != null && fCachedOldFrameVMCs.length >= 1) { + fCachedOldFrameVMCs[0] = topFrameVmc; + for (int i = 0; i < fCachedOldFrameVMCs.length; i++) + update.setChild(fCachedOldFrameVMCs[i], i); + } else { + update.setChild(topFrameVmc, 0); + } + update.done(); + } + }); } }); + } catch (RejectedExecutionException e) { + update.done(); + } } @@ -209,7 +218,7 @@ public class StackFramesVMNode extends AbstractDMVMNode final IExecutionDMContext execDmc = findDmcInPath(update.getViewerInput(), update.getElementPath(), IExecutionDMContext.class); IRunControl runControlService = getServicesTracker().getService(IRunControl.class); - IStepQueueManager stepQueueMgrService = getServicesTracker().getService(IStepQueueManager.class); + StepQueueManager stepQueueMgrService = getServicesTracker().getService(StepQueueManager.class); if (execDmc == null || runControlService == null || stepQueueMgrService == null) return; String imageKey = null; @@ -271,6 +280,31 @@ public class StackFramesVMNode extends AbstractDMVMNode } + @Override + public void getContextsForEvent(final VMDelta parentDelta, Object e, final DataRequestMonitor rm) { + if (e instanceof ModelProxyInstalledEvent) { + // Retrieve the list of stack frames, and mark the top frame to be selected. + getElementsTopStackFrameOnly( + new VMChildrenUpdate( + parentDelta, getVMProvider().getPresentationContext(), -1, -1, + new DataRequestMonitor>(getExecutor(), null) { + @Override + public void handleCompleted() { + if (getStatus().isOK() && getData().size() != 0) { + rm.setData(new IVMContext[] { (IVMContext)getData().get(0) }); + } else { + // In case of errors, return an empty set of frames. + rm.setData(new IVMContext[0]); + } + rm.done(); + } + }) + ); + return; + } + super.getContextsForEvent(parentDelta, e, rm); + } + public int getDeltaFlags(Object e) { // This node generates delta if the timers have changed, or if the // label has changed. @@ -282,9 +316,12 @@ public class StackFramesVMNode extends AbstractDMVMNode } else { return IModelDelta.CONTENT; } - } else if (e instanceof IStepQueueManager.ISteppingTimedOutEvent) { + } else if (e instanceof StepQueueManager.ISteppingTimedOutEvent) { return IModelDelta.CONTENT; + } else if (e instanceof ModelProxyInstalledEvent) { + return IModelDelta.SELECT | IModelDelta.EXPAND; } + return IModelDelta.NO_CHANGE; } @@ -300,8 +337,10 @@ public class StackFramesVMNode extends AbstractDMVMNode buildDeltaForSuspendedEvent((ISuspendedDMEvent)e, execDmc, execDmc, parent, nodeOffset, rm); } else if (e instanceof IResumedDMEvent) { buildDeltaForResumedEvent((IResumedDMEvent)e, parent, nodeOffset, rm); - } else if (e instanceof IStepQueueManager.ISteppingTimedOutEvent) { - buildDeltaForSteppingTimedOutEvent((IStepQueueManager.ISteppingTimedOutEvent)e, parent, nodeOffset, rm); + } else if (e instanceof StepQueueManager.ISteppingTimedOutEvent) { + buildDeltaForSteppingTimedOutEvent((StepQueueManager.ISteppingTimedOutEvent)e, parent, nodeOffset, rm); + } else if (e instanceof ModelProxyInstalledEvent) { + buildDeltaForModelProxyInstalledEvent(parent, nodeOffset, rm); } else { rm.done(); } @@ -372,9 +411,27 @@ public class StackFramesVMNode extends AbstractDMVMNode rm.done(); } - private void buildDeltaForSteppingTimedOutEvent(final IStepQueueManager.ISteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) { + private void buildDeltaForSteppingTimedOutEvent(final StepQueueManager.ISteppingTimedOutEvent e, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) { // Repaint the stack frame images to have the running symbol. parentDelta.setFlags(parentDelta.getFlags() | IModelDelta.CONTENT); rm.done(); } + + private void buildDeltaForModelProxyInstalledEvent(final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) { + // Retrieve the list of stack frames, and mark the top frame to be selected. + getElementsTopStackFrameOnly( + new VMChildrenUpdate( + parentDelta, getVMProvider().getPresentationContext(), -1, -1, + new DataRequestMonitor>(getExecutor(), null) { + @Override + public void handleCompleted() { + if (getStatus().isOK() && getData().size() != 0) { + parentDelta.addNode( getData().get(0), 0, IModelDelta.SELECT | IModelDelta.EXPAND); + } + rm.done(); + } + }) + ); + } + } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMNode.java index e91fc401214..436aec4aeca 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMNode.java @@ -10,7 +10,12 @@ *******************************************************************************/ package org.eclipse.dd.dsf.ui.viewmodel; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.DsfExecutor; +import org.eclipse.dd.dsf.service.IDsfService; +import org.eclipse.dd.dsf.ui.DsfUIPlugin; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.ILabelUpdate; @@ -46,8 +51,9 @@ abstract public class AbstractVMNode implements IVMNode { fDisposed = true; } - public IVMContext getContextFromEvent(Object event) { - return null; + public void getContextsForEvent(VMDelta parentDelta, Object event, DataRequestMonitor rm) { + rm.setStatus(new Status(IStatus.ERROR, DsfUIPlugin.PLUGIN_ID, IDsfService.NOT_SUPPORTED, "", null)); //$NON-NLS-1$ + rm.done(); } protected boolean isDisposed() { diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java index bfb34b0b151..495dc80c536 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/AbstractVMProvider.java @@ -322,7 +322,7 @@ abstract public class AbstractVMProvider implements IVMProvider * overrides this method to optionally return the results for an update from * a cache. */ - protected void updateNode(final IVMNode node, IHasChildrenUpdate[] updates) { + public void updateNode(final IVMNode node, IHasChildrenUpdate[] updates) { IHasChildrenUpdate[] updateProxies = new IHasChildrenUpdate[updates.length]; for (int i = 0; i < updates.length; i++) { final IHasChildrenUpdate update = updates[i]; @@ -340,7 +340,7 @@ abstract public class AbstractVMProvider implements IVMProvider if (getStatus().getCode() == IDsfService.NOT_SUPPORTED) { updateNode( node, - new VMChildrenUpdate[] { new VMChildrenUpdate( + new VMChildrenUpdate( update, -1, -1, new ViewerDataRequestMonitor>(getExecutor(), update) { @Override @@ -349,7 +349,7 @@ abstract public class AbstractVMProvider implements IVMProvider update.done(); } }) - }); + ); } else { update.setStatus(getStatus()); @@ -370,13 +370,11 @@ abstract public class AbstractVMProvider implements IVMProvider * overrides this method to optionally return the results for an update from * a cache. */ - protected void updateNode(final IVMNode node, IChildrenCountUpdate[] updates) { - IChildrenCountUpdate[] updateProxies = new IChildrenCountUpdate[updates.length]; - for (int i = 0; i < updates.length; i++) { - final IChildrenCountUpdate update = updates[i]; - updateProxies[i] = new VMChildrenCountUpdate( + public void updateNode(final IVMNode node, final IChildrenCountUpdate update) { + node.update(new IChildrenCountUpdate[] { + new VMChildrenCountUpdate( update, - new ViewerDataRequestMonitor(getExecutor(), updates[i]) { + new ViewerDataRequestMonitor(getExecutor(), update) { @Override protected void handleOK() { update.setChildCount(getData()); @@ -388,7 +386,7 @@ abstract public class AbstractVMProvider implements IVMProvider if (getStatus().getCode() == IDsfService.NOT_SUPPORTED) { updateNode( node, - new VMChildrenUpdate[] { new VMChildrenUpdate( + new VMChildrenUpdate( update, -1, -1, new ViewerDataRequestMonitor>(getExecutor(), update) { @Override @@ -397,14 +395,13 @@ abstract public class AbstractVMProvider implements IVMProvider update.done(); } }) - }); + ); } } - }); - } - node.update(updateProxies); + }) + }); } /** @@ -415,8 +412,8 @@ abstract public class AbstractVMProvider implements IVMProvider * overrides this method to optionally return the results for an update from * a cache. */ - protected void updateNode(IVMNode node, IChildrenUpdate[] updates) { - node.update(updates); + public void updateNode(IVMNode node, IChildrenUpdate update) { + node.update(new IChildrenUpdate[] { update }); } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DefaultVMContentProviderStrategy.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DefaultVMContentProviderStrategy.java index afff0d73f4c..6009f7b16c9 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DefaultVMContentProviderStrategy.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DefaultVMContentProviderStrategy.java @@ -170,7 +170,7 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider update.setChildCount(0); update.done(); } else if (childNodes.length == 1) { - getVMProvider().updateNode(childNodes[0], new IChildrenCountUpdate[] { update } ); + getVMProvider().updateNode(childNodes[0], update); } else { getChildrenCountsForNode( update, @@ -208,7 +208,7 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider // Invalid update, just mark done. update.done(); } else if (childNodes.length == 1) { - getVMProvider().updateNode(childNodes[0], new IChildrenUpdate[] { update }); + getVMProvider().updateNode(childNodes[0], update); } else { getChildrenCountsForNode( update, @@ -261,23 +261,22 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider final int nodeIndex = i; getVMProvider().updateNode( childNodes[i], - new IChildrenCountUpdate[] { - new VMChildrenCountUpdate( - update, - childrenCountMultiReqMon.add( - new DataRequestMonitor(getVMProvider().getExecutor(), null) { - @Override - protected void handleOK() { - counts[nodeIndex] = getData(); - } - - @Override - protected void handleCompleted() { - super.handleCompleted(); - childrenCountMultiReqMon.requestMonitorDone(this); - } - })) - }); + new VMChildrenCountUpdate( + update, + childrenCountMultiReqMon.add( + new DataRequestMonitor(getVMProvider().getExecutor(), null) { + @Override + protected void handleOK() { + counts[nodeIndex] = getData(); + } + + @Override + protected void handleCompleted() { + super.handleCompleted(); + childrenCountMultiReqMon.requestMonitorDone(this); + } + })) + ); } } @@ -315,21 +314,19 @@ public class DefaultVMContentProviderStrategy implements IElementContentProvider if (elementsLength > 0) { getVMProvider().updateNode( nodes[i], - new IChildrenUpdate[] { - new VMChildrenUpdate( - update, elementsStartIdx, elementsLength, - elementsMultiRequestMon.add(new DataRequestMonitor>(getVMProvider().getExecutor(), null) { - @Override - protected void handleCompleted() { - if (getStatus().isOK()) { - for (int i = 0; i < elementsLength; i++) { - update.setChild(getData().get(i), elementsStartIdx + nodeStartIdx + i); - } + new VMChildrenUpdate( + update, elementsStartIdx, elementsLength, + elementsMultiRequestMon.add(new DataRequestMonitor>(getVMProvider().getExecutor(), null) { + @Override + protected void handleCompleted() { + if (getStatus().isOK()) { + for (int i = 0; i < elementsLength; i++) { + update.setChild(getData().get(i), elementsStartIdx + nodeStartIdx + i); } - elementsMultiRequestMon.requestMonitorDone(this); } - })) - } + elementsMultiRequestMon.requestMonitorDone(this); + } + })) ); } } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DefaultVMModelProxyStrategy.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DefaultVMModelProxyStrategy.java index 4a3739f5439..f51c807277a 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DefaultVMModelProxyStrategy.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/DefaultVMModelProxyStrategy.java @@ -24,9 +24,8 @@ import org.eclipse.dd.dsf.concurrent.CountingRequestMonitor; import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.MultiRequestMonitor; import org.eclipse.dd.dsf.concurrent.RequestMonitor; +import org.eclipse.dd.dsf.service.IDsfService; import org.eclipse.debug.internal.ui.DebugUIPlugin; -import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; -import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; @@ -182,6 +181,7 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy { */ public void installed(Viewer viewer) { fViewer = viewer; + fProvider.handleEvent(new ModelProxyInstalledEvent(this, viewer, fRootElement)); } /** @@ -262,8 +262,8 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy { // If no child nodes have deltas we can stop here. if (childNodesWithDeltaFlags.size() == 0) { - rm.done(); rm.setData(viewRootDelta); + rm.done(); return; } @@ -284,19 +284,26 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy { protected void buildChildDeltas(final IVMNode node, final Object event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor rm) { - final IVMContext vmc = node.getContextFromEvent(event); - - if (vmc != null) { - buildChildDeltasForEventContext(vmc, node, event, parentDelta, nodeOffset, rm); - } else { - // The DMC for this node was not found in the event. Call the - // super-class to resort to the default behavior which may add a - // delta for every element in this node. - buildChildDeltasForAllContexts(node, event, parentDelta, nodeOffset, rm); - } + node.getContextsForEvent( + parentDelta, + event, + new DataRequestMonitor(getVMProvider().getExecutor(), rm) { + @Override + protected void handleCompleted() { + if (getStatus().isOK()) { + assert getData() != null; + buildChildDeltasForEventContext(getData(), node, event, parentDelta, nodeOffset, rm); + } else if (getStatus().getCode() == IDsfService.NOT_SUPPORTED) { + // The DMC for this node was not found in the event. Call the + // super-class to resort to the default behavior which may add a + // delta for every element in this node. + buildChildDeltasForAllContexts(node, event, parentDelta, nodeOffset, rm); + } + } + }); } - protected void buildChildDeltasForEventContext(final IVMContext vmc, final IVMNode node, final Object event, + protected void buildChildDeltasForEventContext(final IVMContext[] vmcs, final IVMNode node, final Object event, final VMDelta parentDelta, final int nodeOffset, final RequestMonitor requestMonitor) { final Map childNodeDeltas = getChildNodesWithDeltaFlags(node, parentDelta, event); @@ -324,31 +331,34 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy { // elements and then finding the DMC that the event is for. getVMProvider().updateNode( node, - new IChildrenUpdate[] { - new VMChildrenUpdate( - parentDelta, getVMProvider().getPresentationContext(), -1, -1, - new DataRequestMonitor>(getVMProvider().getExecutor(), null) { - @Override - protected void handleCompleted() { - if (isDisposed()) return; - - // Check for an empty list of elements. If it's empty then we - // don't have to call the children nodes, so return here. - // No need to propagate error, there's no means or need to display it. - if (!getStatus().isOK() || getData().isEmpty()) { - requestMonitor.done(); - return; - } - - // Find the index. + new VMChildrenUpdate( + parentDelta, getVMProvider().getPresentationContext(), -1, -1, + new DataRequestMonitor>(getVMProvider().getExecutor(), null) { + @Override + protected void handleCompleted() { + if (isDisposed()) return; + + // Check for an empty list of elements. If it's empty then we + // don't have to call the children nodes, so return here. + // No need to propagate error, there's no means or need to display it. + if (!getStatus().isOK() || getData().isEmpty()) { + requestMonitor.done(); + return; + } + + CountingRequestMonitor countingRm = + new CountingRequestMonitor(getVMProvider().getExecutor(), requestMonitor); + + int count = 0; + for (IVMContext vmc : vmcs) { + // Find the index of the vmc in the full list of elements. int i; for (i = 0; i < getData().size(); i++) { if (vmc.equals(getData().get(i))) break; } if (i == getData().size()) { // Element not found, no need to generate the delta. - requestMonitor.done(); - return; + continue; } // Optimization: Try to find a delta with a matching element, if found use it. @@ -359,18 +369,27 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy { delta = parentDelta.addNode(vmc, elementIndex, IModelDelta.NO_CHANGE); } - callChildNodesToBuildDelta(node, childNodeDeltas, delta, event, requestMonitor); + callChildNodesToBuildDelta(node, childNodeDeltas, delta, event, countingRm); + count++; } - }) - }); + countingRm.setDoneCount(count); + } + })); } else { - // Optimization: Try to find a delta with a matching element, if found use it. - // Otherwise create a new delta for the event element. - VMDelta delta = (VMDelta)parentDelta.getChildDelta(vmc); - if (delta == null) { - delta = parentDelta.addNode(vmc, IModelDelta.NO_CHANGE); + CountingRequestMonitor countingRm = + new CountingRequestMonitor(getVMProvider().getExecutor(), requestMonitor); + int count = 0; + for (IVMContext vmc : vmcs) { + // Optimization: Try to find a delta with a matching element, if found use it. + // Otherwise create a new delta for the event element. + VMDelta delta = (VMDelta)parentDelta.getChildDelta(vmc); + if (delta == null) { + delta = parentDelta.addNode(vmc, IModelDelta.NO_CHANGE); + } + callChildNodesToBuildDelta(node, childNodeDeltas, delta, event, requestMonitor); + count++; } - callChildNodesToBuildDelta(node, childNodeDeltas, delta, event, requestMonitor); + countingRm.setDoneCount(count); } } @@ -414,49 +433,48 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy { // each element as the parent of their delta. getVMProvider().updateNode( node, - new IChildrenUpdate[] { - new VMChildrenUpdate( - parentDelta, getVMProvider().getPresentationContext(), -1, -1, - new DataRequestMonitor>(getVMProvider().getExecutor(), null) { - @Override - protected void handleCompleted() { - if (fDisposed) return; - - // Check for an empty list of elements. If it's empty then we - // don't have to call the children nodes, so return here. - // No need to propagate error, there's no means or need to display it. - if (!getStatus().isOK() || getData().size() == 0) { - requestMonitor.done(); - return; - } - - final MultiRequestMonitor elementsDeltasMultiRequestMon = - new MultiRequestMonitor(getVMProvider().getExecutor(), null) { + new VMChildrenUpdate( + parentDelta, getVMProvider().getPresentationContext(), -1, -1, + new DataRequestMonitor>(getVMProvider().getExecutor(), null) { + @Override + protected void handleCompleted() { + if (fDisposed) return; + + // Check for an empty list of elements. If it's empty then we + // don't have to call the children nodes, so return here. + // No need to propagate error, there's no means or need to display it. + if (!getStatus().isOK() || getData().size() == 0) { + requestMonitor.done(); + return; + } + + final MultiRequestMonitor elementsDeltasMultiRequestMon = + new MultiRequestMonitor(getVMProvider().getExecutor(), null) { + @Override + protected void handleCompleted() { + if (isDisposed()) return; + requestMonitor.done(); + } + }; + + // For each element from this node, create a new delta, + // and then call all the child nodes to build their delta. + for (int i = 0; i < getData().size(); i++) { + int elementIndex = nodeOffset >= 0 ? nodeOffset + i : -1; + VMDelta delta = + parentDelta.addNode(getData().get(i), elementIndex, IModelDelta.NO_CHANGE); + callChildNodesToBuildDelta( + node, childNodesWithDeltaFlags, delta, event, + elementsDeltasMultiRequestMon.add(new RequestMonitor(getVMProvider().getExecutor(), null) { @Override protected void handleCompleted() { - if (isDisposed()) return; - requestMonitor.done(); + elementsDeltasMultiRequestMon.requestMonitorDone(this); } - }; - - // For each element from this node, create a new delta, - // and then call all the child nodes to build their delta. - for (int i = 0; i < getData().size(); i++) { - int elementIndex = nodeOffset >= 0 ? nodeOffset + i : -1; - VMDelta delta = - parentDelta.addNode(getData().get(i), elementIndex, IModelDelta.NO_CHANGE); - callChildNodesToBuildDelta( - node, childNodesWithDeltaFlags, delta, event, - elementsDeltasMultiRequestMon.add(new RequestMonitor(getVMProvider().getExecutor(), null) { - @Override - protected void handleCompleted() { - elementsDeltasMultiRequestMon.requestMonitorDone(this); - } - })); - } + })); } - }) - }); + } + }) + ); } } @@ -568,19 +586,18 @@ public class DefaultVMModelProxyStrategy implements IVMModelProxy { final int nodeIndex = i; getVMProvider().updateNode( childNodes[i], - new IChildrenCountUpdate[] { - new VMChildrenCountUpdate( - delta, getVMProvider().getPresentationContext(), - childrenCountMultiRequestMon.add( - new DataRequestMonitor(getVMProvider().getExecutor(), null) { - @Override - protected void handleCompleted() { - counts[nodeIndex] = getData(); - childrenCountMultiRequestMon.requestMonitorDone(this); - } - }) - ) - }); + new VMChildrenCountUpdate( + delta, getVMProvider().getPresentationContext(), + childrenCountMultiRequestMon.add( + new DataRequestMonitor(getVMProvider().getExecutor(), null) { + @Override + protected void handleCompleted() { + counts[nodeIndex] = getData(); + childrenCountMultiRequestMon.requestMonitorDone(this); + } + }) + ) + ); } } else { Map data = new HashMap(); diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMModelProxy.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMModelProxy.java index 07afe0dae52..ae2a808d020 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMModelProxy.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMModelProxy.java @@ -15,17 +15,32 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; /** - * + * View Model extension to the platform IModelProxy interface. This extension + * allows the IVMProvider implementation to delegate the model proxy implementation + * into a separate object. */ @SuppressWarnings("restriction") public interface IVMModelProxy extends IModelProxy { - + + /** + * Returns the root element that this model proxy was created for. + */ public Object getRootElement(); + /** + * Returns whether the given event applies to the root element and the + * nodes in this model proxy. + */ public boolean isDeltaEvent(Object event); + /** + * Creates a model delta for the given event. + */ public void createDelta(final Object event, final DataRequestMonitor rm); + /** + * Sends the given delta to this model proxy's listeners. + */ public void fireModelChanged(IModelDelta delta); } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMNode.java index 90036d72736..f3ea5927271 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMNode.java @@ -11,6 +11,7 @@ package org.eclipse.dd.dsf.ui.viewmodel; import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.RequestMonitor; import org.eclipse.dd.dsf.service.IDsfService; import org.eclipse.dd.dsf.ui.viewmodel.dm.AbstractDMVMProvider; @@ -92,20 +93,21 @@ public interface IVMNode extends IElementContentProvider public void buildDelta(Object event, VMDelta parent, int nodeOffset, RequestMonitor requestMonitor); /** - * Returns the view model element for the given data model event. This method + * Retireves the view model elements for the given data model event. This method * is optional and it allows the view model provider to optimize event processing * by avoiding the need to retrieve all possible elements for the given node. *

* For example: If a threads node implementation is given a thread stopped event in - * for this method, and the stopped event included a reference to the thread. Then + * this method, and the stopped event included a reference to the thread. Then * the implementation should create a view model context for that thread and return it * here. * + * @param parentDelta The parent delta in the processing of this event. * @param event The event to check for the data model object. - * @return A view model object if it can be calculated, null - * if it cannot. + * @param Request monitor for the array of elements corresponding to the + * given event. */ - public IVMContext getContextFromEvent(Object event); + public void getContextsForEvent(VMDelta parentDelta, Object event, DataRequestMonitor rm); /** * Releases the resources held by this node. diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMProvider.java index 2a924b2b09f..54331ac1b9b 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMProvider.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/IVMProvider.java @@ -3,8 +3,11 @@ package org.eclipse.dd.dsf.ui.viewmodel; import java.util.concurrent.Executor; import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IColumnPresentationFactory; import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementContentProvider; +import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxyFactory; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputProvider; @@ -39,6 +42,12 @@ import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputProvi public interface IVMProvider extends IElementContentProvider, IModelProxyFactory, IColumnPresentationFactory, IViewerInputProvider { + /** + * Returns the presentation context of the viewer that this provider + * is configured for. + */ + public IPresentationContext getPresentationContext(); + /** * Returns the VM Adapter associated with the provider. */ @@ -66,10 +75,26 @@ public interface IVMProvider public IVMNode[] getAllVMNodes(); /** - * Returns the presentation context of the viewer that this provider - * is configured for. + * Calls the given view model node to perform the given updates. This + * method is different than calling the IVMNode update method directly in that + * it allows the provider to do additional processing on the update such as caching. */ - public IPresentationContext getPresentationContext(); + public void updateNode(final IVMNode node, IHasChildrenUpdate[] updates); + + /** + * Calls the given view model node to perform the given updates. This + * method is different than calling the IVMNode update method directly in that + * it allows the provider to do additional processing on the update such as caching. + */ + public void updateNode(final IVMNode node, IChildrenCountUpdate updates); + + /** + * Calls the given view model node to perform the given updates. This + * method is different than calling the IVMNode update method directly in that + * it allows the provider to do additional processing on the update such as caching. + */ + public void updateNode(IVMNode node, IChildrenUpdate updates); + /** * Cleans up the resources associated with this provider. diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/ModelProxyInstalledEvent.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/ModelProxyInstalledEvent.java new file mode 100644 index 00000000000..68073af3ddb --- /dev/null +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/ModelProxyInstalledEvent.java @@ -0,0 +1,41 @@ +package org.eclipse.dd.dsf.ui.viewmodel; + +import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; +import org.eclipse.jface.viewers.Viewer; + +/** + * Event generated by an IModelProxy implementation when it is installed + * into a viewer. + */ +public class ModelProxyInstalledEvent { + private final IModelProxy fProxy; + private final Viewer fViewer; + private final Object fRootElement; + + public ModelProxyInstalledEvent(IModelProxy proxy, Viewer viewer, Object rootElement) { + fProxy = proxy; + fViewer = viewer; + fRootElement = rootElement; + } + + /** + * Returns the IModelProxy that generated this event. + */ + public IModelProxy getModelProxy() { + return fProxy; + } + + /** + * Returns the element that this model proxy was registered for. + */ + public Object getRootElement() { + return fRootElement; + } + + /** + * Returns the viewer that installed this model proxy. + */ + public Viewer getViewer() { + return fViewer; + } +} \ No newline at end of file diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/RootVMNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/RootVMNode.java index ae2895f8b39..5f34b2c05ad 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/RootVMNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/RootVMNode.java @@ -45,6 +45,9 @@ public class RootVMNode extends AbstractVMNode implements IRootVMNode { * event should be processed to generate a delta. */ public boolean isDeltaEvent(Object rootObject, Object event) { + if (event instanceof ModelProxyInstalledEvent) { + return rootObject.equals( ((ModelProxyInstalledEvent)event).getRootElement() ); + } return true; } diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMNode.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMNode.java index d265947d89b..d94b6f06f5b 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMNode.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/dm/AbstractDMVMNode.java @@ -15,6 +15,7 @@ import java.util.concurrent.RejectedExecutionException; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.dd.dsf.concurrent.ConfinedToDsfExecutor; +import org.eclipse.dd.dsf.concurrent.DataRequestMonitor; import org.eclipse.dd.dsf.concurrent.DsfRunnable; import org.eclipse.dd.dsf.concurrent.Immutable; import org.eclipse.dd.dsf.datamodel.DMContexts; @@ -28,6 +29,7 @@ import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMContext; import org.eclipse.dd.dsf.ui.viewmodel.AbstractVMNode; import org.eclipse.dd.dsf.ui.viewmodel.IVMContext; import org.eclipse.dd.dsf.ui.viewmodel.IVMNode; +import org.eclipse.dd.dsf.ui.viewmodel.VMDelta; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenCountUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IChildrenUpdate; import org.eclipse.debug.internal.ui.viewers.model.provisional.IHasChildrenUpdate; @@ -129,15 +131,17 @@ abstract public class AbstractDMVMNode extends AbstractVMNode implements IVMNode } @Override - public IVMContext getContextFromEvent(Object event) { + public void getContextsForEvent(VMDelta parentDelta, Object event, DataRequestMonitor rm) { if (event instanceof IDMEvent) { IDMEvent dmEvent = (IDMEvent)event; IDMContext dmc = DMContexts.getAncestorOfType(dmEvent.getDMContext(), fDMCClassType); if (dmc != null) { - return createVMContext(dmc); + rm.setData(new IVMContext[] { createVMContext(dmc) }); + rm.done(); + return; } - } - return null; + } + super.getContextsForEvent(parentDelta, event, rm); } protected AbstractDMVMProvider getDMVMProvider() { diff --git a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/update/AbstractCachingVMProvider.java b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/update/AbstractCachingVMProvider.java index 98e7b4acc76..3851620e4db 100644 --- a/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/update/AbstractCachingVMProvider.java +++ b/plugins/org.eclipse.dd.dsf.ui/src/org/eclipse/dd/dsf/ui/viewmodel/update/AbstractCachingVMProvider.java @@ -285,7 +285,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa } @Override - protected void updateNode(IVMNode node, IHasChildrenUpdate[] updates) { + public void updateNode(IVMNode node, IHasChildrenUpdate[] updates) { LinkedList missUpdates = new LinkedList(); for(final IHasChildrenUpdate update : updates) { ElementDataKey key = makeEntryKey(node, update); @@ -316,20 +316,14 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa } @Override - protected void updateNode(IVMNode node, IChildrenCountUpdate[] updates) { - // Given our knowledge of DefaultVMContentProviderStragety, make an - // assumption about the updates argument: there should always be - // exactly one update in this array. - assert updates.length == 1; - final IChildrenCountUpdate update = updates[0]; - + public void updateNode(IVMNode node, final IChildrenCountUpdate update) { ElementDataKey key = makeEntryKey(node, update); final ElementDataEntry entry = getElementDataEntry(key); if(entry.fChildrenCount != null) { update.setChildCount(entry.fChildrenCount.intValue()); update.done(); } else { - updates[0] = new VMChildrenCountUpdate(update, new DataRequestMonitor(getExecutor(), null) { + IChildrenCountUpdate updateProxy = new VMChildrenCountUpdate(update, new DataRequestMonitor(getExecutor(), null) { @Override protected void handleCompleted() { if(getStatus().isOK()) { @@ -341,17 +335,12 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa update.done(); } }); - super.updateNode(node, updates); + super.updateNode(node, updateProxy); } } @Override - protected void updateNode(IVMNode node, IChildrenUpdate[] updates) { - // Given our knowledge of DefaultVMContentProviderStragety, make an - // assumption about the updates argument: there should always be - // exactly one update in this array. - assert updates.length == 1; - final IChildrenUpdate update = updates[0]; + public void updateNode(IVMNode node, final IChildrenUpdate update) { ElementDataKey key = makeEntryKey(node, update); @@ -360,7 +349,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa // We need to retrieve all the children if we don't have any children information. // Or if the client requested all children (offset = -1, length -1) and we have not // retrieved that before. - updates[0] = new VMChildrenUpdate( + IChildrenUpdate updateProxy = new VMChildrenUpdate( update, update.getOffset(), update.getLength(), new DataRequestMonitor>(getExecutor(), null) { @@ -396,7 +385,7 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa update.done(); } }); - super.updateNode(node, updates); + super.updateNode(node, updateProxy); } else if (update.getOffset() < 0 ) { // The update requested all children. Fill in all children assuming that // the children array is complete. @@ -450,7 +439,9 @@ public class AbstractCachingVMProvider extends AbstractVMProvider implements ICa })); } - super.updateNode( node, partialUpdates.toArray(new IChildrenUpdate[partialUpdates.size()]) ); + for (IChildrenUpdate partialUpdate : partialUpdates) { + super.updateNode(node, partialUpdate); + } multiRm.setDoneCount(partialUpdates.size()); } else { // we have all of the children in cache; return from cache