13 |
13 |
14 import java.util.HashMap; |
14 import java.util.HashMap; |
15 import java.util.Hashtable; |
15 import java.util.Hashtable; |
16 import java.util.Map; |
16 import java.util.Map; |
17 |
17 |
|
18 import org.eclipse.cdt.debug.core.CDebugCorePlugin; |
|
19 import org.eclipse.cdt.debug.core.model.ICBreakpoint; |
18 import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; |
20 import org.eclipse.cdt.dsf.concurrent.CountingRequestMonitor; |
19 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; |
21 import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor; |
20 import org.eclipse.cdt.dsf.concurrent.Immutable; |
22 import org.eclipse.cdt.dsf.concurrent.Immutable; |
21 import org.eclipse.cdt.dsf.concurrent.RequestMonitor; |
23 import org.eclipse.cdt.dsf.concurrent.RequestMonitor; |
22 import org.eclipse.cdt.dsf.datamodel.AbstractDMContext; |
24 import org.eclipse.cdt.dsf.datamodel.AbstractDMContext; |
25 import org.eclipse.cdt.dsf.datamodel.IDMContext; |
27 import org.eclipse.cdt.dsf.datamodel.IDMContext; |
26 import org.eclipse.cdt.dsf.debug.service.IBreakpoints; |
28 import org.eclipse.cdt.dsf.debug.service.IBreakpoints; |
27 import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; |
29 import org.eclipse.cdt.dsf.debug.service.command.ICommandControl; |
28 import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent; |
30 import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlShutdownDMEvent; |
29 import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; |
31 import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin; |
|
32 import org.eclipse.cdt.dsf.mi.service.MIRunControl.SuspendedEvent; |
|
33 import org.eclipse.cdt.dsf.mi.service.breakpoint.actions.BreakpointActionAdapter; |
30 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakAfter; |
34 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakAfter; |
31 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakCondition; |
35 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakCondition; |
32 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete; |
36 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDelete; |
33 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDisable; |
37 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakDisable; |
34 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakEnable; |
38 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakEnable; |
35 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert; |
39 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakInsert; |
36 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakList; |
40 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakList; |
37 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakWatch; |
41 import org.eclipse.cdt.dsf.mi.service.command.commands.MIBreakWatch; |
|
42 import org.eclipse.cdt.dsf.mi.service.command.events.MIBreakpointHitEvent; |
38 import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointScopeEvent; |
43 import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointScopeEvent; |
|
44 import org.eclipse.cdt.dsf.mi.service.command.events.MIWatchpointTriggerEvent; |
39 import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo; |
45 import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakInsertInfo; |
40 import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo; |
46 import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakListInfo; |
41 import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint; |
47 import org.eclipse.cdt.dsf.mi.service.command.output.MIBreakpoint; |
42 import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; |
48 import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo; |
43 import org.eclipse.cdt.dsf.service.AbstractDsfService; |
49 import org.eclipse.cdt.dsf.service.AbstractDsfService; |
44 import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; |
50 import org.eclipse.cdt.dsf.service.DsfServiceEventHandler; |
45 import org.eclipse.cdt.dsf.service.DsfSession; |
51 import org.eclipse.cdt.dsf.service.DsfSession; |
|
52 import org.eclipse.core.runtime.CoreException; |
|
53 import org.eclipse.core.runtime.IProgressMonitor; |
46 import org.eclipse.core.runtime.IStatus; |
54 import org.eclipse.core.runtime.IStatus; |
47 import org.eclipse.core.runtime.Status; |
55 import org.eclipse.core.runtime.Status; |
|
56 import org.eclipse.core.runtime.jobs.Job; |
48 import org.osgi.framework.BundleContext; |
57 import org.osgi.framework.BundleContext; |
49 |
58 |
50 /** |
59 /** |
51 * Initial breakpoint service implementation. |
60 * Initial breakpoint service implementation. |
52 * Implements the IBreakpoints interface. |
61 * Implements the IBreakpoints interface. |
279 */ |
288 */ |
280 @DsfServiceEventHandler |
289 @DsfServiceEventHandler |
281 public void eventDispatched(ICommandControlShutdownDMEvent e) { |
290 public void eventDispatched(ICommandControlShutdownDMEvent e) { |
282 } |
291 } |
283 |
292 |
|
293 @DsfServiceEventHandler |
|
294 public void eventDispatched(SuspendedEvent e) { |
|
295 |
|
296 if (e.getMIEvent() instanceof MIBreakpointHitEvent) { |
|
297 MIBreakpointHitEvent evt = (MIBreakpointHitEvent) e.getMIEvent(); |
|
298 performBreakpointAction(evt.getDMContext(), evt.getNumber()); |
|
299 return; |
|
300 } |
|
301 |
|
302 if (e.getMIEvent() instanceof MIWatchpointTriggerEvent) { |
|
303 MIWatchpointTriggerEvent evt = (MIWatchpointTriggerEvent) e.getMIEvent(); |
|
304 performBreakpointAction(evt.getDMContext(), evt.getNumber()); |
|
305 return; |
|
306 } |
|
307 } |
|
308 |
|
309 private void performBreakpointAction(final IDMContext context, int number) { |
|
310 // Identify the platform breakpoint |
|
311 final ICBreakpoint breakpoint = findPlatformBreakpoint(context, number); |
|
312 |
|
313 // Perform the actions asynchronously (otherwise we can have a deadlock...) |
|
314 new Job("Breakpoint action") { //$NON-NLS-1$ |
|
315 { setSystem(true); } |
|
316 @Override |
|
317 protected IStatus run(IProgressMonitor monitor) { |
|
318 CDebugCorePlugin.getDefault().getBreakpointActionManager().executeActions(breakpoint, new BreakpointActionAdapter(getExecutor(), getServicesTracker(), context)); |
|
319 return Status.OK_STATUS; |
|
320 }; |
|
321 }.schedule(); |
|
322 } |
|
323 |
|
324 // Helper function to locate the platform breakpoint corresponding |
|
325 // to the target breakpoint/watchpoint that was just hit |
|
326 |
|
327 // FIXME: (Bug228703) Need a way to identify the correct context where the BP was hit |
|
328 private ICBreakpoint findPlatformBreakpoint(IDMContext context, int targetBreakpointID) { |
|
329 // Hmm, the service has no tracking of MIBreakpointDMContext. So this workaround. |
|
330 IBreakpointsTargetDMContext btDMC = DMContexts.getAncestorOfType(context, IBreakpointsTargetDMContext.class); |
|
331 assert btDMC != null; |
|
332 IBreakpointDMContext dmc = new MIBreakpointDMContext(MIBreakpoints.this, new IDMContext[] { btDMC }, targetBreakpointID); |
|
333 |
|
334 MIBreakpointsManager bpMediator = getServicesTracker().getService(MIBreakpointsManager.class); |
|
335 ICBreakpoint cdtBP = (ICBreakpoint)bpMediator.getPlatformBreakpoint(btDMC, dmc); |
|
336 |
|
337 return cdtBP; |
|
338 } |
|
339 |
284 /////////////////////////////////////////////////////////////////////////// |
340 /////////////////////////////////////////////////////////////////////////// |
285 // IBreakpoints interface |
341 // IBreakpoints interface |
286 /////////////////////////////////////////////////////////////////////////// |
342 /////////////////////////////////////////////////////////////////////////// |
287 |
343 |
288 //------------------------------------------------------------------------- |
344 //------------------------------------------------------------------------- |
761 Map<String, Object> properties = new HashMap<String, Object>(attributes); |
817 Map<String, Object> properties = new HashMap<String, Object>(attributes); |
762 |
818 |
763 // Retrieve the breakpoint parameters |
819 // Retrieve the breakpoint parameters |
764 // At this point, we know their are OK so there is no need to re-validate |
820 // At this point, we know their are OK so there is no need to re-validate |
765 MIBreakpointDMContext breakpointCtx = (MIBreakpointDMContext) dmc; |
821 MIBreakpointDMContext breakpointCtx = (MIBreakpointDMContext) dmc; |
766 IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class); |
822 final IBreakpointsTargetDMContext context = DMContexts.getAncestorOfType(dmc, IBreakpointsTargetDMContext.class); |
767 final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context); |
823 final Map<Integer, MIBreakpointDMData> contextBreakpoints = fBreakpoints.get(context); |
768 final int reference = breakpointCtx.getReference(); |
824 final int reference = breakpointCtx.getReference(); |
769 MIBreakpointDMData breakpoint = contextBreakpoints.get(reference); |
825 MIBreakpointDMData breakpoint = contextBreakpoints.get(reference); |
770 |
826 |
771 // Track the number of change requests |
827 // Track the number of change requests |
780 }; |
836 }; |
781 |
837 |
782 // Determine if the breakpoint condition changed |
838 // Determine if the breakpoint condition changed |
783 String conditionAttribute = CONDITION; |
839 String conditionAttribute = CONDITION; |
784 if (properties.containsKey(conditionAttribute)) { |
840 if (properties.containsKey(conditionAttribute)) { |
785 String oldValue = breakpoint.getCondition(); |
841 final String oldValue = breakpoint.getCondition(); |
786 String newValue = (String) properties.get(conditionAttribute); |
842 String newValue = (String) properties.get(conditionAttribute); |
787 if (newValue == null) newValue = NULL_STRING; |
843 if (newValue == null) newValue = NULL_STRING; |
788 if (!oldValue.equals(newValue)) { |
844 if (!oldValue.equals(newValue)) { |
789 changeCondition(context, reference, newValue, countingRm); |
845 changeCondition(context, reference, newValue, new RequestMonitor(getExecutor(), countingRm){ |
|
846 |
|
847 @Override |
|
848 protected void handleError() { |
|
849 // Failed to change the condition, restore the old condition. |
|
850 // See comment in changeCondition() for more. |
|
851 MIBreakpointsManager bpMediator = getServicesTracker().getService(MIBreakpointsManager.class); |
|
852 final ICBreakpoint cdtBP = (ICBreakpoint)bpMediator.getPlatformBreakpoint(context, dmc); |
|
853 rollbackCondition(cdtBP, oldValue); |
|
854 |
|
855 countingRm.done(); |
|
856 }}); |
790 numberOfChanges++; |
857 numberOfChanges++; |
791 } |
858 } |
792 properties.remove(conditionAttribute); |
859 properties.remove(conditionAttribute); |
793 } |
860 } |
794 |
861 |
821 properties.remove(enableAttribute); |
888 properties.remove(enableAttribute); |
822 } |
889 } |
823 |
890 |
824 // Set the number of completions required |
891 // Set the number of completions required |
825 countingRm.setDoneCount(numberOfChanges); |
892 countingRm.setDoneCount(numberOfChanges); |
|
893 } |
|
894 |
|
895 private void rollbackCondition(final ICBreakpoint cdtBP, final String oldValue) { |
|
896 if (cdtBP == null) |
|
897 return; |
|
898 |
|
899 new Job("rollback breakpont condition") { //$NON-NLS-1$ |
|
900 { setSystem(true); } |
|
901 @Override |
|
902 protected IStatus run(IProgressMonitor monitor) { |
|
903 try { |
|
904 if (oldValue != null) |
|
905 cdtBP.setCondition(oldValue); |
|
906 else |
|
907 cdtBP.setCondition(NULL_STRING); |
|
908 } catch (CoreException e) { |
|
909 // ignore |
|
910 } |
|
911 return Status.OK_STATUS; |
|
912 }}.schedule(); |
826 } |
913 } |
827 |
914 |
828 /** |
915 /** |
829 * Update the breakpoint condition |
916 * Update the breakpoint condition |
830 * |
917 * |