Overhauled BreakpointsMediator to support both EDC and GDB properly. See Eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=292468
authorl12wang
Mon, 23 Nov 2009 00:59:16 -0600
changeset 117 09f3d307f081
parent 116 05ea843f7d56
child 118 f0e9dc42b68e
Overhauled BreakpointsMediator to support both EDC and GDB properly. See Eclipse bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=292468
cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointAttributeTranslator.java
cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpoints.java
cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java
cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java
cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslatorExtension.java
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointAttributeTranslator.java	Mon Nov 23 00:59:16 2009 -0600
@@ -0,0 +1,561 @@
+/*******************************************************************************
+ * 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	Tue Nov 17 14:33:45 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpoints.java	Mon Nov 23 00:59:16 2009 -0600
@@ -15,6 +15,8 @@
 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;
@@ -27,6 +29,8 @@
 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;
@@ -35,7 +39,9 @@
 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;
@@ -43,8 +49,11 @@
 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;
 
 /**
@@ -281,6 +290,53 @@
     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
 	///////////////////////////////////////////////////////////////////////////
@@ -763,7 +819,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;
-        IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class);
+        final 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);
@@ -782,11 +838,22 @@
         // Determine if the breakpoint condition changed
 		String conditionAttribute = CONDITION;
 		if (properties.containsKey(conditionAttribute)) {
-			String oldValue = breakpoint.getCondition();
+			final String oldValue = breakpoint.getCondition();
 			String newValue = (String) properties.get(conditionAttribute);
 			if (newValue == null) newValue = NULL_STRING;
 	        if (!oldValue.equals(newValue)) {
-	        	changeCondition(context, reference, newValue, countingRm);
+	        	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();
+					}});
 	        	numberOfChanges++;
 	        }
 			properties.remove(conditionAttribute);
@@ -825,6 +892,26 @@
         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	Tue Nov 17 14:33:45 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.dsf.gdb/src/org/eclipse/cdt/dsf/mi/service/MIBreakpointsManager.java	Mon Nov 23 00:59:16 2009 -0600
@@ -15,74 +15,8 @@
 
 package org.eclipse.cdt.dsf.mi.service;
 
-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.debug.service.BreakpointsMediator;
 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
@@ -90,107 +24,8 @@
  * 
  * It relies on MIBreakpoints for the actual back-end interface.
  */
-public class MIBreakpointsManager extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointListener
+public class MIBreakpointsManager extends BreakpointsMediator
 {
-    // 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
@@ -200,1515 +35,6 @@
      * @param debugModelId  the debugging model
      */
     public MIBreakpointsManager(DsfSession session, String 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());
-        }
+        super(session, new MIBreakpointAttributeTranslator(session, debugModelId));
     }
-
-    /**
-     * 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	Tue Nov 17 14:33:45 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java	Mon Nov 23 00:59:16 2009 -0600
@@ -7,13 +7,14 @@
  *
  * Contributors:
  *     Wind River - Initial API and implementation
- *     Ericsson   - Low-level breakpoints integration  
+ *     Ericsson   - Low-level breakpoints integration
+ *     Nokia - refactored to work for both GDB and EDC.  Nov. 2009.
  *******************************************************************************/
 
 package org.eclipse.cdt.dsf.debug.service;
 
 import java.util.ArrayList;
-import java.util.Collections;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Hashtable;
@@ -27,7 +28,6 @@
 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.ImmediateExecutor;
 import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
 import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
 import org.eclipse.cdt.dsf.datamodel.IDMContext;
@@ -50,7 +50,9 @@
 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
 {
@@ -72,7 +74,7 @@
     /**
      * DSF Debug service for creating breakpoints.
      */
-    IBreakpoints fBreakpoints;
+    IBreakpoints fBreakpointsService;
     
     /**
      * Platform breakpoint manager
@@ -108,7 +110,6 @@
     private static class TargetBP implements ITargetBreakpointInfo {
     	
     	private Map<String, Object> fAttributes;
-    	private Map<String, Object> fAttributesDelta; // not really useful ?
     	private IBreakpointDMContext fTargetBPContext;
     	private IStatus fStatus;
     	
@@ -137,7 +138,21 @@
 		}
     }
     
-    ///////////////////////////////////////////////////////////////////////////
+	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
     ///////////////////////////////////////////////////////////////////////////
 
@@ -153,6 +168,43 @@
 	private Map<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>> fPlatformBPs = 
 		new HashMap<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>>();
 
+	/**
+	 * 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;
+		}
+
+		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
@@ -160,23 +212,8 @@
      */
 	private Set<IBreakpoint> fRunningEvents    = new HashSet<IBreakpoint>();
 
-	private static class PendingEventInfo {
-		PendingEventInfo(BreakpointEventType eventType, IBreakpointsTargetDMContext bpsTargetDmc, RequestMonitor rm) {
-			fEventType = eventType;
-			fBPsTargetDmc = bpsTargetDmc;
-			fRequestMonitor = rm;
-		}
-		
-		RequestMonitor fRequestMonitor;
-		BreakpointEventType fEventType;
-		IBreakpointsTargetDMContext fBPsTargetDmc;
-	}
-	
-	/**
-	 * @see fPendingRequests
-	 */
 	private Map<IBreakpoint, LinkedList<PendingEventInfo>> fPendingEvents = 
-		Collections.synchronizedMap(new HashMap<IBreakpoint, LinkedList<PendingEventInfo>>());
+			new HashMap<IBreakpoint, LinkedList<PendingEventInfo>>();
 	
     ///////////////////////////////////////////////////////////////////////////
     // AbstractDsfService    
@@ -219,7 +256,7 @@
     private void doInitialize(RequestMonitor rm) {
     	
     	// Get the services references
-        fBreakpoints  = getServicesTracker().getService(IBreakpoints.class);
+        fBreakpointsService  = getServicesTracker().getService(IBreakpoints.class);
         fBreakpointManager = DebugPlugin.getDefault().getBreakpointManager();
         fAttributeTranslator.initialize(this);
 
@@ -328,12 +365,15 @@
 
     	// Remove the breakpoints for given DMC from the internal maps.
         Map<IBreakpoint, List<TargetBP>> 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$
+        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$
             { setSystem(true); }
 
@@ -341,7 +381,7 @@
 			// and install them on the target
         	@Override
             protected IStatus run(IProgressMonitor monitor) {
-        		doBreakpointsRemoved(DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(), dmc, rm);
+        		doBreakpointsRemoved(bps, dmc, rm);
                 return Status.OK_STATUS;
             }
         }.schedule();    
@@ -356,6 +396,8 @@
      * @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)
