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