11/*******************************************************************************
2- * Copyright (c) 2019, 2020 École Polytechnique de Montréal and others
2+ * Copyright (c) 2019, 2025 École Polytechnique de Montréal and others
33 *
44 * All rights reserved. This program and the accompanying materials are
55 * made available under the terms of the Eclipse Public License 2.0 which
@@ -96,13 +96,13 @@ public class StateSystemDataProvider extends AbstractTmfTraceDataProvider implem
9696
9797 private static final AtomicLong ENTRY_ID = new AtomicLong ();
9898
99- private Map <Long , Pair <ITmfStateSystem , Integer >> fIDToDisplayQuark = new HashMap <>();
99+ private Map <Long , Pair <ITmfStateSystem , Integer >> fIDToSSQuark = new HashMap <>();
100100
101101 // Use to add one event for every state system and module
102- private final Map <ITmfStateSystem , Long > fSsToId = new HashMap <>();
103- private final List < ModuleEntryModel > fModuleEntryModelList = new ArrayList <>();
102+ private final Map <Long , ITmfStateSystem > fIdToSs = new HashMap <>();
103+ private final Map < Long , ModuleEntryModel > fIdToModuleEntryModel = new HashMap <>();
104104
105- private final Map <ITmfAnalysisModuleWithStateSystems , Boolean > fModulesToStatus = new HashMap <>();
105+ private final Map <ITmfAnalysisModuleWithStateSystems , Boolean > fModulesToStatus = new ConcurrentHashMap <>();
106106
107107 /*
108108 * Entry Builder is a table to stash the entries so it won't duplicate the
@@ -148,16 +148,16 @@ public class StateSystemDataProvider extends AbstractTmfTraceDataProvider implem
148148 }
149149
150150 private static final Comparator <ITimeGraphEntryModel > NAME_COMPARATOR = (a , b ) -> {
151- if (a instanceof TraceEntryModel && b instanceof TraceEntryModel ) {
152- ITmfTrace ta = ((TraceEntryModel ) a ).getTrace ();
153- ITmfTrace tb = ((TraceEntryModel ) b ).getTrace ();
154- // Puts the experiment entries at the top of the list
155- if (ta instanceof TmfExperiment && !(tb instanceof TmfExperiment )) {
156- return -1 ;
157- } else if (!(ta instanceof TmfExperiment ) && (tb instanceof TmfExperiment )) {
158- return 1 ;
159- }
151+ if (a instanceof TraceEntryModel && b instanceof TraceEntryModel ) {
152+ ITmfTrace ta = ((TraceEntryModel ) a ).getTrace ();
153+ ITmfTrace tb = ((TraceEntryModel ) b ).getTrace ();
154+ // Puts the experiment entries at the top of the list
155+ if (ta instanceof TmfExperiment && !(tb instanceof TmfExperiment )) {
156+ return -1 ;
157+ } else if (!(ta instanceof TmfExperiment ) && (tb instanceof TmfExperiment )) {
158+ return 1 ;
160159 }
160+ }
161161
162162 try {
163163 return Long .compare (Long .parseLong (a .getName ()), Long .parseLong (b .getName ()));
@@ -176,8 +176,34 @@ public class StateSystemDataProvider extends AbstractTmfTraceDataProvider implem
176176 */
177177 public StateSystemDataProvider (ITmfTrace trace ) {
178178 super (trace );
179+ updateRegisteredAnalysisModules (trace );
180+ }
181+
182+ private void updateRegisteredAnalysisModules (ITmfTrace trace ) {
183+ Set <ITmfAnalysisModuleWithStateSystems > traceAnalyses = new HashSet <>(fModulesToStatus .keySet ());
179184 for (ITmfAnalysisModuleWithStateSystems module : Objects .requireNonNull (Iterables .filter (trace .getAnalysisModules (), ITmfAnalysisModuleWithStateSystems .class ))) {
180- fModulesToStatus .put (module , false );
185+ traceAnalyses .remove (module );
186+ fModulesToStatus .putIfAbsent (module , false );
187+ }
188+
189+ // Remove any deleted state system modules
190+ synchronized (fEntryBuilder ) {
191+ for (ITmfAnalysisModuleWithStateSystems module : traceAnalyses ) {
192+ // Remove module
193+ fModulesToStatus .remove (module );
194+ // Remove corresponding entries
195+ String traceName = Objects .requireNonNull (trace .getName ());
196+ EntryModelBuilder entry = fEntryBuilder .get (-1L , traceName );
197+ if (entry != null ) {
198+ long parentId = entry .getId ();
199+ entry = fEntryBuilder .get (parentId , module .getName ());
200+ if (entry != null ) {
201+ // Delete module entry and its children
202+ removeEntryAndChildren (entry .getId ());
203+ fEntryBuilder .remove (parentId , module .getName ());
204+ }
205+ }
206+ }
181207 }
182208 }
183209
@@ -217,7 +243,7 @@ private Map<Long, Pair<ITmfStateSystem, Integer>> getSelectedEntries(Map<String,
217243 Map <Long , Pair <ITmfStateSystem , Integer >> idToQuark = new HashMap <>();
218244 synchronized (fEntryBuilder ) {
219245 for (Long id : selectedItems ) {
220- Pair <ITmfStateSystem , Integer > pair = fIDToDisplayQuark .get (id );
246+ Pair <ITmfStateSystem , Integer > pair = fIDToSSQuark .get (id );
221247 if (pair != null ) {
222248 idToQuark .put (id , pair );
223249 }
@@ -325,7 +351,7 @@ public TraceEntryModel build() {
325351 * The end time
326352 */
327353 protected TraceEntryModel (long id , long parentId , String traceName , long startTime , long endTime , ITmfTrace trace ) {
328- super (id , parentId , traceName , startTime , endTime );
354+ super (id , parentId , traceName , startTime , endTime , false );
329355 fEntryTrace = trace ;
330356 }
331357
@@ -506,10 +532,11 @@ public int getQuark() {
506532
507533 @ Override
508534 public @ NonNull TmfModelResponse <TmfTreeModel <TimeGraphEntryModel >> fetchTree (Map <String , Object > fetchParameters , @ Nullable IProgressMonitor monitor ) {
535+
509536 // need to create the tree
510537 boolean fetchTreeIsComplete ;
511538 synchronized (fEntryBuilder ) {
512- fModuleEntryModelList .clear ();
539+ fIdToModuleEntryModel .clear ();
513540 fetchTreeIsComplete = addTrace (monitor );
514541 if (monitor != null && monitor .isCanceled ()) {
515542 return new TmfModelResponse <>(null , Status .CANCELLED , CommonStatusMessage .TASK_CANCELLED );
@@ -529,6 +556,8 @@ public int getQuark() {
529556 private boolean addTrace (@ Nullable IProgressMonitor monitor ) {
530557 boolean fetchTreeIsComplete = true ;
531558 ITmfTrace trace = getTrace ();
559+ // Add newly created analysis and remove deleted analysis
560+ updateRegisteredAnalysisModules (trace );
532561
533562 // look if the trace entry already exist
534563 String traceName = Objects .requireNonNull (trace .getName ());
@@ -548,18 +577,20 @@ private boolean addTrace(@Nullable IProgressMonitor monitor) {
548577 if (monitor != null && monitor .isCanceled ()) {
549578 return false ;
550579 }
580+ boolean analysisIsDone = Objects .requireNonNull (moduleWithStatus .getValue ());
551581 ITmfAnalysisModuleWithStateSystems module = Objects .requireNonNull (moduleWithStatus .getKey ());
552- Boolean analysisIsDone = Objects .requireNonNull (moduleWithStatus .getValue ());
582+ // Children entry of the trace are the modules
583+ boolean complete = addModule (monitor , module , rootId , trace .getStartTime ().toNanos ());
553584 if (!analysisIsDone || fStartedAnalysis .contains (module )) {
554585 // Children entry of the trace are the modules
555- fetchTreeIsComplete &= addModule ( monitor , module , rootId , trace . getStartTime (). toNanos ()) ;
586+ fetchTreeIsComplete &= complete ;
556587 fStartedAnalysis .remove (module );
557588 }
558589 }
559590
560591 // Update end Time
561592 long traceEnd = traceEntry .getEndTime ();
562- for (ModuleEntryModel moduleEntryModel : fModuleEntryModelList ) {
593+ for (ModuleEntryModel moduleEntryModel : fIdToModuleEntryModel . values () ) {
563594 if (monitor != null && monitor .isCanceled ()) {
564595 return false ;
565596 }
@@ -598,16 +629,16 @@ private boolean addModule(@Nullable IProgressMonitor monitor, ITmfAnalysisModule
598629 long moduleId = moduleEntry .getId ();
599630
600631 // Add child entry
601- boolean fetchTreeIsComplete = true ;
602- Long moduleEnd = startTime ;
632+ boolean complete = true ;
633+ long moduleEnd = getTrace (). getEndTime (). toNanos () ;
603634 boolean hasChildren = false ;
604635 for (ITmfStateSystem ss : module .getStateSystems ()) {
605636 if (monitor != null && monitor .isCanceled ()) {
606637 return false ;
607638 }
608639
609640 // Children entry of the modules are state system
610- fetchTreeIsComplete &= ss .waitUntilBuilt (0 );
641+ complete &= ss .waitUntilBuilt (0 );
611642 if (!ss .isCancelled ()) {
612643 addStateSystem (monitor , ss , moduleId );
613644 moduleEnd = Long .max (moduleEnd , ss .getCurrentEndTime ());
@@ -619,7 +650,7 @@ private boolean addModule(@Nullable IProgressMonitor monitor, ITmfAnalysisModule
619650 */
620651 EntryModelBuilder ssEntry = fEntryBuilder .get (moduleId , ss .getSSID ());
621652 if (ssEntry != null ) {
622- deleteElementFromBuildEntryList (ssEntry .getId ());
653+ removeEntryAndChildren (ssEntry .getId ());
623654 }
624655 }
625656 }
@@ -628,13 +659,13 @@ private boolean addModule(@Nullable IProgressMonitor monitor, ITmfAnalysisModule
628659 moduleEntry .setEndTime (moduleEnd );
629660 fEntryBuilder .put (parentId , moduleName , moduleEntry );
630661 ModuleEntryModel finalModuleEntry = moduleEntry .build ();
631- fModuleEntryModelList . add ( finalModuleEntry );
632- if (fetchTreeIsComplete && hasChildren ) {
662+ fIdToModuleEntryModel . put ( finalModuleEntry . getId (), finalModuleEntry );
663+ if (complete && hasChildren ) {
633664 // Analysis is complete
634665 fModulesToStatus .put (module , true );
635666 }
636667
637- return fetchTreeIsComplete ;
668+ return complete ;
638669 }
639670
640671 private void addStateSystem (@ Nullable IProgressMonitor monitor , ITmfStateSystem ss , long parentId ) {
@@ -654,18 +685,18 @@ private void addStateSystem(@Nullable IProgressMonitor monitor, ITmfStateSystem
654685 fEntryBuilder .put (parentId , ssName , stateSystemEntryModel );
655686 }
656687 // Update entry
657- long ssId = stateSystemEntryModel .getId ();
688+ long id = stateSystemEntryModel .getId ();
658689 stateSystemEntryModel .setEndTime (endTime );
659690 fEntryBuilder .put (parentId , ssName , stateSystemEntryModel );
660- fSsToId .put (ss , ssId );
691+ fIdToSs .put (id , ss );
661692
662693 // Add child entry
663694 for (Integer attrib : ss .getSubAttributes (ITmfStateSystem .ROOT_ATTRIBUTE , false )) {
664695 if (monitor != null && monitor .isCanceled ()) {
665696 return ;
666697 }
667698 // Children of the state system are recursive hierarchy
668- addSubAttributes (monitor , ssId , startTime , endTime , ss , attrib );
699+ addSubAttributes (monitor , id , startTime , endTime , ss , attrib );
669700 }
670701 }
671702
@@ -685,7 +716,7 @@ private void addSubAttributes(@Nullable IProgressMonitor monitor, Long parentId,
685716 long id = attributeEntry .getId ();
686717
687718 Pair <ITmfStateSystem , Integer > displayQuark = new Pair <>(ss , attrib );
688- fIDToDisplayQuark .put (id , displayQuark );
719+ fIDToSSQuark .put (id , displayQuark );
689720
690721 // Add child entry
691722 for (Integer child : ss .getSubAttributes (attrib , false )) {
@@ -713,11 +744,13 @@ private List<TimeGraphEntryModel> buildEntryList(@Nullable IProgressMonitor moni
713744 return entryList ;
714745 }
715746
716- private void deleteElementFromBuildEntryList (Long rowID ) {
717- for (EntryModelBuilder entry : fEntryBuilder .row (rowID ).values ()) {
718- deleteElementFromBuildEntryList (entry .getId ());
747+ private void removeEntryAndChildren (Long entryID ) {
748+ for (EntryModelBuilder entry : fEntryBuilder .row (entryID ).values ()) {
749+ removeEntryAndChildren (entry .getId ());
719750 }
720- fEntryBuilder .row (rowID ).clear ();
751+ fEntryBuilder .row (entryID ).clear ();
752+ fIDToSSQuark .remove (entryID );
753+ fIdToSs .remove (entryID );
721754 }
722755
723756 private void waitForInitialization (ITmfTrace trace , ITmfAnalysisModuleWithStateSystems module ) {
@@ -741,69 +774,77 @@ private void waitForInitialization(ITmfTrace trace, ITmfAnalysisModuleWithStateS
741774 }
742775
743776 @ Override
744- public @ NonNull TmfModelResponse <@ NonNull TimeGraphModel > fetchRowModel (Map <String , Object > fetchParameters , @ Nullable IProgressMonitor monitor ) {
745- Table <ITmfStateSystem , Integer , Long > table = HashBasedTable .create ();
746- // Get the quarks to display
777+ public @ NonNull TmfModelResponse <TimeGraphModel > fetchRowModel (Map <String , Object > fetchParameters , @ Nullable IProgressMonitor monitor ) {
747778 Collection <Long > selectedItems = DataProviderParameterUtils .extractSelectedItems (fetchParameters );
779+ if (selectedItems == null ) {
780+ return new TmfModelResponse <>(null , ITmfResponse .Status .FAILED , CommonStatusMessage .INCORRECT_QUERY_PARAMETERS );
781+ }
782+
783+ List <ITimeGraphRowModel > allRows = new ArrayList <>();
784+
785+ // Add requested module and state system rows
786+ synchronized (fEntryBuilder ) {
787+ selectedItems .forEach (id -> {
788+ ITimeGraphRowModel moduleRow = getModuleRowModel (id );
789+ if (moduleRow != null ) {
790+ allRows .add (moduleRow );
791+ }
792+ ITimeGraphRowModel ssRow = getStateSystemRowModel (id );
793+ if (ssRow != null ) {
794+ allRows .add (ssRow );
795+ }
796+ });
797+ }
798+
799+ // Get the quarks to display
800+ Table <ITmfStateSystem , Integer , Long > table = HashBasedTable .create ();
748801 synchronized (fEntryBuilder ) {
749- if (selectedItems == null ) {
750- // No selected items, take them all
751- selectedItems = fIDToDisplayQuark .keySet ();
752- }
753802 for (Long id : selectedItems ) {
754- Pair <ITmfStateSystem , Integer > pair = fIDToDisplayQuark .get (id );
803+ Pair <ITmfStateSystem , Integer > pair = fIDToSSQuark .get (id );
755804 if (pair != null ) {
756805 table .put (pair .getFirst (), pair .getSecond (), id );
757806 }
758807 }
759808 }
760- List <@ NonNull ITimeGraphRowModel > allRows = new ArrayList <>();
761809 try {
762810 List <Long > times = DataProviderParameterUtils .extractTimeRequested (fetchParameters );
763811 for (Entry <ITmfStateSystem , Map <Integer , Long >> ssEntry : table .rowMap ().entrySet ()) {
764812 ITmfStateSystem ss = Objects .requireNonNull (ssEntry .getKey ());
765- List <@ NonNull ITimeGraphRowModel > rows = getRowModels (ss , ssEntry .getValue (), times , fetchParameters , monitor );
813+ List <ITimeGraphRowModel > rows = getRowModels (ss , ssEntry .getValue (), times , fetchParameters , monitor );
814+ allRows .addAll (rows );
766815 if (monitor != null && monitor .isCanceled ()) {
767816 return new TmfModelResponse <>(null , Status .CANCELLED , CommonStatusMessage .TASK_CANCELLED );
768817 }
769- synchronized (fEntryBuilder ) {
770- // Add the SS
771- Long ssId = fSsToId .get (ss );
772- if (ssId != null && selectedItems .contains (ssId )) {
773- TimeGraphRowModel ssRow = new TimeGraphRowModel (ssId , new ArrayList <>());
774- List <@ NonNull ITimeGraphState > states = ssRow .getStates ();
775- states .add (new TimeGraphState (ss .getStartTime (), ss .getCurrentEndTime () - ss .getStartTime (), Integer .MAX_VALUE , null , new OutputElementStyle (TRANSPARENT )));
776- rows .add (ssRow );
777- }
778- }
779- allRows .addAll (rows );
780- }
781-
782- synchronized (fEntryBuilder ) {
783- for (ModuleEntryModel module : fModuleEntryModelList ) {
784- if (selectedItems .contains (module .getId ())) {
785- allRows .add (getModuleRowModels (module ));
786- }
787- }
788- }
789-
790- if (monitor != null && monitor .isCanceled ()) {
791- return new TmfModelResponse <>(null , Status .CANCELLED , CommonStatusMessage .TASK_CANCELLED );
792818 }
793819 return new TmfModelResponse <>(new TimeGraphModel (allRows ), Status .COMPLETED , CommonStatusMessage .COMPLETED );
794820 } catch (IndexOutOfBoundsException | TimeRangeException | StateSystemDisposedException e ) {
795821 return new TmfModelResponse <>(null , Status .FAILED , CommonStatusMessage .STATE_SYSTEM_FAILED );
796822 }
797823 }
798824
799- private static ITimeGraphRowModel getModuleRowModels (ModuleEntryModel module ) {
800- TimeGraphRowModel moduleRow = new TimeGraphRowModel (module .getId (), new ArrayList <>());
801- List <@ NonNull ITimeGraphState > states = moduleRow .getStates ();
802- states .add (new TimeGraphState (module .getStartTime (), module .getEndTime () - module .getStartTime (), Integer .MAX_VALUE , null , new OutputElementStyle (TRANSPARENT )));
803- return moduleRow ;
825+ private @ Nullable ITimeGraphRowModel getModuleRowModel (long id ) {
826+ ModuleEntryModel module = fIdToModuleEntryModel .get (id );
827+ if (module != null ) {
828+ TimeGraphRowModel moduleRow = new TimeGraphRowModel (module .getId (), new ArrayList <>());
829+ List <ITimeGraphState > states = moduleRow .getStates ();
830+ states .add (new TimeGraphState (module .getStartTime (), module .getEndTime () - module .getStartTime (), Integer .MAX_VALUE , null , new OutputElementStyle (TRANSPARENT )));
831+ return moduleRow ;
832+ }
833+ return null ;
834+ }
835+
836+ private @ Nullable ITimeGraphRowModel getStateSystemRowModel (long id ) {
837+ ITmfStateSystem ss = fIdToSs .get (id );
838+ if (ss != null ) {
839+ TimeGraphRowModel ssRow = new TimeGraphRowModel (id , new ArrayList <>());
840+ List <ITimeGraphState > states = ssRow .getStates ();
841+ states .add (new TimeGraphState (ss .getStartTime (), ss .getCurrentEndTime () - ss .getStartTime (), Integer .MAX_VALUE , null , new OutputElementStyle (TRANSPARENT )));
842+ return ssRow ;
843+ }
844+ return null ;
804845 }
805846
806- private List <@ NonNull ITimeGraphRowModel > getRowModels (ITmfStateSystem ss , Map <Integer , Long > idToDisplayQuark ,
847+ private List <@ NonNull ITimeGraphRowModel > getRowModels (ITmfStateSystem ss , Map <Integer , Long > quarkToId ,
807848 @ Nullable List <Long > times , Map <String , Object > fetchParameters , @ Nullable IProgressMonitor monitor ) throws StateSystemDisposedException {
808849 // Create predicates
809850 Map <@ NonNull Integer , @ NonNull Predicate <@ NonNull Multimap <@ NonNull String , @ NonNull Object >>> predicates = new HashMap <>();
@@ -812,12 +853,12 @@ private static ITimeGraphRowModel getModuleRowModels(ModuleEntryModel module) {
812853 predicates .putAll (computeRegexPredicate (regexesMap ));
813854 }
814855 // Create quark to row
815- Map <Integer , ITimeGraphRowModel > quarkToRow = new HashMap <>(idToDisplayQuark .size ());
816- for (Entry <Integer , Long > entry : idToDisplayQuark .entrySet ()) {
856+ Map <Integer , ITimeGraphRowModel > quarkToRow = new HashMap <>(quarkToId .size ());
857+ for (Entry <Integer , Long > entry : quarkToId .entrySet ()) {
817858 quarkToRow .put (entry .getKey (), new TimeGraphRowModel (entry .getValue (), new ArrayList <>()));
818859 }
819860
820- for (ITmfStateInterval interval : ss .query2D (idToDisplayQuark .keySet (), getTimes (ss , times ))) {
861+ for (ITmfStateInterval interval : ss .query2D (quarkToId .keySet (), getTimes (ss , times ))) {
821862 if (monitor != null && monitor .isCanceled ()) {
822863 return Collections .emptyList ();
823864 }
0 commit comments