@@ -376,6 +418,8 @@
      * @return platform breakpoint. null if not found. 
      */
     public IBreakpoint getPlatformBreakpoint(IBreakpointsTargetDMContext dmc, IBreakpointDMContext bp) {
+    	assert getExecutor().isInExecutorThread();
+
     	for (IBreakpointsTargetDMContext bpContext : fPlatformBPs.keySet()) {
     		if (dmc != null && !dmc.equals(bpContext))
     			continue;
@@ -448,7 +492,7 @@
 		// Install the back-end breakpoint(s)
 		for (int _i = 0; _i < attrsList.size(); _i++) {
 			final int i = _i;
-            fBreakpoints.insertBreakpoint(
+            fBreakpointsService.insertBreakpoint(
                 dmc, attrsList.get(i), 
 				new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
 				@Override
@@ -508,16 +552,14 @@
         for (int i = 0; i < bpList.size(); i++) {
         	final TargetBP bp = bpList.get(i);
         	if (bp.getTargetBreakpoint() != null) {
-        		fBreakpoints.removeBreakpoint(
+        		fBreakpointsService.removeBreakpoint(
         				bp.getTargetBreakpoint(), 
         				new RequestMonitor(getExecutor(), countingRm) {
         					@Override
         					protected void handleCompleted() {
         				        bp.setStatus(getStatus());
-        				        bp.fAttributesDelta = bp.fAttributes;
         				        if (isSuccess()) {
             						bp.setTargetBreakpoint(null);
-        				        	bp.fAttributes = null;
         				        } 
         				        countingRm.done();
         					}
@@ -530,225 +572,12 @@
         countingRm.setDoneCount(count);
     }
 	
-	/**
-	 * Modify an individual breakpoint
-	 * 
-	 * @param context
-	 * @param breakpoint
-	 * @param attributes
-	 * @param drm
-	 * @throws CoreException
-	 */
-	private void modifyBreakpoint(final IBreakpointsTargetDMContext context, final IBreakpoint breakpoint,
-			final List<Map<String, Object>> newAttrsList, final DataRequestMonitor<List<TargetBP>> drm)
-	{
-	    // 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<TargetBP>> platformBPs = fPlatformBPs.get(context);
-        if (platformBPs == null) {
-            drm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
-            drm.done();
-            return;
-        }
-
-        final List<TargetBP> oldBpList = platformBPs.get(breakpoint);
-        
-        final List<TargetBP> bpList = new ArrayList<TargetBP>(newAttrsList.size());
-        
-        if (oldBpList == null || oldBpList.size() == 0) { // not targetBP installed
-            drm.setData(bpList);
-        	drm.done();
-        	return;
-        }
-        
-        for (int i = 0; i < newAttrsList.size(); i++) {
-        	bpList.add(new TargetBP(newAttrsList.get(i)));
-        }
-        
-        // Create a list of attribute changes.  The length of this list will
-        // always be max(oldAttrList.size(), newAttrsList.size()), padded with
-        // null's if oldAttrsList was longer.
-        calcBPsAttrs(oldBpList, bpList);
-        
-        // Create the request monitor that will be called when all
-        // modifying/inserting/removing is complete.
-        final CountingRequestMonitor countingRM = new CountingRequestMonitor(getExecutor(), drm) {
-            @Override
-            protected void handleCompleted() {
-                // Save the new list of target breakpoints 
-            	platformBPs.put(breakpoint, bpList);
-                drm.setData(bpList);
-                drm.done();
-            }
-        };
-        
-        // Set the count, if could be zero if no breakpoints have actually changed.
-        int coutingRmCount = 0;
-        
-        // Process the changed breakpoints.
-        for (int _i = 0; _i < bpList.size(); _i++) {
-        	final int i = _i;
-        	final TargetBP bp = bpList.get(i);
-            if (bp.fAttributes == null) {
-                // The list of new attribute maps was shorter than the old.
-                // Remove the corresponding target-side bp.  
-            	// Note the target BP context may be null if the target
-            	// BP failed to insert in the first place.
-            	if (bp.getTargetBreakpoint() != null) {
-            		fBreakpoints.removeBreakpoint(
-            				bp.getTargetBreakpoint(), 
-            				new RequestMonitor(getExecutor(), countingRM) {
-            					@Override
-            					protected void handleCompleted() {
-            						bp.fStatus = getStatus();
-            						countingRM.done();
-            					}
-            				});
-                    coutingRmCount++;
-            	}
-            } else if ( bp.getTargetBreakpoint() == null) {
-                // 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 handleCompleted() {
-                        	if (isSuccess()) {
-                        		bp.fTargetBPContext = getData();
-                        	}
-                        	bp.fStatus = getStatus();
-                            countingRM.done();
-                        }
-                    });
-                coutingRmCount++;
-            } else if (bp.fAttributesDelta.size() == 0) { 
-            	// Breakpoint attributes have not changed, only copy over the old status.
-            	bp.fStatus = oldBpList.get(i).fStatus;
-            } else if ( !fAttributeTranslator.canUpdateAttributes(bp.getTargetBreakpoint(), bp.fAttributesDelta) ) {
-                // 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.
-                RequestMonitor removeRm = new RequestMonitor(getExecutor(), countingRM) {
-                    @Override
-                    protected void handleCompleted() {
-                    	if (isSuccess()) {
-                    		bp.fTargetBPContext = null;
-	                        fBreakpoints.insertBreakpoint(
-	                            context, newAttrsList.get(i),
-	                            new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), countingRM) {
-	                                @Override
-	                                protected void handleCompleted() {
-	                                    if (isSuccess()) {
-	                                        bp.fTargetBPContext = getData();
-	                                    } 
-	                                    bp.fStatus = getStatus();
-	                                    countingRM.done();
-	                                }
-	                            });
-                    	} else {
-                    		// Failed to remove old breakpoint, do not proceed to insert a new one
-                    		// just save the error from target with the old context.
-                            bp.fStatus = getStatus();
-                            countingRM.done();
-                    	}
-                    }
-                };
-
-            	fBreakpoints.removeBreakpoint(bp.getTargetBreakpoint(), removeRm);
-                coutingRmCount++;
-            } else {
-                // The back end can modify the breakpoint.  Update the breakpoint with the 
-                // new attributes.
-                fBreakpoints.updateBreakpoint(
-                    bp.getTargetBreakpoint(), bp.fAttributes, 
-                    new RequestMonitor(getExecutor(), countingRM) {
-                        @Override
-                        protected void handleCompleted() {
-                            bp.fStatus = getStatus();
-                            countingRM.done();
-                        }
-                    });
-                coutingRmCount++;
-            }
-        }
-        countingRM.setDoneCount(coutingRmCount);
-	} 
-	
-	/**
-	 * Determine the set of modified attributes
-	 * 
-	 * @param oldAttributes
-	 * @param newAttributes
-	 * @return
-	 */
-	private void calcBPsAttrs(List<TargetBP> oldBpList, List<TargetBP> bpList) {
-	    // Go through the bp attributes common to the old and the new lists and calculate
-	    // their deltas.
-		int i = 0;
-	    for (i = 0; i < oldBpList.size() && i < bpList.size(); i++) {
-    		TargetBP newBp = bpList.get(i);
-    		TargetBP oldBp = oldBpList.get(i);
-    		newBp.fTargetBPContext = oldBp.getTargetBreakpoint();
-	        Map<String, Object> oldAttributes = oldBp.fAttributes; 
-	        Map<String, Object> newAttributes = newBp.fAttributes;
-    	    
-	        if (oldAttributes == null) {
-	        	// Reached a point in the old BP list where breakpoints were 
-	        	// removed.  Break out of the loop.
-	        	break;
-	        }
-	        
-    		bpList.get(i).fAttributesDelta = getAttributesDelta(oldAttributes, newAttributes);
-	    } 
-	    
-	    // Add all the new attributes as deltas
-	    for (; i < bpList.size(); i++) {
-	    	TargetBP newBP = bpList.get(i); 
-	        newBP.fAttributesDelta =  newBP.fAttributes;
-	    }
-	    
-	    // For breakpoints that were removed create TargetBP entry with a 
-	    // null set of attributes
-	    for (; i < oldBpList.size(); i++) {
-	    	TargetBP oldBp = oldBpList.get(i);
-	    	if (oldBp.fAttributes == null) {
-	    		// Guard against old removed breakpoints
-	    		break;
-	    	}
-	    	TargetBP newBp = new TargetBP(null);
-	    	newBp.fTargetBPContext = oldBp.getTargetBreakpoint();
-	    	newBp.fAttributesDelta = oldBpList.get(i).fAttributes;
-	    	bpList.add(newBp);
-	    }	    
-	}
-
     ///////////////////////////////////////////////////////////////////////////
     // IBreakpointManagerListener implementation
     ///////////////////////////////////////////////////////////////////////////
 
 	public void breakpointManagerEnablementChanged(boolean enabled) {
-		Map<String, Object> platformAttrDelta = new HashMap<String, Object>(1);
-		platformAttrDelta.put(IBreakpoint.ENABLED, enabled);
-		
-		Map<IBreakpoint, Map<String, Object>> bp2DeltaMap = new HashMap<IBreakpoint, Map<String, Object>>(); 
-		for (IBreakpoint bp : fBreakpointManager.getBreakpoints()) {
-			if (! fAttributeTranslator.supportsBreakpoint(bp))
-				continue;
-
-			bp2DeltaMap.put(bp, platformAttrDelta);
-		}
-		
-		doBreakpointsChanged(bp2DeltaMap);
+		// do nothing. breakpointsChanged() will be called to handle the change.
 	}
 
 	@ThreadSafe
@@ -756,141 +585,30 @@
 		doBreakpointsAdded(bps, null, null);
 	}
 	
-	@SuppressWarnings("unchecked")
-	private void doBreakpointsAdded(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
-		final List<IBreakpoint> bpCandidates = new ArrayList<IBreakpoint>(bps.length);
-		
-		for (int i = 0; i < bps.length; i++) {
-			IBreakpoint bp = bps[i];
-			
-			if (fAttributeTranslator.supportsBreakpoint(bp)) {
-				try {
-					if (fAttributeTranslator2 != null) {
-						if (bp.getMarker() == null)
-							continue;
-						
-						// if the breakpoint is not enabled, ask translator2 if it can set (and manage)
-						// disabled breakpoint itself. If not, just bail out.
-						//
-						Map<String, Object> platformAttrs = bp.getMarker().getAttributes();
-						
-						if (! (Boolean)platformAttrs.get(IBreakpoint.ENABLED) || ! fBreakpointManager.isEnabled()) {
-							Map<String, Object> platformAttr = new HashMap<String, Object>(1);
-							platformAttr.put(IBreakpoint.ENABLED, Boolean.FALSE);
-							Map<String, Object> targetAttr = fAttributeTranslator2.convertAttributeDelta(platformAttr);
-							if (! fAttributeTranslator2.canUpdateAttributes(null, targetAttr)) {
-								// bail out.
-								continue;
-							}
-						}
-					}
-					
-					bpCandidates.add(bp);
-				} catch (CoreException e) {
-					DsfPlugin.getDefault().getLog().log(e.getStatus());
-				}
-			}
-		}
+	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 (bpCandidates.isEmpty()) {
+		if (bpsInfo.length == 0) {
 			if (rm != null) {
 				rm.done();
 			}
 			return;
 		}
-				
+
 		try {
             getExecutor().execute(new DsfRunnable() {
 				public void run() {
-					final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
-						new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpCandidates.size(), 1);
-					
-	                CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
-		                    @Override
-		                    protected void handleCompleted() {
-		                    	processPendingRequests();
-		                    	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.ADDED);
-		                        super.handleCompleted();
-		                    }
-		                };	            	
-	                int processPendingCountingRmCount = 0;
-	            	
-	            	for (final IBreakpoint breakpoint : bpCandidates) {
-	            		final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs = 
-	            			new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
-	            		eventBPs.put(breakpoint, targetBPs);	
-	            			
-						if (fRunningEvents.contains(breakpoint)) {
-							PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.ADDED, bpsTargetDmc, processPendingCountingRm);
-							processPendingCountingRmCount++;
-							updatePendingRequest(breakpoint, pendingEvent);
-							continue;
-						}
-		                // Mark the breakpoint as being updated and go
-		                fRunningEvents.add(breakpoint);
+					Collection<IBreakpointsTargetDMContext> dmcs = new ArrayList<IBreakpointsTargetDMContext>();
+					if (bpsTargetDmc == null)
+						dmcs.addAll(fPlatformBPs.keySet());
+					else
+						dmcs.add(bpsTargetDmc);
 
-	            		final CountingRequestMonitor bpTargetsCountingRm = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
-								@Override
-								protected void handleCompleted() {
-			                    	// Indicate that the running event has completed
-			                    	fRunningEvents.remove(breakpoint);
-			                    	super.handleCompleted();
-								}
-							};
-						int bpTargetsCountingRmCount = 0;
-						processPendingCountingRmCount++;
-	
-						
-						// Install the breakpoint in all the execution contexts
-						for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
-							if (bpsTargetDmc != null && !bpsTargetDmc.equals(dmc)) {
-								continue;
-							}
-							
-			                // Now ask lower level to set the bp.
-							//
-							if (fAttributeTranslator2 != null) {
-								fAttributeTranslator2.getTargetBreakpointAttributes(dmc, breakpoint, fBreakpointManager.isEnabled(),
-										new DataRequestMonitor<List<Map<String,Object>>>(getExecutor(), bpTargetsCountingRm){
-											@Override
-											protected void handleSuccess() {
-												installBreakpoint(
-											    		dmc, breakpoint, getData(), 
-											    		new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRm) {
-											    			@Override
-															protected void handleSuccess() {
-											    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
-											    				super.handleSuccess();
-											    			};
-											    		});
-											}});
-							}
-							else {	// Old way
-								List<Map<String, Object>> attrsArray;
-								try {
-									attrsArray = fAttributeTranslator.getBreakpointAttributes(breakpoint, fBreakpointManager.isEnabled());
-								} catch (CoreException e) {
-									attrsArray = new ArrayList<Map<String, Object>>();
-									DsfPlugin.getDefault().getLog().log(e.getStatus());
-								}
-				        		
-								installBreakpoint(
-						    		dmc, breakpoint, attrsArray, 
-						    		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);	            	
+					doBreakpointsAddedInExecutor(bpsInfo, dmcs, rm);
 				}
 			});
 		} catch (RejectedExecutionException e) {
@@ -904,191 +622,278 @@
 		}
 	}
 	
