/*******************************************************************************
 * Copyright (c) 2007, 2018 Wind River and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Wind River - Initial API and implementation
 *     Ericsson   - High-level breakpoints integration
 *     Ericsson   - Added breakpoint filter support
 *     Ericsson   - Re-factored the service and put a few comments
 *     Ericsson   - Added Action support
 *     Marc Khouzam (Ericsson) - Fix support for thread filter (Bug 355833)
 *     Marc Khouzam (Ericsson) - Generalize thread filtering logic (Bug 431986)
 *     Marc Khouzam (Ericsson) - Accept multiple calls to startTrackingBreakpoints (Bug 389945)
 *     Marc Khouzam (Ericsson) - Support for dynamic printf (Bug 400628)
 *     Alvaro Sanchez-Leon (Ericsson) - Sometimes breakpoints set and immediately deleted when debugging with GDB (Bug 442394)
 *     Alvaro Sanchez-Leon (Ericsson) - Breakpoint Enable does not work after restarting the application (Bug 456959)
 *******************************************************************************/

package org.eclipse.cdt.dsf.mi.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import java.util.concurrent.RejectedExecutionException;

import org.eclipse.cdt.core.model.ICModelMarker;
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
import org.eclipse.cdt.debug.core.breakpointactions.BreakpointActionManager;
import org.eclipse.cdt.debug.core.model.ICAddressBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpoint;
import org.eclipse.cdt.debug.core.model.ICBreakpointExtension;
import org.eclipse.cdt.debug.core.model.ICBreakpointType;
import org.eclipse.cdt.debug.core.model.ICDynamicPrintf;
import org.eclipse.cdt.debug.core.model.ICEventBreakpoint;
import org.eclipse.cdt.debug.core.model.ICFunctionBreakpoint;
import org.eclipse.cdt.debug.core.model.ICLineBreakpoint;
import org.eclipse.cdt.debug.core.model.ICTracepoint;
import org.eclipse.cdt.debug.core.model.ICWatchpoint;
import org.eclipse.cdt.debug.core.model.ICWatchpoint2;
import org.eclipse.cdt.debug.internal.core.breakpoints.BreakpointProblems;
import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.concurrent.ImmediateExecutor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMData;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
import org.eclipse.cdt.dsf.debug.service.IDsfBreakpointExtension;
import org.eclipse.cdt.dsf.debug.service.IProcesses;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExecutionDMContext;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IExitedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IStartedDMEvent;
import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup;
import org.eclipse.cdt.dsf.debug.service.ISourceLookup.ISourceLookupDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointAddedEvent;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointRemovedEvent;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.BreakpointUpdatedEvent;
import org.eclipse.cdt.dsf.mi.service.MIBreakpoints.MIBreakpointDMContext;
import org.eclipse.cdt.dsf.mi.service.MIRunControl.SuspendedEvent;
import org.eclipse.cdt.dsf.mi.service.breakpoint.actions.BreakpointActionAdapter;
import org.eclipse.cdt.dsf.mi.service.command.events.IMIDMEvent;
import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent;
import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointScopeEvent;
import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent;
import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint;
import org.eclipse.cdt.dsf.service.AbstractDsfService;
import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.gdb.internal.eventbkpts.GdbCatchpoints;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IMarkerDelta;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IBreakpointListener;
import org.eclipse.debug.core.IBreakpointManager;
import org.eclipse.debug.core.IBreakpointManagerListener;
import org.eclipse.debug.core.model.IBreakpoint;
import org.osgi.framework.BundleContext;

import com.ibm.icu.text.MessageFormat;

/**
 * Breakpoint service interface.  The breakpoint service tracks CDT breakpoint
 * objects, and based on those, it manages breakpoints in the debugger back end.
 *
 * It relies on MIBreakpoints for the actual back-end interface.
 */
