Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPawel Piech2010-01-08 18:45:28 +0000
committerPawel Piech2010-01-08 18:45:28 +0000
commit3c3cbab6e717ee65e63ea20970b562c386fe4c05 (patch)
tree47e687594d5ddae2e9de71845323b6d1e6a984f7 /dsf/org.eclipse.cdt.dsf
parent3e8602621d11299ecabcc64a70b5b0d41967acf4 (diff)
downloadorg.eclipse.cdt-3c3cbab6e717ee65e63ea20970b562c386fe4c05.tar.gz
org.eclipse.cdt-3c3cbab6e717ee65e63ea20970b562c386fe4c05.tar.xz
org.eclipse.cdt-3c3cbab6e717ee65e63ea20970b562c386fe4c05.zip
Bug 292468 - [breakpoints] Cannot update breakpoint status properly with current IBreakpointAttributeTranslator
Diffstat (limited to 'dsf/org.eclipse.cdt.dsf')
-rw-r--r--dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java14
-rw-r--r--dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator2.java1140
-rw-r--r--dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator.java47
-rw-r--r--dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator2.java154
4 files changed, 1348 insertions, 7 deletions
diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java
index 864c3400f20..ec9711d0eb8 100644
--- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java
+++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator.java
@@ -48,7 +48,21 @@ import org.eclipse.debug.core.model.IBreakpoint;
import org.osgi.framework.BundleContext;
/**
+ * Breakpoints mediator is a DSF service which synchronizes breakpoints in the
+ * IDE and breakpoints in the debugger. The IDE breakpoints are managed by the
+ * {@link IBreakpointManager} while the debugger breakpoints are accessed
+ * through the {@link IBreakpoints} service.
+ * <p>
+ * This class is not intended to be extended by clients. Instead clients should
+ * implement the {@link IBreakpointAttributeTranslator} interface which is used
+ * to translate breakpoint attributes between the IDE and debugger breakpoints.
+ * <p>
+ * Note: This breakpoint mediator implementation has been superseded by a more
+ * powerful {@link BreakpointsMediator2} implementation.
*
+ * @since 1.0
+ * @see IBreakpointAttributeTranslator
+ * @see BreakpointsMediator2
*/
public class BreakpointsMediator extends AbstractDsfService implements IBreakpointManagerListener, IBreakpointListener
{
diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator2.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator2.java
new file mode 100644
index 00000000000..77952f8300d
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/BreakpointsMediator2.java
@@ -0,0 +1,1140 @@
+/*******************************************************************************
+ * Copyright (c) 2007, 2008 Wind River and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River - Initial API and implementation
+ * Ericsson - Low-level breakpoints integration
+ * Nokia - refactored to work for both GDB and EDC. Nov. 2009.
+ *******************************************************************************/
+
+package org.eclipse.cdt.dsf.debug.service;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.RejectedExecutionException;
+
+import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
+import org.eclipse.cdt.dsf.concurrent.IDsfStatusConstants;
+import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
+import org.eclipse.cdt.dsf.internal.DsfPlugin;
+import org.eclipse.cdt.dsf.service.AbstractDsfService;
+import org.eclipse.cdt.dsf.service.DsfSession;
+import org.eclipse.core.resources.IMarkerDelta;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Plugin;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.debug.core.DebugPlugin;
+import org.eclipse.debug.core.IBreakpointManager;
+import org.eclipse.debug.core.IBreakpointsListener;
+import org.eclipse.debug.core.model.IBreakpoint;
+import org.osgi.framework.BundleContext;
+
+/**
+/**
+ * Breakpoints mediator is a DSF service which synchronizes breakpoints in the
+ * IDE and breakpoints in the debugger. The IDE breakpoints are managed by the
+ * {@link IBreakpointManager} while the debugger breakpoints are accessed
+ * through the {@link IBreakpoints} service.
+ * <p>
+ * This class is not intended to be extended by clients. Instead clients should
+ * implement the {@link IBreakpointAttributeTranslator2} interface which is used
+ * to translate breakpoint attributes between the IDE and debugger breakpoints.
+ * <p>
+ * Note: This breakpoint mediator is a second generation implementation that
+ * succeeds {@link BreakpointsMediator}. This new implementation includes
+ * the following additional features:
+ * <ul>
+ * <li> support for multiple target breakpoints for each IDE breakpoint, </li>
+ * <li> support for retrieving the mapping between IDE breakpoints and
+ * debugger breakpoints,</li>
+ * <li> support for updating IDE breakpoint status based on full target
+ * breakpoint data. </li>
+ * </ul>
+ *
+ * @see IBreakpointAttributeTranslator2
+ * @see BreakpointsMediator
+ *
+ * @since 2.1
+ */
+public class BreakpointsMediator2 extends AbstractDsfService implements IBreakpointsListener
+{
+ public enum BreakpointEventType {ADDED, REMOVED, MODIFIED};
+
+ /**
+ * The attribute translator that this service will use to map the platform
+ * breakpoint attributes to the corresponding target attributes, and vice
+ * versa.
+ */
+ private IBreakpointAttributeTranslator2 fAttributeTranslator2;
+
+ /**
+ * DSF Debug service for creating breakpoints.
+ */
+ IBreakpoints fBreakpointsService;
+
+ /**
+ * Platform breakpoint manager
+ */
+ IBreakpointManager fBreakpointManager;
+
+ /**
+ * Object describing the information about a single target breakpoint
+ * corresponding to specific platform breakpoint and breakpoint target
+ * context.
+ */
+ public interface ITargetBreakpointInfo {
+
+ /**
+ * Returns the breakpoint attributes as returned by the attribute translator.
+ */
+ public Map<String, Object> getAttributes();
+
+ /**
+ * Returns the target breakpoint context. Returns <code>null</code> if the
+ * breakpoint failed to install on target.
+ */
+ public IBreakpointDMContext getTargetBreakpoint();
+
+ /**
+ * Returns the status result of the last breakpoint operation (install/remove).
+ */
+ public IStatus getStatus();
+ }
+
+ private static class TargetBP implements ITargetBreakpointInfo {
+
+ private Map<String, Object> fAttributes;
+ private IBreakpointDMContext fTargetBPContext;
+ private IStatus fStatus;
+
+ public TargetBP(Map<String, Object> attrs) {
+ fAttributes = attrs;
+ }
+
+ public Map<String, Object> getAttributes() {
+ return fAttributes;
+ }
+
+ public IBreakpointDMContext getTargetBreakpoint() {
+ return fTargetBPContext;
+ }
+
+ public IStatus getStatus() {
+ return fStatus;
+ }
+
+ public void setTargetBreakpoint(IBreakpointDMContext fTargetBPContext) {
+ this.fTargetBPContext = fTargetBPContext;
+ }
+
+ public void setStatus(IStatus status) {
+ this.fStatus = status;
+ }
+ }
+
+ private class PlatformBreakpointInfo {
+ IBreakpoint breakpoint;
+ boolean enabled;
+ // All attributes available from UI, including standard and extended ones.
+ Map<String, Object> attributes;
+
+ public PlatformBreakpointInfo(IBreakpoint bp, boolean enabled, Map<String, Object> attributes) {
+ super();
+ breakpoint = bp;
+ this.enabled = enabled;
+ this.attributes = attributes;
+ }
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Breakpoints tracking
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Holds the set of platform breakpoints with their breakpoint information
+ * structures, per context (i.e. each platform breakpoint is
+ * replicated for each execution context).
+ * - Context entry added/removed on start/stopTrackingBreakpoints()
+ * - Augmented on breakpointAdded()
+ * - Modified on breakpointChanged()
+ * - Diminished on breakpointRemoved()
+ */
+ private Map<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>> fPlatformBPs =
+ new HashMap<IBreakpointsTargetDMContext, Map<IBreakpoint, List<TargetBP>>>();
+
+ /**
+ * Mapping of platform breakpoints to all their attributes (standard ones and
+ * extended ones) from UI. This will be used to check what attributes have
+ * changed for a breakpoint when the breakpoint is changed. The map is <br>
+ * 1. augmented in breakpointsAdded(); <br>
+ * 2. updated in breakpointsChanged(); <br>
+ * 3. diminished in breakpointsRemoved();
+ */
+ private Map<IBreakpoint, Map<String, Object>> fBreakpointAttributes =
+ new HashMap<IBreakpoint, Map<String, Object>>();
+
+ /**
+ * Hold info about a breakpoint events (added, removed, changed) for later
+ * handling.
+ */
+ private static class PendingEventInfo {
+ PendingEventInfo(BreakpointEventType eventType, PlatformBreakpointInfo bpInfo,
+ Collection<IBreakpointsTargetDMContext> bpsTargetDmc, RequestMonitor rm) {
+ fEventType = eventType;
+ fBPInfo = bpInfo;
+ fBPTargetContexts = bpsTargetDmc;
+ fRequestMonitor = rm;
+ fAttributeDelta = null;
+ }
+
+ PendingEventInfo(BreakpointEventType eventType, Collection<IBreakpointsTargetDMContext> updateContexts,
+ Map<String, Object> attrDelta) {
+ fEventType = eventType;
+ fBPTargetContexts = updateContexts;
+ fAttributeDelta = attrDelta;
+ fRequestMonitor = null;
+ fBPInfo = null;
+ }
+
+ PlatformBreakpointInfo fBPInfo;
+ RequestMonitor fRequestMonitor;
+ BreakpointEventType fEventType;
+ Collection<IBreakpointsTargetDMContext> fBPTargetContexts;
+ Map<String, Object> fAttributeDelta; // for change event only
+ }
+
+ /**
+ * Due to the very asynchronous nature of DSF, a new breakpoint request can
+ * pop up at any time before an ongoing one is completed. The following set
+ * is used to store requests until the ongoing operation completes.
+ */
+ private Set<IBreakpoint> fRunningEvents = new HashSet<IBreakpoint>();
+
+ private Map<IBreakpoint, LinkedList<PendingEventInfo>> fPendingEvents =
+ new HashMap<IBreakpoint, LinkedList<PendingEventInfo>>();
+
+ ///////////////////////////////////////////////////////////////////////////
+ // AbstractDsfService
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * The service constructor
+ *
+ * @param session
+ * @param debugModelId
+ */
+ public BreakpointsMediator2(DsfSession session, IBreakpointAttributeTranslator2 attributeTranslator) {
+ super(session);
+ fAttributeTranslator2 = attributeTranslator;
+ }
+
+ @Override
+ public void initialize(final RequestMonitor rm) {
+ // - Collect references for the services we interact with
+ // - Register to interesting events
+ // - Obtain the list of platform breakpoints
+ // - Register the service for interested parties
+ super.initialize(
+ new RequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleSuccess() {
+ doInitialize(rm);
+ }});
+ }
+
+ /**
+ * Asynchronous service initialization
+ *
+ * @param requestMonitor
+ */
+ private void doInitialize(RequestMonitor rm) {
+
+ // Get the services references
+ fBreakpointsService = getServicesTracker().getService(IBreakpoints.class);
+ fBreakpointManager = DebugPlugin.getDefault().getBreakpointManager();
+ fAttributeTranslator2.initialize(this);
+
+ // Register to the useful events
+ fBreakpointManager.addBreakpointListener(this);
+
+ // Register this service
+ register(new String[] { BreakpointsMediator2.class.getName() },
+ new Hashtable<String, String>());
+
+ rm.done();
+ }
+
+ @Override
+ public void shutdown(final RequestMonitor rm) {
+ // - 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...
+
+ // Stop accepting requests and events
+ unregister();
+ fBreakpointManager.removeBreakpointListener(this);
+ fAttributeTranslator2.dispose();
+
+ // 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() {
+ BreakpointsMediator2.super.shutdown(rm);
+ }
+ };
+
+ // We have to make a copy of the fPlatformBPs keys because uninstallBreakpoints()
+ // modifies the map as it walks through it.
+ List<IBreakpointsTargetDMContext> platformBPKeysCopy = new ArrayList<IBreakpointsTargetDMContext>(fPlatformBPs.size());
+ platformBPKeysCopy.addAll(0, fPlatformBPs.keySet());
+ for (IBreakpointsTargetDMContext dmc : platformBPKeysCopy) {
+ stopTrackingBreakpoints(dmc, countingRm);
+ }
+ countingRm.setDoneCount(platformBPKeysCopy.size());
+ }
+
+ @Override
+ protected BundleContext getBundleContext() {
+ return DsfPlugin.getBundleContext();
+ }
+
+ protected String getPluginID() {
+ return DsfPlugin.PLUGIN_ID;
+ }
+
+ protected Plugin getPlugin() {
+ return DsfPlugin.getDefault();
+ }
+
+ /**
+ * 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 #stopTrackingBreakpoints} 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) {
+ // - Augment the maps with the new execution context
+ // - Install the platform breakpoints on the selected target
+
+ // Make sure a mapping for this execution context does not already exist
+ Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
+ if (platformBPs != null) {
+ rm.setStatus(new Status(IStatus.ERROR, getPluginID(), INTERNAL_ERROR, "Context already initialized", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ // Create entries in the breakpoint tables for the new context. These entries should only
+ // be removed when this service stops tracking breakpoints for the given context.
+ fPlatformBPs.put(dmc, new HashMap<IBreakpoint, List<TargetBP>>());
+
+ // Install the platform breakpoints (stored in fPlatformBPs) on the target.
+ // We need to use a background thread for this operation because we are
+ // accessing the resources system to retrieve the breakpoint attributes.
+ // Accessing the resources system potentially requires using global locks.
+ // Also we will be calling IBreakpointAttributeTranslator which is prohibited
+ // from being called on the session executor thread.
+ new Job("Install initial breakpoint list.") { //$NON-NLS-1$
+ { setSystem(true); }
+
+ // Get the stored breakpoints from the platform BreakpointManager
+ // and install them on the target
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ doBreakpointsAdded(DebugPlugin.getDefault().getBreakpointManager().getBreakpoints(), dmc, rm);
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+
+ /**
+ * Remove and stop installing breakpoints for the given breakpoints target context.
+ * @param dmc Context to stop tracking breakpoints for.
+ * @param rm Completion callback.
+ */
+ public void stopTrackingBreakpoints(final IBreakpointsTargetDMContext dmc, final RequestMonitor rm) {
+ // - Remove the target breakpoints for the given execution context
+ // - Update the maps
+
+ // Remove the breakpoints for given DMC from the internal maps.
+ Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
+ if (platformBPs == null || platformBPs.size() == 0) {
+ rm.setStatus(new Status(IStatus.INFO /* NOT error */, getPluginID(), INTERNAL_ERROR, "Breakpoints not installed for given context", null)); //$NON-NLS-1$
+ rm.done();
+ return;
+ }
+
+ // Just remove the IBreakpoints installed for the "dmc".
+ final IBreakpoint[] bps = platformBPs.keySet().toArray(new IBreakpoint[platformBPs.size()]);
+
+ new Job("Uninstall target breakpoints list.") { //$NON-NLS-1$
+ { setSystem(true); }
+
+ // Get the stored breakpoints from the platform BreakpointManager
+ // and install them on the target
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ doBreakpointsRemoved(bps, dmc, rm);
+ return Status.OK_STATUS;
+ }
+ }.schedule();
+ }
+
+ /**
+ * Find target breakpoints installed in the given context that are resolved
+ * from the given platform breakpoint.
+ *
+ * @param dmc - context
+ * @param platformBp - platform breakpoint
+ * @return array of target breakpoints.
+ */
+ public ITargetBreakpointInfo[] getTargetBreakpoints(IBreakpointsTargetDMContext dmc, IBreakpoint platformBp) {
+ assert getExecutor().isInExecutorThread();
+
+ Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
+
+ if (platformBPs != null)
+ {
+ List<TargetBP> bpInfo = platformBPs.get(platformBp);
+ if (bpInfo != null) {
+ return bpInfo.toArray(new ITargetBreakpointInfo[bpInfo.size()]);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Find the platform breakpoint that's mapped to the given target breakpoint.
+ *
+ * @param dmc - context of the target breakpoint, can be null.
+ * @param bp - target breakpoint
+ * @return platform breakpoint. null if not found.
+ */
+ public IBreakpoint getPlatformBreakpoint(IBreakpointsTargetDMContext dmc, IBreakpointDMContext bp) {
+ assert getExecutor().isInExecutorThread();
+
+ for (IBreakpointsTargetDMContext bpContext : fPlatformBPs.keySet()) {
+ if (dmc != null && !dmc.equals(bpContext))
+ continue;
+
+ Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(bpContext);
+
+ if (platformBPs != null && platformBPs.size() > 0)
+ {
+ for(Map.Entry<IBreakpoint, List<TargetBP>> e: platformBPs.entrySet())
+ {
+ // Stop at the first occurrence
+ for (TargetBP tbp : e.getValue())
+ if(tbp.getTargetBreakpoint().equals(bp))
+ return e.getKey();
+ }
+ }
+ }
+
+ return null;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Back-end interface functions
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Install a new platform breakpoint on the back-end. A platform breakpoint
+ * can resolve into multiple back-end breakpoints, e.g. when threads are taken
+ * into account.
+ *
+ * @param dmc
+ * @param breakpoint
+ * @param attrsList - list of attribute map, each mapping to a potential target BP.
+ * @param rm
+ */
+ private void installBreakpoint(IBreakpointsTargetDMContext dmc, final IBreakpoint breakpoint,
+ final List<Map<String, Object>> attrsList, final DataRequestMonitor<List<TargetBP>> rm)
+ {
+ // Retrieve the set of breakpoints for this context
+ final Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
+ assert platformBPs != null;
+
+ // Ensure the breakpoint is not already installed
+ assert !platformBPs.containsKey(breakpoint);
+
+ final ArrayList<TargetBP> targetBPsAttempted = new ArrayList<TargetBP>(attrsList.size());
+ for (int i = 0; i < attrsList.size(); i++) {
+ targetBPsAttempted.add(new TargetBP(attrsList.get(i)));
+ }
+
+ final ArrayList<TargetBP> targetBPsInstalled = new ArrayList<TargetBP>(attrsList.size());
+
+ // Update the breakpoint status when all back-end breakpoints have been installed
+ final CountingRequestMonitor installRM = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ // Store successful targetBPs with the platform breakpoint
+ if (targetBPsInstalled.size() > 0)
+ platformBPs.put(breakpoint, targetBPsInstalled);
+
+ // Store all targetBPs, success or failure, in the rm.
+ rm.setData(targetBPsAttempted);
+ rm.done();
+ }
+ };
+
+ // A back-end breakpoint needs to be installed for each specified attributes map.
+ installRM.setDoneCount(attrsList.size());
+
+ // Install the back-end breakpoint(s)
+ for (int _i = 0; _i < attrsList.size(); _i++) {
+ final int i = _i;
+ fBreakpointsService.insertBreakpoint(
+ dmc, attrsList.get(i),
+ new DataRequestMonitor<IBreakpointDMContext>(getExecutor(), installRM) {
+ @Override
+ protected void handleCompleted() {
+ TargetBP targetBP = targetBPsAttempted.get(i);
+ if (isSuccess()) {
+ // Add the breakpoint back-end mapping
+ targetBP.setTargetBreakpoint(getData());
+
+ targetBPsInstalled.add(targetBP);
+ }
+ targetBP.setStatus(getStatus());
+
+ installRM.done();
+ }
+ });
+ }
+ }
+
+ /**
+ * Un-install an individual breakpoint on the back-end. For one platform
+ * breakpoint, there could be multiple corresponding back-end breakpoints.
+ *
+ * @param dmc
+ * @param breakpoint
+ * @param drm
+ */
+ private void uninstallBreakpoint(final IBreakpointsTargetDMContext dmc, final IBreakpoint breakpoint,
+ final DataRequestMonitor<List<TargetBP>> drm)
+ {
+ // Remove the back-end breakpoints
+ final Map<IBreakpoint, List<TargetBP>> platformBPs = fPlatformBPs.get(dmc);
+ if (platformBPs == null) {
+ drm.setStatus(new Status(IStatus.ERROR, getPluginID(), INVALID_HANDLE, "Invalid breakpoint", null)); //$NON-NLS-1$
+ drm.done();
+ return;
+ }
+
+ final List<TargetBP> bpList = platformBPs.get(breakpoint);
+ assert bpList != null;
+
+ // Only try to remove those targetBPs that are successfully installed.
+
+ // Remove completion monitor
+ final CountingRequestMonitor countingRm = new CountingRequestMonitor(getExecutor(), drm) {
+ @Override
+ protected void handleCompleted() {
+ platformBPs.remove(breakpoint);
+
+ // Complete the request monitor.
+ drm.setData(bpList);
+ drm.done();
+ }
+ };
+
+ int count = 0;
+ for (int i = 0; i < bpList.size(); i++) {
+ final TargetBP bp = bpList.get(i);
+ if (bp.getTargetBreakpoint() != null) {
+ fBreakpointsService.removeBreakpoint(
+ bp.getTargetBreakpoint(),
+ new RequestMonitor(getExecutor(), countingRm) {
+ @Override
+ protected void handleCompleted() {
+ bp.setStatus(getStatus());
+ if (isSuccess()) {
+ bp.setTargetBreakpoint(null);
+ }
+ countingRm.done();
+ }
+ });
+ count++;
+ } else {
+ bp.setStatus(Status.OK_STATUS);
+ }
+ }
+ countingRm.setDoneCount(count);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // IBreakpointManagerListener implementation
+ ///////////////////////////////////////////////////////////////////////////
+
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @ThreadSafeAndProhibitedFromDsfExecutor("getExecutor()")
+ public void breakpointsAdded(final IBreakpoint[] bps) {
+ doBreakpointsAdded(bps, null, null);
+ }
+
+ protected void doBreakpointsAdded(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
+ // Collect attributes (which will access system resource)
+ // in non DSF dispatch thread.
+ //
+ final PlatformBreakpointInfo[] bpsInfo = collectBreakpointsInfo(bps);
+
+ // Nothing to do
+ if (bpsInfo.length == 0) {
+ if (rm != null) {
+ rm.done();
+ }
+ return;
+ }
+
+ try {
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ Collection<IBreakpointsTargetDMContext> dmcs = new ArrayList<IBreakpointsTargetDMContext>();
+ if (bpsTargetDmc == null)
+ dmcs.addAll(fPlatformBPs.keySet());
+ else
+ dmcs.add(bpsTargetDmc);
+
+ doBreakpointsAddedInExecutor(bpsInfo, dmcs, rm);
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ IStatus status = new Status(IStatus.ERROR, getPluginID(), IDsfStatusConstants.INTERNAL_ERROR, "Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", e);//$NON-NLS-1$ //$NON-NLS-2$
+ if (rm != null) {
+ rm.setStatus(status);
+ rm.done();
+ } else {
+ getPlugin().getLog().log(status);
+ }
+ }
+ }
+
+ /**
+ * Collect breakpoint info. This method must not be called in DSF dispatch thread.
+ * @param bps
+ * @return
+ */
+ private PlatformBreakpointInfo[] collectBreakpointsInfo(IBreakpoint[] bps) {
+ List<PlatformBreakpointInfo> bpsInfo = new ArrayList<PlatformBreakpointInfo>(bps.length);
+
+ for (IBreakpoint bp : bps) {
+ if (bp.getMarker() == null)
+ continue;
+
+ if (fAttributeTranslator2.supportsBreakpoint(bp)) {
+ try {
+ Map<String, Object> attrs = fAttributeTranslator2.getAllBreakpointAttributes(bp, fBreakpointManager.isEnabled());
+ boolean enabled = bp.isEnabled() && fBreakpointManager.isEnabled();
+ bpsInfo.add(new PlatformBreakpointInfo(bp, enabled, attrs));
+ } catch (CoreException e) {
+ getPlugin().getLog().log(e.getStatus());
+ }
+ }
+ }
+
+ return bpsInfo.toArray(new PlatformBreakpointInfo[bpsInfo.size()]);
+ }
+
+ protected void doBreakpointsAddedInExecutor(PlatformBreakpointInfo[] bpsInfo, Collection<IBreakpointsTargetDMContext> bpTargetDMCs, final RequestMonitor rm) {
+ final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =
+ new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpsInfo.length, 1);
+
+ CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ processPendingRequests();
+ fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.ADDED);
+ if (rm != null)
+ // don't call this if "rm" is null as this will
+ // log errors if any and pack Eclipse error
+ // log view with errors meaningless to user.
+ super.handleCompleted();
+ }
+ };
+ int processPendingCountingRmCount = 0;
+
+ for (final PlatformBreakpointInfo bpinfo : bpsInfo) {
+ final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs =
+ new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
+ eventBPs.put(bpinfo.breakpoint, targetBPs);
+
+ // Remember the new attributes of the bp in our global buffer,
+ // even if we cannot or fail to install the bp.
+ fBreakpointAttributes.put(bpinfo.breakpoint, bpinfo.attributes);
+
+ if (fRunningEvents.contains(bpinfo.breakpoint)) {
+ PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.ADDED, bpinfo, bpTargetDMCs, processPendingCountingRm);
+ processPendingCountingRmCount++;
+ updatePendingRequest(bpinfo.breakpoint, pendingEvent);
+ continue;
+ }
+
+ processPendingCountingRmCount++;
+
+ // Mark the breakpoint as being updated and go
+ fRunningEvents.add(bpinfo.breakpoint);
+
+ final CountingRequestMonitor bpTargetsCountingRm = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
+ @Override
+ protected void handleCompleted() {
+ // Indicate that the running event has completed
+ fRunningEvents.remove(bpinfo.breakpoint);
+ super.handleCompleted();
+ }
+ };
+
+ int bpTargetsCountingRmCount = 0;
+
+ // Install the breakpoint in all the execution contexts
+ for (final IBreakpointsTargetDMContext dmc : bpTargetDMCs) {
+
+ // Now ask lower level to set the bp.
+ //
+ // if the breakpoint is disabled, ask back-end if it can set (and manage)
+ // disabled breakpoint. If not, just bail out.
+ //
+ if (! bpinfo.enabled) {
+ Map<String, Object> attr = new HashMap<String, Object>(1);
+ attr.put(IBreakpoint.ENABLED, Boolean.FALSE);
+ Map<String, Object> targetEnablementAttr = fAttributeTranslator2.convertAttributes(attr);
+ if (! fAttributeTranslator2.canUpdateAttributes(bpinfo.breakpoint, dmc, targetEnablementAttr)) {
+ // bail out. Continue with the next dmc & breakpoint.
+ continue;
+ }
+ }
+
+ // Now do the real work.
+ //
+ fAttributeTranslator2.resolveBreakpoint(dmc, bpinfo.breakpoint, bpinfo.attributes,
+ new DataRequestMonitor<List<Map<String,Object>>>(getExecutor(), bpTargetsCountingRm){
+ @Override
+ protected void handleSuccess() {
+ installBreakpoint(
+ dmc, bpinfo.breakpoint, getData(),
+ new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRm) {
+ @Override
+ protected void handleSuccess() {
+ targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
+ super.handleSuccess();
+ };
+ });
+ }});
+
+ bpTargetsCountingRmCount++;
+ }
+
+ bpTargetsCountingRm.setDoneCount(bpTargetsCountingRmCount);
+ }
+
+ processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
+ }
+
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @ThreadSafeAndProhibitedFromDsfExecutor("getExecutor()")
+ public void breakpointsChanged(IBreakpoint[] bps, IMarkerDelta[] deltas) {
+ if (fAttributeTranslator2 == null)
+ return;
+
+ final PlatformBreakpointInfo[] bpsInfo = collectBreakpointsInfo(bps);
+
+ if (bpsInfo.length == 0)
+ return; // nothing to do
+
+ try {
+ getExecutor().execute( new DsfRunnable() {
+ public void run() {
+ Map<String, Object> tmp = new HashMap<String, Object>(1);
+ tmp.put(IBreakpoint.ENABLED, true);
+ final String targetEnablementKey = fAttributeTranslator2.convertAttributes(tmp).keySet().iterator().next();
+
+ for (PlatformBreakpointInfo bpinfo : bpsInfo) {
+ /*
+ * We cannot depend on "deltas" for attribute change.
+ * For instance, delta can be null when extended
+ * attributes (e.g. breakpoint thread filter for GDB)
+ * are changed.
+ */
+ Map<String, Object> newAttrs = bpinfo.attributes;
+ Map<String, Object> oldAttrs = fBreakpointAttributes.get(bpinfo.breakpoint);
+
+ // remember the new attributes.
+ fBreakpointAttributes.put(bpinfo.breakpoint, newAttrs);
+
+ if (oldAttrs == null)
+ continue;
+
+ final Map<String, Object> attrDelta = getAttributesDelta(oldAttrs, newAttrs);
+ if (attrDelta.size() == 0)
+ continue;
+
+ final List<IBreakpointsTargetDMContext> reinstallContexts = new ArrayList<IBreakpointsTargetDMContext>();
+
+ List<IBreakpointsTargetDMContext> updateContexts = new ArrayList<IBreakpointsTargetDMContext>();
+
+ // Now change the breakpoint for each known context.
+ //
+ for (final IBreakpointsTargetDMContext btContext : fPlatformBPs.keySet()) {
+
+ if (! fAttributeTranslator2.canUpdateAttributes(bpinfo.breakpoint, btContext, attrDelta)) {
+ // backend cannot handle at least one of the platform BP attribute change,
+ // we'll re-install the bp.
+ reinstallContexts.add(btContext);
+ }
+ else {
+ // Backend claims it can handle the attributes change, let it do it.
+ updateContexts.add(btContext);
+ }
+
+ }
+
+ final PlatformBreakpointInfo[] oneBPInfo = new PlatformBreakpointInfo[] {bpinfo};
+ IBreakpoint[] oneBP = new IBreakpoint[] {bpinfo.breakpoint};
+
+ if (reinstallContexts.size() > 0) {
+ // Check if it's only enablement change (user click enable/disable
+ // button or "Skip all breakpoints" button), which is common operation.
+ //
+ if (attrDelta.size() == 1 && attrDelta.containsKey(targetEnablementKey)) { // only enablement changed.
+ if (bpinfo.enabled) {
+ // change from disable to enable. Install the bp.
+ doBreakpointsAddedInExecutor(oneBPInfo, reinstallContexts, null);
+ }
+ else {
+ // change from enable to disable. Remove the bp.
+ doBreakpointsRemovedInExecutor(oneBP, reinstallContexts, null);
+ }
+ }
+ else {
+ doBreakpointsRemovedInExecutor(oneBP, reinstallContexts, new RequestMonitor(getExecutor(), null) {
+ // What should we do if removal of some or all targetBP fails ?
+ // Go on with the installation of new targetBPs and let clients (i.e. AttributeTranslators)
+ // handle the errors.
+ @Override
+ protected void handleCompleted() {
+ doBreakpointsAddedInExecutor(oneBPInfo, reinstallContexts, null);
+ }});
+ }
+ }
+
+ if (updateContexts.size() > 0)
+ modifyTargetBreakpoints(bpinfo.breakpoint, updateContexts, attrDelta);
+ }
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ getPlugin().getLog().log(new Status(IStatus.ERROR, getPluginID(), IDsfStatusConstants.INTERNAL_ERROR, "Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", e)); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ }
+
+ /**
+ * For the given platform BP, ask the backend to modify all its target BPs
+ * with the given attribute change. <br>
+ * This must be called in DSF executor thread.
+ *
+ * @param bp
+ * @param updateContexts
+ * target contexts in which to do the modification.
+ * @param targetAttrDelta
+ * target-recognizable attribute(s) with new values.
+ */
+ private void modifyTargetBreakpoints(final IBreakpoint bp, Collection<IBreakpointsTargetDMContext> updateContexts, Map<String, Object> targetAttrDelta) {
+ // If the breakpoint is currently being updated, queue the request and exit
+ if (fRunningEvents.contains(bp)) {
+ PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.MODIFIED, updateContexts, targetAttrDelta);
+ updatePendingRequest(bp, pendingEvent);
+ return;
+ }
+
+ CountingRequestMonitor modifyTargetBPCRM = new CountingRequestMonitor(getExecutor(), null) {
+ @Override
+ protected void handleCompleted() {
+ fRunningEvents.remove(bp);
+ }};
+
+ int targetBPCount = 0;
+
+ fRunningEvents.add(bp);
+
+ for (IBreakpointsTargetDMContext context : updateContexts) {
+ List<TargetBP> targetBPs = fPlatformBPs.get(context).get(bp);
+ if (targetBPs != null) {
+ for (TargetBP tbp : targetBPs) {
+ // this must be an installed breakpoint.
+ assert (tbp.getTargetBreakpoint() != null);
+
+ targetBPCount++;
+ fBreakpointsService.updateBreakpoint(tbp.getTargetBreakpoint(), targetAttrDelta, modifyTargetBPCRM);
+ }
+ }
+ }
+
+ modifyTargetBPCRM.setDoneCount(targetBPCount);
+ }
+
+ /**
+ * @noreference This method is not intended to be referenced by clients.
+ */
+ @ThreadSafeAndProhibitedFromDsfExecutor("getExecutor()")
+ public void breakpointsRemoved(final IBreakpoint[] bps, IMarkerDelta delta[]) {
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ for (IBreakpoint bp : bps)
+ fBreakpointAttributes.remove(bp);
+ }
+ });
+
+ doBreakpointsRemoved(bps, null, null);
+ }
+
+ protected void doBreakpointsRemoved(final IBreakpoint[] bps, final IBreakpointsTargetDMContext bpsTargetDmc, final RequestMonitor rm) {
+
+ final List<IBreakpoint> bpCandidates = new ArrayList<IBreakpoint>();
+
+ for (int i = 0; i < bps.length; i++) {
+ IBreakpoint bp = bps[i];
+
+ if (fAttributeTranslator2.supportsBreakpoint(bp)) {
+ bpCandidates.add(bp);
+ }
+ }
+
+ if (bpCandidates.isEmpty()) { // nothing to do
+ if (rm != null)
+ rm.done();
+ return;
+ }
+
+ try {
+ getExecutor().execute(new DsfRunnable() {
+ public void run() {
+ Collection<IBreakpointsTargetDMContext> contexts = new ArrayList<IBreakpointsTargetDMContext>();
+ if (bpsTargetDmc == null)
+ contexts.addAll(fPlatformBPs.keySet());
+ else
+ contexts.add(bpsTargetDmc);
+
+ doBreakpointsRemovedInExecutor(bpCandidates.toArray(new IBreakpoint[bpCandidates.size()]), contexts, rm);
+ }
+ });
+ } catch (RejectedExecutionException e) {
+ IStatus status = new Status(IStatus.ERROR, getPluginID(), IDsfStatusConstants.INTERNAL_ERROR,
+ "Request for monitor: '" + toString() + "' resulted in a rejected execution exception.", e);//$NON-NLS-1$ //$NON-NLS-2$
+ if (rm != null) {
+ rm.setStatus(status);
+ rm.done();
+ } else {
+ getPlugin().getLog().log(status);
+ }
+ }
+ }
+
+ protected void doBreakpointsRemovedInExecutor(IBreakpoint[] bpCandidates,
+ Collection<IBreakpointsTargetDMContext> targetContexts, final RequestMonitor rm) {
+
+ final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs =
+ new HashMap<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>>(bpCandidates.length, 1);
+
+ CountingRequestMonitor processPendingCountingRm = new CountingRequestMonitor(getExecutor(), rm) {
+ @Override
+ protected void handleCompleted() {
+ processPendingRequests();
+ fireUpdateBreakpointsStatus(eventBPs, BreakpointEventType.REMOVED);
+ if (rm != null)
+ // don't call this if "rm" is null as this will
+ // log errors if any and pack Eclipse error
+ // log view with errors meaningless to user.
+ super.handleCompleted();
+ }
+ };
+ int processPendingCountingRmCount = 0;
+
+ for (final IBreakpoint breakpoint : bpCandidates) {
+
+ // If the breakpoint is currently being updated, queue the request and exit
+ if (fRunningEvents.contains(breakpoint)) {
+ PendingEventInfo pendingEvent = new PendingEventInfo(BreakpointEventType.REMOVED, null, targetContexts, processPendingCountingRm);
+ processPendingCountingRmCount++;
+ updatePendingRequest(breakpoint, pendingEvent);
+ continue; // handle next breakpoint
+ }
+
+ processPendingCountingRmCount++;
+
+ final Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]> targetBPs =
+ new HashMap<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>(fPlatformBPs.size(), 1);
+ eventBPs.put(breakpoint, targetBPs);
+
+ CountingRequestMonitor bpTargetsCountingRM = new CountingRequestMonitor(getExecutor(), processPendingCountingRm) {
+ @Override
+ protected void handleCompleted() {
+ // Indicate that the running event has completed
+ fRunningEvents.remove(breakpoint);
+ super.handleCompleted();
+ }
+ };
+
+ int bpTargetsCoutingRMCount = 0;
+
+ // Mark the breakpoint as being updated and go
+ fRunningEvents.add(breakpoint);
+
+ // Remove the breakpoint in all the execution contexts
+ for (final IBreakpointsTargetDMContext dmc : targetContexts) {
+
+ if (fPlatformBPs.get(dmc).containsKey(breakpoint)) { // there are targetBPs installed
+ // now do time-consuming part of the work.
+
+ uninstallBreakpoint(
+ dmc, breakpoint,
+ new DataRequestMonitor<List<TargetBP>>(getExecutor(), bpTargetsCountingRM) {
+ @Override
+ protected void handleSuccess() {
+ targetBPs.put(dmc, getData().toArray(new ITargetBreakpointInfo[getData().size()]));
+ super.handleSuccess();
+ };
+ });
+ bpTargetsCoutingRMCount++;
+ } else {
+ // Breakpoint not installed for given context, do nothing.
+ }
+ }
+
+ bpTargetsCountingRM.setDoneCount(bpTargetsCoutingRMCount);
+ }
+
+ processPendingCountingRm.setDoneCount(processPendingCountingRmCount);
+ }
+
+ private void updatePendingRequest(IBreakpoint breakpoint, PendingEventInfo pendingEvent) {
+ LinkedList<PendingEventInfo> pendingEventsList = fPendingEvents.get(breakpoint);
+ if (pendingEventsList == null) {
+ pendingEventsList = new LinkedList<PendingEventInfo>();
+ fPendingEvents.put(breakpoint, pendingEventsList);
+ }
+ if (pendingEventsList.size() > 0 &&
+ pendingEventsList.getLast().fEventType == BreakpointEventType.MODIFIED) {
+ pendingEventsList.removeLast();
+ }
+ pendingEventsList.add(pendingEvent);
+ }
+
+ private void processPendingRequests() {
+ /*
+ * This will process only first pending request for each breakpoint,
+ * whose RequestMonitor (see "processPendingCountingRm" in such methods as
+ * doBreakpointsRemovedInExecutor()) will invoke this method again.
+ */
+ if (fPendingEvents.isEmpty()) return; // Nothing to do
+
+ // Make a copy to avoid ConcurrentModificationException
+ // as we are deleting element in the loop.
+ Set<IBreakpoint> bpsInPendingEvents = new HashSet<IBreakpoint>(fPendingEvents.keySet());
+ for (IBreakpoint bp : bpsInPendingEvents) {
+ if (! fRunningEvents.contains(bp)) {
+ LinkedList<PendingEventInfo> eventInfoList = fPendingEvents.get(bp);
+
+ // Process the first pending request for this breakpoint
+ PendingEventInfo eventInfo = eventInfoList.removeFirst();
+
+ if (eventInfoList.isEmpty())
+ fPendingEvents.remove(bp);
+
+ switch (eventInfo.fEventType) {
+ case ADDED:
+ doBreakpointsAddedInExecutor(new PlatformBreakpointInfo[] {eventInfo.fBPInfo}, eventInfo.fBPTargetContexts, eventInfo.fRequestMonitor);
+ break;
+ case MODIFIED:
+ modifyTargetBreakpoints(bp, eventInfo.fBPTargetContexts, eventInfo.fAttributeDelta);
+ break;
+ case REMOVED:
+ doBreakpointsRemovedInExecutor(new IBreakpoint[]{bp}, eventInfo.fBPTargetContexts, eventInfo.fRequestMonitor);
+ break;
+ }
+ }
+ }
+ }
+
+ private void fireUpdateBreakpointsStatus(final Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> eventBPs, final BreakpointEventType eventType) {
+ // Update breakpoint status
+ new Job("Breakpoint status update") { //$NON-NLS-1$
+ { setSystem(true); }
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ fAttributeTranslator2.updateBreakpointsStatus(eventBPs, eventType);
+ return Status.OK_STATUS;
+ };
+ }.schedule();
+
+ }
+
+ /**
+ * Determine the set of modified attributes.
+ *
+ * @param oldAttributes old map of attributes.
+ * @param newAttributes new map of attributes.
+ * @return new and changed attribute in the new map. May be empty indicating the two maps are equal.
+ */
+ private Map<String, Object> getAttributesDelta(Map<String, Object> oldAttributes, Map<String, Object> newAttributes) {
+
+ Map<String, Object> delta = new HashMap<String,Object>();
+
+ Set<String> oldKeySet = oldAttributes.keySet();
+ Set<String> newKeySet = newAttributes.keySet();
+
+ Set<String> commonKeys = new HashSet<String>(newKeySet); commonKeys.retainAll(oldKeySet);
+ Set<String> addedKeys = new HashSet<String>(newKeySet); addedKeys.removeAll(oldKeySet);
+ Set<String> removedKeys = new HashSet<String>(oldKeySet); removedKeys.removeAll(newKeySet);
+
+ // Add the modified attributes
+ for (String key : commonKeys) {
+ if (!(oldAttributes.get(key).equals(newAttributes.get(key))))
+ delta.put(key, newAttributes.get(key));
+ }
+
+ // Add the new attributes
+ for (String key : addedKeys) {
+ delta.put(key, newAttributes.get(key));
+ }
+
+ // Remove the deleted attributes
+ for (String key : removedKeys) {
+ delta.put(key, null);
+ }
+
+ return delta;
+ }
+}
diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator.java
index 3d7761d0d37..e17a086cb7f 100644
--- a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator.java
+++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator.java
@@ -13,29 +13,62 @@ package org.eclipse.cdt.dsf.debug.service;
import java.util.List;
import java.util.Map;
+import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.model.IBreakpoint;
/**
- * Breakpoint attribute translator interface
+ * Breakpoint attribute translator is used by the {@link BreakpointsMediator}
+ * to map IDE breakpoint attributes to debugger breakpoint attributes.
+ * <p>
+ * Note: The attribute translator is expected to access IDE breakpoint manager
+ * objects which are synchronized using the resource system. Therefore all the
+ * translator methods are called using background threads. When the attribute
+ * translator needs to access DSF services, it needs to schedule a runnable using
+ * the DSF session executable.
*
+ * @see BreakpointMediator
* @since 1.0
*/
-
@ThreadSafeAndProhibitedFromDsfExecutor("")
public interface IBreakpointAttributeTranslator {
- public void initialize(BreakpointsMediator mediator);
-
+ /**
+ * Initializes the translator. This method is called by the breakpoint
+ * mediator service, when the mediator service is initialized.
+ */
+ @ConfinedToDsfExecutor("")
+ public void initialize(BreakpointsMediator mediator);
+
+ /**
+ * Disposes the translator. Also called by the mediator upon service
+ * shutdown.
+ */
+ @ConfinedToDsfExecutor("")
public void dispose();
-
+
+ /**
+ * Returns whether the given IDE breakpoint is supported by this debugger.
+ */
+ public boolean supportsBreakpoint(IBreakpoint bp);
+
+ /**
+ * Returns the target breakpoint attributes for the given IDE breakpoint.
+ */
public List<Map<String, Object>> getBreakpointAttributes(IBreakpoint breakpoint, boolean bpManagerEnabled) throws CoreException;
+ /**
+ * Based on the given change in IDE breakpoint attributes, this method returns
+ * whether the given target breakpoint can be modified using
+ * {@link IBreakpoints#updateBreakpoint(IBreakpointDMContext, Map, org.eclipse.cdt.dsf.concurrent.RequestMonitor)}
+ * method.
+ */
public boolean canUpdateAttributes(IBreakpointDMContext bp, Map<String, Object> delta);
- public boolean supportsBreakpoint(IBreakpoint bp);
-
+ /**
+ * Notifies the translator to update the given IDE breakpoint's status.
+ */
public void updateBreakpointStatus(IBreakpoint bp);
} \ No newline at end of file
diff --git a/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator2.java b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator2.java
new file mode 100644
index 00000000000..e76da5827b0
--- /dev/null
+++ b/dsf/org.eclipse.cdt.dsf/src/org/eclipse/cdt/dsf/debug/service/IBreakpointAttributeTranslator2.java
@@ -0,0 +1,154 @@
+/*******************************************************************************
+ * Copyright (c) 2008 Wind River Systems and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Wind River Systems - initial API and implementation
+ * Nokia - enhanced to work for both GDB and EDC. Nov. 2009.
+ *******************************************************************************/
+package org.eclipse.cdt.dsf.debug.service;
+
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
+import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafe;
+import org.eclipse.cdt.dsf.concurrent.ThreadSafeAndProhibitedFromDsfExecutor;
+import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator2.BreakpointEventType;
+import org.eclipse.cdt.dsf.debug.service.BreakpointsMediator2.ITargetBreakpointInfo;
+import org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointsTargetDMContext;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.debug.core.model.IBreakpoint;
+
+/**
+ * Breakpoint attribute translator is used by the {@link BreakpointsMediator2}
+ * to map IDE breakpoint attributes to debugger breakpoint attributes.
+ * <p>
+ * Note: The attribute translator is expected to access IDE breakpoint manager
+ * objects which are synchronized using the resource system. It may also need to
+ * access DSF services using the DSF session executor. Therefore, the
+ * implementation needs to pay special attention to the synchronization
+ * annotations on each method of the interface.
+ *
+ * @see BreakpointMediator
+ * @since 2.1
+ */
+public interface IBreakpointAttributeTranslator2 {
+
+ /**
+ * Initializes the translator. This method is called by the breakpoint
+ * mediator service, when the mediator service is initialized.
+ */
+ @ConfinedToDsfExecutor("")
+ public void initialize(BreakpointsMediator2 mediator);
+
+ /**
+ * Disposes the translator. Also called by the mediator upon service
+ * shutdown.
+ */
+ @ConfinedToDsfExecutor("")
+ public void dispose();
+
+ /**
+ * Returns whether the given IDE breakpoint is supported by this debugger.
+ */
+ @ThreadSafeAndProhibitedFromDsfExecutor("")
+ public boolean supportsBreakpoint(IBreakpoint bp);
+
+ /**
+ * Resolve the breakpoint in given context. A platform BP may be mapped to
+ * ont or more target BPs, e.g. a breakpoint in an in-line function may be
+ * mapped to several target BPs, or a thread-specific BP may be mapped to
+ * several target BPs each of which is for one thread. This method will get
+ * the list of attribute maps each of which corresponds to one target BP.
+ * <p>
+ * This method is and must be called in DSF execution thread.
+ *
+ * @param context
+ * - a IBreakpointsTargetDMContext object (which could be a
+ * process or a loaded module) in which we locate target BPs for
+ * the platform BP. Cannot be null.
+ * @param breakpoint
+ * - platform breakpoint.
+ * @param bpAttributes
+ * - all attributes of the breakpoint, usually output from
+ * {@link #getAllBreakpointAttributes(IBreakpoint, boolean)}.
+ * @param drm
+ * - on completion of the request, the DataRequestMonitor
+ * contains one or more attribute maps each of which
+ * corresponding to one target breakpoint.
+ * @throws CoreException
+ */
+ @ConfinedToDsfExecutor("")
+ public void resolveBreakpoint(IBreakpointsTargetDMContext context, IBreakpoint breakpoint,
+ Map<String, Object> bpAttributes, DataRequestMonitor<List<Map<String, Object>>> drm);
+
+ /**
+ * Get all platform defined attributes for a breakpoint plus all attributes
+ * defined by any breakpoint extension such as ICBreakpointExtension in CDT.
+ * In other words, get all attributes available from UI.
+ * <p>
+ * The attributes returned are independent of runtime context (process,
+ * module, etc), whereas attributes from
+ * {@link #resolveBreakpoint(IBreakpointsTargetDMContext, IBreakpoint, Map, DataRequestMonitor)}
+ * are context sensitive.
+ * <p>
+ * Note this method must not be called in DSF dispatch thread because we are
+ * accessing the resources system to retrieve the breakpoint attributes.
+ * Accessing the resources system potentially requires using global locks.
+ *
+ * @param platformBP
+ * @param bpManagerEnabled
+ * @return list of target (debugger implementation) recognizable attributes.
+ * @throws CoreException
+ */
+ @ThreadSafeAndProhibitedFromDsfExecutor("")
+ public Map<String, Object> getAllBreakpointAttributes(IBreakpoint platformBP, boolean bpManagerEnabled) throws CoreException;
+
+ /**
+ * Convert platform breakpoint attributes to target attributes. This usually
+ * involves changing attributes keys to target recognizable ones. For
+ * instance, GDB integration has its own breakpoint attribute keys.
+ * <p>
+ * This method overlaps somewhat with the {@link #resolveBreakpoint}
+ * method. However, this method is currently only used by the mediator in
+ * conjunction with the {@link #canUpdateAttributes} method.
+ *
+ * @param platformBPAttr
+ * @return
+ */
+ @ThreadSafe
+ public Map<String, Object> convertAttributes(Map<String, Object> platformBPAttr);
+
+ /**
+ * Update platform about breakpoint status change, e.g. breakpoint installed on target successfully or breakpoint
+ * removed from target successfully.
+ * <p>
+ * Note this method is not and must not be called in DSF dispatch thread.
+ *
+ * @param bpsInfo
+ * @param eventType
+ */
+ @ThreadSafeAndProhibitedFromDsfExecutor("")
+ public void updateBreakpointsStatus(Map<IBreakpoint, Map<IBreakpointsTargetDMContext, ITargetBreakpointInfo[]>> bpsInfo, BreakpointEventType eventType);
+
+ /**
+ * This is enhanced version of
+ * {@link #canUpdateAttributes(org.eclipse.cdt.dsf.debug.service.IBreakpoints.IBreakpointDMContext, Map)}
+ * in that this API gives more context parameters so that client can make
+ * decision on a finer granularity when needed.
+ * <p>
+ * This will be called in DSF dispatch thread.
+ *
+ * @param bp platform breakpoint.
+ * @param context
+ * @param attributes target-recognizable attributes.
+ * @return false as long as one of the attributes cannot be updated by client, otherwise true.
+ */
+ @ConfinedToDsfExecutor("")
+ public boolean canUpdateAttributes(IBreakpoint bp, IBreakpointsTargetDMContext context, Map<String, Object> attributes);
+} \ No newline at end of file

Back to the top