-    ///////////////////////////////////////////////////////////////////////////
-    // IBreakpointListener implementation
-    ///////////////////////////////////////////////////////////////////////////
-
-	@SuppressWarnings("unchecked")
-	public void breakpointsChanged(IBreakpoint[] bps, IMarkerDelta[] deltas) {
-		Map<IBreakpoint, Map<String, Object>> bp2DeltaMap = new HashMap<IBreakpoint, Map<String, Object>>(); 
-		for (int i = 0; i < bps.length; i++) {
-			IBreakpoint bp = bps[i];
-			
-			if (deltas[i] == null)
-				continue;
-			
+	/**
+	 * 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))
-				continue;
-
-			try {
-				Map<String, Object> oldAttrs = deltas[i].getAttributes();
-				Map<String, Object> newAttrs = bp.getMarker().getAttributes();
-				
-				Map<String, Object> platformAttrDelta = getAttributesDelta(oldAttrs, newAttrs);
-				
-				if (platformAttrDelta.size() == 0) // no change. possible when user cancels breakpoint properties dialog.
-					continue;
-
-				bp2DeltaMap.put(bp, platformAttrDelta);
-			} catch (CoreException e) {
-				DsfPlugin.getDefault().getLog().log(e.getStatus());
+			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());
+				}
 			}
 		}
 		
-		doBreakpointsChanged(bp2DeltaMap);
+		return bpsInfo.toArray(new PlatformBreakpointInfo[bpsInfo.size()]);
 	}
-	
-	/**
-	 * 
-	 * @param bp2DeltaMap - pairs of (breakpoint, attrDelta), where attrDelta contains changed 
-	 * and new attributes for the breakpoint.  
-	 */
-	private void doBreakpointsChanged(Map<IBreakpoint, Map<String, Object>> bp2DeltaMap) {
 
-		final Map<IBreakpoint, List<Map<String, Object>>> bpsAttrs = 
-			new HashMap<IBreakpoint, List<Map<String, Object>>>(bp2DeltaMap.size() * 4/3);
-
-		for (IBreakpoint bp : bp2DeltaMap.keySet()) {
-			try {
-				Map<String, Object> platformAttrDelta = bp2DeltaMap.get(bp);
-				
-				if (fAttributeTranslator2 != null) {
-					Map<String, Object> targetAttrDelta = fAttributeTranslator2.convertAttributeDelta(platformAttrDelta);
+	protected void doBreakpointsAddedInExecutor(PlatformBreakpointInfo[] bpsInfo, Collection<IBreakpointsTargetDMContext> bpTargetDMCs, RequestMonitor rm) {
+		final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
+			new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpsInfo.length, 1);
 		
-					if (! fAttributeTranslator2.canUpdateAttributes(null, targetAttrDelta)) {
-						// DSF client cannot handle at least one of the attribute change, just remove
-						// old target BPs and install new ones.
-						final IBreakpoint[] platformBPs = new IBreakpoint[] {bp};
-						
-						if (platformAttrDelta.containsKey(IBreakpoint.ENABLED)) {
-							if ((Boolean)platformAttrDelta.get(IBreakpoint.ENABLED))
-								// platform BP changed from disabled to enabled
-								doBreakpointsAdded(platformBPs, null, null);
-							else
-								doBreakpointsRemoved(platformBPs, null, null);
-						}
-						else {
-							// other attribute change, remove old and install new.
-							doBreakpointsRemoved(platformBPs, null, new RequestMonitor(getExecutor(), null) {
-								@Override
-								protected void handleSuccess() {
-									doBreakpointsAdded(platformBPs, null, null);
-								}});
-						}
+        CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
+                @Override
+                protected void handleCompleted() {
+                	processPendingRequests();
+                	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.ADDED);
+                    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;
 					}
-					else 
-						updateBreakpoint(bp, targetAttrDelta);
 				}
-				else { // old way
-					
-	                // Retrieve the breakpoint attributes
-	        		List<Map<String, Object>> attrsArray = 
-	        		    fAttributeTranslator.getBreakpointAttributes(bp, fBreakpointManager.isEnabled());
-	        		
-	        		bpsAttrs.put(bp, attrsArray);
-				}
-			} catch (CoreException e) {
-				DsfPlugin.getDefault().getLog().log(e.getStatus());
+            	
+				// 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);	            	
+	}
+
+	/*
+	 * 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;
 		
-		if (bpsAttrs.isEmpty()) return; // nothing to do
+		final PlatformBreakpointInfo[] bpsInfo = collectBreakpointsInfo(bps);
+		
+		if (bpsInfo.length == 0) 
+			return; // nothing to do
 		
 		try {
-			// Modify the breakpoint in all the target contexts
 	        getExecutor().execute( new DsfRunnable() { 
 	            public void run() {
-					final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
-						new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpsAttrs.size(), 1);
+	            	Map<String, Object> tmp = new HashMap<String, Object>(1);
+					tmp.put(IBreakpoint.ENABLED, true);
+					final String targetEnablementKey = fAttributeTranslator2.convertAttributes(tmp).keySet().iterator().next();
 
-					CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), null) {
-	                    @Override
-	                    protected void handleCompleted() {
-	                    	processPendingRequests();
-	                    	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.MODIFIED);
-	                    }
-	                };	            	
-	                int processPendingCountingRmCount = 0;
-	            	
-	            	for (final IBreakpoint breakpoint : bpsAttrs.keySet()) {
-	            		final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs = 
-	            			new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
-	            		eventBPs.put(breakpoint, targetBPs);	
-
-	            		// If the breakpoint is currently being updated, queue the request and exit
-		            	if (fRunningEvents.contains(breakpoint)) {
-		            		updatePendingRequest(breakpoint, new PendingEventInfo(BreakpointEventType.MODIFIED, null, null));
+					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;
-		            	}
-		            	
-		                // Keep track of the updates
-		                CountingRequestMonitor bpTargetsCountingRm = 
-		                	new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
-			                    @Override
-			                    protected void handleCompleted() {
-			                    	// Indicate that the running event has completed
-			                    	fRunningEvents.remove(breakpoint);
-			                    	super.handleCompleted();
-			                    }
-			                };
-			            processPendingCountingRmCount++;
-		                bpTargetsCountingRm.setDoneCount(fPlatformBPs.size());
-	
-		                // Mark the breakpoint as being updated and go
-		                fRunningEvents.add(breakpoint);
-		                
-		                // Modify the breakpoint in all the execution contexts
-		                for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
-		                    modifyBreakpoint(
-		                    		dmc, breakpoint, bpsAttrs.get(breakpoint), 
-		                    		new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRm) {
-						    			@Override
-										protected void handleSuccess() {
-						    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
-						    				super.handleSuccess();
-						    			};
-		                    		});
-		                }
+
+						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};
+
+						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);
 	            	}
-	            	processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
 	            }
 	        });
 	    } 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$
 	    }
+
 	}
 
 	/**
-	 * For the given platform BP, update all its target BPs with the given attribute change.
+	 * 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 targetAttrDelta - target attribute change.  
+	 * @param updateContexts 
+	 * 			  target contexts in which to do the modification.
+	 * @param targetAttrDelta
+	 *            target-recognizable attribute(s) with new values.
 	 */
-	private void updateBreakpoint(final IBreakpoint bp, final Map<String, Object> targetAttrDelta) {
-        getExecutor().execute(new DsfRunnable() {
-        	public void run() {
-				for (IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
-					List<TargetBP> targetBPs = fPlatformBPs.get(dmc).get(bp);
-					if (targetBPs != null) {
-						for (TargetBP tbp : targetBPs) {
-							// this must be an installed bp.
-							assert (tbp.getTargetBreakpoint() != null);
-							
-							fBreakpoints.updateBreakpoint(tbp.getTargetBreakpoint(), targetAttrDelta, new RequestMonitor(getExecutor(), null) {});
-						}
-					}
+	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;
+    	}
+		
+    	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);
 	}
 	
-	public void doBreakpointsRemoved(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
+	protected void doBreakpointsRemoved(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
 	
 		final List<IBreakpoint> bpCandidates = new ArrayList<IBreakpoint>();
 		
@@ -1096,10 +901,7 @@
 			IBreakpoint bp = bps[i];
 			
 			if (fAttributeTranslator.supportsBreakpoint(bp)) {
-				if (bpsTargetDmc == null)
-					bpCandidates.add(bp);
-				else if (fPlatformBPs.get(bpsTargetDmc).containsKey(bp))	// target BPs are installed in the context 
-					bpCandidates.add(bp);
+				bpCandidates.add(bp);
 			}
 		}
 		
@@ -1112,72 +914,18 @@
 		try {
 	        getExecutor().execute(new DsfRunnable() {
 	        	public void run() {
-					final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
-						new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpCandidates.size(), 1);
+					Collection<IBreakpointsTargetDMContext> contexts = new ArrayList<IBreakpointsTargetDMContext>();
+					if (bpsTargetDmc == null)
+						contexts.addAll(fPlatformBPs.keySet());
+					else
+						contexts.add(bpsTargetDmc);
 
-					CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
-            			@Override
-            			protected void handleCompleted() {
-            				processPendingRequests();
-	                    	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.REMOVED);
-            				super.handleCompleted();
-            			}
-            		};
-            		int processPendingCountingRmCount = 0;
-            		
-					for (final IBreakpoint breakpoint : bpCandidates) {
-	            		final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs = 
-	            			new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
-	            		eventBPs.put(breakpoint, targetBPs);	
-				
-		            	// If the breakpoint is currently being updated, queue the request and exit
-		            	if (fRunningEvents.contains(breakpoint)) {
-		            		PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.REMOVED, bpsTargetDmc, processPendingCountingRm);
-            				processPendingCountingRmCount++;
-		            		updatePendingRequest(breakpoint, pendingEvent);
-							continue;
-		            	}
-		            	
-	            		CountingRequestMonitor bpTargetDmcCRM = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
-							@Override
-							protected void handleCompleted() {
-		                    	// Indicate that the running event has completed
-		                    	fRunningEvents.remove(breakpoint);
-		                    	super.handleCompleted();
-							}
-						};
-						processPendingCountingRmCount++;
-						int bpTargetDmcCRMCount = 0;
-
-	            		// Remove the breakpoint in all the execution contexts
-	            		for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
-	            			if (bpsTargetDmc != null && !bpsTargetDmc.equals(dmc)) {
-	            				continue;
-	            			}
-	            			
-	            			if (fPlatformBPs.get(dmc).containsKey(breakpoint)) {		// there are targetBPs installed 
-	            				uninstallBreakpoint(
-	            						dmc, breakpoint,
-	            						new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetDmcCRM) {
-							    			@Override
-											protected void handleSuccess() {
-							    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
-							    				super.handleSuccess();
-							    			};
-	            						});
-	            				bpTargetDmcCRMCount++;
-	            			} else {
-	            				// Breakpoint not installed for given context, do nothing.
-	            			}
-	            		}
-	            		bpTargetDmcCRM.setDoneCount(bpTargetDmcCRMCount);
-					}
-					
-					processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
+					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$
+			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();
@@ -1187,6 +935,79 @@
         }
 	}
 	
+	protected void doBreakpointsRemovedInExecutor(IBreakpoint[] bpCandidates, 
+			Collection<IBreakpointsTargetDMContext> targetContexts, 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);
+				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) {
@@ -1201,91 +1022,38 @@
 	}
 	
 	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
 		
-		final List<PendingEventInfo> modifyBPs = new ArrayList<PendingEventInfo>(1);
-		final Map<IBreakpointsTargetDMContext, List<PendingEventInfo>> addBPs =
-			new HashMap<IBreakpointsTargetDMContext, List<PendingEventInfo>>(1);
-		final Map<IBreakpointsTargetDMContext, List<PendingEventInfo>> removeBPs =
-			new HashMap<IBreakpointsTargetDMContext, List<PendingEventInfo>>(1);
-		
-		// Make a copy to avoid java.util.ConcurrentModificationException.
+		// 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 : fPendingEvents.keySet()) {
 		for (IBreakpoint bp : bpsInPendingEvents) {
-	    	// Process the next pending update for this breakpoint
-	    	if (!fRunningEvents.contains(bp)) {
-	    		LinkedList<PendingEventInfo> eventInfoList = fPendingEvents.get(bp);
-	    		PendingEventInfo eventInfo = eventInfoList.removeFirst();
-	    		if (eventInfoList.isEmpty()) {
-	    			fPendingEvents.remove(bp);
-	    		}
-	    		BreakpointEventType type = eventInfo.fEventType;
-	    		if (type.equals(BreakpointEventType.MODIFIED)) {
-	    			modifyBPs.add(eventInfo);
-	    		} else if (type.equals(BreakpointEventType.ADDED)){
-	    			List<PendingEventInfo> addList = addBPs.get(eventInfo.fBPsTargetDmc);
-	    			if (addList == null) {
-	    				addList = new ArrayList<PendingEventInfo>(1);
-	    				addBPs.put(eventInfo.fBPsTargetDmc, addList);
-	    			}
-	    			addList.add(eventInfo);
-	    		} else if (type.equals(BreakpointEventType.REMOVED)){
-	    			List<PendingEventInfo> removeList = removeBPs.get(eventInfo.fBPsTargetDmc);
-	    			if (removeList == null) {
-	    				removeList = new ArrayList<PendingEventInfo>(1);
-	    				removeBPs.put(eventInfo.fBPsTargetDmc, removeList);
-	    			}
-	    			removeList.add(eventInfo);
-	    		}
-	    	}
-		}
+	    	if (! fRunningEvents.contains(bp)) {
+				LinkedList<PendingEventInfo> eventInfoList = fPendingEvents.get(bp);
 
-		if (modifyBPs.size() != 0 || removeBPs.size() != 0) {
-			new Job("Deferred breakpoint changed job") { //$NON-NLS-1$
-	            { setSystem(true); }
-	            @Override
-	            protected IStatus run(IProgressMonitor monitor) {
-	            	if (modifyBPs.size() != 0) {
-	            		breakpointsChanged(modifyBPs.toArray(new IBreakpoint[modifyBPs.size()]), null);	            		
-	            	}
-	            	if (addBPs.size() != 0) {
-	            		for (Map.Entry<IBreakpointsTargetDMContext, List<PendingEventInfo>> addBPsEntry : addBPs.entrySet()) {
-	            			IBreakpointsTargetDMContext bpsTargetDmc = addBPsEntry.getKey();
-	            			final List<PendingEventInfo> addBpList = addBPsEntry.getValue();
-	            			RequestMonitor rm = new RequestMonitor(ImmediateExecutor.getInstance(), null) {
-	            				@Override
-								protected void handleCompleted() {
-	            					for (PendingEventInfo eventInfo : addBpList) {
-	            						if (eventInfo.fRequestMonitor != null) {
-	            							eventInfo.fRequestMonitor.done();
-	            						}
-	            					}
-	            				};
-	            			};
-		            		doBreakpointsAdded(addBpList.toArray(new IBreakpoint[addBpList.size()]), bpsTargetDmc, rm);	            			            			
-	            		}
-	            	} 
-	            	if (removeBPs.size() != 0) {
-	            		for (Map.Entry<IBreakpointsTargetDMContext, List<PendingEventInfo>> removeBPsEntry : removeBPs.entrySet()) {
-	            			IBreakpointsTargetDMContext bpsTargetDmc = removeBPsEntry.getKey();
-	            			final List<PendingEventInfo> removeBpList = removeBPsEntry.getValue();
-	            			RequestMonitor rm = new RequestMonitor(ImmediateExecutor.getInstance(), null) {
-	            				@Override
-								protected void handleCompleted() {
-	            					for (PendingEventInfo eventInfo : removeBpList) {
-	            						if (eventInfo.fRequestMonitor != null) {
-	            							eventInfo.fRequestMonitor.done();
-	            						}
-	            					}
-	            				};
-	            			};
-		            		doBreakpointsRemoved(removeBpList.toArray(new IBreakpoint[removeBpList.size()]), bpsTargetDmc, rm);	            			            			
-	            		}
-	            	} 
-	                return Status.OK_STATUS;
-	            };
-			}.schedule();
+		    	// 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;
+				}
+	    	}
 		}
 	}
 	
