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
equal deleted inserted replaced
116:05ea843f7d56 117:09f3d307f081
     5  * which accompanies this distribution, and is available at
     5  * which accompanies this distribution, and is available at
     6  * http://www.eclipse.org/legal/epl-v10.html
     6  * http://www.eclipse.org/legal/epl-v10.html
     7  *
     7  *
     8  * Contributors:
     8  * Contributors:
     9  *     Wind River - Initial API and implementation
     9  *     Wind River - Initial API and implementation
    10  *     Ericsson   - Low-level breakpoints integration  
    10  *     Ericsson   - Low-level breakpoints integration
       
    11  *     Nokia - refactored to work for both GDB and EDC.  Nov. 2009.
    11  *******************************************************************************/
    12  *******************************************************************************/
    12 
    13 
    13 package org.eclipse.cdt.dsf.debug.service;
    14 package org.eclipse.cdt.dsf.debug.service;
    14 
    15 
    15 import java.util.ArrayList;
    16 import java.util.ArrayList;
    16 import java.util.Collections;
    17 import java.util.Collection;
    17 import java.util.HashMap;
    18 import java.util.HashMap;
    18 import java.util.HashSet;
    19 import java.util.HashSet;
    19 import java.util.Hashtable;
    20 import java.util.Hashtable;
    20 import java.util.LinkedList;
    21 import java.util.LinkedList;
    21 import java.util.List;
    22 import java.util.List;
    25 
    26 
    26 import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
    27 import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
    27 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
    28 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
    28 import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
    29 import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
    29 import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
    30 import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
    30 import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
       
    31 import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
    31 import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
    32 import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
    32 import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
    33 import org.eclipse.cdt.dsf.datamodel.IDMContext;
    33 import org.eclipse.cdt.dsf.datamodel.IDMContext;
    34 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
    34 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
    35 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
    35 import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
    48 import org.eclipse.debug.core.IBreakpointsListener;
    48 import org.eclipse.debug.core.IBreakpointsListener;
    49 import org.eclipse.debug.core.model.IBreakpoint;
    49 import org.eclipse.debug.core.model.IBreakpoint;
    50 import org.osgi.framework.BundleContext;
    50 import org.osgi.framework.BundleContext;
    51 
    51 
    52 /**
    52 /**
    53  * 
    53  * see these bugs for design of this service.<br>
       
    54  * - https://bugs.eclipse.org/bugs/show_bug.cgi?id=218557
       
    55  * - https://bugs.eclipse.org/bugs/show_bug.cgi?id=292468
    54  */
    56  */
    55 public class BreakpointsMediator extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointsListener
    57 public class BreakpointsMediator extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointsListener
    56 {
    58 {
    57 	public enum BreakpointEventType {ADDED, REMOVED, MODIFIED}; 	
    59 	public enum BreakpointEventType {ADDED, REMOVED, MODIFIED}; 	
    58 	
    60 	
    70     private IBreakpointAttributeTranslatorExtension fAttributeTranslator2;
    72     private IBreakpointAttributeTranslatorExtension fAttributeTranslator2;
    71 
    73 
    72     /**
    74     /**
    73      * DSF Debug service for creating breakpoints.
    75      * DSF Debug service for creating breakpoints.
    74      */
    76      */
    75     IBreakpoints fBreakpoints;
    77     IBreakpoints fBreakpointsService;
    76     
    78     
    77     /**
    79     /**
    78      * Platform breakpoint manager
    80      * Platform breakpoint manager
    79      */
    81      */
    80     IBreakpointManager fBreakpointManager;
    82     IBreakpointManager fBreakpointManager;
   106     }
   108     }
   107     
   109     
   108     private static class TargetBP implements ITargetBreakpointInfo {
   110     private static class TargetBP implements ITargetBreakpointInfo {
   109     	
   111     	
   110     	private Map<String, Object> fAttributes;
   112     	private Map<String, Object> fAttributes;
   111     	private Map<String, Object> fAttributesDelta; // not really useful ?
       
   112     	private IBreakpointDMContext fTargetBPContext;
   113     	private IBreakpointDMContext fTargetBPContext;
   113     	private IStatus fStatus;
   114     	private IStatus fStatus;
   114     	
   115     	
   115     	public TargetBP(Map<String, Object> attrs) {
   116     	public TargetBP(Map<String, Object> attrs) {
   116     		fAttributes = attrs;
   117     		fAttributes = attrs;
   135 		public void setStatus(IStatus status) {
   136 		public void setStatus(IStatus status) {
   136 			this.fStatus = status;
   137 			this.fStatus = status;
   137 		}
   138 		}
   138     }
   139     }
   139     
   140     
   140     ///////////////////////////////////////////////////////////////////////////
   141 	private class PlatformBreakpointInfo {
       
   142 		IBreakpoint 		breakpoint;
       
   143 		boolean 			enabled;
       
   144 		// All attributes available from UI, including standard and extended ones.
       
   145 		Map<String, Object>	attributes;
       
   146 		
       
   147 		public PlatformBreakpointInfo(IBreakpoint bp, boolean enabled, Map<String, Object> attributes) {
       
   148 			super();
       
   149 			breakpoint = bp;
       
   150 			this.enabled = enabled;
       
   151 			this.attributes = attributes;
       
   152 		}
       
   153 	}
       
   154 
       
   155 	///////////////////////////////////////////////////////////////////////////
   141     // Breakpoints tracking
   156     // Breakpoints tracking
   142     ///////////////////////////////////////////////////////////////////////////
   157     ///////////////////////////////////////////////////////////////////////////
   143 
   158 
   144     /**
   159     /**
   145      * Holds the set of platform breakpoints with their breakpoint information 
   160      * Holds the set of platform breakpoints with their breakpoint information 
   151      * - Diminished on breakpointRemoved()
   166      * - Diminished on breakpointRemoved()
   152      */
   167      */
   153 	private Map<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>> fPlatformBPs = 
   168 	private Map<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>> fPlatformBPs = 
   154 		new HashMap<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>>();
   169 		new HashMap<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>>();
   155 
   170 
       
   171 	/**
       
   172 	 * Holds platform breakpoints with all their attributes (standard ones and
       
   173 	 * extended ones) from UI. This will be used to check what attributes have
       
   174 	 * changed for a breakpoint when the breakpoint is changed. The map is <br>
       
   175 	 * 1. augmented in doBreakpointsAdded(); <br>
       
   176 	 * 2. updated in breakpointsChanged(); <br>
       
   177 	 * 3. diminished in breakpointsRemoved();
       
   178 	 */
       
   179 	private Map<IBreakpoint, Map<String, Object>> fBreakpointAttributes = 
       
   180 		new HashMap<IBreakpoint, Map<String, Object>>();
       
   181 	
       
   182 	private static class PendingEventInfo {
       
   183 		PendingEventInfo(BreakpointEventType eventType, PlatformBreakpointInfo bpInfo,
       
   184 				Collection<IBreakpointsTargetDMContext> bpsTargetDmc, RequestMonitor rm) {
       
   185 			fEventType = eventType;
       
   186 			fBPInfo = bpInfo;
       
   187 			fBPTargetContexts = bpsTargetDmc;
       
   188 			fRequestMonitor = rm;
       
   189 			fAttributeDelta = null;
       
   190 		}
       
   191 		
       
   192 		public PendingEventInfo(BreakpointEventType eventType, Collection<IBreakpointsTargetDMContext> updateContexts,
       
   193 				Map<String, Object> attrDelta) {
       
   194 			fEventType = eventType;
       
   195 			fBPTargetContexts = updateContexts;
       
   196 			fAttributeDelta = attrDelta;
       
   197 			fRequestMonitor = null;
       
   198 			fBPInfo = null;
       
   199 		}
       
   200 
       
   201 		PlatformBreakpointInfo fBPInfo;
       
   202 		RequestMonitor fRequestMonitor;
       
   203 		BreakpointEventType fEventType;
       
   204 		Collection<IBreakpointsTargetDMContext> fBPTargetContexts;
       
   205 		Map<String, Object>	fAttributeDelta;	// for change event only
       
   206 	}
       
   207 	
   156     /**
   208     /**
   157      * Due to the very asynchronous nature of DSF, a new breakpoint request can
   209      * Due to the very asynchronous nature of DSF, a new breakpoint request can
   158      * pop up at any time before an ongoing one is completed. The following set
   210      * pop up at any time before an ongoing one is completed. The following set
   159      * is used to store requests until the ongoing operation completes.
   211      * is used to store requests until the ongoing operation completes.
   160      */
   212      */
   161 	private Set<IBreakpoint> fRunningEvents    = new HashSet<IBreakpoint>();
   213 	private Set<IBreakpoint> fRunningEvents    = new HashSet<IBreakpoint>();
   162 
   214 
   163 	private static class PendingEventInfo {
       
   164 		PendingEventInfo(BreakpointEventType eventType, IBreakpointsTargetDMContext bpsTargetDmc, RequestMonitor rm) {
       
   165 			fEventType = eventType;
       
   166 			fBPsTargetDmc = bpsTargetDmc;
       
   167 			fRequestMonitor = rm;
       
   168 		}
       
   169 		
       
   170 		RequestMonitor fRequestMonitor;
       
   171 		BreakpointEventType fEventType;
       
   172 		IBreakpointsTargetDMContext fBPsTargetDmc;
       
   173 	}
       
   174 	
       
   175 	/**
       
   176 	 * @see fPendingRequests
       
   177 	 */
       
   178 	private Map<IBreakpoint, LinkedList<PendingEventInfo>> fPendingEvents = 
   215 	private Map<IBreakpoint, LinkedList<PendingEventInfo>> fPendingEvents = 
   179 		Collections.synchronizedMap(new HashMap<IBreakpoint, LinkedList<PendingEventInfo>>());
   216 			new HashMap<IBreakpoint, LinkedList<PendingEventInfo>>();
   180 	
   217 	
   181     ///////////////////////////////////////////////////////////////////////////
   218     ///////////////////////////////////////////////////////////////////////////
   182     // AbstractDsfService    
   219     // AbstractDsfService    
   183     ///////////////////////////////////////////////////////////////////////////
   220     ///////////////////////////////////////////////////////////////////////////
   184 
   221 
   217      * @param requestMonitor
   254      * @param requestMonitor
   218      */
   255      */
   219     private void doInitialize(RequestMonitor rm) {
   256     private void doInitialize(RequestMonitor rm) {
   220     	
   257     	
   221     	// Get the services references
   258     	// Get the services references
   222         fBreakpoints  = getServicesTracker().getService(IBreakpoints.class);
   259         fBreakpointsService  = getServicesTracker().getService(IBreakpoints.class);
   223         fBreakpointManager = DebugPlugin.getDefault().getBreakpointManager();
   260         fBreakpointManager = DebugPlugin.getDefault().getBreakpointManager();
   224         fAttributeTranslator.initialize(this);
   261         fAttributeTranslator.initialize(this);
   225 
   262 
   226         // Register to the useful events
   263         // Register to the useful events
   227         fBreakpointManager.addBreakpointListener(this);
   264         fBreakpointManager.addBreakpointListener(this);
   326         // - Remove the target breakpoints for the given execution context
   363         // - Remove the target breakpoints for the given execution context
   327         // - Update the maps
   364         // - Update the maps
   328 
   365 
   329     	// Remove the breakpoints for given DMC from the internal maps.
   366     	// Remove the breakpoints for given DMC from the internal maps.
   330         Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
   367         Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
   331         if (platformBPs == null) {
   368         if (platformBPs == null || platformBPs.size() == 0) {
   332             rm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INTERNAL_ERROR, "Breakpoints not installed for given context", null)); //$NON-NLS-1$
   369             rm.setStatus(new Status(IStatus.INFO /* NOT error */, DsfPlugin.PLUGIN_ID, INTERNAL_ERROR, "Breakpoints not installed for given context", null)); //$NON-NLS-1$
   333             rm.done();
   370             rm.done();
   334             return;
   371             return;
   335         }
   372         }
   336 
   373         
       
   374         // Just remove the IBreakpoints installed for the "dmc".
       
   375         final IBreakpoint[] bps = platformBPs.keySet().toArray(new IBreakpoint[platformBPs.size()]);
       
   376         
   337 		new Job("Uninstall target breakpoints list.") { //$NON-NLS-1$
   377 		new Job("Uninstall target breakpoints list.") { //$NON-NLS-1$
   338             { setSystem(true); }
   378             { setSystem(true); }
   339 
   379 
   340 			// Get the stored breakpoints from the platform BreakpointManager
   380 			// Get the stored breakpoints from the platform BreakpointManager
   341 			// and install them on the target
   381 			// and install them on the target
   342         	@Override
   382         	@Override
   343             protected IStatus run(IProgressMonitor monitor) {
   383             protected IStatus run(IProgressMonitor monitor) {
   344         		doBreakpointsRemoved(DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(), dmc, rm);
   384         		doBreakpointsRemoved(bps, dmc, rm);
   345                 return Status.OK_STATUS;
   385                 return Status.OK_STATUS;
   346             }
   386             }
   347         }.schedule();    
   387         }.schedule();    
   348     }
   388     }
   349     
   389     
   354      * @param dmc - context
   394      * @param dmc - context
   355      * @param platformBp - platform breakpoint
   395      * @param platformBp - platform breakpoint
   356      * @return array of target breakpoints. 
   396      * @return array of target breakpoints. 
   357      */
   397      */
   358     public ITargetBreakpointInfo[] getTargetBreakpoints(IBreakpointsTargetDMContext dmc, IBreakpoint platformBp) {
   398     public ITargetBreakpointInfo[] getTargetBreakpoints(IBreakpointsTargetDMContext dmc, IBreakpoint platformBp) {
       
   399     	assert getExecutor().isInExecutorThread();
       
   400     	
   359         Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
   401         Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
   360 
   402 
   361         if (platformBPs != null)
   403         if (platformBPs != null)
   362         {
   404         {
   363         	List<TargetBP> bpInfo = platformBPs.get(platformBp);
   405         	List<TargetBP> bpInfo = platformBPs.get(platformBp);
   374      * @param dmc - context of the target breakpoint, can be null.
   416      * @param dmc - context of the target breakpoint, can be null.
   375      * @param bp - target breakpoint
   417      * @param bp - target breakpoint
   376      * @return platform breakpoint. null if not found. 
   418      * @return platform breakpoint. null if not found. 
   377      */
   419      */
   378     public IBreakpoint getPlatformBreakpoint(IBreakpointsTargetDMContext dmc, IBreakpointDMContext bp) {
   420     public IBreakpoint getPlatformBreakpoint(IBreakpointsTargetDMContext dmc, IBreakpointDMContext bp) {
       
   421     	assert getExecutor().isInExecutorThread();
       
   422 
   379     	for (IBreakpointsTargetDMContext bpContext : fPlatformBPs.keySet()) {
   423     	for (IBreakpointsTargetDMContext bpContext : fPlatformBPs.keySet()) {
   380     		if (dmc != null && !dmc.equals(bpContext))
   424     		if (dmc != null && !dmc.equals(bpContext))
   381     			continue;
   425     			continue;
   382     		
   426     		
   383 	        Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(bpContext);
   427 	        Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(bpContext);
   446 		installRM.setDoneCount(attrsList.size());
   490 		installRM.setDoneCount(attrsList.size());
   447 
   491 
   448 		// Install the back-end breakpoint(s)
   492 		// Install the back-end breakpoint(s)
   449 		for (int _i = 0; _i < attrsList.size(); _i++) {
   493 		for (int _i = 0; _i < attrsList.size(); _i++) {
   450 			final int i = _i;
   494 			final int i = _i;
   451             fBreakpoints.insertBreakpoint(
   495             fBreakpointsService.insertBreakpoint(
   452                 dmc, attrsList.get(i), 
   496                 dmc, attrsList.get(i), 
   453 				new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
   497 				new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
   454 				@Override
   498 				@Override
   455                 protected void handleCompleted() {
   499                 protected void handleCompleted() {
   456 					TargetBP targetBP = targetBPsAttempted.get(i);
   500 					TargetBP targetBP = targetBPsAttempted.get(i);
   506 
   550 
   507         int count = 0;
   551         int count = 0;
   508         for (int i = 0; i < bpList.size(); i++) {
   552         for (int i = 0; i < bpList.size(); i++) {
   509         	final TargetBP bp = bpList.get(i);
   553         	final TargetBP bp = bpList.get(i);
   510         	if (bp.getTargetBreakpoint() != null) {
   554         	if (bp.getTargetBreakpoint() != null) {
   511         		fBreakpoints.removeBreakpoint(
   555         		fBreakpointsService.removeBreakpoint(
   512         				bp.getTargetBreakpoint(), 
   556         				bp.getTargetBreakpoint(), 
   513         				new RequestMonitor(getExecutor(), countingRm) {
   557         				new RequestMonitor(getExecutor(), countingRm) {
   514         					@Override
   558         					@Override
   515         					protected void handleCompleted() {
   559         					protected void handleCompleted() {
   516         				        bp.setStatus(getStatus());
   560         				        bp.setStatus(getStatus());
   517         				        bp.fAttributesDelta = bp.fAttributes;
       
   518         				        if (isSuccess()) {
   561         				        if (isSuccess()) {
   519             						bp.setTargetBreakpoint(null);
   562             						bp.setTargetBreakpoint(null);
   520         				        	bp.fAttributes = null;
       
   521         				        } 
   563         				        } 
   522         				        countingRm.done();
   564         				        countingRm.done();
   523         					}
   565         					}
   524         				});
   566         				});
   525         		count++;
   567         		count++;
   528         	}
   570         	}
   529         }
   571         }
   530         countingRm.setDoneCount(count);
   572         countingRm.setDoneCount(count);
   531     }
   573     }
   532 	
   574 	
   533 	/**
       
   534 	 * Modify an individual breakpoint
       
   535 	 * 
       
   536 	 * @param context
       
   537 	 * @param breakpoint
       
   538 	 * @param attributes
       
   539 	 * @param drm
       
   540 	 * @throws CoreException
       
   541 	 */
       
   542 	private void modifyBreakpoint(final IBreakpointsTargetDMContext context, final IBreakpoint breakpoint,
       
   543 			final List<Map<String, Object>> newAttrsList, final DataRequestMonitor<List<TargetBP>> drm)
       
   544 	{
       
   545 	    // This method uses several lists to track the changed breakpoints:
       
   546 	    // commonAttrsList - attributes which have not changed 
       
   547 	    // oldAttrsList - attributes for the breakpoint before the change
       
   548 	    // newAttrsList - attributes for the breakpoint after the change
       
   549 	    // oldBpContexts - target-side breakpoints from before the change
       
   550 	    // newBpContexts - target-side breakpoints after the change
       
   551 	    // attrDeltasList - changes in the attributes for each attribute map in 
       
   552 	    //     oldAttrsList and newAttrsList
       
   553 	    
       
   554     	// Get the maps
       
   555         final Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(context);
       
   556         if (platformBPs == null) {
       
   557             drm.setStatus(new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, INVALID_HANDLE, "Invalid context", null)); //$NON-NLS-1$
       
   558             drm.done();
       
   559             return;
       
   560         }
       
   561 
       
   562         final List<TargetBP> oldBpList = platformBPs.get(breakpoint);
       
   563         
       
   564         final List<TargetBP> bpList = new ArrayList<TargetBP>(newAttrsList.size());
       
   565         
       
   566         if (oldBpList == null || oldBpList.size() == 0) { // not targetBP installed
       
   567             drm.setData(bpList);
       
   568         	drm.done();
       
   569         	return;
       
   570         }
       
   571         
       
   572         for (int i = 0; i < newAttrsList.size(); i++) {
       
   573         	bpList.add(new TargetBP(newAttrsList.get(i)));
       
   574         }
       
   575         
       
   576         // Create a list of attribute changes.  The length of this list will
       
   577         // always be max(oldAttrList.size(), newAttrsList.size()), padded with
       
   578         // null's if oldAttrsList was longer.
       
   579         calcBPsAttrs(oldBpList, bpList);
       
   580         
       
   581         // Create the request monitor that will be called when all
       
   582         // modifying/inserting/removing is complete.
       
   583         final CountingRequestMonitor countingRM = new CountingRequestMonitor(getExecutor(), drm) {
       
   584             @Override
       
   585             protected void handleCompleted() {
       
   586                 // Save the new list of target breakpoints 
       
   587             	platformBPs.put(breakpoint, bpList);
       
   588                 drm.setData(bpList);
       
   589                 drm.done();
       
   590             }
       
   591         };
       
   592         
       
   593         // Set the count, if could be zero if no breakpoints have actually changed.
       
   594         int coutingRmCount = 0;
       
   595         
       
   596         // Process the changed breakpoints.
       
   597         for (int _i = 0; _i < bpList.size(); _i++) {
       
   598         	final int i = _i;
       
   599         	final TargetBP bp = bpList.get(i);
       
   600             if (bp.fAttributes == null) {
       
   601                 // The list of new attribute maps was shorter than the old.
       
   602                 // Remove the corresponding target-side bp.  
       
   603             	// Note the target BP context may be null if the target
       
   604             	// BP failed to insert in the first place.
       
   605             	if (bp.getTargetBreakpoint() != null) {
       
   606             		fBreakpoints.removeBreakpoint(
       
   607             				bp.getTargetBreakpoint(), 
       
   608             				new RequestMonitor(getExecutor(), countingRM) {
       
   609             					@Override
       
   610             					protected void handleCompleted() {
       
   611             						bp.fStatus = getStatus();
       
   612             						countingRM.done();
       
   613             					}
       
   614             				});
       
   615                     coutingRmCount++;
       
   616             	}
       
   617             } else if ( bp.getTargetBreakpoint() == null) {
       
   618                 // The list of new attribute maps was longer, just insert
       
   619                 // the new breakpoint
       
   620                 final Map<String, Object> attrs = newAttrsList.get(i);
       
   621                 fBreakpoints.insertBreakpoint(
       
   622                     context, attrs, 
       
   623                     new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), countingRM) {
       
   624                         @Override
       
   625                         protected void handleCompleted() {
       
   626                         	if (isSuccess()) {
       
   627                         		bp.fTargetBPContext = getData();
       
   628                         	}
       
   629                         	bp.fStatus = getStatus();
       
   630                             countingRM.done();
       
   631                         }
       
   632                     });
       
   633                 coutingRmCount++;
       
   634             } else if (bp.fAttributesDelta.size() == 0) { 
       
   635             	// Breakpoint attributes have not changed, only copy over the old status.
       
   636             	bp.fStatus = oldBpList.get(i).fStatus;
       
   637             } else if ( !fAttributeTranslator.canUpdateAttributes(bp.getTargetBreakpoint(), bp.fAttributesDelta) ) {
       
   638                 // The attribute translator tells us that the debugger cannot modify the 
       
   639                 // breakpoint to change the given attributes.  Remove the breakpoint
       
   640                 // and insert a new one.
       
   641                 RequestMonitor removeRm = new RequestMonitor(getExecutor(), countingRM) {
       
   642                     @Override
       
   643                     protected void handleCompleted() {
       
   644                     	if (isSuccess()) {
       
   645                     		bp.fTargetBPContext = null;
       
   646 	                        fBreakpoints.insertBreakpoint(
       
   647 	                            context, newAttrsList.get(i),
       
   648 	                            new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), countingRM) {
       
   649 	                                @Override
       
   650 	                                protected void handleCompleted() {
       
   651 	                                    if (isSuccess()) {
       
   652 	                                        bp.fTargetBPContext = getData();
       
   653 	                                    } 
       
   654 	                                    bp.fStatus = getStatus();
       
   655 	                                    countingRM.done();
       
   656 	                                }
       
   657 	                            });
       
   658                     	} else {
       
   659                     		// Failed to remove old breakpoint, do not proceed to insert a new one
       
   660                     		// just save the error from target with the old context.
       
   661                             bp.fStatus = getStatus();
       
   662                             countingRM.done();
       
   663                     	}
       
   664                     }
       
   665                 };
       
   666 
       
   667             	fBreakpoints.removeBreakpoint(bp.getTargetBreakpoint(), removeRm);
       
   668                 coutingRmCount++;
       
   669             } else {
       
   670                 // The back end can modify the breakpoint.  Update the breakpoint with the 
       
   671                 // new attributes.
       
   672                 fBreakpoints.updateBreakpoint(
       
   673                     bp.getTargetBreakpoint(), bp.fAttributes, 
       
   674                     new RequestMonitor(getExecutor(), countingRM) {
       
   675                         @Override
       
   676                         protected void handleCompleted() {
       
   677                             bp.fStatus = getStatus();
       
   678                             countingRM.done();
       
   679                         }
       
   680                     });
       
   681                 coutingRmCount++;
       
   682             }
       
   683         }
       
   684         countingRM.setDoneCount(coutingRmCount);
       
   685 	} 
       
   686 	
       
   687 	/**
       
   688 	 * Determine the set of modified attributes
       
   689 	 * 
       
   690 	 * @param oldAttributes
       
   691 	 * @param newAttributes
       
   692 	 * @return
       
   693 	 */
       
   694 	private void calcBPsAttrs(List<TargetBP> oldBpList, List<TargetBP> bpList) {
       
   695 	    // Go through the bp attributes common to the old and the new lists and calculate
       
   696 	    // their deltas.
       
   697 		int i = 0;
       
   698 	    for (i = 0; i < oldBpList.size() && i < bpList.size(); i++) {
       
   699     		TargetBP newBp = bpList.get(i);
       
   700     		TargetBP oldBp = oldBpList.get(i);
       
   701     		newBp.fTargetBPContext = oldBp.getTargetBreakpoint();
       
   702 	        Map<String, Object> oldAttributes = oldBp.fAttributes; 
       
   703 	        Map<String, Object> newAttributes = newBp.fAttributes;
       
   704     	    
       
   705 	        if (oldAttributes == null) {
       
   706 	        	// Reached a point in the old BP list where breakpoints were 
       
   707 	        	// removed.  Break out of the loop.
       
   708 	        	break;
       
   709 	        }
       
   710 	        
       
   711     		bpList.get(i).fAttributesDelta = getAttributesDelta(oldAttributes, newAttributes);
       
   712 	    } 
       
   713 	    
       
   714 	    // Add all the new attributes as deltas
       
   715 	    for (; i < bpList.size(); i++) {
       
   716 	    	TargetBP newBP = bpList.get(i); 
       
   717 	        newBP.fAttributesDelta =  newBP.fAttributes;
       
   718 	    }
       
   719 	    
       
   720 	    // For breakpoints that were removed create TargetBP entry with a 
       
   721 	    // null set of attributes
       
   722 	    for (; i < oldBpList.size(); i++) {
       
   723 	    	TargetBP oldBp = oldBpList.get(i);
       
   724 	    	if (oldBp.fAttributes == null) {
       
   725 	    		// Guard against old removed breakpoints
       
   726 	    		break;
       
   727 	    	}
       
   728 	    	TargetBP newBp = new TargetBP(null);
       
   729 	    	newBp.fTargetBPContext = oldBp.getTargetBreakpoint();
       
   730 	    	newBp.fAttributesDelta = oldBpList.get(i).fAttributes;
       
   731 	    	bpList.add(newBp);
       
   732 	    }	    
       
   733 	}
       
   734 
       
   735     ///////////////////////////////////////////////////////////////////////////
   575     ///////////////////////////////////////////////////////////////////////////
   736     // IBreakpointManagerListener implementation
   576     // IBreakpointManagerListener implementation
   737     ///////////////////////////////////////////////////////////////////////////
   577     ///////////////////////////////////////////////////////////////////////////
   738 
   578 
   739 	public void breakpointManagerEnablementChanged(boolean enabled) {
   579 	public void breakpointManagerEnablementChanged(boolean enabled) {
   740 		Map<String, Object> platformAttrDelta = new HashMap<String, Object>(1);
   580 		// do nothing. breakpointsChanged() will be called to handle the change.
   741 		platformAttrDelta.put(IBreakpoint.ENABLED, enabled);
       
   742 		
       
   743 		Map<IBreakpoint, Map<String, Object>> bp2DeltaMap = new HashMap<IBreakpoint, Map<String, Object>>(); 
       
   744 		for (IBreakpoint bp : fBreakpointManager.getBreakpoints()) {
       
   745 			if (! fAttributeTranslator.supportsBreakpoint(bp))
       
   746 				continue;
       
   747 
       
   748 			bp2DeltaMap.put(bp, platformAttrDelta);
       
   749 		}
       
   750 		
       
   751 		doBreakpointsChanged(bp2DeltaMap);
       
   752 	}
   581 	}
   753 
   582 
   754 	@ThreadSafe
   583 	@ThreadSafe
   755 	public void breakpointsAdded(final IBreakpoint[] bps) {
   584 	public void breakpointsAdded(final IBreakpoint[] bps) {
   756 		doBreakpointsAdded(bps, null, null);
   585 		doBreakpointsAdded(bps, null, null);
   757 	}
   586 	}
   758 	
   587 	
   759 	@SuppressWarnings("unchecked")
   588 	protected void doBreakpointsAdded(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
   760 	private void doBreakpointsAdded(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
   589 		// Collect attributes (which will access system resource)
   761 		final List<IBreakpoint> bpCandidates = new ArrayList<IBreakpoint>(bps.length);
   590 		// in non DSF dispatch thread.
   762 		
   591 		//
   763 		for (int i = 0; i < bps.length; i++) {
   592 		final PlatformBreakpointInfo[] bpsInfo = collectBreakpointsInfo(bps);
   764 			IBreakpoint bp = bps[i];
       
   765 			
       
   766 			if (fAttributeTranslator.supportsBreakpoint(bp)) {
       
   767 				try {
       
   768 					if (fAttributeTranslator2 != null) {
       
   769 						if (bp.getMarker() == null)
       
   770 							continue;
       
   771 						
       
   772 						// if the breakpoint is not enabled, ask translator2 if it can set (and manage)
       
   773 						// disabled breakpoint itself. If not, just bail out.
       
   774 						//
       
   775 						Map<String, Object> platformAttrs = bp.getMarker().getAttributes();
       
   776 						
       
   777 						if (! (Boolean)platformAttrs.get(IBreakpoint.ENABLED) || ! fBreakpointManager.isEnabled()) {
       
   778 							Map<String, Object> platformAttr = new HashMap<String, Object>(1);
       
   779 							platformAttr.put(IBreakpoint.ENABLED, Boolean.FALSE);
       
   780 							Map<String, Object> targetAttr = fAttributeTranslator2.convertAttributeDelta(platformAttr);
       
   781 							if (! fAttributeTranslator2.canUpdateAttributes(null, targetAttr)) {
       
   782 								// bail out.
       
   783 								continue;
       
   784 							}
       
   785 						}
       
   786 					}
       
   787 					
       
   788 					bpCandidates.add(bp);
       
   789 				} catch (CoreException e) {
       
   790 					DsfPlugin.getDefault().getLog().log(e.getStatus());
       
   791 				}
       
   792 			}
       
   793 		}
       
   794 		
   593 		
   795 		// Nothing to do
   594 		// Nothing to do
   796 		if (bpCandidates.isEmpty()) {
   595 		if (bpsInfo.length == 0) {
   797 			if (rm != null) {
   596 			if (rm != null) {
   798 				rm.done();
   597 				rm.done();
   799 			}
   598 			}
   800 			return;
   599 			return;
   801 		}
   600 		}
   802 				
   601 
   803 		try {
   602 		try {
   804             getExecutor().execute(new DsfRunnable() {
   603             getExecutor().execute(new DsfRunnable() {
   805 				public void run() {
   604 				public void run() {
   806 					final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
   605 					Collection<IBreakpointsTargetDMContext> dmcs = new ArrayList<IBreakpointsTargetDMContext>();
   807 						new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpCandidates.size(), 1);
   606 					if (bpsTargetDmc == null)
   808 					
   607 						dmcs.addAll(fPlatformBPs.keySet());
   809 	                CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
   608 					else
   810 		                    @Override
   609 						dmcs.add(bpsTargetDmc);
   811 		                    protected void handleCompleted() {
   610 
   812 		                    	processPendingRequests();
   611 					doBreakpointsAddedInExecutor(bpsInfo, dmcs, rm);
   813 		                    	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.ADDED);
       
   814 		                        super.handleCompleted();
       
   815 		                    }
       
   816 		                };	            	
       
   817 	                int processPendingCountingRmCount = 0;
       
   818 	            	
       
   819 	            	for (final IBreakpoint breakpoint : bpCandidates) {
       
   820 	            		final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs = 
       
   821 	            			new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
       
   822 	            		eventBPs.put(breakpoint, targetBPs);	
       
   823 	            			
       
   824 						if (fRunningEvents.contains(breakpoint)) {
       
   825 							PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.ADDED, bpsTargetDmc, processPendingCountingRm);
       
   826 							processPendingCountingRmCount++;
       
   827 							updatePendingRequest(breakpoint, pendingEvent);
       
   828 							continue;
       
   829 						}
       
   830 		                // Mark the breakpoint as being updated and go
       
   831 		                fRunningEvents.add(breakpoint);
       
   832 
       
   833 	            		final CountingRequestMonitor bpTargetsCountingRm = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
       
   834 								@Override
       
   835 								protected void handleCompleted() {
       
   836 			                    	// Indicate that the running event has completed
       
   837 			                    	fRunningEvents.remove(breakpoint);
       
   838 			                    	super.handleCompleted();
       
   839 								}
       
   840 							};
       
   841 						int bpTargetsCountingRmCount = 0;
       
   842 						processPendingCountingRmCount++;
       
   843 	
       
   844 						
       
   845 						// Install the breakpoint in all the execution contexts
       
   846 						for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
       
   847 							if (bpsTargetDmc != null && !bpsTargetDmc.equals(dmc)) {
       
   848 								continue;
       
   849 							}
       
   850 							
       
   851 			                // Now ask lower level to set the bp.
       
   852 							//
       
   853 							if (fAttributeTranslator2 != null) {
       
   854 								fAttributeTranslator2.getTargetBreakpointAttributes(dmc, breakpoint, fBreakpointManager.isEnabled(),
       
   855 										new DataRequestMonitor<List<Map<String,Object>>>(getExecutor(), bpTargetsCountingRm){
       
   856 											@Override
       
   857 											protected void handleSuccess() {
       
   858 												installBreakpoint(
       
   859 											    		dmc, breakpoint, getData(), 
       
   860 											    		new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRm) {
       
   861 											    			@Override
       
   862 															protected void handleSuccess() {
       
   863 											    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
       
   864 											    				super.handleSuccess();
       
   865 											    			};
       
   866 											    		});
       
   867 											}});
       
   868 							}
       
   869 							else {	// Old way
       
   870 								List<Map<String, Object>> attrsArray;
       
   871 								try {
       
   872 									attrsArray = fAttributeTranslator.getBreakpointAttributes(breakpoint, fBreakpointManager.isEnabled());
       
   873 								} catch (CoreException e) {
       
   874 									attrsArray = new ArrayList<Map<String, Object>>();
       
   875 									DsfPlugin.getDefault().getLog().log(e.getStatus());
       
   876 								}
       
   877 				        		
       
   878 								installBreakpoint(
       
   879 						    		dmc, breakpoint, attrsArray, 
       
   880 						    		new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRm) {
       
   881 						    			@Override
       
   882 										protected void handleSuccess() {
       
   883 						    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
       
   884 						    				super.handleSuccess();
       
   885 						    			};
       
   886 						    		});
       
   887 							}
       
   888 							
       
   889 							bpTargetsCountingRmCount++;
       
   890 						}
       
   891 						bpTargetsCountingRm.setDoneCount(bpTargetsCountingRmCount);
       
   892 	            	}
       
   893 	            	processPendingCountingRm.setDoneCount(processPendingCountingRmCount);	            	
       
   894 				}
   612 				}
   895 			});
   613 			});
   896 		} catch (RejectedExecutionException e) {
   614 		} catch (RejectedExecutionException e) {
   897 			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$
   615 			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$
   898 			if (rm != null) {
   616 			if (rm != null) {
   902 				DsfPlugin.getDefault().getLog().log(status); 
   620 				DsfPlugin.getDefault().getLog().log(status); 
   903 			}
   621 			}
   904 		}
   622 		}
   905 	}
   623 	}
   906 	
   624 	
   907     ///////////////////////////////////////////////////////////////////////////
   625 	/**
   908     // IBreakpointListener implementation
   626 	 * Collect breakpoint info. This method must not be called in DSF dispatch thread.
   909     ///////////////////////////////////////////////////////////////////////////
   627 	 * @param bps
   910 
   628 	 * @return
   911 	@SuppressWarnings("unchecked")
   629 	 */
   912 	public void breakpointsChanged(IBreakpoint[] bps, IMarkerDelta[] deltas) {
   630     private PlatformBreakpointInfo[] collectBreakpointsInfo(IBreakpoint[] bps) {
   913 		Map<IBreakpoint, Map<String, Object>> bp2DeltaMap = new HashMap<IBreakpoint, Map<String, Object>>(); 
   631 		List<PlatformBreakpointInfo> bpsInfo = new ArrayList<PlatformBreakpointInfo>(bps.length);
   914 		for (int i = 0; i < bps.length; i++) {
   632 		
   915 			IBreakpoint bp = bps[i];
   633 		for (IBreakpoint bp : bps) {
   916 			
       
   917 			if (deltas[i] == null)
       
   918 				continue;
       
   919 			
       
   920 			if (bp.getMarker() == null)
   634 			if (bp.getMarker() == null)
   921 				continue;
   635 				continue;
   922 			
   636 			
   923 			if (! fAttributeTranslator.supportsBreakpoint(bp))
   637 			if (fAttributeTranslator.supportsBreakpoint(bp)) {
       
   638 				try {
       
   639 	        		Map<String, Object> attrs = fAttributeTranslator2.getAllBreakpointAttributes(bp, fBreakpointManager.isEnabled());
       
   640 	        		boolean enabled = bp.isEnabled() && fBreakpointManager.isEnabled();
       
   641 					bpsInfo.add(new PlatformBreakpointInfo(bp, enabled, attrs));
       
   642 				} catch (CoreException e) {
       
   643 					DsfPlugin.getDefault().getLog().log(e.getStatus());
       
   644 				}
       
   645 			}
       
   646 		}
       
   647 		
       
   648 		return bpsInfo.toArray(new PlatformBreakpointInfo[bpsInfo.size()]);
       
   649 	}
       
   650 
       
   651 	protected void doBreakpointsAddedInExecutor(PlatformBreakpointInfo[] bpsInfo, Collection<IBreakpointsTargetDMContext> bpTargetDMCs, RequestMonitor rm) {
       
   652 		final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
       
   653 			new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpsInfo.length, 1);
       
   654 		
       
   655         CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
       
   656                 @Override
       
   657                 protected void handleCompleted() {
       
   658                 	processPendingRequests();
       
   659                 	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.ADDED);
       
   660                     super.handleCompleted();
       
   661                 }
       
   662             };	            	
       
   663         int processPendingCountingRmCount = 0;
       
   664     	
       
   665     	for (final PlatformBreakpointInfo bpinfo : bpsInfo) {
       
   666     		final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs = 
       
   667     			new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
       
   668     		eventBPs.put(bpinfo.breakpoint, targetBPs);	
       
   669     	
       
   670 			// Remember the new attributes of the bp in our global buffer,
       
   671 			// even if we cannot or fail to install the bp.
       
   672 			fBreakpointAttributes.put(bpinfo.breakpoint, bpinfo.attributes);
       
   673     		
       
   674 			if (fRunningEvents.contains(bpinfo.breakpoint)) {
       
   675 				PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.ADDED, bpinfo, bpTargetDMCs, processPendingCountingRm);
       
   676 				processPendingCountingRmCount++;
       
   677 				updatePendingRequest(bpinfo.breakpoint, pendingEvent);
   924 				continue;
   678 				continue;
   925 
   679 			}
   926 			try {
   680 			
   927 				Map<String, Object> oldAttrs = deltas[i].getAttributes();
   681 			processPendingCountingRmCount++;
   928 				Map<String, Object> newAttrs = bp.getMarker().getAttributes();
   682 
       
   683             // Mark the breakpoint as being updated and go
       
   684             fRunningEvents.add(bpinfo.breakpoint);
       
   685 
       
   686     		final CountingRequestMonitor bpTargetsCountingRm = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
       
   687 				@Override
       
   688 				protected void handleCompleted() {
       
   689                 	// Indicate that the running event has completed
       
   690                 	fRunningEvents.remove(bpinfo.breakpoint);
       
   691                 	super.handleCompleted();
       
   692 				}
       
   693     		};
       
   694 
       
   695 			int bpTargetsCountingRmCount = 0;
       
   696 
       
   697 			// Install the breakpoint in all the execution contexts
       
   698 			for (final IBreakpointsTargetDMContext dmc : bpTargetDMCs) {
   929 				
   699 				
   930 				Map<String, Object> platformAttrDelta = getAttributesDelta(oldAttrs, newAttrs);
   700                 // Now ask lower level to set the bp.
       
   701 				//
       
   702 				// if the breakpoint is disabled, ask back-end if it can set (and manage)
       
   703 				// disabled breakpoint. If not, just bail out.
       
   704 				//
       
   705 				if (! bpinfo.enabled) {
       
   706 					Map<String, Object> attr = new HashMap<String, Object>(1);
       
   707 					attr.put(IBreakpoint.ENABLED, Boolean.FALSE);
       
   708 					Map<String, Object> targetEnablementAttr = fAttributeTranslator2.convertAttributes(attr);
       
   709 					if (! fAttributeTranslator2.canUpdateAttributes(bpinfo.breakpoint, dmc, targetEnablementAttr)) {
       
   710 						// bail out. Continue with the next dmc & breakpoint.
       
   711 						continue;
       
   712 					}
       
   713 				}
       
   714             	
       
   715 				// Now do the real work.
       
   716 				//
       
   717 				fAttributeTranslator2.resolveBreakpoint(dmc, bpinfo.breakpoint, bpinfo.attributes,
       
   718 						new DataRequestMonitor<List<Map<String,Object>>>(getExecutor(), bpTargetsCountingRm){
       
   719 							@Override
       
   720 							protected void handleSuccess() {
       
   721 								installBreakpoint(
       
   722 							    		dmc, bpinfo.breakpoint, getData(), 
       
   723 							    		new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRm) {
       
   724 							    			@Override
       
   725 											protected void handleSuccess() {
       
   726 							    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
       
   727 							    				super.handleSuccess();
       
   728 							    			};
       
   729 							    		});
       
   730 							}});
   931 				
   731 				
   932 				if (platformAttrDelta.size() == 0) // no change. possible when user cancels breakpoint properties dialog.
   732 				bpTargetsCountingRmCount++;
   933 					continue;
       
   934 
       
   935 				bp2DeltaMap.put(bp, platformAttrDelta);
       
   936 			} catch (CoreException e) {
       
   937 				DsfPlugin.getDefault().getLog().log(e.getStatus());
       
   938 			}
   733 			}
   939 		}
   734 			
   940 		
   735 			bpTargetsCountingRm.setDoneCount(bpTargetsCountingRmCount);
   941 		doBreakpointsChanged(bp2DeltaMap);
   736     	}
   942 	}
   737     	
   943 	
   738     	processPendingCountingRm.setDoneCount(processPendingCountingRmCount);	            	
   944 	/**
   739 	}
       
   740 
       
   741 	/*
       
   742 	 * Note this method must not be called in DSF dispatch thread.
   945 	 * 
   743 	 * 
   946 	 * @param bp2DeltaMap - pairs of (breakpoint, attrDelta), where attrDelta contains changed 
   744 	 * @param bps
   947 	 * and new attributes for the breakpoint.  
   745 	 * @param deltas
   948 	 */
   746 	 */
   949 	private void doBreakpointsChanged(Map<IBreakpoint, Map<String, Object>> bp2DeltaMap) {
   747 	public void breakpointsChanged(IBreakpoint[] bps, IMarkerDelta[] deltas) {
   950 
   748 		if (fAttributeTranslator2 == null)
   951 		final Map<IBreakpoint, List<Map<String, Object>>> bpsAttrs = 
   749 			return;
   952 			new HashMap<IBreakpoint, List<Map<String, Object>>>(bp2DeltaMap.size() * 4/3);
   750 		
   953 
   751 		final PlatformBreakpointInfo[] bpsInfo = collectBreakpointsInfo(bps);
   954 		for (IBreakpoint bp : bp2DeltaMap.keySet()) {
   752 		
   955 			try {
   753 		if (bpsInfo.length == 0) 
   956 				Map<String, Object> platformAttrDelta = bp2DeltaMap.get(bp);
   754 			return; // nothing to do
   957 				
       
   958 				if (fAttributeTranslator2 != null) {
       
   959 					Map<String, Object> targetAttrDelta = fAttributeTranslator2.convertAttributeDelta(platformAttrDelta);
       
   960 		
       
   961 					if (! fAttributeTranslator2.canUpdateAttributes(null, targetAttrDelta)) {
       
   962 						// DSF client cannot handle at least one of the attribute change, just remove
       
   963 						// old target BPs and install new ones.
       
   964 						final IBreakpoint[] platformBPs = new IBreakpoint[] {bp};
       
   965 						
       
   966 						if (platformAttrDelta.containsKey(IBreakpoint.ENABLED)) {
       
   967 							if ((Boolean)platformAttrDelta.get(IBreakpoint.ENABLED))
       
   968 								// platform BP changed from disabled to enabled
       
   969 								doBreakpointsAdded(platformBPs, null, null);
       
   970 							else
       
   971 								doBreakpointsRemoved(platformBPs, null, null);
       
   972 						}
       
   973 						else {
       
   974 							// other attribute change, remove old and install new.
       
   975 							doBreakpointsRemoved(platformBPs, null, new RequestMonitor(getExecutor(), null) {
       
   976 								@Override
       
   977 								protected void handleSuccess() {
       
   978 									doBreakpointsAdded(platformBPs, null, null);
       
   979 								}});
       
   980 						}
       
   981 					}
       
   982 					else 
       
   983 						updateBreakpoint(bp, targetAttrDelta);
       
   984 				}
       
   985 				else { // old way
       
   986 					
       
   987 	                // Retrieve the breakpoint attributes
       
   988 	        		List<Map<String, Object>> attrsArray = 
       
   989 	        		    fAttributeTranslator.getBreakpointAttributes(bp, fBreakpointManager.isEnabled());
       
   990 	        		
       
   991 	        		bpsAttrs.put(bp, attrsArray);
       
   992 				}
       
   993 			} catch (CoreException e) {
       
   994 				DsfPlugin.getDefault().getLog().log(e.getStatus());
       
   995 			}
       
   996 		}
       
   997 		
       
   998 		if (bpsAttrs.isEmpty()) return; // nothing to do
       
   999 		
   755 		
  1000 		try {
   756 		try {
  1001 			// Modify the breakpoint in all the target contexts
       
  1002 	        getExecutor().execute( new DsfRunnable() { 
   757 	        getExecutor().execute( new DsfRunnable() { 
  1003 	            public void run() {
   758 	            public void run() {
  1004 					final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
   759 	            	Map<String, Object> tmp = new HashMap<String, Object>(1);
  1005 						new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpsAttrs.size(), 1);
   760 					tmp.put(IBreakpoint.ENABLED, true);
  1006 
   761 					final String targetEnablementKey = fAttributeTranslator2.convertAttributes(tmp).keySet().iterator().next();
  1007 					CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), null) {
   762 
  1008 	                    @Override
   763 					for (PlatformBreakpointInfo bpinfo : bpsInfo) {
  1009 	                    protected void handleCompleted() {
   764 						/*
  1010 	                    	processPendingRequests();
   765 						 * We cannot depend on "deltas" for attribute change.
  1011 	                    	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.MODIFIED);
   766 						 * For instance, delta can be null when extended
  1012 	                    }
   767 						 * attributes (e.g. breakpoint thread filter for GDB)
  1013 	                };	            	
   768 						 * are changed.
  1014 	                int processPendingCountingRmCount = 0;
   769 						 */
  1015 	            	
   770 						Map<String, Object> newAttrs = bpinfo.attributes;
  1016 	            	for (final IBreakpoint breakpoint : bpsAttrs.keySet()) {
   771 						Map<String, Object> oldAttrs = fBreakpointAttributes.get(bpinfo.breakpoint);
  1017 	            		final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs = 
   772 						
  1018 	            			new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
   773 						// remember the new attributes.
  1019 	            		eventBPs.put(breakpoint, targetBPs);	
   774 						fBreakpointAttributes.put(bpinfo.breakpoint, newAttrs);
  1020 
   775 						
  1021 	            		// If the breakpoint is currently being updated, queue the request and exit
   776 						final Map<String, Object> attrDelta = getAttributesDelta(oldAttrs, newAttrs);
  1022 		            	if (fRunningEvents.contains(breakpoint)) {
   777 						if (attrDelta.size() == 0) 
  1023 		            		updatePendingRequest(breakpoint, new PendingEventInfo(BreakpointEventType.MODIFIED, null, null));
       
  1024 							continue;
   778 							continue;
  1025 		            	}
   779 
  1026 		            	
   780 						final List<IBreakpointsTargetDMContext> reinstallContexts = new ArrayList<IBreakpointsTargetDMContext>();
  1027 		                // Keep track of the updates
   781 						
  1028 		                CountingRequestMonitor bpTargetsCountingRm = 
   782 						List<IBreakpointsTargetDMContext> updateContexts = new ArrayList<IBreakpointsTargetDMContext>();
  1029 		                	new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
   783 						
  1030 			                    @Override
   784 						// Now change the breakpoint for each known context.
  1031 			                    protected void handleCompleted() {
   785 						//
  1032 			                    	// Indicate that the running event has completed
   786 						for (final IBreakpointsTargetDMContext btContext : fPlatformBPs.keySet()) {
  1033 			                    	fRunningEvents.remove(breakpoint);
   787 							
  1034 			                    	super.handleCompleted();
   788 							if (! fAttributeTranslator2.canUpdateAttributes(bpinfo.breakpoint, btContext, attrDelta)) {
  1035 			                    }
   789 								// backend cannot handle at least one of the platform BP attribute change,
  1036 			                };
   790 								// we'll handle the re-installation.
  1037 			            processPendingCountingRmCount++;
   791 								reinstallContexts.add(btContext);
  1038 		                bpTargetsCountingRm.setDoneCount(fPlatformBPs.size());
   792 							}
  1039 	
   793 							else {
  1040 		                // Mark the breakpoint as being updated and go
   794 								// Backend claims it can handle the attributes change, let it do it.
  1041 		                fRunningEvents.add(breakpoint);
   795 								updateContexts.add(btContext);
  1042 		                
   796 							}
  1043 		                // Modify the breakpoint in all the execution contexts
   797 							
  1044 		                for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
   798 						}
  1045 		                    modifyBreakpoint(
   799 
  1046 		                    		dmc, breakpoint, bpsAttrs.get(breakpoint), 
   800 						final PlatformBreakpointInfo[] oneBPInfo = new PlatformBreakpointInfo[] {bpinfo};
  1047 		                    		new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRm) {
   801 						IBreakpoint[] oneBP = new IBreakpoint[] {bpinfo.breakpoint};
  1048 						    			@Override
   802 
  1049 										protected void handleSuccess() {
   803 						if (reinstallContexts.size() > 0) {
  1050 						    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
   804 							// Check if it's only enablement change (user click enable/disable 
  1051 						    				super.handleSuccess();
   805 							// button or "Skip all breakpoints" button), which is common operation.
  1052 						    			};
   806 							//
  1053 		                    		});
   807 							if (attrDelta.size() == 1 && attrDelta.containsKey(targetEnablementKey)) { // only enablement changed.	
  1054 		                }
   808 								if (bpinfo.enabled)  {
       
   809 									// change from disable to enable. Install the bp.
       
   810 									doBreakpointsAddedInExecutor(oneBPInfo, reinstallContexts, null);
       
   811 								}
       
   812 								else {
       
   813 									// change from enable to disable. Remove the bp.
       
   814 									doBreakpointsRemovedInExecutor(oneBP,  reinstallContexts, null);
       
   815 								}
       
   816 							}
       
   817 							else {
       
   818 								doBreakpointsRemovedInExecutor(oneBP, reinstallContexts, new RequestMonitor(getExecutor(), null) {
       
   819 									// What should we do if removal of some or all targetBP fails ? 
       
   820 									// Go on with the installation of new targetBPs and let clients (i.e. AttributeTranslators) 
       
   821 									// handle the errors.
       
   822 									@Override
       
   823 									protected void handleCompleted() {
       
   824 										doBreakpointsAddedInExecutor(oneBPInfo, reinstallContexts, null);
       
   825 									}});
       
   826 							}
       
   827 						}
       
   828 						
       
   829 						if (updateContexts.size() > 0)
       
   830 							modifyTargetBreakpoints(bpinfo.breakpoint, updateContexts, attrDelta);
  1055 	            	}
   831 	            	}
  1056 	            	processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
       
  1057 	            }
   832 	            }
  1058 	        });
   833 	        });
  1059 	    } catch (RejectedExecutionException e) {
   834 	    } catch (RejectedExecutionException e) {
  1060 			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$
   835 			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$
  1061 	    }
   836 	    }
       
   837 
  1062 	}
   838 	}
  1063 
   839 
  1064 	/**
   840 	/**
  1065 	 * For the given platform BP, update all its target BPs with the given attribute change.
   841 	 * For the given platform BP, ask the backend to modify all its target BPs
       
   842 	 * with the given attribute change. <br>
       
   843 	 * This must be called in DSF executor thread.
  1066 	 * 
   844 	 * 
  1067 	 * @param bp
   845 	 * @param bp
  1068 	 * @param targetAttrDelta - target attribute change.  
   846 	 * @param updateContexts 
       
   847 	 * 			  target contexts in which to do the modification.
       
   848 	 * @param targetAttrDelta
       
   849 	 *            target-recognizable attribute(s) with new values.
  1069 	 */
   850 	 */
  1070 	private void updateBreakpoint(final IBreakpoint bp, final Map<String, Object> targetAttrDelta) {
   851 	private void modifyTargetBreakpoints(final IBreakpoint bp, Collection<IBreakpointsTargetDMContext> updateContexts, Map<String, Object> targetAttrDelta) {
  1071         getExecutor().execute(new DsfRunnable() {
   852 		// If the breakpoint is currently being updated, queue the request and exit
  1072         	public void run() {
   853     	if (fRunningEvents.contains(bp)) {
  1073 				for (IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
   854     		PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.MODIFIED, updateContexts, targetAttrDelta);
  1074 					List<TargetBP> targetBPs = fPlatformBPs.get(dmc).get(bp);
   855     		updatePendingRequest(bp, pendingEvent);
  1075 					if (targetBPs != null) {
   856 			return;
  1076 						for (TargetBP tbp : targetBPs) {
   857     	}
  1077 							// this must be an installed bp.
   858 		
  1078 							assert (tbp.getTargetBreakpoint() != null);
   859     	CountingRequestMonitor modifyTargetBPCRM = new CountingRequestMonitor(getExecutor(), null) {
  1079 							
   860 			@Override
  1080 							fBreakpoints.updateBreakpoint(tbp.getTargetBreakpoint(), targetAttrDelta, new RequestMonitor(getExecutor(), null) {});
   861 			protected void handleCompleted() {
  1081 						}
   862 				fRunningEvents.remove(bp);
  1082 					}
   863 			}};
       
   864 			
       
   865     	int targetBPCount = 0;
       
   866     	
       
   867     	fRunningEvents.add(bp);
       
   868     	
       
   869 		for (IBreakpointsTargetDMContext context : updateContexts) {
       
   870 			List<TargetBP> targetBPs = fPlatformBPs.get(context).get(bp);
       
   871 			if (targetBPs != null) {
       
   872 				for (TargetBP tbp : targetBPs) {
       
   873 					// this must be an installed breakpoint.
       
   874 					assert (tbp.getTargetBreakpoint() != null);
       
   875 					
       
   876 					targetBPCount++;
       
   877 					fBreakpointsService.updateBreakpoint(tbp.getTargetBreakpoint(), targetAttrDelta, modifyTargetBPCRM);
  1083 				}
   878 				}
  1084         	}});
   879 			}
       
   880 		}
       
   881 		
       
   882 		modifyTargetBPCRM.setDoneCount(targetBPCount);
  1085 	}
   883 	}
  1086 
   884 
  1087 	public void breakpointsRemoved(final IBreakpoint[] bps, IMarkerDelta delta[]) {
   885 	public void breakpointsRemoved(final IBreakpoint[] bps, IMarkerDelta delta[]) {
       
   886 		getExecutor().execute(new DsfRunnable() {
       
   887 			public void run() {
       
   888 				for (IBreakpoint bp : bps)
       
   889 					fBreakpointAttributes.remove(bp);
       
   890 			}
       
   891 		});
       
   892 		
  1088 		doBreakpointsRemoved(bps, null, null);
   893 		doBreakpointsRemoved(bps, null, null);
  1089 	}
   894 	}
  1090 	
   895 	
  1091 	public void doBreakpointsRemoved(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
   896 	protected void doBreakpointsRemoved(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
  1092 	
   897 	
  1093 		final List<IBreakpoint> bpCandidates = new ArrayList<IBreakpoint>();
   898 		final List<IBreakpoint> bpCandidates = new ArrayList<IBreakpoint>();
  1094 		
   899 		
  1095 		for (int i = 0; i < bps.length; i++) {
   900 		for (int i = 0; i < bps.length; i++) {
  1096 			IBreakpoint bp = bps[i];
   901 			IBreakpoint bp = bps[i];
  1097 			
   902 			
  1098 			if (fAttributeTranslator.supportsBreakpoint(bp)) {
   903 			if (fAttributeTranslator.supportsBreakpoint(bp)) {
  1099 				if (bpsTargetDmc == null)
   904 				bpCandidates.add(bp);
  1100 					bpCandidates.add(bp);
       
  1101 				else if (fPlatformBPs.get(bpsTargetDmc).containsKey(bp))	// target BPs are installed in the context 
       
  1102 					bpCandidates.add(bp);
       
  1103 			}
   905 			}
  1104 		}
   906 		}
  1105 		
   907 		
  1106 		if (bpCandidates.isEmpty()) { // nothing to do
   908 		if (bpCandidates.isEmpty()) { // nothing to do
  1107 			if (rm != null)
   909 			if (rm != null)
  1110 		}
   912 		}
  1111 		
   913 		
  1112 		try {
   914 		try {
  1113 	        getExecutor().execute(new DsfRunnable() {
   915 	        getExecutor().execute(new DsfRunnable() {
  1114 	        	public void run() {
   916 	        	public void run() {
  1115 					final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
   917 					Collection<IBreakpointsTargetDMContext> contexts = new ArrayList<IBreakpointsTargetDMContext>();
  1116 						new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpCandidates.size(), 1);
   918 					if (bpsTargetDmc == null)
  1117 
   919 						contexts.addAll(fPlatformBPs.keySet());
  1118 					CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
   920 					else
  1119             			@Override
   921 						contexts.add(bpsTargetDmc);
  1120             			protected void handleCompleted() {
   922 
  1121             				processPendingRequests();
   923 					doBreakpointsRemovedInExecutor(bpCandidates.toArray(new IBreakpoint[bpCandidates.size()]), contexts, rm);
  1122 	                    	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.REMOVED);
       
  1123             				super.handleCompleted();
       
  1124             			}
       
  1125             		};
       
  1126             		int processPendingCountingRmCount = 0;
       
  1127             		
       
  1128 					for (final IBreakpoint breakpoint : bpCandidates) {
       
  1129 	            		final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs = 
       
  1130 	            			new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
       
  1131 	            		eventBPs.put(breakpoint, targetBPs);	
       
  1132 				
       
  1133 		            	// If the breakpoint is currently being updated, queue the request and exit
       
  1134 		            	if (fRunningEvents.contains(breakpoint)) {
       
  1135 		            		PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.REMOVED, bpsTargetDmc, processPendingCountingRm);
       
  1136             				processPendingCountingRmCount++;
       
  1137 		            		updatePendingRequest(breakpoint, pendingEvent);
       
  1138 							continue;
       
  1139 		            	}
       
  1140 		            	
       
  1141 	            		CountingRequestMonitor bpTargetDmcCRM = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
       
  1142 							@Override
       
  1143 							protected void handleCompleted() {
       
  1144 		                    	// Indicate that the running event has completed
       
  1145 		                    	fRunningEvents.remove(breakpoint);
       
  1146 		                    	super.handleCompleted();
       
  1147 							}
       
  1148 						};
       
  1149 						processPendingCountingRmCount++;
       
  1150 						int bpTargetDmcCRMCount = 0;
       
  1151 
       
  1152 	            		// Remove the breakpoint in all the execution contexts
       
  1153 	            		for (final IBreakpointsTargetDMContext dmc : fPlatformBPs.keySet()) {
       
  1154 	            			if (bpsTargetDmc != null && !bpsTargetDmc.equals(dmc)) {
       
  1155 	            				continue;
       
  1156 	            			}
       
  1157 	            			
       
  1158 	            			if (fPlatformBPs.get(dmc).containsKey(breakpoint)) {		// there are targetBPs installed 
       
  1159 	            				uninstallBreakpoint(
       
  1160 	            						dmc, breakpoint,
       
  1161 	            						new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetDmcCRM) {
       
  1162 							    			@Override
       
  1163 											protected void handleSuccess() {
       
  1164 							    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
       
  1165 							    				super.handleSuccess();
       
  1166 							    			};
       
  1167 	            						});
       
  1168 	            				bpTargetDmcCRMCount++;
       
  1169 	            			} else {
       
  1170 	            				// Breakpoint not installed for given context, do nothing.
       
  1171 	            			}
       
  1172 	            		}
       
  1173 	            		bpTargetDmcCRM.setDoneCount(bpTargetDmcCRMCount);
       
  1174 					}
       
  1175 					
       
  1176 					processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
       
  1177 	        	}
   924 	        	}
  1178 	        });
   925 	        });
  1179         } catch (RejectedExecutionException e) {
   926         } catch (RejectedExecutionException e) {
  1180 			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$
   927 			IStatus status = new Status(IStatus.ERROR, DsfPlugin.PLUGIN_ID, IDsfStatusConstants.INTERNAL_ERROR, 
       
   928 					"Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", e);//$NON-NLS-1$ //$NON-NLS-2$
  1181 			if (rm != null) {
   929 			if (rm != null) {
  1182 				rm.setStatus(status);
   930 				rm.setStatus(status);
  1183 				rm.done();
   931 				rm.done();
  1184 			} else {
   932 			} else {
  1185 				DsfPlugin.getDefault().getLog().log(status); 
   933 				DsfPlugin.getDefault().getLog().log(status); 
  1186 			}
   934 			}
  1187         }
   935         }
  1188 	}
   936 	}
  1189 	
   937 	
       
   938 	protected void doBreakpointsRemovedInExecutor(IBreakpoint[] bpCandidates, 
       
   939 			Collection<IBreakpointsTargetDMContext> targetContexts, RequestMonitor rm) {
       
   940 		
       
   941 		final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =  
       
   942 			new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpCandidates.length, 1);
       
   943 
       
   944 		CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
       
   945 			@Override
       
   946 			protected void handleCompleted() {
       
   947 				processPendingRequests();
       
   948             	fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.REMOVED);
       
   949 				super.handleCompleted();
       
   950 			}
       
   951 		};
       
   952 		int processPendingCountingRmCount = 0;
       
   953 		
       
   954 		for (final IBreakpoint breakpoint : bpCandidates) {
       
   955 
       
   956 			// If the breakpoint is currently being updated, queue the request and exit
       
   957         	if (fRunningEvents.contains(breakpoint)) {
       
   958         		PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.REMOVED, null, targetContexts, processPendingCountingRm);
       
   959                 processPendingCountingRmCount++;
       
   960         		updatePendingRequest(breakpoint, pendingEvent);
       
   961 				continue;	// handle next breakpoint
       
   962         	}
       
   963 
       
   964             processPendingCountingRmCount++;
       
   965 
       
   966             final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs = 
       
   967     			new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
       
   968     		eventBPs.put(breakpoint, targetBPs);	
       
   969 	
       
   970     		CountingRequestMonitor bpTargetsCountingRM = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
       
   971 				@Override
       
   972 				protected void handleCompleted() {
       
   973 					// Indicate that the running event has completed
       
   974                 	fRunningEvents.remove(breakpoint);
       
   975                 	super.handleCompleted();
       
   976 				}
       
   977 			};
       
   978             
       
   979 			int bpTargetsCoutingRMCount = 0;
       
   980 
       
   981         	// Mark the breakpoint as being updated and go
       
   982             fRunningEvents.add(breakpoint);
       
   983 
       
   984     		// Remove the breakpoint in all the execution contexts
       
   985     		for (final IBreakpointsTargetDMContext dmc : targetContexts) {
       
   986     			
       
   987     			if (fPlatformBPs.get(dmc).containsKey(breakpoint)) {		// there are targetBPs installed 
       
   988     				// now do time-consuming part of the work.
       
   989     				
       
   990     				uninstallBreakpoint(
       
   991     						dmc, breakpoint,
       
   992     						new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRM) {
       
   993 				    			@Override
       
   994 								protected void handleSuccess() {
       
   995 				    				targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
       
   996 				    				super.handleSuccess();
       
   997 				    			};
       
   998     						});
       
   999     				bpTargetsCoutingRMCount++;
       
  1000     			} else {
       
  1001     				// Breakpoint not installed for given context, do nothing.
       
  1002     			}
       
  1003     		}
       
  1004     		
       
  1005     		bpTargetsCountingRM.setDoneCount(bpTargetsCoutingRMCount);
       
  1006 		}
       
  1007 		
       
  1008 		processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
       
  1009 	}
       
  1010 
  1190 	private void updatePendingRequest(IBreakpoint breakpoint, PendingEventInfo pendingEvent) {
  1011 	private void updatePendingRequest(IBreakpoint breakpoint, PendingEventInfo pendingEvent) {
  1191 		LinkedList<PendingEventInfo> pendingEventsList = fPendingEvents.get(breakpoint);
  1012 		LinkedList<PendingEventInfo> pendingEventsList = fPendingEvents.get(breakpoint);
  1192 		if (pendingEventsList == null) {
  1013 		if (pendingEventsList == null) {
  1193 			pendingEventsList = new LinkedList<PendingEventInfo>();
  1014 			pendingEventsList = new LinkedList<PendingEventInfo>();
  1194 			fPendingEvents.put(breakpoint, pendingEventsList);
  1015 			fPendingEvents.put(breakpoint, pendingEventsList);
  1199 		}
  1020 		}
  1200 		pendingEventsList.add(pendingEvent);
  1021 		pendingEventsList.add(pendingEvent);
  1201 	}
  1022 	}
  1202 	
  1023 	
  1203 	private void processPendingRequests() {
  1024 	private void processPendingRequests() {
       
  1025 		/*
       
  1026 		 * This will process only first pending request for each breakpoint,
       
  1027 		 * whose RequestMonitor (see "processPendingCountingRm" in such methods as 
       
  1028 		 * doBreakpointsRemovedInExecutor()) will invoke this method again.   
       
  1029 		 */
  1204 		if (fPendingEvents.isEmpty()) return;  // Nothing to do
  1030 		if (fPendingEvents.isEmpty()) return;  // Nothing to do
  1205 		
  1031 		
  1206 		final List<PendingEventInfo> modifyBPs = new ArrayList<PendingEventInfo>(1);
  1032 		// Make a copy to avoid ConcurrentModificationException
  1207 		final Map<IBreakpointsTargetDMContext, List<PendingEventInfo>> addBPs =
  1033 		// as we are deleting element in the loop.
  1208 			new HashMap<IBreakpointsTargetDMContext, List<PendingEventInfo>>(1);
       
  1209 		final Map<IBreakpointsTargetDMContext, List<PendingEventInfo>> removeBPs =
       
  1210 			new HashMap<IBreakpointsTargetDMContext, List<PendingEventInfo>>(1);
       
  1211 		
       
  1212 		// Make a copy to avoid java.util.ConcurrentModificationException.
       
  1213 		Set<IBreakpoint> bpsInPendingEvents = new HashSet<IBreakpoint>(fPendingEvents.keySet()); 
  1034 		Set<IBreakpoint> bpsInPendingEvents = new HashSet<IBreakpoint>(fPendingEvents.keySet()); 
  1214 //		for (IBreakpoint bp : fPendingEvents.keySet()) {
       
  1215 		for (IBreakpoint bp : bpsInPendingEvents) {
  1035 		for (IBreakpoint bp : bpsInPendingEvents) {
  1216 	    	// Process the next pending update for this breakpoint
  1036 	    	if (! fRunningEvents.contains(bp)) {
  1217 	    	if (!fRunningEvents.contains(bp)) {
  1037 				LinkedList<PendingEventInfo> eventInfoList = fPendingEvents.get(bp);
  1218 	    		LinkedList<PendingEventInfo> eventInfoList = fPendingEvents.get(bp);
  1038 
  1219 	    		PendingEventInfo eventInfo = eventInfoList.removeFirst();
  1039 		    	// Process the first pending request for this breakpoint
  1220 	    		if (eventInfoList.isEmpty()) {
  1040 		   		PendingEventInfo eventInfo = eventInfoList.removeFirst();
  1221 	    			fPendingEvents.remove(bp);
  1041 	
  1222 	    		}
  1042 				if (eventInfoList.isEmpty())
  1223 	    		BreakpointEventType type = eventInfo.fEventType;
  1043 					fPendingEvents.remove(bp);
  1224 	    		if (type.equals(BreakpointEventType.MODIFIED)) {
  1044 	
  1225 	    			modifyBPs.add(eventInfo);
  1045 				switch (eventInfo.fEventType) {
  1226 	    		} else if (type.equals(BreakpointEventType.ADDED)){
  1046 				case ADDED:
  1227 	    			List<PendingEventInfo> addList = addBPs.get(eventInfo.fBPsTargetDmc);
  1047 					doBreakpointsAddedInExecutor(new PlatformBreakpointInfo[] {eventInfo.fBPInfo}, eventInfo.fBPTargetContexts, eventInfo.fRequestMonitor);
  1228 	    			if (addList == null) {
  1048 					break;
  1229 	    				addList = new ArrayList<PendingEventInfo>(1);
  1049 				case MODIFIED:
  1230 	    				addBPs.put(eventInfo.fBPsTargetDmc, addList);
  1050 					modifyTargetBreakpoints(bp, eventInfo.fBPTargetContexts, eventInfo.fAttributeDelta);
  1231 	    			}
  1051 					break;
  1232 	    			addList.add(eventInfo);
  1052 				case REMOVED:
  1233 	    		} else if (type.equals(BreakpointEventType.REMOVED)){
  1053 					doBreakpointsRemovedInExecutor(new IBreakpoint[]{bp}, eventInfo.fBPTargetContexts, eventInfo.fRequestMonitor);
  1234 	    			List<PendingEventInfo> removeList = removeBPs.get(eventInfo.fBPsTargetDmc);
  1054 					break;
  1235 	    			if (removeList == null) {
  1055 				}
  1236 	    				removeList = new ArrayList<PendingEventInfo>(1);
       
  1237 	    				removeBPs.put(eventInfo.fBPsTargetDmc, removeList);
       
  1238 	    			}
       
  1239 	    			removeList.add(eventInfo);
       
  1240 	    		}
       
  1241 	    	}
  1056 	    	}
  1242 		}
       
  1243 
       
  1244 		if (modifyBPs.size() != 0 || removeBPs.size() != 0) {
       
  1245 			new Job("Deferred breakpoint changed job") { //$NON-NLS-1$
       
  1246 	            { setSystem(true); }
       
  1247 	            @Override
       
  1248 	            protected IStatus run(IProgressMonitor monitor) {
       
  1249 	            	if (modifyBPs.size() != 0) {
       
  1250 	            		breakpointsChanged(modifyBPs.toArray(new IBreakpoint[modifyBPs.size()]), null);	            		
       
  1251 	            	}
       
  1252 	            	if (addBPs.size() != 0) {
       
  1253 	            		for (Map.Entry<IBreakpointsTargetDMContext, List<PendingEventInfo>> addBPsEntry : addBPs.entrySet()) {
       
  1254 	            			IBreakpointsTargetDMContext bpsTargetDmc = addBPsEntry.getKey();
       
  1255 	            			final List<PendingEventInfo> addBpList = addBPsEntry.getValue();
       
  1256 	            			RequestMonitor rm = new RequestMonitor(ImmediateExecutor.getInstance(), null) {
       
  1257 	            				@Override
       
  1258 								protected void handleCompleted() {
       
  1259 	            					for (PendingEventInfo eventInfo : addBpList) {
       
  1260 	            						if (eventInfo.fRequestMonitor != null) {
       
  1261 	            							eventInfo.fRequestMonitor.done();
       
  1262 	            						}
       
  1263 	            					}
       
  1264 	            				};
       
  1265 	            			};
       
  1266 		            		doBreakpointsAdded(addBpList.toArray(new IBreakpoint[addBpList.size()]), bpsTargetDmc, rm);	            			            			
       
  1267 	            		}
       
  1268 	            	} 
       
  1269 	            	if (removeBPs.size() != 0) {
       
  1270 	            		for (Map.Entry<IBreakpointsTargetDMContext, List<PendingEventInfo>> removeBPsEntry : removeBPs.entrySet()) {
       
  1271 	            			IBreakpointsTargetDMContext bpsTargetDmc = removeBPsEntry.getKey();
       
  1272 	            			final List<PendingEventInfo> removeBpList = removeBPsEntry.getValue();
       
  1273 	            			RequestMonitor rm = new RequestMonitor(ImmediateExecutor.getInstance(), null) {
       
  1274 	            				@Override
       
  1275 								protected void handleCompleted() {
       
  1276 	            					for (PendingEventInfo eventInfo : removeBpList) {
       
  1277 	            						if (eventInfo.fRequestMonitor != null) {
       
  1278 	            							eventInfo.fRequestMonitor.done();
       
  1279 	            						}
       
  1280 	            					}
       
  1281 	            				};
       
  1282 	            			};
       
  1283 		            		doBreakpointsRemoved(removeBpList.toArray(new IBreakpoint[removeBpList.size()]), bpsTargetDmc, rm);	            			            			
       
  1284 	            		}
       
  1285 	            	} 
       
  1286 	                return Status.OK_STATUS;
       
  1287 	            };
       
  1288 			}.schedule();
       
  1289 		}
  1057 		}
  1290 	}
  1058 	}
  1291 	
  1059 	
  1292 	private void fireUpdateBreakpointsStatus(final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs, final BreakpointEventType eventType) {
  1060 	private void fireUpdateBreakpointsStatus(final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs, final BreakpointEventType eventType) {
  1293         // Update breakpoint status
  1061         // Update breakpoint status
  1300             	}
  1068             	}
  1301                 
  1069                 
  1302                 if (fAttributeTranslator2 != null) {
  1070                 if (fAttributeTranslator2 != null) {
  1303                 	fAttributeTranslator2.updateBreakpointsStatus(eventBPs, eventType);
  1071                 	fAttributeTranslator2.updateBreakpointsStatus(eventBPs, eventType);
  1304                 }
  1072                 }
       
  1073                 else
       
  1074                 	for (IBreakpoint bp : eventBPs.keySet()) {
       
  1075                 		fAttributeTranslator.updateBreakpointStatus(bp);
       
  1076                 	}
       
  1077                 	
  1305 
  1078 
  1306                 return Status.OK_STATUS;
  1079                 return Status.OK_STATUS;
  1307             };
  1080             };
  1308         }.schedule();
  1081         }.schedule();
  1309 		
  1082