cdt/cdt_6_0_x/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java
changeset 117 09f3d307f081
parent 112 6b1088abccf8
child 118 f0e9dc42b68e
--- 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;
             };