Skip to content

Commit b3b9532

Browse files
committed
tmf:refresh open state system analysis
Refresh open state system analysis during fetchTree Fix cleanup logic in updateRegisteredAnalysisModules Used Amazon Q for understanding code Signed-off-by: Yassine Ibhir <[email protected]>
1 parent 398ef83 commit b3b9532

File tree

1 file changed

+119
-78
lines changed

1 file changed

+119
-78
lines changed

tmf/org.eclipse.tracecompass.tmf.core/src/org/eclipse/tracecompass/internal/tmf/core/statesystem/provider/StateSystemDataProvider.java

Lines changed: 119 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
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

Comments
 (0)