public class MIBreakpointsManager extends AbstractDsfService
		implements IBreakpointManagerListener, IBreakpointListener {
	/**
	 * A listener is notified by {@link MIBreakpointsManager} when
	 * the breakpoints tracking starts or stops.
	 * @since 4.2
	 */
	public interface IMIBreakpointsTrackingListener {

		public void breakpointTrackingStarted(IBreakpointsTargetDMContext bpTargetDMC);

		public void breakpointTrackingStopped(IBreakpointsTargetDMContext bpTargetDMC);
	}

	// Note: Find a way to import this (careful of circular dependencies)
	public static final String GDB_DEBUG_MODEL_ID = "org.eclipse.cdt.dsf.gdb"; //$NON-NLS-1$

	// Extra breakpoint attributes
	private static final String ATTR_DEBUGGER_PATH = GdbPlugin.PLUGIN_ID + ".debuggerPath"; //$NON-NLS-1$
	private static final String ATTR_THREAD_FILTER = GdbPlugin.PLUGIN_ID + ".threadFilter"; //$NON-NLS-1$
	private static final String ATTR_THREAD_ID = GdbPlugin.PLUGIN_ID + ".threadID"; //$NON-NLS-1$

	// Services
	private ICommandControlService fConnection;
	private ISourceLookup fSourceLookup;
	private IProcesses fProcesses;
	private IBreakpoints fBreakpoints;
	private IBreakpointManager fBreakpointManager; // Platform breakpoint manager (not this!)
	private BreakpointActionManager fBreakpointActionManager;

	///////////////////////////////////////////////////////////////////////////
	// Breakpoints tracking
	///////////////////////////////////////////////////////////////////////////

	private String fDebugModelId;

	// Holds the set of platform breakpoints with their corresponding back-end
	// breakpoint attributes, per context (i.e. each platform breakpoint is
	// replicated for each execution context).
	// - Context entry added/removed on start/stopTrackingBreakpoints()
	// - Augmented on breakpointAdded()
	// - Modified on breakpointChanged()
	// - Diminished on breakpointRemoved()
	private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Map<String, Object>>> fPlatformToAttributesMaps = new HashMap<>();

	/**
	 * Returns the structure that maps each breakpoint target to a map of platform breakpoints
	 * and their corresponding back-end attributes.
	 * @since 4.7
	 */
	protected Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Map<String, Object>>> getPlatformToAttributesMaps() {
		return fPlatformToAttributesMaps;
	}

	// Holds the set of target breakpoints, per execution context, and their
	// mapping to the corresponding platform breakpoint. In a given execution
	// context there can only be one platform breakpoint per target breakpoint.
	// Acts as a mapping from target (low-level) BP to the corresponding platform
	// (high-level) BP.
	// Updated when:
	// - We start/stop tracking an execution context
	// - A platform breakpoint is added/removed
	// - A thread filter is applied/removed
	private Map<IBreakpointsTargetDMContext, Map<IBreakpointDMContext, ICBreakpoint>> fBPToPlatformMaps = new HashMap<>();

	/**
	 * Returns the structure that maps each breakpoint target to a map of back-end breakpoints
	 * and their corresponding platform breakpoint.
	 * @since 4.7
	 */
	protected Map<IBreakpointsTargetDMContext, Map<IBreakpointDMContext, ICBreakpoint>> getBPToPlatformMaps() {
		return fBPToPlatformMaps;
	}

	// Holds the mapping from platform breakpoint to the corresponding target
	// breakpoint(s), per context. There can be multiple back-end BPs for a
	// single platform BP in the case of [1] multiple target contexts, and/or
	// [2] thread filtering.
	// Updated when:
	// - We start/stop tracking an execution context
	// - A platform breakpoint is added/removed
	// - A thread filter is applied/removed
	private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Vector<IBreakpointDMContext>>> fPlatformToBPsMaps = new HashMap<>();

	/**
	 * Returns the structure that maps each breakpoint target to a map of platform breakpoints
	 * and their corresponding vector of back-end breakpoints.
	 * @since 4.7
	 */
	protected Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Vector<IBreakpointDMContext>>> getPlatformToBPsMaps() {
		return fPlatformToBPsMaps;
	}

	// Holds the mapping from platform breakpoint to the corresponding target
	// breakpoint threads, per context.
	// Updated when:
	// - We start/stop tracking an execution context
	// - A platform breakpoint is added/removed
	// - A thread filter is applied/removed
	private Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Set<String>>> fPlatformToBPThreadsMaps = new HashMap<>();

	/**
	 * Returns the structure that maps each breakpoint target to a map of platform breakpoints
	 * and their corresponding back-end breakpoint thread ids.
	 * @since 4.7
	 */
	protected Map<IBreakpointsTargetDMContext, Map<ICBreakpoint, Set<String>>> getPlatformToBPThreadsMaps() {
		return fPlatformToBPThreadsMaps;
	}

	// Due to the very asynchronous nature of DSF, a new breakpoint request can
	// pop up at any time before an ongoing one is completed. The following set
	// is used to store requests until the ongoing operation completes.
	private Set<IBreakpoint> fPendingRequests = new HashSet<>();
	private Set<IBreakpoint> fPendingBreakpoints = new HashSet<>();

	private Map<ICBreakpoint, IMarker> fBreakpointMarkerProblems = new HashMap<>();

	private ListenerList<IMIBreakpointsTrackingListener> fTrackingListeners = new ListenerList<>();

	///////////////////////////////////////////////////////////////////////////
	// String constants
	///////////////////////////////////////////////////////////////////////////

	private static final String NULL_STRING = ""; //$NON-NLS-1$

	static final String CONTEXT_ALREADY_INITIALIZED = "Context already initialized"; //$NON-NLS-1$
	static final String INVALID_CONTEXT_TYPE = "Invalid context type"; //$NON-NLS-1$
	static final String INVALID_CONTEXT = "Invalid context"; //$NON-NLS-1$

	static final String UNABLE_TO_READ_BREAKPOINT = "Unable to read initial breakpoint attributes"; //$NON-NLS-1$
	static final String BREAKPOINT_NOT_INSTALLED = "Breakpoints not installed for given context"; //$NON-NLS-1$
	static final String BREAKPOINT_ALREADY_INSTALLED = "Breakpoint already installed"; //$NON-NLS-1$
	static final String BREAKPOINT_ALREADY_REMOVED = "Breakpoint already removed"; //$NON-NLS-1$

	static final String INVALID_BREAKPOINT = "Invalid breakpoint"; //$NON-NLS-1$
	static final String UNKNOWN_BREAKPOINT = "Unknown breakpoint"; //$NON-NLS-1$
	static final String INVALID_PARAMETER = "Invalid breakpoint parameter(s)"; //$NON-NLS-1$

	static final String NO_DEBUGGER_PATH = "No debugger path for breakpoint"; //$NON-NLS-1$
	static final String NO_MARKER_FOR_BREAKPOINT = "No marker associated with breakpoint"; //$NON-NLS-1$

	///////////////////////////////////////////////////////////////////////////
	// AbstractDsfService
	///////////////////////////////////////////////////////////////////////////

	/**
	 * The service constructor.
	 * Performs basic instantiation (method initialize() performs the real
	 * service initialization asynchronously).
	 *
	 * @param session       the debugging session
	 * @param debugModelId  the debugging model
	 */
	public MIBreakpointsManager(DsfSession session, String debugModelId) {
		super(session);
		fDebugModelId = debugModelId;
	}

	//-------------------------------------------------------------------------
	// initialize
	//-------------------------------------------------------------------------
	// - Collect references for the services we interact with
	// - Register to interesting events
	// - Obtain the list of platform breakpoints
	// - Register the service for interested parties
	//-------------------------------------------------------------------------

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.service.AbstractDsfService#initialize(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
	 */
	@Override
	public void initialize(final RequestMonitor rm) {
		super.initialize(new ImmediateRequestMonitor(rm) {
			@Override
			protected void handleSuccess() {
				doInitialize(rm);
			}
		});
	}

	/**
	 * @param rm
	 */
	private void doInitialize(RequestMonitor rm) {

		// Get the required services references from central repository
		fConnection = getServicesTracker().getService(ICommandControlService.class);
		fSourceLookup = getServicesTracker().getService(ISourceLookup.class);
		fBreakpoints = getServicesTracker().getService(IBreakpoints.class);
		fProcesses = getServicesTracker().getService(IProcesses.class);
		fBreakpointManager = DebugPlugin.getDefault().getBreakpointManager();
		fBreakpointActionManager = CDebugCorePlugin.getDefault().getBreakpointActionManager();

		// Register to the useful events
		getSession().addServiceEventListener(this, null);
		fBreakpointManager.addBreakpointListener(this);
		fBreakpointManager.addBreakpointManagerListener(this);

		// And register this service
		register(new String[] { MIBreakpointsManager.class.getName() }, new Hashtable<String, String>());
		rm.done();
	}

	//-------------------------------------------------------------------------
	// shutdown
	//-------------------------------------------------------------------------
	// - Un-register the service
	// - Stop listening to events
	// - Remove the breakpoints installed by this service
	//
	//  Since we are shutting down, there is no overwhelming need
	//  to keep the maps coherent...
	//-------------------------------------------------------------------------

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.service.AbstractDsfService#shutdown(org.eclipse.cdt.dsf.concurrent.RequestMonitor)
	 */
	@Override
	public void shutdown(final RequestMonitor rm) {

		// Stop accepting requests and events
		unregister();
		getSession().removeServiceEventListener(this);
		fBreakpointManager.removeBreakpointListener(this);
		fBreakpointManager.removeBreakpointManagerListener(this);
		fTrackingListeners.clear();

		// Cleanup the breakpoints that are still installed by the service.
		// Use a counting monitor which will call mom to complete the shutdown
		// after the breakpoints are un-installed (successfully or not).
		CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleCompleted() {
				MIBreakpointsManager.super.shutdown(rm);
			}
		};

		List<IBreakpointsTargetDMContext> targetBPKeys = new ArrayList<>(fBPToPlatformMaps.size());
		targetBPKeys.addAll(0, fBPToPlatformMaps.keySet());
		for (IBreakpointsTargetDMContext dmc : targetBPKeys) {
			stopTrackingBreakpoints(dmc, countingRm);
		}
		countingRm.setDoneCount(targetBPKeys.size());
	}

	//-------------------------------------------------------------------------
	// getBundleContext
	//-------------------------------------------------------------------------

	/* (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.service.AbstractDsfService#getBundleContext()
	 */
	@Override
	protected BundleContext getBundleContext() {
		return GdbPlugin.getBundleContext();
	}

	///////////////////////////////////////////////////////////////////////////
	// IBreakpointsManager
	///////////////////////////////////////////////////////////////////////////

	/**
	 * Wrapper around startTrackingBreakpoints() which accepts a containerDmc and sets
	 * each breakpoints filter to include that container.  This method should be called
	 * instead of startTrackingBreakpoints()
	 *
	 * @param containerDmc The container to be added in the bp filter.  This container
	 *                     must have the proper IBreakpointsTargetDMContext in its hierarchy.
	 *
	 * @since 4.6
	 */
	public void startTrackingBpForProcess(final IContainerDMContext containerDmc, final RequestMonitor rm) {
		final IBreakpointsTargetDMContext targetBpDmc = DMContexts.getAncestorOfType(containerDmc,
				IBreakpointsTargetDMContext.class);

		IBreakpoint[] breakpoints = fBreakpointManager.getBreakpoints(fDebugModelId);
		for (IBreakpoint breakpoint : breakpoints) {
			if (breakpoint instanceof ICBreakpoint && supportsBreakpoint(breakpoint)) {
				setTargetFilter((ICBreakpoint) breakpoint, containerDmc);
			}
		}
		startTrackingBreakpoints(targetBpDmc, rm);
	}

	//-------------------------------------------------------------------------
	// startTrackingBreakpoints
	//-------------------------------------------------------------------------
	// - Augment the maps with the new execution context
	// - Install the platform breakpoints on the selected target
	//-------------------------------------------------------------------------

	/**
	 * Install and begin tracking breakpoints for given context.  The service
	 * will keep installing new breakpoints that appear in the IDE for this
	 * context until {@link #uninstallBreakpoints(IDMContext)} is called for that
	 * context.
	 * @param dmc Context to start tracking breakpoints for.
	 * @param rm Completion callback.
	 */
	public void startTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {

		// Validate the execution context
		if (dmc == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_CONTEXT, null));
			rm.done();
			return;
		}

		Map<ICBreakpoint, Map<String, Object>> platformBPs = fPlatformToAttributesMaps.get(dmc);
		Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fPlatformToBPsMaps.get(dmc);
		Map<IBreakpointDMContext, ICBreakpoint> targetIDs = fBPToPlatformMaps.get(dmc);
		Map<ICBreakpoint, Set<String>> threadIDs = fPlatformToBPThreadsMaps.get(dmc);
		if ((platformBPs != null) || (breakpointIDs != null) || (targetIDs != null) || (threadIDs != null)) {
			// If the maps already contains this context we can simply ignore this request.
			// This happens when we start or attach to another process with GDB >= 7.4
			assert platformBPs != null && breakpointIDs != null && targetIDs != null && threadIDs != null;
			rm.done();
			return;
		}

		// Create entries in the breakpoint tables for the new context. These entries should only
		// be removed when this service stops tracking breakpoints for the given context.
		fPlatformToAttributesMaps.put(dmc, new HashMap<ICBreakpoint, Map<String, Object>>());
		fPlatformToBPsMaps.put(dmc, new HashMap<ICBreakpoint, Vector<IBreakpointDMContext>>());
		fBPToPlatformMaps.put(dmc, new HashMap<IBreakpointDMContext, ICBreakpoint>());
		fPlatformToBPThreadsMaps.put(dmc, new HashMap<ICBreakpoint, Set<String>>());

		// Install the platform breakpoints (stored in fPlatformBPs) on the target.
		new Job("DSF BreakpointsManager: Install initial breakpoints on target") { //$NON-NLS-1$
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				// Submit the runnable to plant the breakpoints on dispatch thread.
				getExecutor().submit(
						() -> installInitialBreakpoints(dmc, new RequestMonitor(ImmediateExecutor.getInstance(), rm) {
							@Override
							protected void handleSuccess() {
								// Notify breakpoints tracking listeners that the tracking is started.
								for (Object o : fTrackingListeners.getListeners()) {
									((IMIBreakpointsTrackingListener) o).breakpointTrackingStarted(dmc);
								}
								rm.done();
							}
						}));

				return Status.OK_STATUS;
			}
		}.schedule();
	}

	/**
	 * Installs the breakpoints that existed prior to the activation of this
	 * execution context.
	 *
	 * @param dmc
	 * @param initialPlatformBPs
	 * @param rm
	 */
	private void installInitialBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
		// Retrieve the set of platform breakpoints for this context
		final Map<ICBreakpoint, Map<String, Object>> platformBPs = fPlatformToAttributesMaps.get(dmc);
		if (platformBPs == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
			rm.done();
			return;
		}

		// Read current breakpoints from platform and copy their augmented
		// attributes into the local reference map
		try {
			IBreakpoint[] breakpoints = fBreakpointManager.getBreakpoints(fDebugModelId);
			for (IBreakpoint breakpoint : breakpoints) {
				if (supportsBreakpoint(breakpoint)) {
					boolean filtered = isBreakpointEntirelyFiltered(dmc, (ICBreakpoint) breakpoint);
					if (!filtered) {
						Map<String, Object> attributes = breakpoint.getMarker().getAttributes();
						attributes.put(ATTR_DEBUGGER_PATH, NULL_STRING);
						attributes.put(ATTR_THREAD_FILTER, extractThreads(dmc, (ICBreakpoint) breakpoint));
						attributes.put(ATTR_THREAD_ID, NULL_STRING);
						platformBPs.put((ICBreakpoint) breakpoint, attributes);
					}
				}
			}
		} catch (CoreException e) {
			IStatus status = new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, UNABLE_TO_READ_BREAKPOINT,
					e);
			rm.setStatus(status);
			rm.done();
		}

		// Install the individual breakpoints on the dispatcher thread
		// Requires a counting monitor to know when we are done
		final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm);
		countingRm.setDoneCount(platformBPs.size());

		for (final ICBreakpoint breakpoint : platformBPs.keySet()) {
			final Map<String, Object> attributes = platformBPs.get(breakpoint);
			// Upon determining the debuggerPath, the breakpoint is installed
			determineDebuggerPath(dmc, attributes, new RequestMonitor(getExecutor(), countingRm) {
				@Override
				protected void handleSuccess() {
					// Must install breakpoints right away, even if disabled, so that
					// we can find out if they apply to this target (Bug 389070)
					installBreakpoint(dmc, breakpoint, attributes, countingRm);
				}
			});
		}
	}

	//-------------------------------------------------------------------------
	// stopTrackingBreakpoints
	//-------------------------------------------------------------------------
	// - Remove the target breakpoints for the given execution context
	// - Update the maps
	//-------------------------------------------------------------------------

	/**
	 * Uninstall and stop tracking breakpoints for the given context.
	 * @param dmc Context to start tracking breakpoints for.
	 * @param rm Completion callback.
	 */
	public void stopTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {

		// Validate the context
		if (dmc == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
			rm.done();
			return;
		}

		// Retrieve the set of platform breakpoints for this context
		final Map<ICBreakpoint, Map<String, Object>> platformBPs = fPlatformToAttributesMaps.get(dmc);
		if (platformBPs == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, INVALID_CONTEXT, null));
			rm.done();
			return;
		}

		// Un-install the individual breakpoints on the dispatcher thread
		// (requires a counting monitor to know when we are done).
		// On completion (success or failure), update the maps.
		final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleCompleted() {
				fPlatformToAttributesMaps.remove(dmc);
				fPlatformToBPsMaps.remove(dmc);
				fBPToPlatformMaps.remove(dmc);
				fPlatformToBPThreadsMaps.remove(dmc);
				// Notify breakpoints tracking listeners that the tracking is stopped.
				for (IMIBreakpointsTrackingListener o : fTrackingListeners) {
					o.breakpointTrackingStopped(dmc);
				}
				rm.done();
			}
		};
		countingRm.setDoneCount(platformBPs.size());

		for (final ICBreakpoint breakpoint : platformBPs.keySet()) {
			uninstallBreakpoint(dmc, breakpoint, new RequestMonitor(getExecutor(), countingRm) {
				@Override
				protected void handleCompleted() {
					countingRm.done();
				}
			});
		}
	}

	/**
	 * Return the collection of tracked target breakpoint contexts. Use this method
	 * instead of implying the installed collection from the various maps contained
	 * in the manager.
	 *
	 * @since 5.5
	 */
	protected Collection<IBreakpointsTargetDMContext> getTrackedBreakpointTargetContexts() {
		return fPlatformToAttributesMaps.keySet();
	}

	///////////////////////////////////////////////////////////////////////////
	// Back-end interface functions
	///////////////////////////////////////////////////////////////////////////

	//-------------------------------------------------------------------------
	// installBreakpoint
	//-------------------------------------------------------------------------

	/**
	 * Install a platform breakpoint on the back-end. For a given context, a
	 * platform breakpoint can resolve into multiple back-end breakpoints when
	 * threads are taken into account or if multiple breakpoints are created
	 * on the target using the console.
	 *
	 * @param dmc
	 * @param breakpoint
	 * @param attributes
	 * @param rm
	 */
	private void installBreakpoint(IBreakpointsTargetDMContext dmc, final ICBreakpoint breakpoint,
			final Map<String, Object> attributes, final RequestMonitor rm) {
		// Retrieve the breakpoint maps
		final Map<ICBreakpoint, Map<String, Object>> platformBPs = fPlatformToAttributesMaps.get(dmc);
		assert platformBPs != null;

		final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fPlatformToBPsMaps.get(dmc);
		assert breakpointIDs != null;

		final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fBPToPlatformMaps.get(dmc);
		assert targetBPs != null;

		final Map<ICBreakpoint, Set<String>> threadsIDs = fPlatformToBPThreadsMaps.get(dmc);
		assert threadsIDs != null;

		// Ensure the breakpoint has a valid debugger source path
		if (breakpoint instanceof ICLineBreakpoint && !(breakpoint instanceof ICAddressBreakpoint)
				&& !(breakpoint instanceof ICFunctionBreakpoint)) {
			String debuggerPath = (String) attributes.get(ATTR_DEBUGGER_PATH);
			if (debuggerPath == null || debuggerPath.equals(NULL_STRING)) {
				rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, NO_DEBUGGER_PATH, null));
				rm.done();
				return;
			}
		}

		// A back-end breakpoint needs to be installed for each specified thread
		final Set<String> threads = getThreads(attributes);

		// Update the breakpoint state when all back-end breakpoints have been installed
		final CountingRequestMonitor installRM = new CountingRequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleCompleted() {
				// Store the platform breakpoint
				platformBPs.put(breakpoint, attributes);
				rm.done();
			}
		};
		installRM.setDoneCount(threads.size());

		// Install the back-end breakpoint(s)
		for (final String thread : threads) {
			DataRequestMonitor<IBreakpointDMContext> drm = new DataRequestMonitor<IBreakpointDMContext>(getExecutor(),
					installRM) {
				@Override
				protected void handleSuccess() {
					// Add the new back-end breakpoint to the map
					Vector<IBreakpointDMContext> list = breakpointIDs.get(breakpoint);
					if (list == null) {
						list = new Vector<>();
					}

					IBreakpointDMContext targetBP = getData();
					list.add(targetBP);
					breakpointIDs.put(breakpoint, list);

					// Add the reverse mapping
					targetBPs.put(targetBP, breakpoint);

					// And update the corresponding thread list
					Set<String> thrds = threadsIDs.get(breakpoint);
					if (thrds == null) {
						thrds = new HashSet<>();
					}

					thrds.add(thread);
					threadsIDs.put(breakpoint, thrds);

					// Reset the thread (is it necessary?)
					attributes.put(ATTR_THREAD_ID, NULL_STRING);

					// Remove breakpoint problem marker (if any)
					removeBreakpointProblemMarker(breakpoint);

					// Check for a pending breakpoint before showing that it was properly installed
					fBreakpoints.getBreakpointDMData(targetBP,
							new DataRequestMonitor<IBreakpointDMData>(getExecutor(), null) {
								@Override
								protected void handleCompleted() {
									boolean pending = false;
									if (isSuccess()) {
										IBreakpointDMData data = getData();
										if (data instanceof MIBreakpointDMData) {
											pending = ((MIBreakpointDMData) data).isPending();
										}
									}
									// Finally, update the platform breakpoint to show it was installed, unless we have a pending breakpoint
									if (!pending) {
										try {
											breakpoint.incrementInstallCount();
										} catch (CoreException e) {
										}
									}
									installRM.done();
								}
							});
				}

				@Override
				protected void handleError() {
					String detailedMessage;
					if (getStatus().getException() != null && getStatus().getException().getMessage() != null) {
						detailedMessage = getStatus().getException().getMessage();
					} else {
						detailedMessage = getStatus().getMessage();
					}
					String description = (detailedMessage == null) ? Messages.Breakpoint_attribute_problem
							: MessageFormat.format(Messages.Breakpoint_attribute_detailed_problem,
									new Object[] { detailedMessage });

					addBreakpointProblemMarker(breakpoint, description, IMarker.SEVERITY_WARNING);
					installRM.done();
				}
			};

			// Convert the breakpoint attributes for the back-end
			attributes.put(ATTR_THREAD_ID, thread);
			Map<String, Object> targetAttributes = convertToTargetBreakpoint(breakpoint, attributes);
			// Must install breakpoint right away, even if disabled, so that
			// we can find out if it applies to this target (Bug 389070)
			fBreakpoints.insertBreakpoint(dmc, targetAttributes, drm);
		}
	}

	private void addBreakpointProblemMarker(final ICBreakpoint breakpoint, final String description,
			final int severity) {

		new Job("Add Breakpoint Problem Marker") { //$NON-NLS-1$
			@Override
			protected IStatus run(IProgressMonitor monitor) {

				if (breakpoint instanceof ICLineBreakpoint) {
					// If we have already have a problem marker on this breakpoint
					// we should remove it first.
					IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
					if (marker != null) {
						try {
							marker.delete();
						} catch (CoreException e) {
						}
					}

					ICLineBreakpoint lineBreakpoint = (ICLineBreakpoint) breakpoint;
					try {
						// Locate the workspace resource via the breakpoint marker
						IMarker breakpointMarker = lineBreakpoint.getMarker();
						IResource resource = breakpointMarker.getResource();

						// Add a problem marker to the resource
						IMarker problemMarker = resource.createMarker(BreakpointProblems.BREAKPOINT_PROBLEM_MARKER_ID);
						int lineNumber = lineBreakpoint.getLineNumber();
						String sourceHandle = lineBreakpoint.getSourceHandle();
						problemMarker.setAttribute(IMarker.LOCATION, String.valueOf(lineNumber));
						problemMarker.setAttribute(IMarker.MESSAGE, description);
						problemMarker.setAttribute(IMarker.SEVERITY, severity);
						problemMarker.setAttribute(IMarker.LINE_NUMBER, lineNumber);
						if (sourceHandle != null) {
							problemMarker.setAttribute(ICModelMarker.C_MODEL_MARKER_EXTERNAL_LOCATION, sourceHandle);
						}

						// And save the baby
						fBreakpointMarkerProblems.put(breakpoint, problemMarker);
					} catch (CoreException e) {
					}
				}
				return Status.OK_STATUS;
			}
		}.schedule();
	}

	private void removeBreakpointProblemMarker(final ICBreakpoint breakpoint) {

		new Job("Remove Breakpoint Problem Marker") { //$NON-NLS-1$
			@Override
			protected IStatus run(IProgressMonitor monitor) {

				IMarker marker = fBreakpointMarkerProblems.remove(breakpoint);
				if (marker != null) {
					try {
						marker.delete();
					} catch (CoreException e) {
					}
				}

				return Status.OK_STATUS;
			}
		}.schedule();
	}

	//-------------------------------------------------------------------------
	// uninstallBreakpoint
	//-------------------------------------------------------------------------

	/**
	 * Un-install an individual breakpoint on the back-end. For one platform
	 * breakpoint in a given execution context, there could be multiple
	 * corresponding back-end breakpoints (one per thread).
	 *
	 * @param dmc
	 * @param breakpoint
	 * @param rm
	 *
	 * @since 4.2
	 */
	public void uninstallBreakpoint(final IBreakpointsTargetDMContext dmc, final ICBreakpoint breakpoint,
			RequestMonitor rm) {
		// Remove all relevant target filters
		// Note that this call is important if a breakpoint is removed directly
		// from the gdb console, or else we will try to re-install it (bug 433044)
		removeAllTargetFilters(dmc, breakpoint);

		// Remove breakpoint problem marker (if any)
		removeBreakpointProblemMarker(breakpoint);

		doUninstallBreakpoint(dmc, breakpoint, new ImmediateRequestMonitor(rm) {
			@Override
			protected void handleSuccess() {
				Map<ICBreakpoint, Map<String, Object>> platformBPs = fPlatformToAttributesMaps.get(dmc);
				// Note: Protect against NPE. It looks like we just checked the "platformBPs" is not null,
				// in doUninstallBreakpoint(), but there is a race condition that can make it null
				// in the meantime, if the debug session is destroyed. See bug 511727
				if (platformBPs != null) {
					platformBPs.remove(breakpoint);
				}
				super.handleSuccess();
			}
		});
	}

	/*
	 * Un-install the target breakpoints associated with the given platform breakpoint.
	 * The information related to the platform breakpoints is not cleared from the session.
	 * This allows the target breakpoints to be re-installed when an attribute of the platform
	 * breakpoint is changed.
	 */
	private void doUninstallBreakpoint(final IBreakpointsTargetDMContext dmc, final ICBreakpoint breakpoint,
			final RequestMonitor rm) {
		// Retrieve the breakpoint maps
		final Map<ICBreakpoint, Map<String, Object>> platformBPs = fPlatformToAttributesMaps.get(dmc);
		assert platformBPs != null;

		final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fPlatformToBPsMaps.get(dmc);
		assert breakpointIDs != null;

		final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fBPToPlatformMaps.get(dmc);
		assert targetBPs != null;

		final Map<ICBreakpoint, Set<String>> threadsIDs = fPlatformToBPThreadsMaps.get(dmc);
		assert threadsIDs != null;

		// Minimal validation
		if (!platformBPs.containsKey(breakpoint) || !breakpointIDs.containsKey(breakpoint)
				|| !targetBPs.containsValue(breakpoint)) {
			rm.setStatus(
					new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, BREAKPOINT_ALREADY_REMOVED, null));
			rm.done();
			return;
		}

		// Remove completion monitor
		// Upon completion, update the mappings
		final CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				// Update the mappings
				threadsIDs.remove(breakpoint);
				fPendingRequests.remove(breakpoint);
				rm.done();
			}
		};

		// Remove the back-end breakpoints
		// Remove the entry from the breakpointIDs map right away to indicate that we have already
		// taken care of this breakpoint.  This avoids race conditions with the shutdown
		// which would also try to decrement the install count (bug 344635)
		Vector<IBreakpointDMContext> list = breakpointIDs.remove(breakpoint);
		int count = 0;
		if (list != null) {
			for (final IBreakpointDMContext bp : list) {
				targetBPs.remove(bp);
				decrementInstallCount(bp, breakpoint, new RequestMonitor(getExecutor(), removeRM) {
					@Override
					protected void handleCompleted() {
						fBreakpoints.removeBreakpoint(bp, removeRM);
					}
				});
			}
			count = list.size();
			list.clear(); // probably not necessary
		}
		removeRM.setDoneCount(count);
	}

	private void decrementInstallCount(IBreakpointDMContext targetDmc, final ICBreakpoint breakpoint,
			final RequestMonitor rm) {
		fBreakpoints.getBreakpointDMData(targetDmc, new DataRequestMonitor<IBreakpointDMData>(getExecutor(), rm) {
			@Override
			protected void handleCompleted() {
				boolean pending = false;
				if (isSuccess()) {
					IBreakpointDMData data = getData();
					if (data instanceof MIBreakpointDMData) {
						pending = ((MIBreakpointDMData) data).isPending();
					}
				}
				// Finally, update the platform breakpoint to show it was un-installed.
				// But we don't do this for pending breakpoints since they were
				// not marked as installed.
				if (!pending) {
					try {
						breakpoint.decrementInstallCount();
					} catch (CoreException e) {
					}
				}
				rm.done();
			}
		});
	}
	//-------------------------------------------------------------------------
	// modifyBreakpoint
	//-------------------------------------------------------------------------

	/**
	 * Modify a platform breakpoint which can translate to quite a few updates
	 * on the target...
	 *
	 * @param dmc
	 * @param breakpoint
	 * @param attributes
	 * @param oldValues
	 * @param rm
	 */
	private void modifyBreakpoint(final IBreakpointsTargetDMContext dmc, final ICBreakpoint breakpoint,
			final Map<String, Object> attributes, final IMarkerDelta oldValues, final RequestMonitor rm) {
		// Retrieve the breakpoint maps
		final Map<ICBreakpoint, Map<String, Object>> platformBPs = fPlatformToAttributesMaps.get(dmc);
		assert platformBPs != null;

		final Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fPlatformToBPsMaps.get(dmc);
		assert breakpointIDs != null;

		final Map<IBreakpointDMContext, ICBreakpoint> targetBPs = fBPToPlatformMaps.get(dmc);
		assert targetBPs != null;

		final Map<ICBreakpoint, Set<String>> threadsIDs = fPlatformToBPThreadsMaps.get(dmc);
		assert threadsIDs != null;

		boolean filtered = isBreakpointEntirelyFiltered(dmc, breakpoint);

		if (filtered && !platformBPs.containsKey(breakpoint)) {
			rm.done();
			return;
		}

		// Check if the breakpoint is installed:
		// the installation might have failed; in this case, we try to install it again because
		// some attribute might have changed which will make the install succeed.
		if (!breakpointIDs.containsKey(breakpoint) && !targetBPs.containsValue(breakpoint)) {
			if (!filtered) {
				// Do not try to re-install the breakpoint if the change event is the result of changes
				// in the breakpoint's install count.
				// Excluding ATTR_DEBUGGER_PATH from the comparison because it has been set just before
				// "modifyBreakpoint()" was called.
				// (Bugzilla 534309) Guard against NULL oldValues, which is legitimate, in which case use an empty Map.
				String[] diff = compareAttributes(
						oldValues == null ? Collections.emptyMap() : oldValues.getAttributes(), attributes,
						new String[] { ATTR_DEBUGGER_PATH });
				if (diff.length != 1 || !diff[0].equals(ICBreakpoint.INSTALL_COUNT)) {
					attributes.put(ATTR_DEBUGGER_PATH, NULL_STRING);
					attributes.put(ATTR_THREAD_FILTER, extractThreads(dmc, breakpoint));
					attributes.put(ATTR_THREAD_ID, NULL_STRING);
					determineDebuggerPath(dmc, attributes, new RequestMonitor(getExecutor(), rm) {
						@Override
						protected void handleSuccess() {
							installBreakpoint(dmc, breakpoint, attributes, rm);
						}
					});
				} else {
					rm.done();
				}
			} else {
				rm.done();
			}
			return;
		}

		if (filtered) {
			uninstallBreakpoint(dmc, breakpoint, rm);
			return;
		}

		// Get the original breakpoint attributes
		final Map<String, Object> originalAttributes = platformBPs.get(breakpoint);
		if (originalAttributes == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, INVALID_BREAKPOINT, null));
			rm.done();
			return;
		}

		// Determine the attributes delta
		final Map<String, Object> oldAttributes = new HashMap<>(originalAttributes);
		oldAttributes.put(ATTR_THREAD_FILTER, threadsIDs.get(breakpoint));

		final Set<String> newThreads = extractThreads(dmc, breakpoint);
		Map<String, Object> newAttributes = new HashMap<>(attributes);
		newAttributes.put(ATTR_THREAD_FILTER, newThreads);

		final Map<String, Object> attributesDelta = determineAttributesDelta(oldAttributes, newAttributes);

		// Get the list of back-end breakpoints
		final Vector<IBreakpointDMContext> oldTargetBPs = new Vector<>(breakpointIDs.get(breakpoint));
		if (oldTargetBPs.isEmpty()) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, INVALID_BREAKPOINT, null));
			rm.done();
			return;
		}

		// We're all set for the breakpoint update.
		//
		// The path for a simple update is straightforward:
		// - For each back-end BP corresponding to a platform BP
		//   - Send an update command to the back-end
		//   - If the operation succeeded, update the data structures
		//   - If the operation failed, try to roll-back
		//
		// In cases where the the back-end breakpoint cannot be
		// simply updated (e.g. thread filter modification), the old
		// breakpoint has to be removed and new one(s) inserted.
		//
		// The path for such an update is:
		// - Install the updated breakpoint
		// - In the operation succeeded
		//   - Remove the old breakpoint(s)
		//   - Perform any pending update

		// Update completion monitor
		final CountingRequestMonitor updateRM = new CountingRequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				// Success: simply store the new attributes
				platformBPs.put(breakpoint, attributes);
				rm.done();
			}

			@Override
			protected void handleError() {
				// Store the error message to use in the problem marker
				final String errorMessage = getStatus().getException() != null
						? getStatus().getException().getLocalizedMessage()
						: getStatus().getMessage();
				// Try to uninstall the target breakpoints and add the problem marker
				// with the error message to the platform breakpoint.
				doUninstallBreakpoint(dmc, breakpoint, new ImmediateRequestMonitor(rm) {
					@Override
					protected void handleSuccess() {
						addBreakpointProblemMarker(breakpoint, errorMessage, IMarker.SEVERITY_WARNING);
						rm.done();
					}

					@Override
					protected void handleError() {
						// Reset the breakpoint attributes. This will trigger a
						// breakpoint change event and the correct delta will be
						// computed, resulting in a correctly restored breakpoint
						// at the back-end.
						rollbackAttributes(breakpoint, oldValues);
						platformBPs.put(breakpoint, attributes);

						rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_PARAMETER,
								getStatus().getException()));
						rm.done();
					}
				});
			}
		};

		// Everything OK: remove the old back-end breakpoints
		final Vector<IBreakpointDMContext> newTargetBPs = new Vector<>();
		final CountingRequestMonitor removeRM = new CountingRequestMonitor(getExecutor(), rm) {
			@Override
			protected void handleSuccess() {
				// All right! Save the new list and perform the final update
				Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpointIDs = fPlatformToBPsMaps.get(dmc);
				if (breakpointIDs == null) {
					rm.setStatus(
							new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, INVALID_BREAKPOINT, null));
					rm.done();
					return;
				}
				breakpointIDs.put(breakpoint, newTargetBPs);
				for (IBreakpointDMContext ref : newTargetBPs) {
					fBreakpoints.updateBreakpoint(ref, attributesDelta, updateRM);
				}
				updateRM.setDoneCount(newTargetBPs.size());
			}
		};

		// New back-end breakpoints insertion monitor
		// Holds the list of new back-end breakpoint contexts of the platform breakpoint
		final DataRequestMonitor<Vector<IBreakpointDMContext>> insertRM = new DataRequestMonitor<Vector<IBreakpointDMContext>>(
				getExecutor(), null) {

			@Override
			// In theory, we could have had a partial success and the original threads
			// list would be invalid. We think it is highly unlikely so we assume that
			// either everything went fine or else everything failed.
			protected void handleSuccess() {
				// Get the list of new back-end breakpoints contexts
				newTargetBPs.addAll(getData());
				for (IBreakpointDMContext newRef : newTargetBPs) {
					targetBPs.put(newRef, breakpoint);
				}
				threadsIDs.put(breakpoint, newThreads);
				for (final IBreakpointDMContext ref : oldTargetBPs) {
					targetBPs.remove(ref);
					decrementInstallCount(ref, breakpoint, // A tad early but it should work...
							new RequestMonitor(getExecutor(), removeRM) {
								@Override
								protected void handleCompleted() {
									fBreakpoints.removeBreakpoint(ref, removeRM);
								}
							});
				}
				removeRM.setDoneCount(oldTargetBPs.size());
			}

			@Override
			protected void handleError() {
				// Store the error message to use in the problem marker
				final String errorMessage = getStatus().getException() != null
						? getStatus().getException().getLocalizedMessage()
						: getStatus().getMessage();
				doUninstallBreakpoint(dmc, breakpoint, new ImmediateRequestMonitor(updateRM) {
					@Override
					protected void handleSuccess() {
						addBreakpointProblemMarker(breakpoint, errorMessage, IMarker.SEVERITY_WARNING);
						updateRM.setDoneCount(0);
					}
				});
			}
		};

		// If the changes in the breakpoint attributes justify it, install a
		// new set of back-end breakpoint(s) and then update them
		if (needsResinstallation(attributesDelta)) {
			reinstallBreakpoint(dmc, breakpoint, attributes, newThreads, insertRM);
		} else {
			// Update the back-end breakpoint(s) state
			for (IBreakpointDMContext ref : oldTargetBPs) {
				fBreakpoints.updateBreakpoint(ref, attributesDelta, updateRM);
			}
			updateRM.setDoneCount(oldTargetBPs.size());
		}
	}

	/**
	 * Re-install the back-end breakpoints
	 *
	 * @param context       the target context
	 * @param breakpoint    the platform breakpoint
	 * @param attributes    breakpoint augmented attributes
	 * @param threads       list of threads where breakpoint is to be installed
	 * @param drm           will contain the list of successfully installed back-end breakpoints
	 */
	private void reinstallBreakpoint(final IBreakpointsTargetDMContext context, final ICBreakpoint breakpoint,
			final Map<String, Object> attributes, Set<String> threads,
			final DataRequestMonitor<Vector<IBreakpointDMContext>> drm) {
		// Our new list of back-end breakpoints. Built as we go.
		final Vector<IBreakpointDMContext> breakpointList = new Vector<>();

		// Counting monitor for the new back-end breakpoints to install
		// Once we're done, return the new list of back-end breakpoints contexts
		final CountingRequestMonitor installRM = new CountingRequestMonitor(getExecutor(), drm) {
			@Override
			protected void handleSuccess() {
				// Report whatever we have managed to install
				// It is very likely installation either succeeded or failed for all
				drm.setData(breakpointList);
				drm.done();
			}
		};
		installRM.setDoneCount(threads.size());

		// And install the new back-end breakpoints
		for (String thread : threads) {
			// Convert the breakpoint attributes for the back-end
			// Refresh the set of attributes at each iteration just in case...
			Map<String, Object> attrs = convertToTargetBreakpoint(breakpoint, attributes);
			// Tracepoints and dynamic printf are not affected by "skip-all"
			if (!(breakpoint instanceof ICTracepoint) && !(breakpoint instanceof ICDynamicPrintf)
					&& !fBreakpointManager.isEnabled()) {
				attrs.put(MIBreakpoints.IS_ENABLED, false);
			}

			attrs.put(MIBreakpointDMData.THREAD_ID, thread);

			// Then install the spiked breakpoint
			fBreakpoints.insertBreakpoint(context, attrs,
					new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
						@Override
						protected void handleSuccess() {
							// Add the new back-end breakpoint context to the list
							breakpointList.add(getData());

							// Check for a pending breakpoint before showing that it was properly installed
							fBreakpoints.getBreakpointDMData(getData(),
									new DataRequestMonitor<IBreakpointDMData>(getExecutor(), null) {
										@Override
										protected void handleCompleted() {
											boolean pending = false;
											if (isSuccess()) {
												IBreakpointDMData data = getData();
												if (data instanceof MIBreakpointDMData) {
													pending = ((MIBreakpointDMData) data).isPending();
												}
											}
											// Finally, update the platform breakpoint to show it was installed, unless we have a pending breakpoint
											if (!pending) {
												try {
													breakpoint.incrementInstallCount();
												} catch (CoreException e) {
												}
											}
											installRM.done();
										}
									});
						}

						@Override
						protected void handleError() {
							String detailedMessage;
							if (getStatus().getException() != null && getStatus().getException().getMessage() != null) {
								detailedMessage = getStatus().getException().getMessage();
							} else {
								detailedMessage = getStatus().getMessage();
							}
							String description = (detailedMessage == null) ? Messages.Breakpoint_attribute_problem
									: MessageFormat.format(Messages.Breakpoint_attribute_detailed_problem,
											new Object[] { detailedMessage });
							// Add the new back-end breakpoint context to the list
							installRM.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED,
									description, getStatus().getException()));
							installRM.done();
						}
					});
		}
	}

	///////////////////////////////////////////////////////////////////////////
	// IBreakpointManagerListener implementation
	///////////////////////////////////////////////////////////////////////////

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IBreakpointManagerListener#breakpointManagerEnablementChanged(boolean)
	 */
	@Override
	public void breakpointManagerEnablementChanged(boolean enabled) {

		// Only modify enabled breakpoints
		for (IBreakpointsTargetDMContext context : fPlatformToBPsMaps.keySet()) {
			for (ICBreakpoint breakpoint : fPlatformToBPsMaps.get(context).keySet()) {
				try {
					// Note that Tracepoints and dynamic printf are not affected by "skip-all"
					if (!(breakpoint instanceof ICTracepoint) && !(breakpoint instanceof ICDynamicPrintf)
							&& breakpoint.isEnabled()) {
						for (IBreakpointDMContext ref : fPlatformToBPsMaps.get(context).get(breakpoint)) {
							Map<String, Object> delta = new HashMap<>();
							delta.put(MIBreakpoints.IS_ENABLED, enabled);
							fBreakpoints.updateBreakpoint(ref, delta, new RequestMonitor(getExecutor(), null));
						}
					}
				} catch (CoreException e) {
				}
			}
		}
	}

	///////////////////////////////////////////////////////////////////////////
	// IBreakpointListener implementation
	///////////////////////////////////////////////////////////////////////////

	@ThreadSafe
	@Override
	public void breakpointAdded(final IBreakpoint breakpoint) {
		breakpointAdded(breakpoint, null, new RequestMonitor(getExecutor(), null));
	}

	/**
	 * Extension of {@link #breakpointAdded(IBreakpoint)}
	 *
	 * @param miBpt
	 *            the MIBreakpoint that initiated the breakpointAdded, or null
	 * @since 5.3
	 * @deprecated Use
	 *             {@link #breakpointAdded(IBreakpoint, MIBreakpoint, RequestMonitor)}
	 *             instead. See Bug 530377.
	 */
	@ThreadSafe
	@Deprecated
	public void breakpointAdded(final IBreakpoint breakpoint, MIBreakpoint miBpt) {
		breakpointAdded(breakpoint, miBpt, new RequestMonitor(getExecutor(), null));
	}

	/**
	 * Extension of {@link #breakpointAdded(IBreakpoint)} that can be monitored for
	 * completeness with a {@link RequestMonitor}.
	 *
	 * @param breakpoint
	 *            the added breakpoint
	 * @param miBpt
	 *            the MIBreakpoint that initiated the breakpointAdded, or null
	 * @param rm
	 * @since 5.5
	 */
	@ThreadSafe
	public void breakpointAdded(final IBreakpoint breakpoint, MIBreakpoint miBpt, RequestMonitor rm) {
		if (supportsBreakpoint(breakpoint)) {
			try {
				// Retrieve the breakpoint attributes
				final Map<String, Object> attrs = breakpoint.getMarker().getAttributes();

				getExecutor().execute(new DsfRunnable() {
					@Override
					public void run() {
						// For a new breakpoint, the first thing we do is set the target filter to all existing processes.
						// We will need this when it is time to install the breakpoint.
						// We fetch the processes from our IProcess service to be generic (bug 431986)
						fProcesses.getProcessesBeingDebugged(fConnection.getContext(),
								new DataRequestMonitor<IDMContext[]>(getExecutor(), rm) {
									@Override
									protected void handleCompleted() {
										if (isSuccess()) {
											try {
												IDsfBreakpointExtension filterExtension = getFilterExtension(
														(ICBreakpoint) breakpoint);
												for (IDMContext dmc : getData()) {
													IContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc,
															IContainerDMContext.class);
													assert containerDmc != null;
													if (filterExtension.getThreadFilters(containerDmc) == null) {
														// Do this only if there wasn't already an entry, or else we would
														// erase the content of that previous entry.
														// There can be an entry already when a thread-specific breakpoint is created
														// from the MIBreakpointsSynchronizer (through the gdb console).  In that case the
														// platform bp gets created, and the targetFilter gets set by MIBreakpointsSynchronizer
														// before the call to breakpointAdded() is made and we get to here.
														// Bug 433329
														filterExtension.setTargetFilter(containerDmc);
													}
												}
											} catch (CoreException e1) {
												// Error setting target filter, just skip altogether
											}
										}

										// Now we can install the bp for all target contexts
										final CountingRequestMonitor countingRm = new CountingRequestMonitor(
												getExecutor(), rm) {
											@Override
											protected void handleCompleted() {
												// Log any error when creating the breakpoint
												if (getStatus().getSeverity() == IStatus.ERROR) {
													GdbPlugin.getDefault().getLog().log(getStatus());
												}
												rm.done();
											}
										};
										countingRm.setDoneCount(getTrackedBreakpointTargetContexts().size());

										for (final IBreakpointsTargetDMContext dmc : getTrackedBreakpointTargetContexts()) {
											boolean filtered = isBreakpointEntirelyFiltered(dmc,
													(ICBreakpoint) breakpoint);
											if (!filtered) {
												determineDebuggerPath(dmc, attrs,
														new RequestMonitor(getExecutor(), countingRm) {
															@Override
															protected void handleSuccess() {
																installBreakpoint(dmc, (ICBreakpoint) breakpoint, attrs,
																		countingRm);
															}
														});
											} else {
												countingRm.done();
											}
										}
									}
								});
					}
				});

				// Normal return case, rm handling passed to runnable
				return;
			} catch (CoreException e) {
			} catch (RejectedExecutionException e) {
			}
		}

		// error/abnormal return case
		rm.done();
	}

	/**
	 * @param bp
	 * @return
	 * @throws CoreException
	 * @since 4.7
	 */
	protected IDsfBreakpointExtension getFilterExtension(ICBreakpoint bp) throws CoreException {
		return (IDsfBreakpointExtension) bp.getExtension(GDB_DEBUG_MODEL_ID, ICBreakpointExtension.class);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IBreakpointListener#breakpointChanged(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
	 */
	@Override
	public void breakpointChanged(final IBreakpoint breakpoint, final IMarkerDelta delta) {

		if (supportsBreakpoint(breakpoint)) {

			try {
				// Retrieve the breakpoint attributes
				final Map<String, Object> attrs = breakpoint.getMarker().getAttributes();
				// Tracepoints and dynamic printf are not affected by "skip-all"
				if (!(breakpoint instanceof ICTracepoint) && !(breakpoint instanceof ICDynamicPrintf)
						&& !fBreakpointManager.isEnabled()) {
					attrs.put(ICBreakpoint.ENABLED, false);
				}

				// Modify the breakpoint in all the target contexts
				getExecutor().execute(new DsfRunnable() {
					@Override
					public void run() {

						// If the breakpoint is currently being updated, queue the request and exit
						if (fPendingRequests.contains(breakpoint)) {
							fPendingBreakpoints.add(breakpoint);
							return;
						}

						// Keep track of the updates
						final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
							@Override
							protected void handleCompleted() {

								if (!isSuccess() && getStatus().getSeverity() == IStatus.ERROR) {
									GdbPlugin.getDefault().getLog().log(getStatus());
								}

								// Indicate that the pending request has completed
								fPendingRequests.remove(breakpoint);

								// Process the next pending update for this breakpoint
								if (fPendingBreakpoints.contains(breakpoint)) {
									fPendingBreakpoints.remove(breakpoint);
									breakpointChanged(breakpoint, delta);
								}
							}
						};
						countingRm.setDoneCount(getTrackedBreakpointTargetContexts().size());

						// Mark the breakpoint as being updated and go
						fPendingRequests.add(breakpoint);

						// Modify the breakpoint in all the execution contexts
						for (final IBreakpointsTargetDMContext dmc : getTrackedBreakpointTargetContexts()) {
							determineDebuggerPath(dmc, attrs, new RequestMonitor(getExecutor(), countingRm) {
								@Override
								protected void handleSuccess() {
									modifyBreakpoint(dmc, (ICBreakpoint) breakpoint, attrs, delta, countingRm);
								}
							});
						}
					}
				});

			} catch (CoreException e) {
			} catch (RejectedExecutionException e) {
			}
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.core.IBreakpointListener#breakpointRemoved(org.eclipse.debug.core.model.IBreakpoint, org.eclipse.core.resources.IMarkerDelta)
	 */
	@Override
	public void breakpointRemoved(final IBreakpoint breakpoint, IMarkerDelta delta) {

		if (supportsBreakpoint(breakpoint)) {
			try {
				getExecutor().execute(new DsfRunnable() {
					@Override
					public void run() {
						CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), null) {
							@Override
							protected void handleError() {
								if (getStatus().getSeverity() == IStatus.ERROR) {
									GdbPlugin.getDefault().getLog().log(getStatus());
								}
							}
						};
						countingRm.setDoneCount(getTrackedBreakpointTargetContexts().size());

						// Remove the breakpoint in all the execution contexts
						for (IBreakpointsTargetDMContext dmc : getTrackedBreakpointTargetContexts()) {
							if (fPlatformToAttributesMaps.get(dmc).containsKey(breakpoint)) {
								uninstallBreakpoint(dmc, (ICBreakpoint) breakpoint, countingRm);
							}
						}
					}
				});
			} catch (RejectedExecutionException e) {
			}
		}
	}

	///////////////////////////////////////////////////////////////////////////
	// IServiceEventListener
	///////////////////////////////////////////////////////////////////////////

	//-------------------------------------------------------------------------
	// Breakpoints
	//-------------------------------------------------------------------------

	@DsfServiceEventHandler
	public void eventDispatched(BreakpointAddedEvent e) {
		// Nothing to do - already handled by breakpointAdded()
	}

	@DsfServiceEventHandler
	public void eventDispatched(BreakpointUpdatedEvent e) {
		// Nothing to do - already handled by breakpointChanged()
	}

	@DsfServiceEventHandler
	public void eventDispatched(BreakpointRemovedEvent e) {
		// Nothing to do - already handled by breakpointRemoved()
	}

	/*
	 * When a watchpoint goes out of scope, it is automatically removed from
	 * the back-end. To keep our internal state synchronized, we have to
	 * remove it from our breakpoints maps.
	 * Unfortunately, GDB doesn't generate the correct event...
	 */
	@DsfServiceEventHandler
	public void eventDispatched(MIWatchpointScopeEvent e) {
	}

	//-------------------------------------------------------------------------
	// Breakpoint actions
	//-------------------------------------------------------------------------

	/** @since 4.2 */
	@DsfServiceEventHandler
	public void eventDispatched(ISuspendedDMEvent e) {
		assert e instanceof IMIDMEvent;
		if (e instanceof IMIDMEvent) {
			Object miEvent = ((IMIDMEvent) e).getMIEvent();

			if (miEvent instanceof MIBreakpointHitEvent) {
				// This covers catchpoints, too
				MIBreakpointHitEvent evt = (MIBreakpointHitEvent) miEvent;
				performBreakpointAction(evt.getDMContext(), evt.getNumber());
				return;
			}

			if (miEvent instanceof MIWatchpointTriggerEvent) {
				MIWatchpointTriggerEvent evt = (MIWatchpointTriggerEvent) miEvent;
				performBreakpointAction(evt.getDMContext(), evt.getNumber());
				return;
			}
		}
	}

	/**
	 * @deprecated Replaced by the generic {@link #eventDispatched(ISuspendedDMEvent)}
	 */
	@Deprecated
	@DsfServiceEventHandler
	public void eventDispatched(SuspendedEvent e) {
	}

	private void performBreakpointAction(final IDMContext context, String number) {
		// Identify the platform breakpoint
		final ICBreakpoint breakpoint = findPlatformBreakpoint(number);

		if (breakpoint != null) {
			// Perform the actions asynchronously (otherwise we can have a deadlock...)
			new Job("Breakpoint action") { //$NON-NLS-1$
				{
					setSystem(true);
				}

				@Override
				protected IStatus run(IProgressMonitor monitor) {
					fBreakpointActionManager.executeActions(breakpoint,
							new BreakpointActionAdapter(getExecutor(), getServicesTracker(), context));
					return Status.OK_STATUS;
				}
			}.schedule();
		}
	}

	// Helper function to locate the platform breakpoint corresponding
	// to the target breakpoint/watchpoint that was just hit

	// FIXME: (Bug228703) Need a way to identify the correct context where the BP was hit
	private ICBreakpoint findPlatformBreakpoint(String targetBreakpointID) {
		Set<IBreakpointsTargetDMContext> targets = fBPToPlatformMaps.keySet();
		for (IBreakpointsTargetDMContext target : targets) {
			Map<IBreakpointDMContext, ICBreakpoint> bps = fBPToPlatformMaps.get(target);
			Set<IBreakpointDMContext> contexts = bps.keySet();
			for (IBreakpointDMContext context : contexts) {
				if (context instanceof MIBreakpointDMContext) {
					MIBreakpointDMContext ctx = (MIBreakpointDMContext) context;
					if (ctx.getReference().equals(targetBreakpointID)) {
						return bps.get(context);
					}
				}
			}
		}
		return null;
	}

	/**
	 * Returns a platform breakpoint corresponding to a given target breakpoint.
	 *
	 * @since 3.0
	 */
	public IBreakpoint findPlatformBreakpoint(IBreakpointDMContext bpContext) {
		if (bpContext instanceof MIBreakpointDMContext) {
			IBreakpointsTargetDMContext targetCtx = DMContexts.getAncestorOfType(bpContext,
					IBreakpointsTargetDMContext.class);
			if (targetCtx != null) {
				Map<IBreakpointDMContext, ICBreakpoint> bps = fBPToPlatformMaps.get(targetCtx);
				if (bps != null) {
					return bps.get(bpContext);
				}
			}
		}
		return null;
	}

	//-------------------------------------------------------------------------
	// Process/thread start/exit
	//-------------------------------------------------------------------------
	/**
	 * @noreference This method is not intended to be referenced by clients.
	 * @since 4.4
	 */
	@DsfServiceEventHandler
	public void eventDispatched(IStartedDMEvent e) {
	}

	private void setTargetFilter(ICBreakpoint breakpoint, IContainerDMContext containerDmc) {
		try {
			IDsfBreakpointExtension filterExt = getFilterExtension(breakpoint);
			if (filterExt.getThreadFilters(containerDmc) == null) {
				// Do this only if there wasn't already an entry, or else we would
				// erase the content of that previous entry.
				// This could theoretically happen if the targetFilter is set by
				// someone else, before this method is called.
				// Bug 433329
				filterExt.setTargetFilter(containerDmc);
			}

		} catch (CoreException e) {
		}
	}

	/**
	 * @noreference This method is not intended to be referenced by clients.
	 * @since 4.4
	 */
	@DsfServiceEventHandler
	public void eventDispatched(IExitedDMEvent e) {
		// original code moved to API removeTargetFilter (Bug 456959)
	}

	/**
	 * Remove process from the thread filtering of all breakpoints
	 * @since 4.6
	 */
	public void removeTargetFilter(IContainerDMContext containerDMC) {
		// We must get the list of breakpoints from the platform because our different
		// maps might already have been cleaned up
		IBreakpoint[] allBreakpoints = fBreakpointManager.getBreakpoints(fDebugModelId);
		for (IBreakpoint bp : allBreakpoints) {
			if (supportsBreakpoint(bp)) {
				removeTargetFilter((ICBreakpoint) bp, containerDMC);
			}
		}
	}

	private void removeTargetFilter(ICBreakpoint breakpoint, IContainerDMContext containerDmc) {
		try {
			IDsfBreakpointExtension filterExt = getFilterExtension(breakpoint);
			filterExt.removeTargetFilter(containerDmc);
		} catch (CoreException e) {
		}
	}

	private void removeAllTargetFilters(IBreakpointsTargetDMContext bpTargetDmc, ICBreakpoint breakpoint) {
		try {
			IDsfBreakpointExtension filterExt = getFilterExtension(breakpoint);
			IContainerDMContext[] targets = filterExt.getTargetFilters();
			for (IContainerDMContext target : targets) {
				if (bpTargetDmc.equals(target) || DMContexts.isAncestorOf(target, bpTargetDmc)) {
					filterExt.removeTargetFilter(target);
				}
			}
		} catch (CoreException e) {
		}
	}

	//-------------------------------------------------------------------------
	// Session exit
	//-------------------------------------------------------------------------

	/**
	 * @since 1.1
	 * @nooverride This method is not intended to be re-implemented or extended by clients.
	 * @noreference This method is not intended to be referenced by clients.
	 */
	@DsfServiceEventHandler
	public void eventDispatched(ICommandControlShutdownDMEvent e) {
		terminated();
	}

	private void terminated() {
		// Reset the breakpoint install count
		for (IBreakpointsTargetDMContext ctx : fPlatformToAttributesMaps.keySet()) {
			Map<ICBreakpoint, Map<String, Object>> breakpoints = fPlatformToAttributesMaps.get(ctx);
			clearBreakpointStatus(breakpoints.keySet().toArray(new ICBreakpoint[breakpoints.size()]), ctx);
		}
		// This will prevent Shutdown() from trying to remove bps from a
		// backend that has already shutdown
		fPlatformToAttributesMaps.clear();
	}

	/**
	 * @param bps
	 */
	private void clearBreakpointStatus(final ICBreakpoint[] bps, final IBreakpointsTargetDMContext ctx) {
		IWorkspaceRunnable wr = monitor -> {
			// For every platform breakpoint that has at least one target breakpoint installed
			// we must decrement the install count, for every target breakpoint.
			// Note that we cannot simply call resetInstallCount() because another
			// launch may be using the same platform breakpoint.
			Map<ICBreakpoint, Vector<IBreakpointDMContext>> breakpoints = fPlatformToBPsMaps.get(ctx);
			for (ICBreakpoint breakpoint : breakpoints.keySet()) {
				Vector<IBreakpointDMContext> targetBps = breakpoints.get(breakpoint);
				for (IBreakpointDMContext targetBp : targetBps) {
					decrementInstallCount(targetBp, breakpoint, new RequestMonitor(getExecutor(), null));
				}
			}
		};

		// Create the scheduling rule to clear all bp planted.
		ISchedulingRule rule = null;
		List<ISchedulingRule> markerRules = new ArrayList<>();
		for (ICBreakpoint bp : bps) {
			IMarker marker = bp.getMarker();
			if (marker != null) {
				ISchedulingRule markerRule = ResourcesPlugin.getWorkspace().getRuleFactory()
						.markerRule(marker.getResource());
				if (markerRule == null) {
					markerRules = null;
					break;
				} else {
					markerRules.add(markerRule);
				}
			}
		}
		if (markerRules != null) {
			rule = MultiRule.combine(markerRules.toArray(new ISchedulingRule[markerRules.size()]));
		}

		try {
			// Will run the workspace runnable on the current thread, which
			// is the DSF executor.
			ResourcesPlugin.getWorkspace().run(wr, rule, 0, null);
		} catch (CoreException e) {
			GdbPlugin.getDefault().getLog().log(e.getStatus());
		}

		new Job("Clear Breakpoints Status") { //$NON-NLS-1$
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				// Clear any problem markers
				for (IMarker marker : fBreakpointMarkerProblems.values()) {
					if (marker != null) {
						try {
							marker.delete();
						} catch (CoreException e) {
						}
					}
				}
				fBreakpointMarkerProblems.clear();

				return Status.OK_STATUS;
			}
		}.schedule();
	}

	///////////////////////////////////////////////////////////////////////////
	// Support functions
	///////////////////////////////////////////////////////////////////////////

	/**
	 * Indicates if the platform breakpoint object [bp] is one we can deal with.
	 * For now, it boils down to whether it's a CDT Breakpoint (an
	 * ICBreakpoint). DSF can supports other (custom) types of breakpoints, but
	 * DSF-GDB is tied to ICBreakpoint.
	 *
	 * @param bp the platform breakpoint
	 * @return true if we support it; false otherwise
	 * @since 4.7
	 */
	protected boolean supportsBreakpoint(IBreakpoint bp) {
		if (bp instanceof ICBreakpoint && bp.getModelIdentifier().equals(fDebugModelId)) {
			IMarker marker = bp.getMarker();
			if (marker != null) {
				return true;
			}
		}
		return false;
	}

	/**
	 * determineDebuggerPath
	 *
	 * Adds the path to the source file to the set of attributes
	 * (for the debugger).
	 *
	 * @param dmc
	 * @param attributes
	 * @param rm
	 */
	private void determineDebuggerPath(IBreakpointsTargetDMContext dmc, final Map<String, Object> attributes,
			final RequestMonitor rm) {
		String hostPath = (String) attributes.get(ICBreakpoint.SOURCE_HANDLE);

		if (hostPath != null) {

			ISourceLookupDMContext srcDmc = DMContexts.getAncestorOfType(dmc, ISourceLookupDMContext.class);
			if (srcDmc != null) {
				fSourceLookup.getDebuggerPath(srcDmc, hostPath, new DataRequestMonitor<String>(getExecutor(), rm) {
					@Override
					protected void handleSuccess() {
						attributes.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(getData()));
						rm.done();
					}
				});
			} else {
				// Source lookup not available for given context, use the host
				// path for the debugger path.
				attributes.put(ATTR_DEBUGGER_PATH, adjustDebuggerPath(hostPath));
				rm.done();
			}
		} else {
			// Some types of breakpoints do not require a path
			// (e.g. watchpoints)
			rm.done();
		}
	}

	/**
	 * For some platforms (MinGW) the debugger path needs to be adjusted to work
	 * with earlier GDB versions.
	 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=232415
	 *
	 * @param path
	 *            the absolute path to the source file
	 * @return the adjusted path provided by the breakpoints service.
	 */
	String adjustDebuggerPath(String path) {
		return (fBreakpoints instanceof IMIBreakpointPathAdjuster)
				? ((IMIBreakpointPathAdjuster) fBreakpoints).adjustDebuggerPath(path)
				: path;
	}

	/**
	 * Determine the set of modified attributes.
	 * Elementary set operations in full action :-)
	 *
	 * @param oldAttributes
	 * @param newAttributes
	 * @return
	 */
	private Map<String, Object> determineAttributesDelta(Map<String, Object> oldAttributes,
			Map<String, Object> newAttributes) {

		Map<String, Object> delta = new HashMap<>();

		Set<String> oldKeySet = oldAttributes.keySet();
		Set<String> newKeySet = newAttributes.keySet();

		Set<String> commonKeys = new HashSet<>(newKeySet);
		commonKeys.retainAll(oldKeySet);
		Set<String> addedKeys = new HashSet<>(newKeySet);
		addedKeys.removeAll(oldKeySet);
		Set<String> removedKeys = new HashSet<>(oldKeySet);
		removedKeys.removeAll(newKeySet);

		// Add the modified attributes
		for (String key : commonKeys) {
			if (!(oldAttributes.get(key).equals(newAttributes.get(key)))) {
				delta.put(key, newAttributes.get(key));
			}
		}

		// Add the new attributes
		for (String key : addedKeys) {
			delta.put(key, newAttributes.get(key));
		}

		// Remove the deleted attributes
		for (String key : removedKeys) {
			delta.put(key, null);
		}

		return convertToPlatformAttributes(delta);
	}

	/**
	 * Converts ICBreakpoint attributes to IBreakpoints attributes.
	 *
	 * @param cdtAttributes
	 * @return
	 * @since 5.3
	 */
	protected Map<String, Object> convertToPlatformAttributes(Map<String, Object> cdtAttributes) {

		Map<String, Object> result = new HashMap<>();

		// IBreakpoint attributes
		if (cdtAttributes.containsKey(ATTR_DEBUGGER_PATH)) {
			result.put(MIBreakpoints.FILE_NAME, cdtAttributes.get(ATTR_DEBUGGER_PATH));
		}

		if (cdtAttributes.containsKey(IMarker.LINE_NUMBER)) {
			result.put(MIBreakpoints.LINE_NUMBER, cdtAttributes.get(IMarker.LINE_NUMBER));
		}

		if (cdtAttributes.containsKey(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE)) {
			result.put(MIBreakpoints.COMMANDS, cdtAttributes.get(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE));
		}

		// ICLineBreakpoint attributes
		if (cdtAttributes.containsKey(ICLineBreakpoint.FUNCTION)) {
			result.put(MIBreakpoints.FUNCTION, cdtAttributes.get(ICLineBreakpoint.FUNCTION));
		}

		if (cdtAttributes.containsKey(ICLineBreakpoint.ADDRESS)) {
			result.put(MIBreakpoints.ADDRESS, cdtAttributes.get(ICLineBreakpoint.ADDRESS));
		}

		// ICBreakpoint attributes
		if (cdtAttributes.containsKey(ICBreakpoint.CONDITION)) {
			result.put(MIBreakpoints.CONDITION, cdtAttributes.get(ICBreakpoint.CONDITION));
		}

		if (cdtAttributes.containsKey(ICBreakpoint.IGNORE_COUNT)) {
			result.put(MIBreakpoints.IGNORE_COUNT, cdtAttributes.get(ICBreakpoint.IGNORE_COUNT));
		}

		if (cdtAttributes.containsKey(ICTracepoint.PASS_COUNT)) {
			result.put(MIBreakpoints.PASS_COUNT, cdtAttributes.get(ICTracepoint.PASS_COUNT));
		}

		if (cdtAttributes.containsKey(ICBreakpoint.ENABLED)) {
			result.put(MIBreakpoints.IS_ENABLED, cdtAttributes.get(ICBreakpoint.ENABLED));
		}

		if (cdtAttributes.containsKey(ICBreakpointType.TYPE)) {
			result.put(MIBreakpoints.BREAKPOINT_TYPE, cdtAttributes.get(ICBreakpointType.TYPE));
		}

		// ICWatchpoint attributes
		if (cdtAttributes.containsKey(ICWatchpoint.EXPRESSION)) {
			result.put(MIBreakpoints.EXPRESSION, cdtAttributes.get(ICWatchpoint.EXPRESSION));
		}

		if (cdtAttributes.containsKey(ICWatchpoint.READ)) {
			result.put(MIBreakpoints.READ, cdtAttributes.get(ICWatchpoint.READ));
		}

		if (cdtAttributes.containsKey(ICWatchpoint.WRITE)) {
			result.put(MIBreakpoints.WRITE, cdtAttributes.get(ICWatchpoint.WRITE));
		}

		// Threads
		if (cdtAttributes.containsKey(ATTR_THREAD_FILTER)) {
			result.put(ATTR_THREAD_FILTER, cdtAttributes.get(ATTR_THREAD_FILTER));
		}

		// For IDynamicPrintf
		if (cdtAttributes.containsKey(ICDynamicPrintf.PRINTF_STRING)) {
			result.put(MIBreakpoints.PRINTF_STRING, cdtAttributes.get(ICDynamicPrintf.PRINTF_STRING));
		}

		return result;
	}

	/**
	 * Figure out the corresponding number of back-end breakpoints
	 * Even though the thread IDs are usually integers, they are
	 * stored as strings in CBreakpoints.
	 *
	 * @param attributes
	 * @return
	 */
	@SuppressWarnings("unchecked")
	private Set<String> getThreads(Map<String, Object> attributes) {
		Set<String> threads = (Set<String>) attributes.get(ATTR_THREAD_FILTER);
		if (threads == null) {
			threads = new HashSet<>();
			threads.add("0"); // Thread 0 means all threads //$NON-NLS-1$
		}
		return threads;
	}

	/**
	 * Get the list of threads from the breakpoint's thread filtering mechanism
	 *
	 * @param breakpoint
	 * @return
	 */
	private Set<String> extractThreads(IBreakpointsTargetDMContext bpTargetDmc, ICBreakpoint breakpoint) {
		Set<String> results = new HashSet<>();

		if (supportsThreads(breakpoint)) {
			List<IExecutionDMContext[]> threads = new ArrayList<>(1);

			try {
				// Retrieve all existing targets.
				// Note that these targets can be from different debugging sessions since
				// they are associated with the platform breakpoint.
				IDsfBreakpointExtension filterExtension = getFilterExtension(breakpoint);
				IContainerDMContext[] procTargets = filterExtension.getTargetFilters();

				// Extract the thread IDs
				for (IContainerDMContext procDmc : procTargets) {
					// Look for a target/process that belongs to our session
					if (procDmc.equals(bpTargetDmc) || DMContexts.isAncestorOf(procDmc, bpTargetDmc)) {
						IExecutionDMContext[] threadFilters = filterExtension.getThreadFilters(procDmc);
						if (threadFilters == null) {
							// The breakpoint applies to the entire process.
							// For GDB < 7.4, we set the thread to 0 to indicate that the breakpoint
							// is global for this process.
							// For GDB >= 7.4, things are more complicated.  There will be one bp for all
							// processes, so by setting the thread to 0, the breakpoint will apply
							// to all threads of all processes.  We don't have a choice as there is no
							// way to tell GDB to apply to all threads (including any new ones that will
							// be created) for a single process.
							// So, in this case, if the bp applies to all threads of one process, it will
							// automatically apply to all threads of all processes
							results.add("0"); //$NON-NLS-1$
							return results;
						} else {
							threads.add(threadFilters);
						}
					}
				}
			} catch (CoreException e) {
				// Error with the thread filtering.  Default to all threads.
				results.add("0"); //$NON-NLS-1$
				return results;
			}

			// If there are no threads to filter on, it means the bp applies to the entire process.
			if (threads.isEmpty()) {
				results.add("0"); //$NON-NLS-1$
				return results;
			}

			for (IExecutionDMContext[] targetThreads : threads) {
				if (targetThreads != null) {
					for (IExecutionDMContext thread : targetThreads) {
						if (thread instanceof IMIExecutionDMContext) {
							results.add(((IMIExecutionDMContext) thread).getThreadId());
						} else {
							// If any of the threads is not an IMIExecutionDMContext,
							// we don't support thread filters at all.
							results.clear();
							results.add("0"); //$NON-NLS-1$
							return results;
						}
					}
				} else {
					// Should not happen
					assert false;
				}
			}
		} else {
			results.add("0"); //$NON-NLS-1$
		}

		return results;
	}

	///////////////////////////////////////////////////////////////////////////
	// Non-generic (MI-specific) functions
	///////////////////////////////////////////////////////////////////////////

	/**
	 * Create a collection of DSF-GDB specific breakpoint properties given a
	 * platform/CDT breakpoint object and its properties. Basically, this
	 * determines the set of MI-specific properties to be used in installing the
	 * given breakpoint.
	 *
	 * @param breakpoint
	 *            the platform breakpoint object; was created by CDT
	 * @param attributes
	 *            the breakpoint's properties. By allowing this to be passed in
	 *            (rather than us calling
	 *            IBreakpoint#getMarker()#getProperties()), we allow the caller
	 *            to specify additional/modified properties.
	 * @return a property bag containing the corresponding DSF-GDB properties
	 */
	protected Map<String, Object> convertToTargetBreakpoint(ICBreakpoint breakpoint, Map<String, Object> attributes) {

		Map<String, Object> properties = new HashMap<>();

		if (breakpoint instanceof ICWatchpoint) {
			properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.WATCHPOINT);
			properties.put(MIBreakpoints.EXPRESSION, attributes.get(ICWatchpoint.EXPRESSION));
			properties.put(MIBreakpoints.READ, attributes.get(ICWatchpoint.READ));
			properties.put(MIBreakpoints.WRITE, attributes.get(ICWatchpoint.WRITE));
			properties.put(MIBreakpoints.RANGE, attributes.get(ICWatchpoint2.RANGE));
			properties.put(MIBreakpoints.MEMSPACE, attributes.get(ICWatchpoint2.MEMORYSPACE));
		} else if (breakpoint instanceof ICLineBreakpoint) {
			properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.BREAKPOINT);
			properties.put(MIBreakpoints.FILE_NAME, attributes.get(ATTR_DEBUGGER_PATH));
			properties.put(MIBreakpoints.LINE_NUMBER, attributes.get(IMarker.LINE_NUMBER));
			properties.put(MIBreakpoints.FUNCTION, attributes.get(ICLineBreakpoint.FUNCTION));
			properties.put(MIBreakpoints.ADDRESS, attributes.get(ICLineBreakpoint.ADDRESS));
			properties.put(MIBreakpoints.COMMANDS, attributes.get(BreakpointActionManager.BREAKPOINT_ACTION_ATTRIBUTE));

			if (breakpoint instanceof ICTracepoint) {
				// A tracepoint is a LineBreakpoint, but needs its own type
				properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.TRACEPOINT);
				properties.put(MIBreakpoints.PASS_COUNT, attributes.get(ICTracepoint.PASS_COUNT));
			} else if (breakpoint instanceof ICDynamicPrintf) {
				// A DynamicPrintf is a LineBreakpoint, but needs its own type
				properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.DYNAMICPRINTF);
				properties.put(MIBreakpoints.PRINTF_STRING, attributes.get(ICDynamicPrintf.PRINTF_STRING));
			}
		} else if (breakpoint instanceof ICEventBreakpoint) {
			properties.put(MIBreakpoints.BREAKPOINT_TYPE, MIBreakpoints.CATCHPOINT);
			properties.put(MIBreakpoints.CATCHPOINT_TYPE, GdbCatchpoints
					.eventToGdbCatchpointKeyword((String) attributes.get(ICEventBreakpoint.EVENT_TYPE_ID)));

			String arg = (String) attributes.get(ICEventBreakpoint.EVENT_ARG);
			String[] args;
			if ((arg != null) && (arg.length() != 0)) {
				args = new String[1];
				args[0] = arg;
			} else {
				args = new String[0];
			}
			properties.put(MIBreakpoints.CATCHPOINT_ARGS, args);
		} else {
			assert false : "platform breakpoint is of an unexpected type: " + breakpoint.getClass().getName(); //$NON-NLS-1$
		}

		// Common fields
		properties.put(MIBreakpoints.CONDITION, attributes.get(ICBreakpoint.CONDITION));
		properties.put(MIBreakpoints.IGNORE_COUNT, attributes.get(ICBreakpoint.IGNORE_COUNT));
		properties.put(MIBreakpoints.IS_ENABLED, attributes.get(ICBreakpoint.ENABLED));
		properties.put(MIBreakpointDMData.THREAD_ID, attributes.get(ATTR_THREAD_ID));

		// checks for the breakpoint type, and adds the hardware/temporary flags
		Object breakpointType = attributes.get(ICBreakpointType.TYPE);
		if (breakpointType instanceof Integer) {
			boolean isHardware = ((Integer) breakpointType & ICBreakpointType.HARDWARE) == ICBreakpointType.HARDWARE;
			boolean isTemporary = ((Integer) breakpointType & ICBreakpointType.TEMPORARY) == ICBreakpointType.TEMPORARY;
			properties.put(MIBreakpointDMData.IS_HARDWARE, isHardware);
			properties.put(MIBreakpointDMData.IS_TEMPORARY, isTemporary);
		}

		// Adjust for "skip-all"
		// Tracepoints and dynamic printf are not affected by "skip-all"
		if (!(breakpoint instanceof ICTracepoint) && !(breakpoint instanceof ICDynamicPrintf)
				&& !fBreakpointManager.isEnabled()) {
			properties.put(MIBreakpoints.IS_ENABLED, false);
		}

		return properties;
	}

	/**
	 * Determine if the modified attributes necessitate
	 * a breakpoint removal/re-installation
	 *
	 * @param delta
	 * @return
	 */
	protected boolean needsResinstallation(Map<String, Object> delta) {

		// Check if there is any modified attribute
		if (delta == null) {
			return false;
		}

		// Check the "critical" attributes
		if (delta.containsKey(ATTR_DEBUGGER_PATH) // File name
				|| delta.containsKey(MIBreakpoints.LINE_NUMBER) // Line number
				|| delta.containsKey(MIBreakpoints.BREAKPOINT_TYPE) // breakpoint type
				|| delta.containsKey(MIBreakpoints.FUNCTION) // Function name
				|| delta.containsKey(MIBreakpoints.ADDRESS) // Absolute address
				|| delta.containsKey(ATTR_THREAD_FILTER) // Thread ID
				|| delta.containsKey(MIBreakpoints.EXPRESSION) // Watchpoint expression
				|| delta.containsKey(MIBreakpoints.READ) // Watchpoint type
				|| delta.containsKey(MIBreakpoints.WRITE) // Watchpoint type
				|| delta.containsKey(MIBreakpoints.PRINTF_STRING)) {// Dprintf string
			return true;
		}

		return false;
	}

	/**
	 * @param breakpoint
	 * @param oldValues
	 */
	protected void rollbackAttributes(ICBreakpoint breakpoint, IMarkerDelta oldValues) {

		try {
			String newCondition = breakpoint.getCondition();
			if (newCondition == null) {
				newCondition = NULL_STRING;
			}
			String oldCondition = (oldValues != null) ? oldValues.getAttribute(ICBreakpoint.CONDITION, NULL_STRING)
					: NULL_STRING;
			if (!oldCondition.equals(newCondition)) {
				breakpoint.setCondition(oldCondition);
			} else {
				breakpoint.setCondition(NULL_STRING);
			}
		} catch (CoreException e) {
		}
	}

	/**
	 * Indicates if the back-end supports multiple threads for
	 * this type of breakpoint
	 *
	 * @param breakpoint
	 */
	protected boolean supportsThreads(ICBreakpoint breakpoint) {

		return !(breakpoint instanceof ICWatchpoint);
	}

	/**
	 * Returns whether the breakpoint is filtered for the given target.
	 */
	private boolean isBreakpointEntirelyFiltered(IBreakpointsTargetDMContext bpTargetDmc, ICBreakpoint breakpoint) {
		try {
			IContainerDMContext[] procTargets = getFilterExtension(breakpoint).getTargetFilters();
			for (IContainerDMContext procDmc : procTargets) {
				if (procDmc.equals(bpTargetDmc) || DMContexts.isAncestorOf(procDmc, bpTargetDmc)) {
					return false;
				}
			}
		} catch (CoreException e) {
		}
		return true;
	}

	/**
	 * @since 4.2
	 */
	public void addBreakpointsTrackingListener(IMIBreakpointsTrackingListener listener) {
		fTrackingListeners.add(listener);
	}

	/**
	 * @since 4.2
	 */
	public void removeBreakpointsTrackingListener(IMIBreakpointsTrackingListener listener) {
		fTrackingListeners.remove(listener);
	}

	private String[] compareAttributes(Map<String, Object> oldAttr, Map<String, Object> newAttr, String[] exclude) {
		List<String> list = new ArrayList<>();
		Set<String> names = new HashSet<>(oldAttr.keySet());
		names.addAll(newAttr.keySet());
		for (String n : names) {
			if (exclude != null && Arrays.asList(exclude).contains(n)) {
				continue;
			}
			Object oldValue = oldAttr.get(n);
			if (oldValue != null && !oldValue.equals(newAttr.get(n))) {
				list.add(n);
			} else if (oldValue == null) {
				if (newAttr.get(n) != null) {
					list.add(n);
				}
			}
		}
		return list.toArray(new String[list.size()]);
	}
}
