--- a/cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointAttributeTranslator.java Fri Dec 04 14:31:59 2009 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,561 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009 Nokia 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:
- * Nokia - Initial API and implementation. Nov, 2009.
- *******************************************************************************/
-package org.eclipse.cdt.dsf.mi.service;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import org.eclipse.cdt.debug.core.model.ICBreakpoint;
-import org.eclipse.cdt.debug.core.model.ICBreakpointExtension;
-import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
-import org.eclipse.cdt.debug.core.model.ICWatchpoint;
-import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems;
-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.debug.service.BreakpointsMediator;
-import org.eclipse.cdt.dsf.debug.service.IBreakpointAttributeTranslatorExtension;
-import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension;
-import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
-import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.BreakpointEventType;
-import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.ITargetBreakpointInfo;
-import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
-import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
-import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
-import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
-import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
-import org.eclipse.cdt.dsf.service.DsfServicesTracker;
-import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.core.resources.IMarker;
-import org.eclipse.core.resources.IResource;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
-import org.eclipse.core.runtime.IStatus;
-import org.eclipse.core.runtime.Platform;
-import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
-import org.eclipse.debug.core.DebugException;
-import org.eclipse.debug.core.model.IBreakpoint;
-
-public class MIBreakpointAttributeTranslator implements IBreakpointAttributeTranslatorExtension {
-
- private final static String GDB_DEBUG_MODEL_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$
-
- // Extra breakpoint attributes
- private static final String ATTR_DEBUGGER_PATH = GdbPlugin.PLUGIN_ID + ".debuggerPath"; //$NON-NLS-1$
- private static final String ATTR_THREAD_FILTER = GdbPlugin.PLUGIN_ID + ".threadFilter"; //$NON-NLS-1$
-// private static final String ATTR_THREAD_ID = GdbPlugin.PLUGIN_ID + ".threadID"; //$NON-NLS-1$
-
- private DsfServicesTracker dsfServicesTracker;
- private DsfSession dsfSession;
- private BreakpointsMediator breakpointsMediator;
- private String debugModelId;
-
- /**
- * Manage breakpoint problem markers. <br>
- * It's better be done by MIBreakpoints service so that it's accessible by
- * the MIBreakpoints service too. But to minimize change to MIBreakpoints in
- * this iteration, I just put it here..... 11/18/09
- */
- private Map<ICBreakpoint, IMarker> fBreakpointMarkerProblems =
- new HashMap<ICBreakpoint, IMarker>();
-
- public MIBreakpointAttributeTranslator(DsfSession dsfSession, String debugModelId) {
- super();
- this.dsfSession = dsfSession;
- this.debugModelId = debugModelId;
-
- dsfServicesTracker = new DsfServicesTracker(GdbPlugin.getDefault().getBundle().getBundleContext(), dsfSession.getId());
- }
-
- public boolean canUpdateAttributes(IBreakpointDMContext bp, Map<String, Object> delta) {
- /*
- * This method decides whether we need to re-install the breakpoint
- * based on the attributes change (refer to caller in
- * BreakpointsMediator).
- */
- // Check if there is any modified attribute
- if (delta == null || delta.size() == 0)
- return true;
-
- // Check the "critical" attributes
- if (delta.containsKey(ATTR_DEBUGGER_PATH) // File name
- || delta.containsKey(MIBreakpoints.LINE_NUMBER) // Line number
- || delta.containsKey(MIBreakpoints.FUNCTION) // Function name
- || delta.containsKey(MIBreakpoints.ADDRESS) // Absolute address
- || delta.containsKey(ATTR_THREAD_FILTER) // Thread ID
- || delta.containsKey(MIBreakpoints.EXPRESSION) // Watchpoint expression
- || delta.containsKey(MIBreakpoints.READ) // Watchpoint type
- || delta.containsKey(MIBreakpoints.WRITE)) { // Watchpoint type
- return false;
- }
-
- // for other attrs (ICBreakpoint.INSTALL_COUNT, ICBreakpoint.IGNORE_COUNT,
- // ICBreakpoint.CONDITION, etc), we can update them.
- return true;
- }
-
- public void dispose() {
- if (dsfServicesTracker != null)
- dsfServicesTracker.dispose();
- dsfSession = null;
-
- clearBreakpointProblemMarkers();
- }
-
- public List<Map<String, Object>> getBreakpointAttributes(IBreakpoint bp, boolean bpManagerEnabled)
- throws CoreException {
- // deprecated
- List<Map<String, Object>> retVal = new ArrayList<Map<String, Object>>();
- return retVal;
- }
-
- public void initialize(BreakpointsMediator mediator) {
- breakpointsMediator = mediator;
- }
-
- public boolean supportsBreakpoint(IBreakpoint bp) {
- if (bp instanceof ICBreakpoint && bp.getModelIdentifier().equals(debugModelId)) {
- IMarker marker = bp.getMarker();
- if (marker != null) {
- return true;
- }
- }
- return false;
- }
-
- public void updateBreakpointStatus(IBreakpoint bp) {
- // obsolet, do nothing.
- }
-
- public void updateBreakpointsStatus(Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> bpsInfo,
- BreakpointEventType eventType) {
- for (IBreakpoint bp : bpsInfo.keySet()) {
- if (! (bp instanceof ICBreakpoint)) // not C breakpoints, bail out.
- return;
-
- final ICBreakpoint icbp = (ICBreakpoint) bp;
-
- Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBpPerContext = bpsInfo.get(bp);
-
- switch (eventType) {
- case ADDED: {
- int installCountTotal = 0;
- StringBuffer errMsg = new StringBuffer();
- for (ITargetBreakpointInfo[] tbpInfos : targetBpPerContext.values()) {
- // For each BpTargetDMContext, we increment the installCount for each
- // target BP that has been successfully installed.
- int installCountPerContext = 0;
- for (ITargetBreakpointInfo tbp : tbpInfos) {
- if (tbp.getTargetBreakpoint() != null)
- installCountPerContext++;
- else // failure in installation
- errMsg.append(tbp.getStatus().getMessage()).append('\n');
- }
- installCountTotal += installCountPerContext;
- }
-
- for (int i=0; i < installCountTotal; i++)
- try {
- // this will eventually carried out in a workspace runnable.
- icbp.incrementInstallCount();
- } catch (CoreException e) {
- GdbPlugin.getDefault().getLog().log(e.getStatus());
- }
-
- if (errMsg.length() > 0)
- addBreakpointProblemMarker(icbp, errMsg.toString(), IMarker.SEVERITY_WARNING);
- else // no error, clean message if any.
- removeBreakpointProblemMarker(icbp);
-
- break;
- }
- case MODIFIED:
- break;
-
- case REMOVED: {
- int removeCountTotal = 0;
- for (ITargetBreakpointInfo[] tbpInfos : targetBpPerContext.values()) {
- // For each BpTargetDMContext, we decrement the installCount for each
- // target BP that we tried to remove, even if the removal failed. That's
- // because I've not seen a way to tell platform that removal fails
- // and the BP should be kept in UI.
- removeCountTotal += tbpInfos.length;
- }
-
- for (int i=0; i < removeCountTotal; i++)
- try {
- if (icbp.isRegistered()) // not deleted in UI
- icbp.decrementInstallCount();
- } catch (CoreException e) {
- GdbPlugin.getDefault().getLog().log(e.getStatus());
- }
- break;
- }
- }
- }
- }
-
- public Map<String, Object> convertAttributes(Map<String, Object> platformAttrs) {
- Map<String, Object> targetAttrs = new HashMap<String, Object>();
-
- if (platformAttrs.containsKey(MIBreakpoints.BREAKPOINT_TYPE))
- targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE, platformAttrs.get(MIBreakpoints.BREAKPOINT_TYPE));
-
- if (platformAttrs.containsKey(ICWatchpoint.EXPRESSION))
- targetAttrs.put(MIBreakpoints.EXPRESSION, platformAttrs.get(ICWatchpoint.EXPRESSION));
- if (platformAttrs.containsKey(ICWatchpoint.READ))
- targetAttrs.put(MIBreakpoints.READ, platformAttrs.get(ICWatchpoint.READ));
- if (platformAttrs.containsKey(ICWatchpoint.WRITE))
- targetAttrs.put(MIBreakpoints.WRITE, platformAttrs.get(ICWatchpoint.WRITE));
-
- if (platformAttrs.containsKey(ICBreakpoint.SOURCE_HANDLE))
- targetAttrs.put(MIBreakpoints.FILE_NAME, platformAttrs.get(ICBreakpoint.SOURCE_HANDLE));
-
- if (platformAttrs.containsKey(IMarker.LINE_NUMBER))
- targetAttrs.put(MIBreakpoints.LINE_NUMBER, platformAttrs.get(IMarker.LINE_NUMBER));
- if (platformAttrs.containsKey(ICLineBreakpoint.FUNCTION))
- targetAttrs.put(MIBreakpoints.FUNCTION, platformAttrs.get(ICLineBreakpoint.FUNCTION));
- if (platformAttrs.containsKey(ICLineBreakpoint.ADDRESS))
- targetAttrs.put(MIBreakpoints.ADDRESS, platformAttrs.get(ICLineBreakpoint.ADDRESS));
-
- if (platformAttrs.containsKey(ICBreakpoint.CONDITION))
- targetAttrs.put(MIBreakpoints.CONDITION, platformAttrs.get(ICBreakpoint.CONDITION));
- if (platformAttrs.containsKey(ICBreakpoint.IGNORE_COUNT))
- targetAttrs.put(MIBreakpoints.IGNORE_COUNT, platformAttrs.get(ICBreakpoint.IGNORE_COUNT));
- if (platformAttrs.containsKey(ICBreakpoint.ENABLED))
- targetAttrs.put(MIBreakpoints.IS_ENABLED, platformAttrs.get(ICBreakpoint.ENABLED));
-
- return targetAttrs;
- }
-
- @SuppressWarnings("unchecked")
- public void resolveBreakpoint(IBreakpointsTargetDMContext context, IBreakpoint breakpoint,
- Map<String, Object> bpAttributes, final DataRequestMonitor<List<Map<String, Object>>> drm) {
-
- assert dsfSession.getExecutor().isInExecutorThread();
-
- // Create a copy as we don't want to change "bpAttributes".
- final Map<String, Object> targetBPAttrBase = new HashMap<String, Object>(bpAttributes);
-
- final Set<String> threads = (Set<String>) targetBPAttrBase.get(ATTR_THREAD_FILTER);
-
- final List<Map<String, Object>> targetBPList = new ArrayList<Map<String, Object>>();
-
- // get debugger path (compilation-path) for source file, if any.
- determineDebuggerPath(context, targetBPAttrBase, new RequestMonitor(dsfSession.getExecutor(), drm){
- @Override
- protected void handleSuccess() {
- // Create attribute list for each thread
- for (String thread : threads) {
- Map<String, Object> targetBP = new HashMap<String, Object>(targetBPAttrBase);
- targetBP.put(MIBreakpointDMData.THREAD_ID, thread);
- targetBPList.add(targetBP);
- }
-
- drm.setData(targetBPList);
- drm.done();
- }});
- }
-
- /**
- * determineDebuggerPath
- *
- * Adds the path to the source file to the set of attributes
- * (for the debugger).
- *
- * @param dmc
- * @param targetAttrs
- * @param rm
- */
- private void determineDebuggerPath(IBreakpointsTargetDMContext dmc,
- final Map<String, Object> targetAttrs, final RequestMonitor rm)
- {
- String hostPath = (String) targetAttrs.get(MIBreakpoints.FILE_NAME);
-
- if (hostPath != null) {
- ISourceLookup sourceService = dsfServicesTracker.getService(ISourceLookup.class);
-
- ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(dmc, ISourceLookupDMContext.class);
- if (srcDmc != null) {
- sourceService.getDebuggerPath(srcDmc, hostPath,
- new DataRequestMonitor<String>(dsfSession.getExecutor(), rm) {
- @Override
- protected void handleSuccess() {
- targetAttrs.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(getData()));
- rm.done();
- }
- });
- } else {
- // Source lookup not available for given context, use the host
- // path for the debugger path.
- targetAttrs.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(hostPath));
- rm.done();
- }
- } else {
- // Some types of breakpoints do not require a path
- // (e.g. watchpoints)
- rm.done();
- }
- }
-
- /**
- * See bug232415
- *
- * @param path the absolute path to the source file
- * @return
- */
- private String adjustDebuggerPath(String path) {
- String result = path;
- // Make it MinGW-specific
- if (Platform.getOS().startsWith("win")) { //$NON-NLS-1$
- if (!path.startsWith("/")) { //$NON-NLS-1$
- result = path.substring(path.lastIndexOf('\\') + 1);
- }
- }
- return result;
- }
-
- /**
- * Get the list of threads from the platform breakpoint attributes
- *
- * @param context
- * if the context is not null, only get threads that are children
- * of this context. otherwise get all threads.
- * @param breakpoint
- * @return
- */
- private Set<String> extractThreads(IBreakpointsTargetDMContext context, ICBreakpoint breakpoint) {
- Set<String> results = new HashSet<String>();
-
- // Find the ancestor
- List<IExecutionDMContext[]> threads = new ArrayList<IExecutionDMContext[]>(1);
-
- try {
- // Retrieve the targets
- IDsfBreakpointExtension filterExtension = getFilterExtension(breakpoint);
- IContainerDMContext[] targets = filterExtension.getTargetFilters();
-
- // If no target is present, breakpoint applies to all.
- if (targets.length == 0) {
- results.add("0"); //$NON-NLS-1$
- return results;
- }
-
- // Extract the thread IDs (if there is none, we are covered)
- for (IContainerDMContext ctxt : targets) {
- if (context == null ||
- DMContexts.isAncestorOf(ctxt, context)) {
- threads.add(filterExtension.getThreadFilters(ctxt));
- }
- }
- } catch (CoreException e1) {
- }
-
- if (supportsThreads(breakpoint)) {
- for (IExecutionDMContext[] targetThreads : threads) {
- if (targetThreads != null) {
- for (IExecutionDMContext thread : targetThreads) {
- if (thread instanceof IMIExecutionDMContext) {
- IMIExecutionDMContext dmc = (IMIExecutionDMContext) thread;
- results.add(((Integer) dmc.getThreadId()).toString());
- }
- }
- } else {
- results.add("0"); //$NON-NLS-1$
- break;
- }
- }
- } else {
- results.add("0"); //$NON-NLS-1$
- }
-
- return results;
- }
-
- /**
- * Indicates if the back-end supports multiple threads for
- * this type of breakpoint
- *
- * @param breakpoint
- */
- protected boolean supportsThreads(ICBreakpoint breakpoint) {
-
- return !(breakpoint instanceof ICWatchpoint);
- }
-
- /**
- * @param bp
- * @return
- * @throws CoreException
- */
- private IDsfBreakpointExtension getFilterExtension(ICBreakpoint bp) throws CoreException {
- return (IDsfBreakpointExtension) bp.getExtension(GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
- }
-
- public Map<String, Object> getAllBreakpointAttributes(IBreakpoint breakpoint, boolean bpManagerEnabled) throws CoreException {
-
- assert ! dsfSession.getExecutor().isInExecutorThread();
-
- // Check that the marker exists and retrieve its attributes.
- // Due to accepted race conditions, the breakpoint marker may become
- // null while this method is being invoked. In this case throw an exception
- // and let the caller handle it.
- IMarker marker = breakpoint.getMarker();
- if (marker == null || !marker.exists()) {
- throw new CoreException(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, DebugException.REQUEST_FAILED,
- "Breakpoint marker does not exist", null));
- }
-
- // Suppress cast warning: platform is still on Java 1.3
- @SuppressWarnings("unchecked")
- Map<String, Object> attributes = marker.getAttributes();
-
- Map<String, Object> targetAttrs = convertAttributes(attributes);
-
- // Determine breakpoint type.
- if (breakpoint instanceof ICWatchpoint)
- targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.WATCHPOINT);
- else if (breakpoint instanceof ICLineBreakpoint)
- targetAttrs.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
- else {
- // catchpoint?
- }
-
- // Adjust for "skip-all"
- if (!bpManagerEnabled) {
- targetAttrs.put(MIBreakpoints.IS_ENABLED, false);
- }
-
- Set<String> threads = extractThreads(null, (ICBreakpoint) breakpoint);
- targetAttrs.put(ATTR_THREAD_FILTER, threads);
-
- return targetAttrs;
- }
-
- public boolean canUpdateAttributes(IBreakpoint bp, IBreakpointsTargetDMContext context, Map<String, Object> attrDelta) {
- boolean yesWeCan;
-
- if (attrDelta.containsKey(MIBreakpoints.IS_ENABLED) && bp != null) {
- // GDB special:
- // see https://bugs.eclipse.org/bugs/show_bug.cgi?id=261082
- //
- Map<String, Object> delta = new HashMap<String, Object>(attrDelta);
-
- delta.remove(MIBreakpoints.IS_ENABLED);
-
- yesWeCan = canUpdateAttributes(null, delta);
-
- if (yesWeCan) {
- // other attribute change indicates we can. Now check the ENABLE.
- // if the breakpoint is already installed in the "context" (a process),
- // we can. Otherwise no.
- ITargetBreakpointInfo[] targetBPs = breakpointsMediator.getTargetBreakpoints(context, bp);
- yesWeCan = targetBPs != null && targetBPs.length > 0;
- }
- }
- else
- yesWeCan = canUpdateAttributes(null, attrDelta);
-
- return yesWeCan;
- }
-
- private void addBreakpointProblemMarker(final ICBreakpoint breakpoint, final String description, final int severity) {
-
- new Job("Add Breakpoint Problem Marker") { //$NON-NLS-1$
- {setSystem(true); };
-
- @Override
- protected IStatus run(IProgressMonitor monitor) {
-
- if (breakpoint instanceof ICLineBreakpoint) {
- // If we have already have a problem marker on this breakpoint
- // we should remove it first.
- IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
- if (marker != null) {
- try {
- marker.delete();
- } catch (CoreException e) {
- }
- }
-
- ICLineBreakpoint lineBreakpoint = (ICLineBreakpoint) breakpoint;
- try {
- // Locate the workspace resource via the breakpoint marker
- IMarker breakpoint_marker = lineBreakpoint.getMarker();
- IResource resource = breakpoint_marker.getResource();
-
- // Add a problem marker to the resource
- IMarker problem_marker = resource.createMarker(BreakpointProblems.BREAKPOINT_PROBLEM_MARKER_ID);
- int line_number = lineBreakpoint.getLineNumber();
- problem_marker.setAttribute(IMarker.LOCATION, String.valueOf(line_number));
- problem_marker.setAttribute(IMarker.MESSAGE, description);
- problem_marker.setAttribute(IMarker.SEVERITY, severity);
- problem_marker.setAttribute(IMarker.LINE_NUMBER, line_number);
-
- // And save the baby
- fBreakpointMarkerProblems.put(breakpoint, problem_marker);
- } catch (CoreException e) {
- }
- }
- return Status.OK_STATUS;
- }
- }.schedule();
- }
-
- private void removeBreakpointProblemMarker(final ICBreakpoint breakpoint) {
-
- new Job("Remove Breakpoint Problem Marker") { //$NON-NLS-1$
- {setSystem(true); };
- @Override
- protected IStatus run(IProgressMonitor monitor) {
-
- IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
- if (marker != null) {
- try {
- marker.delete();
- } catch (CoreException e) {
- }
- }
-
- return Status.OK_STATUS;
- }
- }.schedule();
- }
-
- /**
- */
- private void clearBreakpointProblemMarkers()
- {
- new Job("Clear Breakpoint problem markers") { //$NON-NLS-1$
- { setSystem(true); };
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- for (IMarker marker : fBreakpointMarkerProblems.values()) {
- if (marker != null) {
- try {
- marker.delete();
- } catch (CoreException e) {
- }
- }
- }
- fBreakpointMarkerProblems.clear();
- return Status.OK_STATUS;
- }
- }.schedule();
- }
-}
-
\ No newline at end of file
--- a/cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpoints.java Fri Dec 04 14:31:59 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpoints.java Fri Dec 04 14:32:55 2009 -0600
@@ -15,8 +15,6 @@
import java.util.Hashtable;
import java.util.Map;
-import org.eclipse.cdt.debug.core.CDebugCorePlugin;
-import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Immutable;
@@ -29,8 +27,6 @@
import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
-import org.eclipse.cdt.dsf.mi.service.MIRunControl.SuspendedEvent;
-import org.eclipse.cdt.dsf.mi.service.breakpoint.actions.BreakpointActionAdapter;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakAfter;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakCondition;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete;
@@ -39,9 +35,7 @@
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakList;
import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakWatch;
-import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointScopeEvent;
-import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
@@ -49,11 +43,8 @@
import org.eclipse.cdt.dsf.service.AbstractDsfService;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
-import org.eclipse.core.runtime.jobs.Job;
import org.osgi.framework.BundleContext;
/**
@@ -290,53 +281,6 @@
public void eventDispatched(ICommandControlShutdownDMEvent e) {
}
- @DsfServiceEventHandler
- public void eventDispatched(SuspendedEvent e) {
-
- if (e.getMIEvent() instanceof MIBreakpointHitEvent) {
- MIBreakpointHitEvent evt = (MIBreakpointHitEvent) e.getMIEvent();
- performBreakpointAction(evt.getDMContext(), evt.getNumber());
- return;
- }
-
- if (e.getMIEvent() instanceof MIWatchpointTriggerEvent) {
- MIWatchpointTriggerEvent evt = (MIWatchpointTriggerEvent) e.getMIEvent();
- performBreakpointAction(evt.getDMContext(), evt.getNumber());
- return;
- }
- }
-
- private void performBreakpointAction(final IDMContext context, int number) {
- // Identify the platform breakpoint
- final ICBreakpoint breakpoint = findPlatformBreakpoint(context, number);
-
- // Perform the actions asynchronously (otherwise we can have a deadlock...)
- new Job("Breakpoint action") { //$NON-NLS-1$
- { setSystem(true); }
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- CDebugCorePlugin.getDefault().getBreakpointActionManager().executeActions(breakpoint, new BreakpointActionAdapter(getExecutor(), getServicesTracker(), context));
- return Status.OK_STATUS;
- };
- }.schedule();
- }
-
- // Helper function to locate the platform breakpoint corresponding
- // to the target breakpoint/watchpoint that was just hit
-
- // FIXME: (Bug228703) Need a way to identify the correct context where the BP was hit
- private ICBreakpoint findPlatformBreakpoint(IDMContext context, int targetBreakpointID) {
- // Hmm, the service has no tracking of MIBreakpointDMContext. So this workaround.
- IBreakpointsTargetDMContext btDMC = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class);
- assert btDMC != null;
- IBreakpointDMContext dmc = new MIBreakpointDMContext(MIBreakpoints.this, new IDMContext[] { btDMC }, targetBreakpointID);
-
- MIBreakpointsManager bpMediator = getServicesTracker().getService(MIBreakpointsManager.class);
- ICBreakpoint cdtBP = (ICBreakpoint)bpMediator.getPlatformBreakpoint(btDMC, dmc);
-
- return cdtBP;
- }
-
///////////////////////////////////////////////////////////////////////////
// IBreakpoints interface
///////////////////////////////////////////////////////////////////////////
@@ -819,7 +763,7 @@
// Retrieve the breakpoint parameters
// At this point, we know their are OK so there is no need to re-validate
MIBreakpointDMContext breakpointCtx = (MIBreakpointDMContext) dmc;
- final IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
+ IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context);
final int reference = breakpointCtx.getReference();
MIBreakpointDMData breakpoint = contextBreakpoints.get(reference);
@@ -838,22 +782,11 @@
// Determine if the breakpoint condition changed
String conditionAttribute = CONDITION;
if (properties.containsKey(conditionAttribute)) {
- final String oldValue = breakpoint.getCondition();
+ String oldValue = breakpoint.getCondition();
String newValue = (String) properties.get(conditionAttribute);
if (newValue == null) newValue = NULL_STRING;
if (!oldValue.equals(newValue)) {
- changeCondition(context, reference, newValue, new RequestMonitor(getExecutor(), countingRm){
-
- @Override
- protected void handleError() {
- // Failed to change the condition, restore the old condition.
- // See comment in changeCondition() for more.
- MIBreakpointsManager bpMediator = getServicesTracker().getService(MIBreakpointsManager.class);
- final ICBreakpoint cdtBP = (ICBreakpoint)bpMediator.getPlatformBreakpoint(context, dmc);
- rollbackCondition(cdtBP, oldValue);
-
- countingRm.done();
- }});
+ changeCondition(context, reference, newValue, countingRm);
numberOfChanges++;
}
properties.remove(conditionAttribute);
@@ -892,26 +825,6 @@
countingRm.setDoneCount(numberOfChanges);
}
- private void rollbackCondition(final ICBreakpoint cdtBP, final String oldValue) {
- if (cdtBP == null)
- return;
-
- new Job("rollback breakpont condition") { //$NON-NLS-1$
- { setSystem(true); }
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- try {
- if (oldValue != null)
- cdtBP.setCondition(oldValue);
- else
- cdtBP.setCondition(NULL_STRING);
- } catch (CoreException e) {
- // ignore
- }
- return Status.OK_STATUS;
- }}.schedule();
- }
-
/**
* Update the breakpoint condition
*
--- a/cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java Fri Dec 04 14:31:59 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java Fri Dec 04 14:32:55 2009 -0600
@@ -15,8 +15,74 @@
package org.eclipse.cdt.dsf.mi.service;
-import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.debug.core.CDebugCorePlugin;
+import org.eclipse.cdt.debug.core.breakpointactions.BreakpointActionManager;
+import org.eclipse.cdt.debug.core.model.ICAddressBreakpoint;
+import org.eclipse.cdt.debug.core.model.ICBreakpoint;
+import org.eclipse.cdt.debug.core.model.ICBreakpointExtension;
+import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
+import org.eclipse.cdt.debug.core.model.ICWatchpoint;
+import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems;
+import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+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.datamodel.DMContexts;
+import org.eclipse.cdt.dsf.datamodel.IDMContext;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
+import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension;
+import org.eclipse.cdt.dsf.debug.service.IRunControl;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
+import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
+import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControl;
+import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
+import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointAddedEvent;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointRemovedEvent;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointUpdatedEvent;
+import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
+import org.eclipse.cdt.dsf.mi.service.MIRunControl.SuspendedEvent;
+import org.eclipse.cdt.dsf.mi.service.breakpoint.actions.BreakpointActionAdapter;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointScopeEvent;
+import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent;
+import org.eclipse.cdt.dsf.service.AbstractDsfService;
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.resources.IMarker;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.resources.IResource;
+import org.eclipse.core.resources.IWorkspaceRunnable;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.core.runtime.jobs.MultiRule;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointListener;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.IBreakpointManagerListener;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.osgi.framework.BundleContext;
/**
* Breakpoint service interface. The breakpoint service tracks CDT breakpoint
@@ -24,8 +90,107 @@
*
* It relies on MIBreakpoints for the actual back-end interface.
*/
-public class MIBreakpointsManager extends BreakpointsMediator
+public class MIBreakpointsManager extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointListener
{
+ // Note: Find a way to import this (careful of circular dependencies)
+ public final static String GDB_DEBUG_MODEL_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$
+
+ // Extra breakpoint attributes
+ private static final String ATTR_DEBUGGER_PATH = GdbPlugin.PLUGIN_ID + ".debuggerPath"; //$NON-NLS-1$
+ private static final String ATTR_THREAD_FILTER = GdbPlugin.PLUGIN_ID + ".threadFilter"; //$NON-NLS-1$
+ private static final String ATTR_THREAD_ID = GdbPlugin.PLUGIN_ID + ".threadID"; //$NON-NLS-1$
+
+ // Services
+ ICommandControl fConnection;
+ IRunControl fRunControl;
+ ISourceLookup fSourceLookup;
+ IBreakpoints fBreakpoints;
+ IBreakpointManager fBreakpointManager; // Platform breakpoint manager (not this!)
+ BreakpointActionManager fBreakpointActionManager;
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Breakpoints tracking
+ ///////////////////////////////////////////////////////////////////////////
+
+ private String fDebugModelId;
+
+ // Holds the set of platform breakpoints with their corresponding back-end
+ // breakpoint attributes, per context (i.e. each platform breakpoint is
+ // replicated for each execution context).
+ // - Context entry added/removed on start/stopTrackingBreakpoints()
+ // - Augmented on breakpointAdded()
+ // - Modified on breakpointChanged()
+ // - Diminished on breakpointRemoved()
+ private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Map<String, Object>>> fPlatformBPs =
+ new HashMap<IBreakpointsTargetDMContext, Map<ICBreakpoint, Map<String, Object>>>();
+
+ // Holds the set of target breakpoints, per execution context, and their
+ // mapping to the corresponding platform breakpoint. In a given execution
+ // context there can only be one platform breakpoint per target breakpoint.
+ // Acts as a mapping from target (low-level) BP to the corresponding platform
+ // (high-level) BP.
+ // Updated when:
+ // - We start/stop tracking an execution context
+ // - A platform breakpoint is added/removed
+ // - A thread filter is applied/removed
+ private Map<IBreakpointsTargetDMContext, Map<IBreakpointDMContext, ICBreakpoint>> fTargetBPs =
+ new HashMap<IBreakpointsTargetDMContext, Map<IBreakpointDMContext, ICBreakpoint>>();
+
+ // Holds the mapping from platform breakpoint to the corresponding target
+ // breakpoint(s), per context. There can be multiple back-end BPs for a
+ // single platform BP in the case of [1] multiple target contexts, and/or
+ // [2] thread filtering.
+ // Updated when:
+ // - We start/stop tracking an execution context
+ // - A platform breakpoint is added/removed
+ // - A thread filter is applied/removed
+ private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Vector<IBreakpointDMContext>>> fBreakpointIDs =
+ new HashMap<IBreakpointsTargetDMContext, Map<ICBreakpoint, Vector<IBreakpointDMContext>>>();
+
+ // Holds the mapping from platform breakpoint to the corresponding target
+ // breakpoint threads, per context.
+ // Updated when:
+ // - We start/stop tracking an execution context
+ // - A platform breakpoint is added/removed
+ // - A thread filter is applied/removed
+ private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Set<String>>> fBreakpointThreads =
+ new HashMap<IBreakpointsTargetDMContext, Map<ICBreakpoint, Set<String>>>();
+
+ // Due to the very asynchronous nature of DSF, a new breakpoint request can
+ // pop up at any time before an ongoing one is completed. The following set
+ // is used to store requests until the ongoing operation completes.
+ private Set<IBreakpoint> fPendingRequests = new HashSet<IBreakpoint>();
+ private Set<IBreakpoint> fPendingBreakpoints = new HashSet<IBreakpoint>();
+
+ private Map<ICBreakpoint, IMarker> fBreakpointMarkerProblems =
+ new HashMap<ICBreakpoint, IMarker>();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // String constants
+ ///////////////////////////////////////////////////////////////////////////
+
+ private static final String NULL_STRING = ""; //$NON-NLS-1$
+
+ static final String CONTEXT_ALREADY_INITIALIZED = "Context already initialized"; //$NON-NLS-1$
+ static final String INVALID_CONTEXT_TYPE = "Invalid context type"; //$NON-NLS-1$
+ static final String INVALID_CONTEXT = "Invalid context"; //$NON-NLS-1$
+
+ static final String UNABLE_TO_READ_BREAKPOINT = "Unable to read initial breakpoint attributes"; //$NON-NLS-1$
+ static final String BREAKPOINT_NOT_INSTALLED = "Breakpoints not installed for given context"; //$NON-NLS-1$
+ static final String BREAKPOINT_ALREADY_INSTALLED = "Breakpoint already installed"; //$NON-NLS-1$
+ static final String BREAKPOINT_ALREADY_REMOVED = "Breakpoint already removed"; //$NON-NLS-1$
+
+ static final String INVALID_BREAKPOINT = "Invalid breakpoint"; //$NON-NLS-1$
+ static final String UNKNOWN_BREAKPOINT = "Unknown breakpoint"; //$NON-NLS-1$
+ static final String INVALID_PARAMETER = "Invalid breakpoint parameter(s)"; //$NON-NLS-1$
+
+ static final String NO_DEBUGGER_PATH = "No debugger path for breakpoint"; //$NON-NLS-1$
+ static final String NO_MARKER_FOR_BREAKPOINT = "No marker associated with breakpoint"; //$NON-NLS-1$
+
+ ///////////////////////////////////////////////////////////////////////////
+ // AbstractDsfService
+ ///////////////////////////////////////////////////////////////////////////
+
/**
* The service constructor.
* Performs basic instantiation (method initialize() performs the real
@@ -35,6 +200,1515 @@
* @param debugModelId the debugging model
*/
public MIBreakpointsManager(DsfSession session, String debugModelId) {
- super(session, new MIBreakpointAttributeTranslator(session, debugModelId));
+ super(session);
+ fDebugModelId = debugModelId;
+ }
+
+ //-------------------------------------------------------------------------
+ // initialize
+ //-------------------------------------------------------------------------
+ // - Collect references for the services we interact with
+ // - Register to interesting events
+ // - Obtain the list of platform breakpoints
+ // - Register the service for interested parties
+ //-------------------------------------------------------------------------
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.service.AbstractDsfService#initialize(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ @Override
+ public void initialize(final RequestMonitor rm) {
+ super.initialize(
+ new RequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(rm);
+ }});
+ }
+
+ /**
+ * @param rm
+ */
+ private void doInitialize(RequestMonitor rm) {
+
+ // Get the required services references from central repository
+ fConnection = getServicesTracker().getService(ICommandControl.class);
+ fRunControl = getServicesTracker().getService(IRunControl.class);
+ fSourceLookup = getServicesTracker().getService(ISourceLookup.class);
+ fBreakpoints = getServicesTracker().getService(IBreakpoints.class);
+ fBreakpointManager = DebugPlugin.getDefault().getBreakpointManager();
+ fBreakpointActionManager = CDebugCorePlugin.getDefault().getBreakpointActionManager();
+
+ // Register to the useful events
+ getSession().addServiceEventListener(this, null);
+ fBreakpointManager.addBreakpointListener(this);
+ fBreakpointManager.addBreakpointManagerListener(this);
+
+ // And register this service
+ register(new String[] { MIBreakpointsManager.class.getName() },
+ new Hashtable<String, String>());
+ rm.done();
+ }
+
+ //-------------------------------------------------------------------------
+ // shutdown
+ //-------------------------------------------------------------------------
+ // - Un-register the service
+ // - Stop listening to events
+ // - Remove the breakpoints installed by this service
+ //
+ // Since we are shutting down, there is no overwhelming need
+ // to keep the maps coherent...
+ //-------------------------------------------------------------------------
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.service.AbstractDsfService#shutdown(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
+ */
+ @Override
+ public void shutdown(final RequestMonitor rm) {
+
+ // Stop accepting requests and events
+ unregister();
+ getSession().removeServiceEventListener(this);
+ fBreakpointManager.removeBreakpointListener(this);
+ fBreakpointManager.removeBreakpointManagerListener(this);
+
+ // Cleanup the breakpoints that are still installed by the service.
+ // Use a counting monitor which will call mom to complete the shutdown
+ // after the breakpoints are un-installed (successfully or not).
+ CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ MIBreakpointsManager.super.shutdown(rm);
+ }
+ };
+
+ List<IBreakpointsTargetDMContext> targetBPKeys = new ArrayList<IBreakpointsTargetDMContext>(fTargetBPs.size());
+ targetBPKeys.addAll(0, fTargetBPs.keySet());
+ for (IBreakpointsTargetDMContext dmc : targetBPKeys) {
+ stopTrackingBreakpoints(dmc, countingRm);
+ }
+ countingRm.setDoneCount(targetBPKeys.size());
+ }
+
+ //-------------------------------------------------------------------------
+ // getBundleContext
+ //-------------------------------------------------------------------------
+
+ /* (non-Javadoc)
+ * @see org.eclipse.cdt.dsf.service.AbstractDsfService#getBundleContext()
+ */
+ @Override
+ protected BundleContext getBundleContext() {
+ return GdbPlugin.getBundleContext();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IBreakpointsManager
+ ///////////////////////////////////////////////////////////////////////////
+
+ //-------------------------------------------------------------------------
+ // startTrackingBreakpoints
+ //-------------------------------------------------------------------------
+ // - Augment the maps with the new execution context
+ // - Install the platform breakpoints on the selected target
+ //-------------------------------------------------------------------------
+
+ /**
+ * Install and begin tracking breakpoints for given context. The service
+ * will keep installing new breakpoints that appear in the IDE for this
+ * context until {@link #uninstallBreakpoints(IDMContext)} is called for that
+ * context.
+ * @param dmc Context to start tracking breakpoints for.
+ * @param rm Completion callback.
+ */
+ public void startTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
+
+ // Validate the execution context
+ if (dmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_CONTEXT, null));
+ rm.done();
+ return;
+ }
+
+ // Make sure a mapping for this execution context does not already exist
+ Map<ICBreakpoint,Map<String, Object>> platformBPs = fPlatformBPs.get(dmc);
+ Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
+ Map<IBreakpointDMContext, ICBreakpoint> targetIDs = fTargetBPs.get(dmc);
+ Map<ICBreakpoint, Set<String>> threadIDs = fBreakpointThreads.get(dmc);
+ if ((platformBPs != null) || (breakpointIDs != null) || (targetIDs != null) || (threadIDs != null)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, CONTEXT_ALREADY_INITIALIZED, null));
+ rm.done();
+ return;
+ }
+
+ // Create entries in the breakpoint tables for the new context. These entries should only
+ // be removed when this service stops tracking breakpoints for the given context.
+ fPlatformBPs.put(dmc, new HashMap<ICBreakpoint, Map<String, Object>>());
+ fBreakpointIDs.put(dmc, new HashMap<ICBreakpoint, Vector<IBreakpointDMContext>>());
+ fTargetBPs.put(dmc, new HashMap<IBreakpointDMContext, ICBreakpoint>());
+ fBreakpointThreads.put(dmc, new HashMap<ICBreakpoint, Set<String>>());
+
+ // Install the platform breakpoints (stored in fPlatformBPs) on the target.
+ new Job("DSF BreakpointsManager: Install initial breakpoints on target") { //$NON-NLS-1$
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ // Submit the runnable to plant the breakpoints on dispatch thread.
+ getExecutor().submit(new Runnable() {
+ public void run() {
+ installInitialBreakpoints(dmc, rm);
+ }
+ });
+
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+
+ /**
+ * Installs the breakpoints that existed prior to the activation of this
+ * execution context.
+ *
+ * @param dmc
+ * @param initialPlatformBPs
+ * @param rm
+ */
+ private void installInitialBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm)
+ {
+ // Retrieve the set of platform breakpoints for this context
+ final Map<ICBreakpoint,Map<String, Object>> platformBPs = fPlatformBPs.get(dmc);
+ if (platformBPs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
+ rm.done();
+ return;
+ }
+
+ // Read current breakpoints from platform and copy their augmented
+ // attributes into the local reference map
+ try {
+ IBreakpoint[] breakpoints = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(fDebugModelId);
+ for (IBreakpoint breakpoint : breakpoints) {
+ if (supportsBreakpoint(breakpoint)) {
+ @SuppressWarnings("unchecked")
+ Map<String, Object> attributes = breakpoint.getMarker().getAttributes();
+ attributes.put(ATTR_DEBUGGER_PATH, NULL_STRING);
+ attributes.put(ATTR_THREAD_FILTER, extractThreads(dmc, (ICBreakpoint) breakpoint));
+ attributes.put(ATTR_THREAD_ID, NULL_STRING);
+ platformBPs.put((ICBreakpoint) breakpoint, attributes);
+ }
+ }
+ } catch (CoreException e) {
+ IStatus status = new Status(
+ IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNABLE_TO_READ_BREAKPOINT, e);
+ rm.setStatus(status);
+ rm.done();
+ }
+
+ // Install the individual breakpoints on the dispatcher thread
+ // Requires a counting monitor to know when we are done
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm);
+ countingRm.setDoneCount(platformBPs.size());
+
+ for (final ICBreakpoint breakpoint : platformBPs.keySet()) {
+ final Map<String, Object> attributes = platformBPs.get(breakpoint);
+ // Upon determining the debuggerPath, the breakpoint is installed
+ determineDebuggerPath(dmc, attributes, new RequestMonitor(getExecutor(), countingRm) {
+ @Override
+ protected void handleSuccess() {
+ // Install only if the breakpoint is enabled at startup (Bug261082)
+ boolean bpEnabled = attributes.get(ICBreakpoint.ENABLED).equals(true) && fBreakpointManager.isEnabled();
+ if (bpEnabled)
+ installBreakpoint(dmc, breakpoint, attributes, countingRm);
+ else
+ countingRm.done();
+ }
+ });
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // stopTrackingBreakpoints
+ //-------------------------------------------------------------------------
+ // - Remove the target breakpoints for the given execution context
+ // - Update the maps
+ //-------------------------------------------------------------------------
+
+ /**
+ * Uninstall and stop tracking breakpoints for the given context.
+ * @param dmc Context to start tracking breakpoints for.
+ * @param rm Completion callback.
+ */
+ public void stopTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
+
+ // Validate the context
+ if (dmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
+ rm.done();
+ return;
+ }
+
+ // Retrieve the set of platform breakpoints for this context
+ final Map<ICBreakpoint,Map<String, Object>> platformBPs = fPlatformBPs.get(dmc);
+ if (platformBPs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
+ rm.done();
+ return;
+ }
+
+ // Un-install the individual breakpoints on the dispatcher thread
+ // (requires a counting monitor to know when we are done).
+ // On completion (success or failure), update the maps.
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ fPlatformBPs.remove(dmc);
+ fBreakpointIDs.remove(dmc);
+ fTargetBPs.remove(dmc);
+ fBreakpointThreads.remove(dmc);
+ rm.done();
+ }
+ };
+ countingRm.setDoneCount(platformBPs.size());
+
+ for (final ICBreakpoint breakpoint : platformBPs.keySet()) {
+ uninstallBreakpoint(dmc, breakpoint,
+ new RequestMonitor(getExecutor(), countingRm) {
+ @Override
+ protected void handleCompleted() {
+ countingRm.done();
+ }
+ });
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Back-end interface functions
+ ///////////////////////////////////////////////////////////////////////////
+
+ //-------------------------------------------------------------------------
+ // installBreakpoint
+ //-------------------------------------------------------------------------
+
+ /**
+ * Install a platform breakpoint on the back-end. For a given context, a
+ * platform breakpoint can resolve into multiple back-end breakpoints when
+ * threads are taken into account.
+ *
+ * @param dmc
+ * @param breakpoint
+ * @param attributes
+ * @param rm
+ */
+ private void installBreakpoint(IBreakpointsTargetDMContext dmc, final ICBreakpoint breakpoint,
+ final Map<String, Object> attributes, final RequestMonitor rm)
+ {
+ // Retrieve the breakpoint maps
+ final Map<ICBreakpoint,Map<String,Object>> platformBPs = fPlatformBPs.get(dmc);
+ assert platformBPs != null;
+
+ final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
+ assert breakpointIDs != null;
+
+ final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fTargetBPs.get(dmc);
+ assert targetBPs != null;
+
+ final Map<ICBreakpoint, Set<String>> threadsIDs = fBreakpointThreads.get(dmc);
+ assert threadsIDs != null;
+
+ // Minimal validation
+ if (breakpointIDs.containsKey(breakpoint) || targetBPs.containsValue(breakpoint)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, BREAKPOINT_ALREADY_INSTALLED, null));
+ rm.done();
+ return;
+ }
+
+ // Ensure the breakpoint has a valid debugger source path
+ if (breakpoint instanceof ICLineBreakpoint && !(breakpoint instanceof ICAddressBreakpoint)) {
+ String debuggerPath = (String) attributes.get(ATTR_DEBUGGER_PATH);
+ if (debuggerPath == null || debuggerPath == NULL_STRING) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, NO_DEBUGGER_PATH, null));
+ rm.done();
+ return;
+ }
+ }
+
+ // A back-end breakpoint needs to be installed for each specified thread
+ // Note: This is a bit academic since [1] thread info is not kept by the
+ // BreakpointManager (so it can not possibly be restored when a target is
+ // started), and [2] the standard GUI doesn't allow to specify thread at
+ // breakpoint creation. However, it is conceivable that an enhanced Editor
+ // would permit it.
+ final Set<String> threads = getThreads(attributes);
+
+ // Update the breakpoint state when all back-end breakpoints have been installed
+ final CountingRequestMonitor installRM = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ // Store the platform breakpoint
+ platformBPs.put(breakpoint, attributes);
+ rm.done();
+ }
+ };
+ installRM.setDoneCount(threads.size());
+
+ // Install the back-end breakpoint(s)
+ for (final String thread : threads) {
+ DataRequestMonitor<IBreakpointDMContext> drm =
+ new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
+ @Override
+ protected void handleSuccess() {
+ // Add the new back-end breakpoint to the map
+ Vector<IBreakpointDMContext> list = breakpointIDs.get(breakpoint);
+ if (list == null)
+ list = new Vector<IBreakpointDMContext>();
+ IBreakpointDMContext targetBP = getData();
+ list.add(targetBP);
+ breakpointIDs.put(breakpoint, list);
+
+ // Add the reverse mapping
+ targetBPs.put(targetBP, breakpoint);
+
+ // And update the corresponding thread list
+ Set<String> thrds = threadsIDs.get(breakpoint);
+ if (thrds == null)
+ thrds = new HashSet<String>();
+ thrds.add(thread);
+ threadsIDs.put(breakpoint, thrds);
+
+ // Reset the thread (is it necessary?)
+ attributes.put(ATTR_THREAD_ID, NULL_STRING);
+
+ // Remove breakpoint problem marker (if any)
+ removeBreakpointProblemMarker(breakpoint);
+
+ // Finally, update the platform breakpoint
+ try {
+ breakpoint.incrementInstallCount();
+ } catch (CoreException e) {
+ }
+ installRM.done();
+ }
+
+ @Override
+ protected void handleError() {
+ addBreakpointProblemMarker(breakpoint, "Breakpoint attribute problem: installation failed", IMarker.SEVERITY_WARNING); //$NON-NLS-1$
+ installRM.done();
+ }
+ };
+
+ // Convert the breakpoint attributes for the back-end
+ attributes.put(ATTR_THREAD_ID, thread);
+ Map<String,Object> targetAttributes = convertToTargetBreakpoint(breakpoint, attributes);
+ fBreakpoints.insertBreakpoint(dmc, targetAttributes, drm);
+ }
+ }
+
+ private void addBreakpointProblemMarker(final ICBreakpoint breakpoint, final String description, final int severity) {
+
+ new Job("Add Breakpoint Problem Marker") { //$NON-NLS-1$
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+
+ if (breakpoint instanceof ICLineBreakpoint) {
+ // If we have already have a problem marker on this breakpoint
+ // we should remove it first.
+ IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
+ if (marker != null) {
+ try {
+ marker.delete();
+ } catch (CoreException e) {
+ }
+ }
+
+ ICLineBreakpoint lineBreakpoint = (ICLineBreakpoint) breakpoint;
+ try {
+ // Locate the workspace resource via the breakpoint marker
+ IMarker breakpoint_marker = lineBreakpoint.getMarker();
+ IResource resource = breakpoint_marker.getResource();
+
+ // Add a problem marker to the resource
+ IMarker problem_marker = resource.createMarker(BreakpointProblems.BREAKPOINT_PROBLEM_MARKER_ID);
+ int line_number = lineBreakpoint.getLineNumber();
+ problem_marker.setAttribute(IMarker.LOCATION, String.valueOf(line_number));
+ problem_marker.setAttribute(IMarker.MESSAGE, description);
+ problem_marker.setAttribute(IMarker.SEVERITY, severity);
+ problem_marker.setAttribute(IMarker.LINE_NUMBER, line_number);
+
+ // And save the baby
+ fBreakpointMarkerProblems.put(breakpoint, problem_marker);
+ } catch (CoreException e) {
+ }
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+
+ private void removeBreakpointProblemMarker(final ICBreakpoint breakpoint) {
+
+ new Job("Remove Breakpoint Problem Marker") { //$NON-NLS-1$
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+
+ IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
+ if (marker != null) {
+ try {
+ marker.delete();
+ } catch (CoreException e) {
+ }
+ }
+
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+
+ //-------------------------------------------------------------------------
+ // uninstallBreakpoint
+ //-------------------------------------------------------------------------
+
+ /**
+ * Un-install an individual breakpoint on the back-end. For one platform
+ * breakpoint in a given execution context, there could be multiple
+ * corresponding back-end breakpoints (one per thread).
+ *
+ * @param dmc
+ * @param breakpoint
+ * @param rm
+ */
+ private void uninstallBreakpoint(final IBreakpointsTargetDMContext dmc,
+ final ICBreakpoint breakpoint, final RequestMonitor rm)
+ {
+ // Retrieve the breakpoint maps
+ final Map<ICBreakpoint,Map<String,Object>> platformBPs = fPlatformBPs.get(dmc);
+ assert platformBPs != null;
+
+ final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
+ assert breakpointIDs != null;
+
+ final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fTargetBPs.get(dmc);
+ assert targetBPs != null;
+
+ final Map<ICBreakpoint, Set<String>> threadsIDs = fBreakpointThreads.get(dmc);
+ assert threadsIDs != null;
+
+ // Remove breakpoint problem marker (if any)
+ removeBreakpointProblemMarker(breakpoint);
+
+ // Minimal validation
+ if (!platformBPs.containsKey(breakpoint) || !breakpointIDs.containsKey(breakpoint) || !targetBPs.containsValue(breakpoint)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, BREAKPOINT_ALREADY_REMOVED, null));
+ rm.done();
+ return;
+ }
+
+ // Remove completion monitor
+ // Upon completion, update the mappings
+ CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ // Update the mappings
+ platformBPs.remove(breakpoint);
+ threadsIDs.remove(breakpoint);
+
+ Vector<IBreakpointDMContext> contexts = breakpointIDs.get(breakpoint);
+ if (contexts != null) {
+ for (IBreakpointDMContext context : contexts)
+ targetBPs.remove(context);
+ }
+
+ breakpointIDs.get(breakpoint).clear();
+ breakpointIDs.remove(breakpoint);
+
+ fPendingRequests.remove(breakpoint);
+
+ rm.done();
+ }
+ };
+
+ // Remove the back-end breakpoints
+ Vector<IBreakpointDMContext> list = breakpointIDs.get(breakpoint);
+ int count = 0;
+ if (list != null) {
+ for (IBreakpointDMContext bp : list) {
+ fBreakpoints.removeBreakpoint(bp, removeRM);
+ try {
+ breakpoint.decrementInstallCount();
+ } catch (CoreException e) {
+ }
+ }
+ count = list.size();
+ }
+ removeRM.setDoneCount(count);
+ }
+
+ //-------------------------------------------------------------------------
+ // modifyBreakpoint
+ //-------------------------------------------------------------------------
+
+ /**
+ * Modify a platform breakpoint which can translate to quite a few updates
+ * on the target...
+ *
+ * @param dmc
+ * @param breakpoint
+ * @param attributes
+ * @param oldValues
+ * @param rm
+ */
+ private void modifyBreakpoint(final IBreakpointsTargetDMContext dmc, final ICBreakpoint breakpoint,
+ final Map<String,Object> attributes, final IMarkerDelta oldValues, final RequestMonitor rm)
+ {
+ // Retrieve the breakpoint maps
+ final Map<ICBreakpoint,Map<String,Object>> platformBPs = fPlatformBPs.get(dmc);
+ assert platformBPs != null;
+
+ final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
+ assert breakpointIDs != null;
+
+ final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fTargetBPs.get(dmc);
+ assert targetBPs != null;
+
+ final Map<ICBreakpoint, Set<String>> threadsIDs = fBreakpointThreads.get(dmc);
+ assert threadsIDs != null;
+
+ // Minimal validation
+ if (!platformBPs.containsKey(breakpoint)) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, UNKNOWN_BREAKPOINT, null));
+ rm.done();
+ return;
+ }
+
+ // Check if the breakpoint is installed: it might not have been if it wasn't enabled at startup (Bug261082)
+ // Or the installation might have failed; in this case, we still try to install it again because
+ // some attribute might have changed which will make the install succeed.
+ if (!breakpointIDs.containsKey(breakpoint) && !targetBPs.containsValue(breakpoint)) {
+ // Install only if the breakpoint is enabled
+ boolean bpEnabled = attributes.get(ICBreakpoint.ENABLED).equals(true) && fBreakpointManager.isEnabled();
+ if (bpEnabled) {
+ attributes.put(ATTR_DEBUGGER_PATH, NULL_STRING);
+ attributes.put(ATTR_THREAD_FILTER, extractThreads(dmc, breakpoint));
+ attributes.put(ATTR_THREAD_ID, NULL_STRING);
+ determineDebuggerPath(dmc, attributes, new RequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ installBreakpoint(dmc, breakpoint, attributes, rm);
+ }
+ });
+ }
+ else {
+ rm.done();
+ }
+ return;
+ }
+
+ // Get the original breakpoint attributes
+ final Map<String,Object> original_attributes = platformBPs.get(breakpoint);
+ if (original_attributes == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, INVALID_BREAKPOINT, null));
+ rm.done();
+ return;
+ }
+
+ // Determine the attributes delta
+ final Map<String,Object> oldAttributes = new HashMap<String,Object>(original_attributes);
+ oldAttributes.put(ATTR_THREAD_FILTER, threadsIDs.get(breakpoint));
+
+ final Set<String> newThreads = extractThreads(dmc, breakpoint);
+ Map<String,Object> newAttributes = new HashMap<String,Object>(attributes);
+ newAttributes.put(ATTR_THREAD_FILTER, newThreads);
+
+ final Map<String,Object> attributesDelta = determineAttributesDelta(oldAttributes, newAttributes);
+
+ // Get the list of back-end breakpoints
+ final Vector<IBreakpointDMContext> oldTargetBPs = new Vector<IBreakpointDMContext>(breakpointIDs.get(breakpoint));
+ if (oldTargetBPs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, INVALID_BREAKPOINT, null));
+ rm.done();
+ return;
+ }
+
+ // We're all set for the breakpoint update.
+ //
+ // The path for a simple update is straightforward:
+ // - For each back-end BP corresponding to a platform BP
+ // - Send an update command to the back-end
+ // - If the operation succeeded, update the data structures
+ // - If the operation failed, try to roll-back
+ //
+ // In cases where the the back-end breakpoint cannot be
+ // simply updated (e.g. thread filter modification), the old
+ // breakpoint has to be removed and new one(s) inserted.
+ //
+ // The path for such an update is:
+ // - Install the updated breakpoint
+ // - In the operation succeeded
+ // - Remove the old breakpoint(s)
+ // - Perform any pending update
+
+ // Update completion monitor
+ final CountingRequestMonitor updateRM = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ // Success: simply store the new attributes
+ platformBPs.put(breakpoint, attributes);
+ rm.done();
+ }
+
+ @Override
+ protected void handleError() {
+ // Reset the breakpoint attributes. This will trigger a
+ // breakpoint change event and the correct delta will be
+ // computed, resulting in a correctly restored breakpoint
+ // at the back-end.
+ rollbackAttributes(breakpoint, oldValues);
+ platformBPs.put(breakpoint, attributes);
+
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_PARAMETER, null));
+ rm.done();
+ }
+ };
+
+ // Everything OK: remove the old back-end breakpoints
+ final Vector<IBreakpointDMContext> newTargetBPs = new Vector<IBreakpointDMContext>();
+ final CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ // All right! Save the new list and perform the final update
+ Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fBreakpointIDs.get(dmc);
+ if (breakpointIDs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_BREAKPOINT, null));
+ rm.done();
+ return;
+ }
+ breakpointIDs.put(breakpoint, newTargetBPs);
+ for (IBreakpointDMContext ref : newTargetBPs) {
+ fBreakpoints.updateBreakpoint(ref, attributesDelta, updateRM);
+ }
+ updateRM.setDoneCount(newTargetBPs.size());
+ }};
+
+ // New back-end breakpoints insertion monitor
+ // Holds the list of new back-end breakpoint contexts of the platform breakpoint
+ final DataRequestMonitor<Vector<IBreakpointDMContext>> insertRM =
+ new DataRequestMonitor<Vector<IBreakpointDMContext>>(getExecutor(), null) {
+
+ @Override
+ // In theory, we could have had a partial success and the original threads
+ // list would be invalid. We think it is highly unlikely so we assume that
+ // either everything went fine or else everything failed.
+ protected void handleSuccess() {
+ // Get the list of new back-end breakpoints contexts
+ newTargetBPs.addAll(getData());
+ threadsIDs.put(breakpoint, newThreads);
+ for (IBreakpointDMContext ref : oldTargetBPs) {
+ fBreakpoints.removeBreakpoint(ref, removeRM);
+ try {
+ breakpoint.decrementInstallCount(); // A tad early but it should work...
+ } catch (CoreException e) {
+ }
+ }
+ removeRM.setDoneCount(oldTargetBPs.size());
+ }
+
+ @Override
+ protected void handleError() {
+ // Keep the old threads list and reset the attributes
+ // (bad attributes are the likely cause of failure)
+ updateRM.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_PARAMETER, null));
+ updateRM.setDoneCount(0);
+ }
+ };
+
+ // If the changes in the breakpoint attributes justify it, install a
+ // new set of back-end breakpoint(s) and then update them
+ if (needsResinstallation(attributesDelta)) {
+ reinstallBreakpoint(dmc, breakpoint, attributes, newThreads, insertRM);
+ }
+ else {
+ // Update the back-end breakpoint(s) state
+ for (IBreakpointDMContext ref : oldTargetBPs) {
+ fBreakpoints.updateBreakpoint(ref, attributesDelta, updateRM);
+ }
+ updateRM.setDoneCount(oldTargetBPs.size());
+ }
}
+
+ /**
+ * Re-install the back-end breakpoints
+ *
+ * @param context the target context
+ * @param breakpoint the platform breakpoint
+ * @param attributes breakpoint augmented attributes
+ * @param threads list of threads where breakpoint is to be installed
+ * @param drm will contain the list of successfully installed back-end breakpoints
+ */
+ private void reinstallBreakpoint(final IBreakpointsTargetDMContext context, final ICBreakpoint breakpoint,
+ final Map<String,Object> attributes, Set<String> threads, final DataRequestMonitor<Vector<IBreakpointDMContext>> drm)
+ {
+ // Our new list of back-end breakpoints. Built as we go.
+ final Vector<IBreakpointDMContext> breakpointList = new Vector<IBreakpointDMContext>();
+
+ // Counting monitor for the new back-end breakpoints to install
+ // Once we're done, return the new list of back-end breakpoints contexts
+ final CountingRequestMonitor installRM = new CountingRequestMonitor(getExecutor(), drm) {
+ @Override
+ protected void handleSuccess() {
+ // Report whatever we have managed to install
+ // It is very likely installation either succeeded or failed for all
+ drm.setData(breakpointList);
+ drm.done();
+ }
+ };
+ installRM.setDoneCount(threads.size());
+
+ // And install the new back-end breakpoints
+ for (String thread : threads) {
+ // Convert the breakpoint attributes for the back-end
+ // Refresh the set of attributes at each iteration just in case...
+ Map<String,Object> attrs = convertToTargetBreakpoint(breakpoint, attributes);
+ if (!fBreakpointManager.isEnabled()) {
+ attrs.put(MIBreakpoints.IS_ENABLED, false);
+ }
+ // Add the secret ingredient..
+ attrs.put(MIBreakpointDMData.THREAD_ID, thread);
+
+ // Then install the spiked breakpoint
+ fBreakpoints.insertBreakpoint(context, attrs,
+ new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
+ @Override
+ protected void handleSuccess() {
+ // Add the new back-end breakpoint context to the list
+ breakpointList.add(getData());
+ try {
+ breakpoint.incrementInstallCount();
+ } catch (CoreException e) {
+ }
+ installRM.done();
+ }
+
+ @Override
+ protected void handleError() {
+ // Add the new back-end breakpoint context to the list
+ installRM.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_PARAMETER, null));
+ installRM.done();
+ }
+ });
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IBreakpointManagerListener implementation
+ ///////////////////////////////////////////////////////////////////////////
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IBreakpointManagerListener#breakpointManagerEnablementChanged(boolean)
+ */
+ public void breakpointManagerEnablementChanged(boolean enabled) {
+
+ // Only modify enabled breakpoints
+ for (IBreakpointsTargetDMContext context : fBreakpointIDs.keySet()) {
+ for (ICBreakpoint breakpoint : fBreakpointIDs.get(context).keySet()) {
+ try {
+ if (breakpoint.isEnabled()) {
+ for (IBreakpointDMContext ref : fBreakpointIDs.get(context).get(breakpoint)) {
+ Map<String,Object> delta = new HashMap<String,Object>();
+ delta.put(MIBreakpoints.IS_ENABLED, enabled);
+ fBreakpoints.updateBreakpoint(ref, delta, new RequestMonitor(getExecutor(), null));
+ }
+ }
+ } catch (CoreException e) {
+ }
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IBreakpointListener implementation
+ ///////////////////////////////////////////////////////////////////////////
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointAdded(org.eclipse.debug.core.model.IBreakpoint)
+ */
+ @ThreadSafe
+ public void breakpointAdded(final IBreakpoint breakpoint) {
+
+ if (supportsBreakpoint(breakpoint)) {
+ try {
+ // Retrieve the breakpoint attributes
+ @SuppressWarnings("unchecked")
+ final Map<String, Object> attrs = breakpoint.getMarker().getAttributes();
+
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
+ @Override
+ protected void handleError() {
+ if (getStatus().getSeverity() == IStatus.ERROR) {
+ GdbPlugin.getDefault().getLog().log(getStatus());
+ }
+ }
+ };
+ countingRm.setDoneCount(fPlatformBPs.size());
+
+ // Install the breakpoint in all the execution contexts
+ for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
+ determineDebuggerPath(dmc, attrs,
+ new RequestMonitor(getExecutor(), countingRm) {
+ @Override
+ protected void handleSuccess() {
+ installBreakpoint(dmc, (ICBreakpoint) breakpoint,
+ attrs, countingRm);
+ }
+ });
+ }
+ }
+ });
+ } catch (CoreException e) {
+ } catch (RejectedExecutionException e) {
+ }
+ }
+ }
+
+ /**
+ * @param bp
+ * @return
+ * @throws CoreException
+ */
+ private IDsfBreakpointExtension getFilterExtension(ICBreakpoint bp) throws CoreException {
+ return (IDsfBreakpointExtension) bp.getExtension(GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
+ */
+ public void breakpointChanged(final IBreakpoint breakpoint, final IMarkerDelta delta) {
+
+ if (supportsBreakpoint(breakpoint)) {
+
+ try {
+ // Retrieve the breakpoint attributes
+ @SuppressWarnings("unchecked")
+ final Map<String, Object> attrs = breakpoint.getMarker().getAttributes();
+ if (!fBreakpointManager.isEnabled()) {
+ attrs.put(ICBreakpoint.ENABLED, false);
+ }
+
+ // Modify the breakpoint in all the target contexts
+ getExecutor().execute( new DsfRunnable() {
+ public void run() {
+
+ // If the breakpoint is currently being updated, queue the request and exit
+ if (fPendingRequests.contains(breakpoint)) {
+ fPendingBreakpoints.add(breakpoint);
+ return;
+ }
+
+ // Keep track of the updates
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+
+ if (!isSuccess()) {
+ if (getStatus().getSeverity() == IStatus.ERROR) {
+ GdbPlugin.getDefault().getLog().log(getStatus());
+ }
+ }
+
+ // Indicate that the pending request has completed
+ fPendingRequests.remove(breakpoint);
+
+ // Process the next pending update for this breakpoint
+ if (fPendingBreakpoints.contains(breakpoint)) {
+ fPendingBreakpoints.remove(breakpoint);
+ breakpointChanged(breakpoint, delta);
+ }
+ }
+ };
+ countingRm.setDoneCount(fPlatformBPs.size());
+
+ // Mark the breakpoint as being updated and go
+ fPendingRequests.add(breakpoint);
+
+ // Modify the breakpoint in all the execution contexts
+ for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
+ determineDebuggerPath(dmc, attrs,
+ new RequestMonitor(getExecutor(), countingRm) {
+ @Override
+ protected void handleSuccess() {
+ modifyBreakpoint(dmc, (ICBreakpoint) breakpoint, attrs, delta, new RequestMonitor(getExecutor(), countingRm));
+ }
+ });
+ }
+ }
+ });
+ } catch (CoreException e) {
+ } catch (RejectedExecutionException e) {
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
+ */
+ public void breakpointRemoved(final IBreakpoint breakpoint, IMarkerDelta delta) {
+
+ if (supportsBreakpoint(breakpoint)) {
+ try {
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
+ @Override
+ protected void handleError() {
+ if (getStatus().getSeverity() == IStatus.ERROR) {
+ GdbPlugin.getDefault().getLog().log(getStatus());
+ }
+ }
+ };
+ countingRm.setDoneCount(fPlatformBPs.size());
+
+ // Remove the breakpoint in all the execution contexts
+ for (IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
+ if (fPlatformBPs.get(dmc).containsKey(breakpoint)) {
+ uninstallBreakpoint(dmc, (ICBreakpoint) breakpoint, countingRm);
+ }
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ }
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IServiceEventListener
+ ///////////////////////////////////////////////////////////////////////////
+
+ //-------------------------------------------------------------------------
+ // Breakpoints
+ //-------------------------------------------------------------------------
+
+ @DsfServiceEventHandler
+ public void eventDispatched(BreakpointAddedEvent e) {
+ // Nothing to do - already handled by breakpointAdded()
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(BreakpointUpdatedEvent e) {
+ // Nothing to do - already handled by breakpointChanged()
+ }
+
+ @DsfServiceEventHandler
+ public void eventDispatched(BreakpointRemovedEvent e) {
+ // Nothing to do - already handled by breakpointRemoved()
+ }
+
+ /*
+ * When a watchpoint goes out of scope, it is automatically removed from
+ * the back-end. To keep our internal state synchronized, we have to
+ * remove it from our breakpoints maps.
+ * Unfortunately, GDB doesn't generate the correct event...
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(MIWatchpointScopeEvent e) {
+ }
+
+ //-------------------------------------------------------------------------
+ // Breakpoint actions
+ //-------------------------------------------------------------------------
+
+ @DsfServiceEventHandler
+ public void eventDispatched(SuspendedEvent e) {
+
+ if (e.getMIEvent() instanceof MIBreakpointHitEvent) {
+ MIBreakpointHitEvent evt = (MIBreakpointHitEvent) e.getMIEvent();
+ performBreakpointAction(evt.getDMContext(), evt.getNumber());
+ return;
+ }
+
+ if (e.getMIEvent() instanceof MIWatchpointTriggerEvent) {
+ MIWatchpointTriggerEvent evt = (MIWatchpointTriggerEvent) e.getMIEvent();
+ performBreakpointAction(evt.getDMContext(), evt.getNumber());
+ return;
+ }
+ }
+
+ private void performBreakpointAction(final IDMContext context, int number) {
+ // Identify the platform breakpoint
+ final ICBreakpoint breakpoint = findPlatformBreakpoint(number);
+
+ // Perform the actions asynchronously (otherwise we can have a deadlock...)
+ new Job("Breakpoint action") { //$NON-NLS-1$
+ { setSystem(true); }
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ fBreakpointActionManager.executeActions(breakpoint, new BreakpointActionAdapter(getExecutor(), getServicesTracker(), context));
+ return Status.OK_STATUS;
+ };
+ }.schedule();
+ }
+
+ // Helper function to locate the platform breakpoint corresponding
+ // to the target breakpoint/watchpoint that was just hit
+
+ // FIXME: (Bug228703) Need a way to identify the correct context where the BP was hit
+ private ICBreakpoint findPlatformBreakpoint(int targetBreakpointID) {
+ Set<IBreakpointsTargetDMContext> targets = fTargetBPs.keySet();
+ for (IBreakpointsTargetDMContext target : targets) {
+ Map<IBreakpointDMContext, ICBreakpoint> bps = fTargetBPs.get(target);
+ Set<IBreakpointDMContext> contexts = bps.keySet();
+ for (IBreakpointDMContext context : contexts) {
+ if (context instanceof MIBreakpointDMContext) {
+ MIBreakpointDMContext ctx = (MIBreakpointDMContext) context;
+ if (ctx.getReference() == targetBreakpointID) {
+ return bps.get(context);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ //-------------------------------------------------------------------------
+ // Session exit
+ //-------------------------------------------------------------------------
+
+ /**
+ * @since 1.1
+ * @nooverride This method is not intended to be re-implemented or extended by clients.
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @DsfServiceEventHandler
+ public void eventDispatched(ICommandControlShutdownDMEvent e) {
+ terminated();
+ }
+
+ private void terminated() {
+ // Reset the breakpoint install count
+ for (IBreakpointsTargetDMContext ctx : fPlatformBPs.keySet()) {
+ Map<ICBreakpoint, Map<String, Object>> breakpoints = fPlatformBPs.get(ctx);
+ clearBreakpointStatus(breakpoints.keySet().toArray(new ICBreakpoint[breakpoints.size()]), ctx);
+ }
+ // This will prevent Shutdown() from trying to remove bps from a
+ // backend that has already shutdown
+ fPlatformBPs.clear();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Breakpoint status handling functions
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @param bps
+ */
+ private void clearBreakpointStatus(final ICBreakpoint[] bps, final IBreakpointsTargetDMContext ctx)
+ {
+ new Job("Clear Breakpoints Status") { //$NON-NLS-1$
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ IWorkspaceRunnable wr = new IWorkspaceRunnable() {
+ public void run(IProgressMonitor monitor) throws CoreException {
+ // For every platform breakpoint that has at least one target breakpoint installed
+ // we must decrement the install count, for every target breakpoint.
+ // Note that we cannot simply call resetInstallCount() because another
+ // launch may be using the same platform breakpoint.
+ Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpoints = fBreakpointIDs.get(ctx);
+ for (ICBreakpoint breakpoint : breakpoints.keySet()) {
+ Vector<IBreakpointDMContext> targetBps = breakpoints.get(breakpoint);
+ for (int i=0; i<targetBps.size(); i++) {
+ breakpoint.decrementInstallCount();
+ }
+ }
+ }
+ };
+
+ // First clear any problem markers
+ for (IMarker marker : fBreakpointMarkerProblems.values()) {
+ if (marker != null) {
+ try {
+ marker.delete();
+ } catch (CoreException e) {
+ }
+ }
+ }
+ fBreakpointMarkerProblems.clear();
+
+ // Create the scheduling rule to clear all bp planted.
+ ISchedulingRule rule = null;
+ List<ISchedulingRule> markerRules = new ArrayList<ISchedulingRule>();
+ for (ICBreakpoint bp : bps) {
+ IMarker marker = bp.getMarker();
+ if (marker != null) {
+ ISchedulingRule markerRule =
+ ResourcesPlugin.getWorkspace().getRuleFactory().markerRule(
+ marker.getResource());
+ if (markerRule == null) {
+ markerRules = null;
+ break;
+ } else {
+ markerRules.add(markerRule);
+ }
+ }
+ }
+ if (markerRules != null) {
+ rule = MultiRule.combine(markerRules.toArray(new ISchedulingRule[markerRules.size()]));
+ }
+
+ try {
+ ResourcesPlugin.getWorkspace().run(wr, rule, 0, null);
+ } catch (CoreException e) {
+ return e.getStatus();
+ }
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Support functions
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * supportsBreakpoint
+ *
+ * Indicates if it is breakpoint we can deal with. For now, it boils down
+ * to a CDI breakpoint...
+ *
+ * @param bp
+ * @return
+ */
+ private boolean supportsBreakpoint(IBreakpoint bp) {
+ if (bp instanceof ICBreakpoint && bp.getModelIdentifier().equals(fDebugModelId)) {
+ IMarker marker = bp.getMarker();
+ if (marker != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * determineDebuggerPath
+ *
+ * Adds the path to the source file to the set of attributes
+ * (for the debugger).
+ *
+ * @param dmc
+ * @param attributes
+ * @param rm
+ */
+ private void determineDebuggerPath(IBreakpointsTargetDMContext dmc,
+ final Map<String, Object> attributes, final RequestMonitor rm)
+ {
+ String hostPath = (String) attributes.get(ICBreakpoint.SOURCE_HANDLE);
+
+ if (hostPath != null) {
+
+ ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(dmc, ISourceLookupDMContext.class);
+ if (srcDmc != null) {
+ fSourceLookup.getDebuggerPath(srcDmc, hostPath,
+ new DataRequestMonitor<String>(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ attributes.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(getData()));
+ rm.done();
+ }
+ });
+ } else {
+ // Source lookup not available for given context, use the host
+ // path for the debugger path.
+ attributes.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(hostPath));
+ rm.done();
+ }
+ } else {
+ // Some types of breakpoints do not require a path
+ // (e.g. watchpoints)
+ rm.done();
+ }
+ }
+
+ /**
+ * See bug232415
+ *
+ * @param path the absolute path to the source file
+ * @return
+ */
+ private String adjustDebuggerPath(String path) {
+ String result = path;
+ // Make it MinGW-specific
+ if (Platform.getOS().startsWith("win")) { //$NON-NLS-1$
+ if (!path.startsWith("/")) { //$NON-NLS-1$
+ result = path.substring(path.lastIndexOf('\\') + 1);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Determine the set of modified attributes.
+ * Elementary set operations in full action :-)
+ *
+ * @param oldAttributes
+ * @param newAttributes
+ * @return
+ */
+ private Map<String, Object> determineAttributesDelta(Map<String, Object> oldAttributes, Map<String, Object> newAttributes) {
+
+ Map<String, Object> delta = new HashMap<String,Object>();
+
+ Set<String> oldKeySet = oldAttributes.keySet();
+ Set<String> newKeySet = newAttributes.keySet();
+
+ Set<String> commonKeys = new HashSet<String>(newKeySet); commonKeys.retainAll(oldKeySet);
+ Set<String> addedKeys = new HashSet<String>(newKeySet); addedKeys.removeAll(oldKeySet);
+ Set<String> removedKeys = new HashSet<String>(oldKeySet); removedKeys.removeAll(newKeySet);
+
+ // Add the modified attributes
+ for (String key : commonKeys) {
+ if (!(oldAttributes.get(key).equals(newAttributes.get(key))))
+ delta.put(key, newAttributes.get(key));
+ }
+
+ // Add the new attributes
+ for (String key : addedKeys) {
+ delta.put(key, newAttributes.get(key));
+ }
+
+ // Remove the deleted attributes
+ for (String key : removedKeys) {
+ delta.put(key, null);
+ }
+
+ return convertedAttributes(delta);
+ }
+
+ /**
+ * Converts ICBreakpoint attributes to IBreakpoints attributes.
+ *
+ * @param cdt_attributes
+ * @return
+ */
+ private Map<String, Object> convertedAttributes(Map<String, Object> cdt_attributes) {
+
+ Map<String,Object> result = new HashMap<String,Object>();
+
+ // IBreakpoint attributes
+ if (cdt_attributes.containsKey(ATTR_DEBUGGER_PATH))
+ result.put(MIBreakpoints.FILE_NAME, cdt_attributes.get(ATTR_DEBUGGER_PATH));
+
+ if (cdt_attributes.containsKey(IMarker.LINE_NUMBER))
+ result.put(MIBreakpoints.LINE_NUMBER, cdt_attributes.get(IMarker.LINE_NUMBER));
+
+ // ICLineBreakpoint attributes
+ if (cdt_attributes.containsKey(ICLineBreakpoint.FUNCTION))
+ result.put(MIBreakpoints.FUNCTION, cdt_attributes.get(ICLineBreakpoint.FUNCTION));
+
+ if (cdt_attributes.containsKey(ICLineBreakpoint.ADDRESS))
+ result.put(MIBreakpoints.ADDRESS, cdt_attributes.get(ICLineBreakpoint.ADDRESS));
+
+ // ICBreakpoint attributes
+ if (cdt_attributes.containsKey(ICBreakpoint.CONDITION))
+ result.put(MIBreakpoints.CONDITION, cdt_attributes.get(ICBreakpoint.CONDITION));
+
+ if (cdt_attributes.containsKey(ICBreakpoint.IGNORE_COUNT))
+ result.put(MIBreakpoints.IGNORE_COUNT, cdt_attributes.get(ICBreakpoint.IGNORE_COUNT));
+
+ if (cdt_attributes.containsKey(ICBreakpoint.ENABLED))
+ result.put(MIBreakpoints.IS_ENABLED, cdt_attributes.get(ICBreakpoint.ENABLED));
+
+ // ICWatchpoint attributes
+ if (cdt_attributes.containsKey(ICWatchpoint.EXPRESSION))
+ result.put(MIBreakpoints.EXPRESSION, cdt_attributes.get(ICWatchpoint.EXPRESSION));
+
+ if (cdt_attributes.containsKey(ICWatchpoint.READ))
+ result.put(MIBreakpoints.READ, cdt_attributes.get(ICWatchpoint.READ));
+
+ if (cdt_attributes.containsKey(ICWatchpoint.WRITE))
+ result.put(MIBreakpoints.WRITE, cdt_attributes.get(ICWatchpoint.WRITE));
+
+ // Threads
+ if (cdt_attributes.containsKey(ATTR_THREAD_FILTER))
+ result.put(ATTR_THREAD_FILTER, cdt_attributes.get(ATTR_THREAD_FILTER));
+
+ return result;
+ }
+
+ /**
+ * Figure out the corresponding number of back-end breakpoints
+ * Even though the thread IDs are usually integers, they are
+ * stored as strings in CBreakpoints.
+ *
+ * @param attributes
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ private Set<String> getThreads(Map<String, Object> attributes) {
+ Set<String> threads = (Set<String>) attributes.get(ATTR_THREAD_FILTER);
+ if (threads == null) {
+ threads = new HashSet<String>();
+ threads.add("0"); // Thread 0 means all threads //$NON-NLS-1$
+ }
+ return threads;
+ }
+
+ /**
+ * Get the list of threads from the platform breakpoint attributes
+ *
+ * @param breakpoint
+ * @return
+ */
+ private Set<String> extractThreads(IBreakpointsTargetDMContext context, ICBreakpoint breakpoint) {
+ Set<String> results = new HashSet<String>();
+
+ // Find the ancestor
+ List<IExecutionDMContext[]> threads = new ArrayList<IExecutionDMContext[]>(1);
+
+ try {
+ // Retrieve the targets
+ IDsfBreakpointExtension filterExtension = getFilterExtension(breakpoint);
+ IContainerDMContext[] targets = filterExtension.getTargetFilters();
+
+ // If no target is present, breakpoint applies to all.
+ if (targets.length == 0) {
+ results.add("0"); //$NON-NLS-1$
+ return results;
+ }
+
+ // Extract the thread IDs (if there is none, we are covered)
+ for (IContainerDMContext ctxt : targets) {
+ if (DMContexts.isAncestorOf(ctxt, context)) {
+ threads.add(filterExtension.getThreadFilters(ctxt));
+ }
+ }
+ } catch (CoreException e1) {
+ }
+
+ if (supportsThreads(breakpoint)) {
+ for (IExecutionDMContext[] targetThreads : threads) {
+ if (targetThreads != null) {
+ for (IExecutionDMContext thread : targetThreads) {
+ if (thread instanceof IMIExecutionDMContext) {
+ IMIExecutionDMContext dmc = (IMIExecutionDMContext) thread;
+ results.add(((Integer) dmc.getThreadId()).toString());
+ }
+ }
+ } else {
+ results.add("0"); //$NON-NLS-1$
+ break;
+ }
+ }
+ } else {
+ results.add("0"); //$NON-NLS-1$
+ }
+
+ return results;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Non-generic (MI-specific) functions
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Create a target breakpoint from an ICBreakpoint
+ *
+ * @param breakpoint
+ * @param attributes
+ * @return
+ */
+ protected Map<String,Object> convertToTargetBreakpoint(ICBreakpoint breakpoint, Map<String,Object> attributes) {
+
+ Map<String, Object> properties = new HashMap<String, Object>();
+
+ if (breakpoint instanceof ICWatchpoint) {
+ // Convert the CDI watchpoint to an IBreakpoint
+ properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.WATCHPOINT);
+ properties.put(MIBreakpoints.EXPRESSION, attributes.get(ICWatchpoint.EXPRESSION));
+ properties.put(MIBreakpoints.READ, attributes.get(ICWatchpoint.READ));
+ properties.put(MIBreakpoints.WRITE, attributes.get(ICWatchpoint.WRITE));
+ }
+ else if (breakpoint instanceof ICLineBreakpoint) {
+ // Convert the CDI breakpoint to an IBreakpoint
+ properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
+ properties.put(MIBreakpoints.FILE_NAME, attributes.get(ATTR_DEBUGGER_PATH));
+ properties.put(MIBreakpoints.LINE_NUMBER, attributes.get(IMarker.LINE_NUMBER));
+ properties.put(MIBreakpoints.FUNCTION, attributes.get(ICLineBreakpoint.FUNCTION));
+ properties.put(MIBreakpoints.ADDRESS, attributes.get(ICLineBreakpoint.ADDRESS));
+ } else {
+ // catchpoint?
+ }
+
+ // Common fields
+ properties.put(MIBreakpoints.CONDITION, attributes.get(ICBreakpoint.CONDITION));
+ properties.put(MIBreakpoints.IGNORE_COUNT, attributes.get(ICBreakpoint.IGNORE_COUNT));
+ properties.put(MIBreakpoints.IS_ENABLED, attributes.get(ICBreakpoint.ENABLED));
+ properties.put(MIBreakpointDMData.THREAD_ID, attributes.get(ATTR_THREAD_ID));
+
+ // Adjust for "skip-all"
+ if (!fBreakpointManager.isEnabled()) {
+ properties.put(MIBreakpoints.IS_ENABLED, false);
+ }
+
+ return properties;
+ }
+
+ /**
+ * Determine if the modified attributes necessitate
+ * a breakpoint removal/re-installation
+ *
+ * @param delta
+ * @return
+ */
+ protected boolean needsResinstallation(Map<String,Object> delta) {
+
+ // Check if there is any modified attribute
+ if (delta == null)
+ return false;
+
+ // Check the "critical" attributes
+ if (delta.containsKey(ATTR_DEBUGGER_PATH) // File name
+ || delta.containsKey(MIBreakpoints.LINE_NUMBER) // Line number
+ || delta.containsKey(MIBreakpoints.FUNCTION) // Function name
+ || delta.containsKey(MIBreakpoints.ADDRESS) // Absolute address
+ || delta.containsKey(ATTR_THREAD_FILTER) // Thread ID
+ || delta.containsKey(MIBreakpoints.EXPRESSION) // Watchpoint expression
+ || delta.containsKey(MIBreakpoints.READ) // Watchpoint type
+ || delta.containsKey(MIBreakpoints.WRITE)) { // Watchpoint type
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * @param breakpoint
+ * @param oldValues
+ */
+ protected void rollbackAttributes(ICBreakpoint breakpoint, IMarkerDelta oldValues) {
+
+ try {
+ String new_condition = breakpoint.getCondition();
+ if (new_condition == null)
+ new_condition = NULL_STRING;
+ String old_condition = (oldValues != null) ? oldValues.getAttribute(ICBreakpoint.CONDITION, NULL_STRING) : NULL_STRING;
+ if (!old_condition.equals(new_condition)) {
+ breakpoint.setCondition(old_condition);
+ }
+ else {
+ breakpoint.setCondition(NULL_STRING);
+ }
+ } catch (CoreException e) {
+ }
+ }
+
+ /**
+ * Indicates if the back-end supports multiple threads for
+ * this type of breakpoint
+ *
+ * @param breakpoint
+ */
+ protected boolean supportsThreads(ICBreakpoint breakpoint) {
+
+ return !(breakpoint instanceof ICWatchpoint);
+ }
+
}
--- a/cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java Fri Dec 04 14:31:59 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java Fri Dec 04 14:32:55 2009 -0600
@@ -7,14 +7,12 @@
*
* Contributors:
* Wind River - Initial API and implementation
- * Ericsson - Low-level breakpoints integration
- * Nokia - refactored to work for both GDB and EDC. Nov. 2009.
+ * Ericsson - Low-level breakpoints integration
*******************************************************************************/
package org.eclipse.cdt.dsf.debug.service;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
@@ -27,9 +25,9 @@
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
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.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
@@ -43,177 +41,76 @@
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointListener;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.IBreakpointManagerListener;
-import org.eclipse.debug.core.IBreakpointsListener;
import org.eclipse.debug.core.model.IBreakpoint;
import org.osgi.framework.BundleContext;
/**
- * see these bugs for design of this service.<br>
- * - https://bugs.eclipse.org/bugs/show_bug.cgi?id=218557
- * - https://bugs.eclipse.org/bugs/show_bug.cgi?id=292468
+ *
*/
-public class BreakpointsMediator extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointsListener
+public class BreakpointsMediator extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointListener
{
- public enum BreakpointEventType {ADDED, REMOVED, MODIFIED};
-
+
/**
* The attribute translator that this service will use to map the platform
- * breakpoint attributes to the corresponding target attributes, and vice
+ * breakpiont attributes to the corresponding target attributes, and vice
* versa.
*/
private IBreakpointAttributeTranslator fAttributeTranslator;
-
- /**
- * If the attribute translator implements the {@link IBreakpointAttributeTranslatorExtension},
- * this field will be valid, otherwise it is null.
- */
- private IBreakpointAttributeTranslatorExtension fAttributeTranslator2;
/**
* DSF Debug service for creating breakpoints.
*/
- IBreakpoints fBreakpointsService;
+ IBreakpoints fBreakpoints;
/**
* Platform breakpoint manager
*/
IBreakpointManager fBreakpointManager;
-
- /**
- * Object describing the information about a single target breakpoint
- * corresponding to specific platform breakpoint and breakpoint target
- * context.
- *
- * @since 2.1
- */
- public interface ITargetBreakpointInfo {
-
- /**
- * Returns the breakpoint attributes as returned by the attribute translator.
- */
- public Map<String, Object> getAttributes();
-
- /**
- * Returns the target breakpoint context. May be <code>null</code> if the
- * breakpoint failed to install on target.
- */
- public IBreakpointDMContext getTargetBreakpoint();
-
- /**
- * Returns the status result of the last breakpoint operation (install/remove).
- */
- public IStatus getStatus();
- }
+
- private static class TargetBP implements ITargetBreakpointInfo {
-
- private Map<String, Object> fAttributes;
- private IBreakpointDMContext fTargetBPContext;
- private IStatus fStatus;
-
- public TargetBP(Map<String, Object> attrs) {
- fAttributes = attrs;
- }
-
- public Map<String, Object> getAttributes() {
- return fAttributes;
- }
-
- public IBreakpointDMContext getTargetBreakpoint() {
- return fTargetBPContext;
- }
-
- public IStatus getStatus() {
- return fStatus;
- }
-
- public void setTargetBreakpoint(IBreakpointDMContext fTargetBPContext) {
- this.fTargetBPContext = fTargetBPContext;
- }
-
- public void setStatus(IStatus status) {
- this.fStatus = status;
- }
- }
-
- private class PlatformBreakpointInfo {
- IBreakpoint breakpoint;
- boolean enabled;
- // All attributes available from UI, including standard and extended ones.
- Map<String, Object> attributes;
-
- public PlatformBreakpointInfo(IBreakpoint bp, boolean enabled, Map<String, Object> attributes) {
- super();
- breakpoint = bp;
- this.enabled = enabled;
- this.attributes = attributes;
- }
- }
-
- ///////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////
// Breakpoints tracking
///////////////////////////////////////////////////////////////////////////
/**
- * Holds the set of platform breakpoints with their breakpoint information
- * structures, per context (i.e. each platform breakpoint is
+ * Holds the set of platform breakpoints with their corresponding back-end
+ * breakpoint attributes, per context (i.e. each platform breakpoint is
* replicated for each execution context).
* - Context entry added/removed on start/stopTrackingBreakpoints()
* - Augmented on breakpointAdded()
* - Modified on breakpointChanged()
* - Diminished on breakpointRemoved()
*/
- private Map<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>> fPlatformBPs =
- new HashMap<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>>();
+ private Map<IBreakpointsTargetDMContext, Map<IBreakpoint, List<Map<String, Object>>>> fPlatformBPs =
+ new HashMap<IBreakpointsTargetDMContext, Map<IBreakpoint, List<Map<String, Object>>>>();
- /**
- * Holds platform breakpoints with all their attributes (standard ones and
- * extended ones) from UI. This will be used to check what attributes have
- * changed for a breakpoint when the breakpoint is changed. The map is <br>
- * 1. augmented in doBreakpointsAdded(); <br>
- * 2. updated in breakpointsChanged(); <br>
- * 3. diminished in breakpointsRemoved();
- */
- private Map<IBreakpoint, Map<String, Object>> fBreakpointAttributes =
- new HashMap<IBreakpoint, Map<String, Object>>();
-
- private static class PendingEventInfo {
- PendingEventInfo(BreakpointEventType eventType, PlatformBreakpointInfo bpInfo,
- Collection<IBreakpointsTargetDMContext> bpsTargetDmc, RequestMonitor rm) {
- fEventType = eventType;
- fBPInfo = bpInfo;
- fBPTargetContexts = bpsTargetDmc;
- fRequestMonitor = rm;
- fAttributeDelta = null;
- }
-
- public PendingEventInfo(BreakpointEventType eventType, Collection<IBreakpointsTargetDMContext> updateContexts,
- Map<String, Object> attrDelta) {
- fEventType = eventType;
- fBPTargetContexts = updateContexts;
- fAttributeDelta = attrDelta;
- fRequestMonitor = null;
- fBPInfo = null;
- }
+ /**
+ * Holds the mapping from platform breakpoint to the corresponding target
+ * breakpoint(s), per context. There can be multiple back-end BPs for a
+ * single platform BP in the case of [1] multiple target contexts, and/or
+ * [2] thread filtering.
+ * Updated when:
+ * - We start/stop tracking an execution context
+ * - A platform breakpoint is added/removed
+ * - A thread filter is applied/removed
+ */
+ private Map<IBreakpointsTargetDMContext, Map<IBreakpoint, List<IBreakpointDMContext>>> fBreakpointDMContexts =
+ new HashMap<IBreakpointsTargetDMContext, Map<IBreakpoint, List<IBreakpointDMContext>>>();
- PlatformBreakpointInfo fBPInfo;
- RequestMonitor fRequestMonitor;
- BreakpointEventType fEventType;
- Collection<IBreakpointsTargetDMContext> fBPTargetContexts;
- Map<String, Object> fAttributeDelta; // for change event only
- }
-
/**
* Due to the very asynchronous nature of DSF, a new breakpoint request can
* pop up at any time before an ongoing one is completed. The following set
* is used to store requests until the ongoing operation completes.
*/
- private Set<IBreakpoint> fRunningEvents = new HashSet<IBreakpoint>();
-
- private Map<IBreakpoint, LinkedList<PendingEventInfo>> fPendingEvents =
- new HashMap<IBreakpoint, LinkedList<PendingEventInfo>>();
+ private Set<IBreakpoint> fPendingRequests = new HashSet<IBreakpoint>();
+
+ /**
+ * @see fPendingRequests
+ */
+ private Set<IBreakpoint> fPendingBreakpoints = new HashSet<IBreakpoint>();
///////////////////////////////////////////////////////////////////////////
// AbstractDsfService
@@ -228,10 +125,6 @@
public BreakpointsMediator(DsfSession session, IBreakpointAttributeTranslator attributeTranslator) {
super(session);
fAttributeTranslator = attributeTranslator;
-
- fAttributeTranslator2 = null;
- if (attributeTranslator instanceof IBreakpointAttributeTranslatorExtension)
- fAttributeTranslator2 = (IBreakpointAttributeTranslatorExtension)attributeTranslator;
}
@Override
@@ -256,7 +149,7 @@
private void doInitialize(RequestMonitor rm) {
// Get the services references
- fBreakpointsService = getServicesTracker().getService(IBreakpoints.class);
+ fBreakpoints = getServicesTracker().getService(IBreakpoints.class);
fBreakpointManager = DebugPlugin.getDefault().getBreakpointManager();
fAttributeTranslator.initialize(this);
@@ -324,12 +217,20 @@
* @param dmc Context to start tracking breakpoints for.
* @param rm Completion callback.
*/
- public void startTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
+ public void startTrackingBreakpoints(IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
// - Augment the maps with the new execution context
// - Install the platform breakpoints on the selected target
+
+ // Validate the context
+ final IBreakpointsTargetDMContext breakpointsDmc = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
+ if (breakpointsDmc == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INTERNAL_ERROR, "Invalid context type", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
// Make sure a mapping for this execution context does not already exist
- Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
+ Map<IBreakpoint, List<Map<String, Object>>> platformBPs = fPlatformBPs.get(dmc);
if (platformBPs != null) {
rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INTERNAL_ERROR, "Context already initialized", null)); //$NON-NLS-1$
rm.done();
@@ -338,7 +239,8 @@
// Create entries in the breakpoint tables for the new context. These entries should only
// be removed when this service stops tracking breakpoints for the given context.
- fPlatformBPs.put(dmc, new HashMap<IBreakpoint, List<TargetBP>>());
+ fPlatformBPs.put(breakpointsDmc, new HashMap<IBreakpoint, List<Map<String, Object>>>());
+ fBreakpointDMContexts.put(breakpointsDmc, new HashMap<IBreakpoint, List<IBreakpointDMContext>>());
// Install the platform breakpoints (stored in fPlatformBPs) on the target.
// We need to use a background thread for this operation because we are
@@ -346,142 +248,165 @@
// Accessing the resources system potentially requires using global locks.
// Also we will be calling IBreakpointAttributeTranslator which is prohibited
// from being called on the session executor thread.
- new Job("Install initial breakpoint list.") { //$NON-NLS-1$
- { setSystem(true); }
-
- // Get the stored breakpoints from the platform BreakpointManager
- // and install them on the target
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- doBreakpointsAdded(DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(), dmc, rm);
- return Status.OK_STATUS;
- }
- }.schedule();
- }
-
- public void stopTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
- // - Remove the target breakpoints for the given execution context
- // - Update the maps
-
- // Remove the breakpoints for given DMC from the internal maps.
- Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
- if (platformBPs == null || platformBPs.size() == 0) {
- rm.setStatus(new Status(IStatus.INFO /* NOT error */, DsfPlugin.PLUGIN_ID, INTERNAL_ERROR, "Breakpoints not installed for given context", null)); //$NON-NLS-1$
- rm.done();
- return;
- }
-
- // Just remove the IBreakpoints installed for the "dmc".
- final IBreakpoint[] bps = platformBPs.keySet().toArray(new IBreakpoint[platformBPs.size()]);
-
- new Job("Uninstall target breakpoints list.") { //$NON-NLS-1$
+ new Job("MI Debugger: Install initial breakpoint list.") { //$NON-NLS-1$
{ setSystem(true); }
// Get the stored breakpoints from the platform BreakpointManager
// and install them on the target
@Override
protected IStatus run(IProgressMonitor monitor) {
- doBreakpointsRemoved(bps, dmc, rm);
+ // Read initial breakpoints from platform. Copy the breakpoint attributes into a local map.
+ // Note that we cannot write data into fPlatformBPs table here directly because we are not
+ // executing on the dispatch thread.
+ final Map<IBreakpoint, List<Map<String, Object>>> initialPlatformBPs =
+ new HashMap<IBreakpoint, List<Map<String, Object>>>();
+ try {
+ // Get the stored breakpoint list from the platform BreakpointManager
+ IBreakpoint[] bps = DebugPlugin.getDefault().getBreakpointManager().getBreakpoints();
+ // Single out the installable breakpoints...
+ for (IBreakpoint bp : bps) {
+ if (fAttributeTranslator.supportsBreakpoint(bp)) {
+ // Retrieve the breakpoint attributes
+ List<Map<String, Object>> attrsArray =
+ fAttributeTranslator.getBreakpointAttributes(bp, fBreakpointManager.isEnabled());
+ // Store it for now (will be installed on the dispatcher thread)
+ initialPlatformBPs.put(bp, attrsArray);
+ }
+ }
+ } catch (CoreException e) {
+ IStatus status = new Status(
+ IStatus.ERROR, DsfPlugin.PLUGIN_ID, REQUEST_FAILED, "Unable to read initial breakpoint attributes", e); //$NON-NLS-1$
+ rm.setStatus(status);
+ rm.done();
+ return status;
+ }
+
+ // Submit the runnable to plant the breakpoints on dispatch thread.
+ getExecutor().submit(new Runnable() {
+ public void run() {
+ installInitialBreakpoints(breakpointsDmc, initialPlatformBPs, rm);
+ }
+ });
+
return Status.OK_STATUS;
}
}.schedule();
}
-
- /**
- * Find target breakpoints installed in the given context that are resolved
- * from the given platform breakpoint.
- *
- * @param dmc - context
- * @param platformBp - platform breakpoint
- * @return array of target breakpoints.
- */
- public ITargetBreakpointInfo[] getTargetBreakpoints(IBreakpointsTargetDMContext dmc, IBreakpoint platformBp) {
- assert getExecutor().isInExecutorThread();
-
- Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
- if (platformBPs != null)
- {
- List<TargetBP> bpInfo = platformBPs.get(platformBp);
- if (bpInfo != null) {
- return bpInfo.toArray(new ITargetBreakpointInfo[bpInfo.size()]);
- }
- }
- return null;
- }
-
/**
- * Find the platform breakpoint that's mapped to the given target breakpoint.
- *
- * @param dmc - context of the target breakpoint, can be null.
- * @param bp - target breakpoint
- * @return platform breakpoint. null if not found.
+ * Installs the breakpoints that existed prior to the activation of this
+ * breakpoints context.
*/
- public IBreakpoint getPlatformBreakpoint(IBreakpointsTargetDMContext dmc, IBreakpointDMContext bp) {
- assert getExecutor().isInExecutorThread();
+ private void installInitialBreakpoints(final IBreakpointsTargetDMContext dmc,
+ Map<IBreakpoint, List<Map<String, Object>>> initialPlatformBPs,
+ RequestMonitor rm)
+ {
+ // Retrieve the set of platform breakpoints for this context
+ Map<IBreakpoint, List<Map<String, Object>>> platformBPs = fPlatformBPs.get(dmc);
+ if (platformBPs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ // Install the individual breakpoints on the executor thread
+ // Requires a counting monitor to know when we're done
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm);
+ countingRm.setDoneCount(initialPlatformBPs.size());
+
+ for (final IBreakpoint bp : initialPlatformBPs.keySet()) {
+ final List<Map<String, Object>> attrs = initialPlatformBPs.get(bp);
+ // Upon determining the debuggerPath, the breakpoint is installed
+ installBreakpoint(dmc, bp, attrs, new RequestMonitor(getExecutor(), countingRm));
+ }
+ }
+
+
+ public void stopTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
+ // - Remove the target breakpoints for the given execution context
+ // - Update the maps
- for (IBreakpointsTargetDMContext bpContext : fPlatformBPs.keySet()) {
- if (dmc != null && !dmc.equals(bpContext))
- continue;
-
- Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(bpContext);
-
- if (platformBPs != null && platformBPs.size() > 0)
- {
- for(Map.Entry<IBreakpoint, List<TargetBP>> e: platformBPs.entrySet())
- {
- // Stop at the first occurrence
- for (TargetBP tbp : e.getValue())
- if(tbp.getTargetBreakpoint().equals(bp))
- return e.getKey();
- }
- }
- }
+ // Remove the breakpoints for given DMC from the internal maps.
+ Map<IBreakpoint, List<Map<String, Object>>> platformBPs = fPlatformBPs.get(dmc);
+ if (platformBPs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INTERNAL_ERROR, "Breakpoints not installed for given context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ // Uninstall the individual breakpoints on the executor thread
+ // Requires a counting monitor to know when we're done
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm);
+ countingRm.setDoneCount(platformBPs.size());
- return null;
+ for (final IBreakpoint bp : platformBPs.keySet()) {
+ uninstallBreakpoint(dmc, bp,
+ new RequestMonitor(getExecutor(), countingRm) {
+ @Override
+ protected void handleCompleted() {
+ // After the breakpoint is removed from target. Call the attribute
+ // translator to refresh breakpoint status based on the new target
+ // breakpoint status.
+ new Job("Breakpoint status update") { //$NON-NLS-1$
+ { setSystem(true); }
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ fAttributeTranslator.updateBreakpointStatus(bp);
+ return Status.OK_STATUS;
+ };
+ }.schedule();
+
+ countingRm.done();
+ }
+ });
+ }
}
-
+
///////////////////////////////////////////////////////////////////////////
// Back-end interface functions
///////////////////////////////////////////////////////////////////////////
/**
* Install a new platform breakpoint on the back-end. A platform breakpoint
- * can resolve into multiple back-end breakpoints, e.g. when threads are taken
+ * can resolve into multiple back-end breakpoints when threads are taken
* into account.
*
* @param dmc
* @param breakpoint
- * @param attrsList - list of attribute map, each mapping to a potential target BP.
+ * @param attrsList
* @param rm
*/
private void installBreakpoint(IBreakpointsTargetDMContext dmc, final IBreakpoint breakpoint,
- final List<Map<String, Object>> attrsList, final DataRequestMonitor<List<TargetBP>> rm)
+ final List<Map<String, Object>> attrsList, final RequestMonitor rm)
{
// Retrieve the set of breakpoints for this context
- final Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
+ final Map<IBreakpoint, List<Map<String, Object>>> platformBPs = fPlatformBPs.get(dmc);
assert platformBPs != null;
+ final Map<IBreakpoint, List<IBreakpointDMContext>> breakpointIDs = fBreakpointDMContexts.get(dmc);
+ assert breakpointIDs != null; // fBreakpointIds should be updated in parallel with fPlatformBPs
+
// Ensure the breakpoint is not already installed
- assert !platformBPs.containsKey(breakpoint);
-
- final ArrayList<TargetBP> targetBPsAttempted = new ArrayList<TargetBP>(attrsList.size());
- for (int i = 0; i < attrsList.size(); i++) {
- targetBPsAttempted.add(new TargetBP(attrsList.get(i)));
+ if (platformBPs.containsKey(breakpoint)) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_STATE, "Breakpoint already installed", null)); //$NON-NLS-1$
+ rm.done();
+ return;
}
-
- final ArrayList<TargetBP> targetBPsInstalled = new ArrayList<TargetBP>(attrsList.size());
// Update the breakpoint status when all back-end breakpoints have been installed
final CountingRequestMonitor installRM = new CountingRequestMonitor(getExecutor(), rm) {
@Override
protected void handleCompleted() {
- // Store successful targetBPs with the platform breakpoint
- if (targetBPsInstalled.size() > 0)
- platformBPs.put(breakpoint, targetBPsInstalled);
-
- // Store all targetBPs, success or failure, in the rm.
- rm.setData(targetBPsAttempted);
+ // Store the platform breakpoint
+ platformBPs.put(breakpoint, attrsList);
+ new Job("Breakpoint status update") { //$NON-NLS-1$
+ { setSystem(true); }
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ fAttributeTranslator.updateBreakpointStatus(breakpoint);
+ return Status.OK_STATUS;
+ };
+ }.schedule();
rm.done();
}
};
@@ -490,22 +415,25 @@
installRM.setDoneCount(attrsList.size());
// Install the back-end breakpoint(s)
- for (int _i = 0; _i < attrsList.size(); _i++) {
- final int i = _i;
- fBreakpointsService.insertBreakpoint(
- dmc, attrsList.get(i),
+ for (Map<String, Object> attrs : attrsList) {
+ fBreakpoints.insertBreakpoint(
+ dmc, attrs,
new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
@Override
protected void handleCompleted() {
- TargetBP targetBP = targetBPsAttempted.get(i);
+ List<IBreakpointDMContext> list = breakpointIDs.get(breakpoint);
+ if (list == null) {
+ list = new LinkedList<IBreakpointDMContext>();
+ breakpointIDs.put(breakpoint, list);
+ }
+
if (isSuccess()) {
// Add the breakpoint back-end mapping
- targetBP.setTargetBreakpoint(getData());
-
- targetBPsInstalled.add(targetBP);
- }
- targetBP.setStatus(getStatus());
-
+ list.add(getData());
+ } else {
+ // TODO (bug 219841): need to add breakpoint error status tracking
+ // in addition to fBreakpointDMContexts.
+ }
installRM.done();
}
});
@@ -518,612 +446,441 @@
*
* @param dmc
* @param breakpoint
- * @param drm
+ * @param rm
*/
private void uninstallBreakpoint(final IBreakpointsTargetDMContext dmc, final IBreakpoint breakpoint,
- final DataRequestMonitor<List<TargetBP>> drm)
+ final RequestMonitor rm)
{
+ // Remove completion monitor
+ CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ // Remove the attributes mapping
+ Map<IBreakpoint, List<Map<String, Object>>> platformBPs = fPlatformBPs.get(dmc);
+ if (platformBPs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+ platformBPs.remove(breakpoint);
+
+ // Remove the back-end mapping
+ Map<IBreakpoint, List<IBreakpointDMContext>> breakpointIDs = fBreakpointDMContexts.get(dmc);
+ if (breakpointIDs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid breakpoint", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+ breakpointIDs.get(breakpoint).clear();
+ breakpointIDs.remove(breakpoint);
+
+ // Update breakpoint status
+ new Job("Breakpoint status update") { //$NON-NLS-1$
+ { setSystem(true); }
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ fAttributeTranslator.updateBreakpointStatus(breakpoint);
+ return Status.OK_STATUS;
+ };
+ }.schedule();
+
+ rm.done();
+ }
+ };
+
// Remove the back-end breakpoints
- final Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
- if (platformBPs == null) {
- drm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid breakpoint", null)); //$NON-NLS-1$
- drm.done();
+ Map<IBreakpoint, List<IBreakpointDMContext>> breakpointIDs = fBreakpointDMContexts.get(dmc);
+ if (breakpointIDs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid breakpoint", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ List<IBreakpointDMContext> list = breakpointIDs.get(breakpoint);
+ int count = 0;
+ if (list != null) {
+ for (IBreakpointDMContext bp : list) {
+ fBreakpoints.removeBreakpoint(bp, removeRM);
+ }
+ count = list.size();
+ }
+ removeRM.setDoneCount(count);
+ }
+
+ /**
+ * Modify an individual breakpoint
+ *
+ * @param context
+ * @param breakpoint
+ * @param attributes
+ * @param rm
+ * @throws CoreException
+ */
+ private void modifyBreakpoint(final IBreakpointsTargetDMContext context, final IBreakpoint breakpoint,
+ final List<Map<String, Object>> newAttrsList0, final IMarkerDelta oldValues, final RequestMonitor rm)
+ {
+ // This method uses several lists to track the changed breakpoints:
+ // commonAttrsList - attributes which have not changed
+ // oldAttrsList - attributes for the breakpoint before the change
+ // newAttrsList - attributes for the breakpoint after the change
+ // oldBpContexts - target-side breakpoints from before the change
+ // newBpContexts - target-side breakpoints after the change
+ // attrDeltasList - changes in the attributes for each attribute map in
+ // oldAttrsList and newAttrsList
+
+ // Get the maps
+ final Map<IBreakpoint, List<Map<String, Object>>> platformBPs = fPlatformBPs.get(context);
+ final Map<IBreakpoint, List<IBreakpointDMContext>> breakpointIDs = fBreakpointDMContexts.get(context);
+ if (platformBPs == null || breakpointIDs == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ // Get the original breakpoint attributes
+ final List<Map<String, Object>> oldAttrsList0 = platformBPs.get(breakpoint);
+ if (oldAttrsList0 == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid breakpoint", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ // Get the list of corresponding back-end breakpoints
+ final List<IBreakpointDMContext> oldBpContexts = new ArrayList<IBreakpointDMContext>(breakpointIDs.get(breakpoint));
+ if (oldBpContexts == null) {
+ rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid breakpoint", null)); //$NON-NLS-1$
+ rm.done();
return;
}
- final List<TargetBP> bpList = platformBPs.get(breakpoint);
- assert bpList != null;
-
- // Only try to remove those targetBPs that are successfully installed.
-
- // Remove completion monitor
- final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), drm) {
- @Override
- protected void handleCompleted() {
- platformBPs.remove(breakpoint);
-
- // Complete the request monitor.
- drm.setData(bpList);
- drm.done();
- }
- };
+ // Calculate the list of attributes maps that have not changed.
+ // Immediately add these to the list of new breakpoint contexts,
+ // and remove them from further breakpoint attribute comparisons.
+ final List<Map<String, Object>> commonAttrsList = getCommonAttributeMaps(newAttrsList0, oldAttrsList0);
+ final List<IBreakpointDMContext> newBpContexts = new ArrayList<IBreakpointDMContext>(commonAttrsList.size());
- int count = 0;
- for (int i = 0; i < bpList.size(); i++) {
- final TargetBP bp = bpList.get(i);
- if (bp.getTargetBreakpoint() != null) {
- fBreakpointsService.removeBreakpoint(
- bp.getTargetBreakpoint(),
- new RequestMonitor(getExecutor(), countingRm) {
- @Override
- protected void handleCompleted() {
- bp.setStatus(getStatus());
- if (isSuccess()) {
- bp.setTargetBreakpoint(null);
- }
- countingRm.done();
- }
- });
- count++;
- } else {
- bp.setStatus(Status.OK_STATUS);
- }
+ final List<Map<String, Object>> newAttrsList = new ArrayList<Map<String, Object>>(newAttrsList0);
+ newAttrsList.removeAll(commonAttrsList);
+
+ List<Map<String, Object>> oldAttrsList = new ArrayList<Map<String, Object>>(oldAttrsList0);
+ for (int i = 0; i < oldAttrsList.size(); i++) {
+ if (commonAttrsList.contains(oldAttrsList.get(i))) {
+ if (oldBpContexts.size() > i) {
+ newBpContexts.add(oldBpContexts.remove(i));
+ }
+ }
}
- countingRm.setDoneCount(count);
- }
+ oldAttrsList.removeAll(commonAttrsList);
+
+ // Create a list of attribute changes. The lenghth of this list will
+ // always be max(oldAttrList.size(), newAttrsList.size()), padded with
+ // null's if oldAttrsList was longer.
+ final List<Map<String, Object>> attrDeltasList = getAttributesDeltas(oldAttrsList, newAttrsList);
+
+ // Create the request monitor that will be called when all
+ // modifying/inserting/removing is complete.
+ final CountingRequestMonitor countingRM = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ // Save the new list of breakpoint contexts and attributes
+ breakpointIDs.put(breakpoint, newBpContexts);
+ newAttrsList.addAll(commonAttrsList);
+ platformBPs.put(breakpoint, newAttrsList);
+
+ // Update breakpoint status. updateBreakpointStatus() cannot
+ // be called on the executor thread, so we need to
+ // use a Job.
+ new Job("Breakpoint status update") { //$NON-NLS-1$
+ { setSystem(true); }
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ fAttributeTranslator.updateBreakpointStatus(breakpoint);
+ return Status.OK_STATUS;
+ };
+ }.schedule();
+
+ super.handleCompleted();
+ }
+ };
+
+ // Set the count, if could be zero if no breakpoints have actually changed.
+ countingRM.setDoneCount(attrDeltasList.size());
+
+ // Process the changed breakpoints.
+ for (int i = 0; i < attrDeltasList.size(); i++) {
+ if (attrDeltasList.get(i) == null) {
+ // The list of new attribute maps was shorter than the old.
+ // Remove the corresponding target-side bp.
+ fBreakpoints.removeBreakpoint(oldBpContexts.get(i), countingRM);
+ } else if ( i >= oldBpContexts.size()) {
+ // The list of new attribute maps was longer, just insert
+ // the new breakpoint
+ final Map<String, Object> attrs = newAttrsList.get(i);
+ fBreakpoints.insertBreakpoint(
+ context, attrs,
+ new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), countingRM) {
+ @Override
+ protected void handleSuccess() {
+ newBpContexts.add(getData());
+ countingRM.done();
+ }
+ });
+ } else if ( !fAttributeTranslator.canUpdateAttributes(oldBpContexts.get(i), attrDeltasList.get(i)) ) {
+ // The attribute translator tells us that the debugger cannot modify the
+ // breakpoint to change the given attributes. Remove the breakpoint
+ // and insert a new one.
+ final Map<String, Object> attrs = newAttrsList.get(i);
+ fBreakpoints.removeBreakpoint(
+ oldBpContexts.get(i),
+ new RequestMonitor(getExecutor(), countingRM) {
+ @Override
+ protected void handleCompleted() {
+ fBreakpoints.insertBreakpoint(
+ context, attrs,
+ new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), countingRM) {
+ @Override
+ protected void handleCompleted() {
+ if (isSuccess()) {
+ newBpContexts.add(getData());
+ } else {
+ // TODO (bug 219841): need to add breakpoint error status tracking
+ // in addition to fBreakpointDMContexts.
+ }
+ countingRM.done();
+ }
+ });
+ }
+ });
+ } else {
+ // The back end can modify the breakpoint. Update the breakpoint with the
+ // new attributes.
+ final IBreakpointDMContext bpCtx = oldBpContexts.get(i);
+ fBreakpoints.updateBreakpoint(
+ oldBpContexts.get(i), newAttrsList.get(i),
+ new RequestMonitor(getExecutor(), countingRM) {
+ @Override
+ protected void handleSuccess() {
+ newBpContexts.add(bpCtx);
+ countingRM.done();
+ }
+ });
+ }
+ }
+ }
+ private List<Map<String, Object>> getCommonAttributeMaps(List<Map<String, Object>> array1, List<Map<String, Object>> array2)
+ {
+ List<Map<String, Object>> intersection = new LinkedList<Map<String, Object>>();
+ List<Map<String, Object>> list2 = new ArrayList<Map<String, Object>>(array2);
+ for (Map<String, Object> array1Map : array1) {
+ if (list2.remove(array1Map)) {
+ intersection.add(array1Map);
+ }
+ }
+ return intersection;
+ }
+
+ /**
+ * Determine the set of modified attributes
+ *
+ * @param oldAttributes
+ * @param newAttributes
+ * @return
+ */
+ private List<Map<String, Object>> getAttributesDeltas(List<Map<String, Object>> oldAttributesList, List<Map<String, Object>> newAttributesList) {
+ List<Map<String, Object>> deltas = new ArrayList<Map<String, Object>>(oldAttributesList.size());
+
+ // Go through the bp attributes common to the old and the new lists and calculate
+ // their deltas.
+ for (int i = 0; i < oldAttributesList.size() && i < newAttributesList.size(); i++) {
+ Map<String, Object> oldAttributes = oldAttributesList.get(i);
+ Map<String, Object> newAttributes = newAttributesList.get(i);
+
+ Map<String, Object> delta = new HashMap<String, Object>();
+
+ Set<String> oldKeySet = oldAttributes.keySet();
+ Set<String> newKeySet = newAttributes.keySet();
+
+ Set<String> commonKeys = new HashSet<String>(newKeySet); commonKeys.retainAll(oldKeySet);
+ Set<String> addedKeys = new HashSet<String>(newKeySet); addedKeys.removeAll(oldKeySet);
+ Set<String> removedKeys = new HashSet<String>(oldKeySet); removedKeys.removeAll(newKeySet);
+
+ // Add the modified attributes
+ for (String key : commonKeys) {
+ if (!(oldAttributes.get(key).equals(newAttributes.get(key))))
+ delta.put(key, newAttributes.get(key));
+ }
+
+ // Add the new attributes
+ for (String key : addedKeys) {
+ delta.put(key, newAttributes.get(key));
+ }
+
+ // Remove the deleted attributes
+ for (String key : removedKeys) {
+ delta.put(key, null);
+ }
+ deltas.add(delta);
+ }
+
+ // Add all the new attributes as deltas
+ for (int i = deltas.size(); i < newAttributesList.size(); i++) {
+ deltas.add(newAttributesList.get(i));
+ }
+
+ // For any old attribute Maps that were removed, insert a null value in the deltas list.
+ for (int i = deltas.size(); i < oldAttributesList.size(); i++) {
+ deltas.add(null);
+ }
+
+ return deltas;
+ }
+
///////////////////////////////////////////////////////////////////////////
// IBreakpointManagerListener implementation
///////////////////////////////////////////////////////////////////////////
public void breakpointManagerEnablementChanged(boolean enabled) {
- // do nothing. breakpointsChanged() will be called to handle the change.
+ for (IBreakpoint breakpoint : fBreakpointManager.getBreakpoints()) {
+ breakpointChanged(breakpoint, null);
+ }
}
@ThreadSafe
- public void breakpointsAdded(final IBreakpoint[] bps) {
- doBreakpointsAdded(bps, null, null);
- }
-
- protected void doBreakpointsAdded(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
- // Collect attributes (which will access system resource)
- // in non DSF dispatch thread.
- //
- final PlatformBreakpointInfo[] bpsInfo = collectBreakpointsInfo(bps);
-
- // Nothing to do
- if (bpsInfo.length == 0) {
- if (rm != null) {
- rm.done();
- }
- return;
- }
-
- try {
- getExecutor().execute(new DsfRunnable() {
- public void run() {
- Collection<IBreakpointsTargetDMContext> dmcs = new ArrayList<IBreakpointsTargetDMContext>();
- if (bpsTargetDmc == null)
- dmcs.addAll(fPlatformBPs.keySet());
- else
- dmcs.add(bpsTargetDmc);
+ public void breakpointAdded(final IBreakpoint breakpoint) {
+ if (fAttributeTranslator.supportsBreakpoint(breakpoint)) {
+ try {
+ // Retrieve the breakpoint attributes
+ final List<Map<String, Object>> attrsArray =
+ fAttributeTranslator.getBreakpointAttributes(breakpoint, fBreakpointManager.isEnabled());
- doBreakpointsAddedInExecutor(bpsInfo, dmcs, rm);
- }
- });
- } catch (RejectedExecutionException e) {
- IStatus status = new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", e);//$NON-NLS-1$ //$NON-NLS-2$
- if (rm != null) {
- rm.setStatus(status);
- rm.done();
- } else {
- DsfPlugin.getDefault().getLog().log(status);
- }
- }
- }
-
- /**
- * Collect breakpoint info. This method must not be called in DSF dispatch thread.
- * @param bps
- * @return
- */
- private PlatformBreakpointInfo[] collectBreakpointsInfo(IBreakpoint[] bps) {
- List<PlatformBreakpointInfo> bpsInfo = new ArrayList<PlatformBreakpointInfo>(bps.length);
-
- for (IBreakpoint bp : bps) {
- if (bp.getMarker() == null)
- continue;
-
- if (fAttributeTranslator.supportsBreakpoint(bp)) {
- try {
- Map<String, Object> attrs = fAttributeTranslator2.getAllBreakpointAttributes(bp, fBreakpointManager.isEnabled());
- boolean enabled = bp.isEnabled() && fBreakpointManager.isEnabled();
- bpsInfo.add(new PlatformBreakpointInfo(bp, enabled, attrs));
- } catch (CoreException e) {
- DsfPlugin.getDefault().getLog().log(e.getStatus());
- }
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ //TODO pp: need to track pending requests
+
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
+ @Override
+ protected void handleError() {
+ if (getStatus().getSeverity() == IStatus.ERROR) {
+ DsfPlugin.getDefault().getLog().log(getStatus());
+ }
+ }
+ };
+ countingRm.setDoneCount(fPlatformBPs.size());
+
+ // Install the breakpoint in all the execution contexts
+ for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
+ installBreakpoint(dmc, breakpoint, attrsArray, new RequestMonitor(getExecutor(), countingRm));
+ }
+ }
+ });
+ } catch (CoreException e) {
+ DsfPlugin.getDefault().getLog().log(e.getStatus());
+ } catch (RejectedExecutionException e) {
}
}
-
- return bpsInfo.toArray(new PlatformBreakpointInfo[bpsInfo.size()]);
- }
- protected void doBreakpointsAddedInExecutor(PlatformBreakpointInfo[] bpsInfo, Collection<IBreakpointsTargetDMContext> bpTargetDMCs, final RequestMonitor rm) {
- final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =
- new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpsInfo.length, 1);
-
- CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
- @Override
- protected void handleCompleted() {
- processPendingRequests();
- fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.ADDED);
- if (rm != null)
- // don't call this if "rm" is null as this will
- // log errors if any and pack Eclipse error
- // log view with errors useless to user.
- super.handleCompleted();
- }
- };
- int processPendingCountingRmCount = 0;
-
- for (final PlatformBreakpointInfo bpinfo : bpsInfo) {
- final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs =
- new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
- eventBPs.put(bpinfo.breakpoint, targetBPs);
-
- // Remember the new attributes of the bp in our global buffer,
- // even if we cannot or fail to install the bp.
- fBreakpointAttributes.put(bpinfo.breakpoint, bpinfo.attributes);
-
- if (fRunningEvents.contains(bpinfo.breakpoint)) {
- PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.ADDED, bpinfo, bpTargetDMCs, processPendingCountingRm);
- processPendingCountingRmCount++;
- updatePendingRequest(bpinfo.breakpoint, pendingEvent);
- continue;
- }
-
- processPendingCountingRmCount++;
-
- // Mark the breakpoint as being updated and go
- fRunningEvents.add(bpinfo.breakpoint);
-
- final CountingRequestMonitor bpTargetsCountingRm = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
- @Override
- protected void handleCompleted() {
- // Indicate that the running event has completed
- fRunningEvents.remove(bpinfo.breakpoint);
- super.handleCompleted();
- }
- };
-
- int bpTargetsCountingRmCount = 0;
-
- // Install the breakpoint in all the execution contexts
- for (final IBreakpointsTargetDMContext dmc : bpTargetDMCs) {
-
- // Now ask lower level to set the bp.
- //
- // if the breakpoint is disabled, ask back-end if it can set (and manage)
- // disabled breakpoint. If not, just bail out.
- //
- if (! bpinfo.enabled) {
- Map<String, Object> attr = new HashMap<String, Object>(1);
- attr.put(IBreakpoint.ENABLED, Boolean.FALSE);
- Map<String, Object> targetEnablementAttr = fAttributeTranslator2.convertAttributes(attr);
- if (! fAttributeTranslator2.canUpdateAttributes(bpinfo.breakpoint, dmc, targetEnablementAttr)) {
- // bail out. Continue with the next dmc & breakpoint.
- continue;
- }
- }
-
- // Now do the real work.
- //
- fAttributeTranslator2.resolveBreakpoint(dmc, bpinfo.breakpoint, bpinfo.attributes,
- new DataRequestMonitor<List<Map<String,Object>>>(getExecutor(), bpTargetsCountingRm){
- @Override
- protected void handleSuccess() {
- installBreakpoint(
- dmc, bpinfo.breakpoint, getData(),
- new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRm) {
- @Override
- protected void handleSuccess() {
- targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
- super.handleSuccess();
- };
- });
- }});
-
- bpTargetsCountingRmCount++;
- }
-
- bpTargetsCountingRm.setDoneCount(bpTargetsCountingRmCount);
- }
-
- processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
}
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IBreakpointListener implementation
+ ///////////////////////////////////////////////////////////////////////////
- /*
- * Note this method must not be called in DSF dispatch thread.
- *
- * @param bps
- * @param deltas
- */
- public void breakpointsChanged(IBreakpoint[] bps, IMarkerDelta[] deltas) {
- if (fAttributeTranslator2 == null)
- return;
-
- final PlatformBreakpointInfo[] bpsInfo = collectBreakpointsInfo(bps);
-
- if (bpsInfo.length == 0)
- return; // nothing to do
-
- try {
- getExecutor().execute( new DsfRunnable() {
- public void run() {
- Map<String, Object> tmp = new HashMap<String, Object>(1);
- tmp.put(IBreakpoint.ENABLED, true);
- final String targetEnablementKey = fAttributeTranslator2.convertAttributes(tmp).keySet().iterator().next();
+ public void breakpointChanged(final IBreakpoint breakpoint, final IMarkerDelta delta) {
+ if (fAttributeTranslator.supportsBreakpoint(breakpoint)) {
+ try {
+ // Retrieve the breakpoint attributes
+ final List<Map<String, Object>> attrsArray =
+ fAttributeTranslator.getBreakpointAttributes(breakpoint, fBreakpointManager.isEnabled());
+
+ // Modify the breakpoint in all the target contexts
+ getExecutor().execute( new DsfRunnable() {
+ public void run() {
- for (PlatformBreakpointInfo bpinfo : bpsInfo) {
- /*
- * We cannot depend on "deltas" for attribute change.
- * For instance, delta can be null when extended
- * attributes (e.g. breakpoint thread filter for GDB)
- * are changed.
- */
- Map<String, Object> newAttrs = bpinfo.attributes;
- Map<String, Object> oldAttrs = fBreakpointAttributes.get(bpinfo.breakpoint);
-
- // remember the new attributes.
- fBreakpointAttributes.put(bpinfo.breakpoint, newAttrs);
-
- final Map<String, Object> attrDelta = getAttributesDelta(oldAttrs, newAttrs);
- if (attrDelta.size() == 0)
- continue;
+ // If the breakpoint is currently being updated, queue the request and exit
+ if (fPendingRequests.contains(breakpoint)) {
+ fPendingBreakpoints.add(breakpoint);
+ return;
+ }
+
+ // Keep track of the updates
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+
+ if (!isSuccess()) {
+ if (getStatus().getSeverity() == IStatus.ERROR) {
+ DsfPlugin.getDefault().getLog().log(getStatus());
+ }
+ }
- final List<IBreakpointsTargetDMContext> reinstallContexts = new ArrayList<IBreakpointsTargetDMContext>();
-
- List<IBreakpointsTargetDMContext> updateContexts = new ArrayList<IBreakpointsTargetDMContext>();
-
- // Now change the breakpoint for each known context.
- //
- for (final IBreakpointsTargetDMContext btContext : fPlatformBPs.keySet()) {
-
- if (! fAttributeTranslator2.canUpdateAttributes(bpinfo.breakpoint, btContext, attrDelta)) {
- // backend cannot handle at least one of the platform BP attribute change,
- // we'll handle the re-installation.
- reinstallContexts.add(btContext);
- }
- else {
- // Backend claims it can handle the attributes change, let it do it.
- updateContexts.add(btContext);
- }
-
- }
-
- final PlatformBreakpointInfo[] oneBPInfo = new PlatformBreakpointInfo[] {bpinfo};
- IBreakpoint[] oneBP = new IBreakpoint[] {bpinfo.breakpoint};
+ // Indicate that the pending request has completed
+ fPendingRequests.remove(breakpoint);
- if (reinstallContexts.size() > 0) {
- // Check if it's only enablement change (user click enable/disable
- // button or "Skip all breakpoints" button), which is common operation.
- //
- if (attrDelta.size() == 1 && attrDelta.containsKey(targetEnablementKey)) { // only enablement changed.
- if (bpinfo.enabled) {
- // change from disable to enable. Install the bp.
- doBreakpointsAddedInExecutor(oneBPInfo, reinstallContexts, null);
- }
- else {
- // change from enable to disable. Remove the bp.
- doBreakpointsRemovedInExecutor(oneBP, reinstallContexts, null);
- }
- }
- else {
- doBreakpointsRemovedInExecutor(oneBP, reinstallContexts, new RequestMonitor(getExecutor(), null) {
- // What should we do if removal of some or all targetBP fails ?
- // Go on with the installation of new targetBPs and let clients (i.e. AttributeTranslators)
- // handle the errors.
- @Override
- protected void handleCompleted() {
- doBreakpointsAddedInExecutor(oneBPInfo, reinstallContexts, null);
- }});
- }
- }
-
- if (updateContexts.size() > 0)
- modifyTargetBreakpoints(bpinfo.breakpoint, updateContexts, attrDelta);
- }
- }
- });
- } catch (RejectedExecutionException e) {
- DsfPlugin.getDefault().getLog().log(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, "Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", e)); //$NON-NLS-1$ //$NON-NLS-2$
- }
+ // Process the next pending update for this breakpoint
+ if (fPendingBreakpoints.contains(breakpoint)) {
+ fPendingBreakpoints.remove(breakpoint);
+ new Job("Deferred breakpoint changed job") { //$NON-NLS-1$
+ { setSystem(true); }
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ breakpointChanged(breakpoint, delta);
+ return Status.OK_STATUS;
+ };
+ }.schedule();
+ }
+ }
+ };
+ countingRm.setDoneCount(fPlatformBPs.size());
+
+ // Mark the breakpoint as being updated and go
+ fPendingRequests.add(breakpoint);
+
+ // Modify the breakpoint in all the execution contexts
+ for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
+ modifyBreakpoint(dmc, breakpoint, attrsArray, delta, new RequestMonitor(getExecutor(), countingRm));
+ }
+ }
+ });
+ } catch (CoreException e) {
+ DsfPlugin.getDefault().getLog().log(e.getStatus());
+ } catch (RejectedExecutionException e) {
+ }
+ }
}
- /**
- * For the given platform BP, ask the backend to modify all its target BPs
- * with the given attribute change. <br>
- * This must be called in DSF executor thread.
- *
- * @param bp
- * @param updateContexts
- * target contexts in which to do the modification.
- * @param targetAttrDelta
- * target-recognizable attribute(s) with new values.
- */
- private void modifyTargetBreakpoints(final IBreakpoint bp, Collection<IBreakpointsTargetDMContext> updateContexts, Map<String, Object> targetAttrDelta) {
- // If the breakpoint is currently being updated, queue the request and exit
- if (fRunningEvents.contains(bp)) {
- PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.MODIFIED, updateContexts, targetAttrDelta);
- updatePendingRequest(bp, pendingEvent);
- return;
+ public void breakpointRemoved(final IBreakpoint breakpoint, IMarkerDelta delta) {
+
+ if (fAttributeTranslator.supportsBreakpoint(breakpoint)) {
+ try {
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ //TODO pp: need to track pending requests
+
+ CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
+ @Override
+ protected void handleError() {
+ if (getStatus().getSeverity() == IStatus.ERROR) {
+ DsfPlugin.getDefault().getLog().log(getStatus());
+ }
+ }
+ };
+ countingRm.setDoneCount(fPlatformBPs.size());
+
+ // Remove the breakpoint in all the execution contexts
+ for (IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
+ if (fPlatformBPs.get(dmc).remove(breakpoint) != null) {
+ uninstallBreakpoint(dmc, breakpoint, countingRm);
+ } else {
+ // Breakpoint not installed for given context, do nothing.
+ }
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ }
}
- CountingRequestMonitor modifyTargetBPCRM = new CountingRequestMonitor(getExecutor(), null) {
- @Override
- protected void handleCompleted() {
- fRunningEvents.remove(bp);
- }};
-
- int targetBPCount = 0;
-
- fRunningEvents.add(bp);
-
- for (IBreakpointsTargetDMContext context : updateContexts) {
- List<TargetBP> targetBPs = fPlatformBPs.get(context).get(bp);
- if (targetBPs != null) {
- for (TargetBP tbp : targetBPs) {
- // this must be an installed breakpoint.
- assert (tbp.getTargetBreakpoint() != null);
-
- targetBPCount++;
- fBreakpointsService.updateBreakpoint(tbp.getTargetBreakpoint(), targetAttrDelta, modifyTargetBPCRM);
- }
- }
- }
-
- modifyTargetBPCRM.setDoneCount(targetBPCount);
}
-
- public void breakpointsRemoved(final IBreakpoint[] bps, IMarkerDelta delta[]) {
- getExecutor().execute(new DsfRunnable() {
- public void run() {
- for (IBreakpoint bp : bps)
- fBreakpointAttributes.remove(bp);
- }
- });
-
- doBreakpointsRemoved(bps, null, null);
- }
-
- protected void doBreakpointsRemoved(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
-
- final List<IBreakpoint> bpCandidates = new ArrayList<IBreakpoint>();
-
- for (int i = 0; i < bps.length; i++) {
- IBreakpoint bp = bps[i];
-
- if (fAttributeTranslator.supportsBreakpoint(bp)) {
- bpCandidates.add(bp);
- }
- }
-
- if (bpCandidates.isEmpty()) { // nothing to do
- if (rm != null)
- rm.done();
- return;
- }
-
- try {
- getExecutor().execute(new DsfRunnable() {
- public void run() {
- Collection<IBreakpointsTargetDMContext> contexts = new ArrayList<IBreakpointsTargetDMContext>();
- if (bpsTargetDmc == null)
- contexts.addAll(fPlatformBPs.keySet());
- else
- contexts.add(bpsTargetDmc);
-
- doBreakpointsRemovedInExecutor(bpCandidates.toArray(new IBreakpoint[bpCandidates.size()]), contexts, rm);
- }
- });
- } catch (RejectedExecutionException e) {
- IStatus status = new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR,
- "Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", e);//$NON-NLS-1$ //$NON-NLS-2$
- if (rm != null) {
- rm.setStatus(status);
- rm.done();
- } else {
- DsfPlugin.getDefault().getLog().log(status);
- }
- }
- }
-
- protected void doBreakpointsRemovedInExecutor(IBreakpoint[] bpCandidates,
- Collection<IBreakpointsTargetDMContext> targetContexts, final RequestMonitor rm) {
-
- final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =
- new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpCandidates.length, 1);
-
- CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
- @Override
- protected void handleCompleted() {
- processPendingRequests();
- fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.REMOVED);
- if (rm != null)
- // don't call this if "rm" is null as this will
- // log errors if any and pack Eclipse error
- // log view with errors useless to user.
- super.handleCompleted();
- }
- };
- int processPendingCountingRmCount = 0;
-
- for (final IBreakpoint breakpoint : bpCandidates) {
-
- // If the breakpoint is currently being updated, queue the request and exit
- if (fRunningEvents.contains(breakpoint)) {
- PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.REMOVED, null, targetContexts, processPendingCountingRm);
- processPendingCountingRmCount++;
- updatePendingRequest(breakpoint, pendingEvent);
- continue; // handle next breakpoint
- }
-
- processPendingCountingRmCount++;
-
- final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs =
- new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
- eventBPs.put(breakpoint, targetBPs);
-
- CountingRequestMonitor bpTargetsCountingRM = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
- @Override
- protected void handleCompleted() {
- // Indicate that the running event has completed
- fRunningEvents.remove(breakpoint);
- super.handleCompleted();
- }
- };
-
- int bpTargetsCoutingRMCount = 0;
-
- // Mark the breakpoint as being updated and go
- fRunningEvents.add(breakpoint);
-
- // Remove the breakpoint in all the execution contexts
- for (final IBreakpointsTargetDMContext dmc : targetContexts) {
-
- if (fPlatformBPs.get(dmc).containsKey(breakpoint)) { // there are targetBPs installed
- // now do time-consuming part of the work.
-
- uninstallBreakpoint(
- dmc, breakpoint,
- new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRM) {
- @Override
- protected void handleSuccess() {
- targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
- super.handleSuccess();
- };
- });
- bpTargetsCoutingRMCount++;
- } else {
- // Breakpoint not installed for given context, do nothing.
- }
- }
-
- bpTargetsCountingRM.setDoneCount(bpTargetsCoutingRMCount);
- }
-
- processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
- }
-
- private void updatePendingRequest(IBreakpoint breakpoint, PendingEventInfo pendingEvent) {
- LinkedList<PendingEventInfo> pendingEventsList = fPendingEvents.get(breakpoint);
- if (pendingEventsList == null) {
- pendingEventsList = new LinkedList<PendingEventInfo>();
- fPendingEvents.put(breakpoint, pendingEventsList);
- }
- if (pendingEventsList.size() > 0 &&
- pendingEventsList.getLast().fEventType == BreakpointEventType.MODIFIED) {
- pendingEventsList.removeLast();
- }
- pendingEventsList.add(pendingEvent);
- }
-
- private void processPendingRequests() {
- /*
- * This will process only first pending request for each breakpoint,
- * whose RequestMonitor (see "processPendingCountingRm" in such methods as
- * doBreakpointsRemovedInExecutor()) will invoke this method again.
- */
- if (fPendingEvents.isEmpty()) return; // Nothing to do
-
- // Make a copy to avoid ConcurrentModificationException
- // as we are deleting element in the loop.
- Set<IBreakpoint> bpsInPendingEvents = new HashSet<IBreakpoint>(fPendingEvents.keySet());
- for (IBreakpoint bp : bpsInPendingEvents) {
- if (! fRunningEvents.contains(bp)) {
- LinkedList<PendingEventInfo> eventInfoList = fPendingEvents.get(bp);
-
- // Process the first pending request for this breakpoint
- PendingEventInfo eventInfo = eventInfoList.removeFirst();
-
- if (eventInfoList.isEmpty())
- fPendingEvents.remove(bp);
-
- switch (eventInfo.fEventType) {
- case ADDED:
- doBreakpointsAddedInExecutor(new PlatformBreakpointInfo[] {eventInfo.fBPInfo}, eventInfo.fBPTargetContexts, eventInfo.fRequestMonitor);
- break;
- case MODIFIED:
- modifyTargetBreakpoints(bp, eventInfo.fBPTargetContexts, eventInfo.fAttributeDelta);
- break;
- case REMOVED:
- doBreakpointsRemovedInExecutor(new IBreakpoint[]{bp}, eventInfo.fBPTargetContexts, eventInfo.fRequestMonitor);
- break;
- }
- }
- }
- }
-
- private void fireUpdateBreakpointsStatus(final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs, final BreakpointEventType eventType) {
- // Update breakpoint status
- new Job("Breakpoint status update") { //$NON-NLS-1$
- { setSystem(true); }
- @Override
- protected IStatus run(IProgressMonitor monitor) {
- for (IBreakpoint bp : eventBPs.keySet()) {
- fAttributeTranslator.updateBreakpointStatus(bp);
- }
-
- if (fAttributeTranslator2 != null) {
- fAttributeTranslator2.updateBreakpointsStatus(eventBPs, eventType);
- }
- else
- for (IBreakpoint bp : eventBPs.keySet()) {
- fAttributeTranslator.updateBreakpointStatus(bp);
- }
-
-
- return Status.OK_STATUS;
- };
- }.schedule();
-
- }
-
- /**
- * Determine the set of modified attributes.
- *
- * @param oldAttributes old map of attributes.
- * @param newAttributes new map of attributes.
- * @return new and changed attribute in the new map. May be empty indicating the two maps are equal.
- */
- private Map<String, Object> getAttributesDelta(Map<String, Object> oldAttributes, Map<String, Object> newAttributes) {
-
- Map<String, Object> delta = new HashMap<String,Object>();
-
- Set<String> oldKeySet = oldAttributes.keySet();
- Set<String> newKeySet = newAttributes.keySet();
-
- Set<String> commonKeys = new HashSet<String>(newKeySet); commonKeys.retainAll(oldKeySet);
- Set<String> addedKeys = new HashSet<String>(newKeySet); addedKeys.removeAll(oldKeySet);
- Set<String> removedKeys = new HashSet<String>(oldKeySet); removedKeys.removeAll(newKeySet);
-
- // Add the modified attributes
- for (String key : commonKeys) {
- if (!(oldAttributes.get(key).equals(newAttributes.get(key))))
- delta.put(key, newAttributes.get(key));
- }
-
- // Add the new attributes
- for (String key : addedKeys) {
- delta.put(key, newAttributes.get(key));
- }
-
- // Remove the deleted attributes
- for (String key : removedKeys) {
- delta.put(key, null);
- }
-
- return delta;
- }
}
--- a/cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslatorExtension.java Fri Dec 04 14:31:59 2009 -0600
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2008 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
- * Nokia - enhanced to work for both GDB and EDC. Nov. 2009.
- *******************************************************************************/
-package org.eclipse.cdt.dsf.debug.service;
-
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
-import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.BreakpointEventType;
-import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.ITargetBreakpointInfo;
-import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.debug.core.model.IBreakpoint;
-
-/**
- * Enhanced breakpoint attribute translator interface
- *
- * @since 2.1
- */
-
-public interface IBreakpointAttributeTranslatorExtension extends IBreakpointAttributeTranslator {
- /**
- * Resolve the breakpoint in given context. A platform BP may be mapped to
- * two or more target BPs, e.g. a breakpoint in an in-line function may be
- * mapped to several target BPs, or a thread-specific BP may be mapped to
- * several target BPs each of which is for one thread. This method will get
- * the list of attribute maps each of which corresponds to one target BP.<br>
- * <br>
- * This method is and must be called in DSF execution thread.
- *
- * @param context
- * - a IBreakpointsTargetDMContext object (which could be a
- * process or a loaded module) in which we locate target BPs for
- * the platform BP. Cannot be null.
- * @param breakpoint
- * - platform breakpoint.
- * @param bpAttributes
- * - all attributes of the breakpoint, usually output from
- * {@link #getAllBreakpointAttributes(IBreakpoint, boolean)}.
- * @param drm
- * - on completion of the request, the DataRequestMonitor
- * contains one or more attribute maps each of which
- * corresponding to one target breakpoint.
- * @throws CoreException
- */
- public void resolveBreakpoint(IBreakpointsTargetDMContext context, IBreakpoint breakpoint,
- Map<String, Object> bpAttributes, DataRequestMonitor<List<Map<String, Object>>> drm);
-
- /**
- * Get all platform defined attributes for a breakpoint plus all attributes
- * defined by any breakpoint extension such as ICBreakpointExtension in CDT.
- * In other words, get all attributes available from UI. <br>
- * <br>
- * The attributes returned are independent of runtime context (process,
- * module, etc), whereas attributes from
- * {@link #resolveBreakpoint(IBreakpointsTargetDMContext, IBreakpoint, Map, DataRequestMonitor)}
- * are context sensitive. <br>
- * <br>
- * Note this method must not be called in DSF dispatch thread because we are
- * accessing the resources system to retrieve the breakpoint attributes.
- * Accessing the resources system potentially requires using global locks.
- *
- * @param platformBP
- * @param bpManagerEnabled
- * @return list of target (debugger implementation) recognizable attributes.
- * @throws CoreException
- */
- public Map<String, Object> getAllBreakpointAttributes(IBreakpoint platformBP, boolean bpManagerEnabled) throws CoreException;
-
- /**
- * Convert platform breakpoint attributes to target attributes. This usually
- * involves changing attributes keys to target recognizable ones. For
- * instance, GDB integration has its own breakpoint attribute keys. <br>
- *
- * @param platformBPAttr
- * @return
- */
- public Map<String, Object> convertAttributes(Map<String, Object> platformBPAttr);
-
- /**
- * Update platform about breakpoint status change, e.g. breakpoint installed on target successfully or breakpoint
- * removed from target successfully.<br>
- * <br>
- * Note this method is not and must not be called in DSF dispatch thread.
- *
- * @param bpsInfo
- * @param eventType
- */
- public void updateBreakpointsStatus(Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> bpsInfo, BreakpointEventType eventType);
-
- /**
- * This is enhanced version of
- * {@link #canUpdateAttributes(org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext, Map)}
- * in that this API gives more context parameters so that client can make
- * decision on a finer granularity when needed.<br>
- * <br>
- * This will be called in DSF dispatch thread.
- *
- * @param bp platform breakpoint.
- * @param context
- * @param attributes target-recognizable attributes.
- * @return false as long as one of the attributes cannot be updated by client, otherwise true.
- */
- public boolean canUpdateAttributes(IBreakpoint bp, IBreakpointsTargetDMContext context, Map<String, Object> attributes);
-}
\ No newline at end of file
--- a/cdt/cdt_6_0_x/org.eclipse.cdt.examples.dsf.pda/src/org/eclipse/cdt/examples/dsf/pda/launch/PDAServicesInitSequence.java Fri Dec 04 14:31:59 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.examples.dsf.pda/src/org/eclipse/cdt/examples/dsf/pda/launch/PDAServicesInitSequence.java Fri Dec 04 14:32:55 2009 -0600
@@ -75,7 +75,7 @@
// Create the breakpoint mediator and start tracking PDA breakpoints.
final BreakpointsMediator bpmService = new BreakpointsMediator(
- fSession, new PDABreakpointAttributeTranslator(fCommandControl.getContext()));
+ fSession, new PDABreakpointAttributeTranslator());
bpmService.initialize(new RequestMonitor(getExecutor(), requestMonitor) {
@Override
protected void handleSuccess() {
--- a/cdt/cdt_6_0_x/org.eclipse.cdt.examples.dsf.pda/src/org/eclipse/cdt/examples/dsf/pda/service/PDABreakpointAttributeTranslator.java Fri Dec 04 14:31:59 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.examples.dsf.pda/src/org/eclipse/cdt/examples/dsf/pda/service/PDABreakpointAttributeTranslator.java Fri Dec 04 14:32:55 2009 -0600
@@ -14,15 +14,10 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.Future;
import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator;
import org.eclipse.cdt.dsf.debug.service.IBreakpointAttributeTranslator;
-import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator.ITargetBreakpointInfo;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
-import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.examples.dsf.pda.PDAPlugin;
import org.eclipse.cdt.examples.dsf.pda.breakpoints.PDALineBreakpoint;
import org.eclipse.cdt.examples.dsf.pda.breakpoints.PDAWatchpoint;
@@ -59,18 +54,9 @@
PDAWatchpoint.MODIFICATION
};
- private final IBreakpointsTargetDMContext fBreakpointsTargetDmc;
-
- private BreakpointsMediator fMediator;
-
- public PDABreakpointAttributeTranslator(IBreakpointsTargetDMContext breakpointsTargetDmc) {
- fBreakpointsTargetDmc = breakpointsTargetDmc;
- }
-
// PDA breakpoints translator doesn't keep any state and it doesn't
// need to initialize or clean up.
public void initialize(BreakpointsMediator mediator) {
- fMediator = mediator;
}
public void dispose() {
@@ -142,38 +128,8 @@
return bp.getModelIdentifier().equals(PDAPlugin.ID_PDA_DEBUG_MODEL);
}
- public void updateBreakpointStatus(final IBreakpoint bp) {
- Future<ITargetBreakpointInfo[]> future = fMediator.getSession().getExecutor().submit(new Callable<ITargetBreakpointInfo[]>() {
- public ITargetBreakpointInfo[] call() throws Exception {
- return fMediator.getTargetBreakpoints(fBreakpointsTargetDmc, bp);
- }
- });
-
-
- ITargetBreakpointInfo[] targetBPs = null;
- try {
- targetBPs = future.get();
- } catch (InterruptedException e1) {
- } catch (ExecutionException e1) {
- assert false;
- }
-
- try {
- boolean oldInstalled = ((PDALineBreakpoint)bp).getInstalled();
- boolean newInstalled = false;
- for (int i = 0; targetBPs != null && i < targetBPs.length; i++) {
- if (targetBPs[i].getTargetBreakpoint() != null) {
- newInstalled = true;
- break;
- }
- }
- if (oldInstalled != newInstalled) {
- ((PDALineBreakpoint)bp).setInstalled(newInstalled);
- }
- System.out.println(bp.toString() + " installed = " + newInstalled);
- } catch (CoreException e) {
- // Marker access race condition: most likely the breakpoint has already been removed
- }
+ public void updateBreakpointStatus(IBreakpoint bp) {
+ // PDA breakpoints do not support status reporting
}
}