@@ -1302,6 +1070,11 @@
                 if (fAttributeTranslator2 != null) {
                 	fAttributeTranslator2.updateBreakpointsStatus(eventBPs, eventType);
                 }
+                else
+                	for (IBreakpoint bp : eventBPs.keySet()) {
+                		fAttributeTranslator.updateBreakpointStatus(bp);
+                	}
+                	
 
                 return Status.OK_STATUS;
             };
--- a/cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslatorExtension.java	Tue Nov 17 14:33:45 2009 -0600
+++ b/cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslatorExtension.java	Mon Nov 23 00:59:16 2009 -0600
@@ -7,6 +7,7 @@
  * 
  * 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;
 
@@ -14,7 +15,6 @@
 import java.util.Map;
 
 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
-import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
 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;
@@ -22,59 +22,93 @@
 import org.eclipse.debug.core.model.IBreakpoint;
 
 /**
- * Breakpoint attribute translator interface
+ * Enhanced breakpoint attribute translator interface
  * 
  * @since 2.1
  */
 
-@ThreadSafeAndProhibitedFromDsfExecutor("")
 public interface IBreakpointAttributeTranslatorExtension extends IBreakpointAttributeTranslator {
 	/**
-	 * Convert all attributes of the given platform breakpoint (BP) to
-	 * attributes of potential target breakpoints. Two tasks are involved:<br>
-	 * 1. Convert the attributes to debugger specific ones, if needed. For
-	 * instance, GDB implementation has its own breakpoint attribute keys. <br>
-	 * 2. Resolve the breakpoint. 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 return an
-	 * attribute map for each of the target BP.<br>
+	 * 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 must be called in DSF execution thread.
+	 * 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.
+	 *            the platform BP. Cannot be null.
 	 * @param breakpoint
 	 *            - platform breakpoint.
-	 * @param bpManagerEnabled
-	 *            - flag from platform breakpoint manager indicating that all
-	 *            breakpoints are enabled.
+	 * @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 getTargetBreakpointAttributes(IBreakpointsTargetDMContext context, IBreakpoint breakpoint, 
-    		boolean bpManagerEnabled, DataRequestMonitor<List<Map<String, Object>>> drm);
+    public void resolveBreakpoint(IBreakpointsTargetDMContext context, IBreakpoint breakpoint, 
+    		Map<String, Object> bpAttributes, DataRequestMonitor<List<Map<String, Object>>> drm);
 
-    /**
-     * Convert platform breakpoint attributes to target-recognizable attributes. 
-     * This method does not perform task #2 done by {@link this#getTargetBreakpointAttributes(List, IBreakpoint, boolean)}.
-     * 
-     * @param platformBPAttrDelta
-     * @return
-     */
-    public Map<String, Object> convertAttributeDelta(Map<String, Object> platformBPAttrDelta);
+	/**
+	 * 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.
-     *  
+     * 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