|
16 | 16 | import java.util.Collection; |
17 | 17 | import java.util.Collections; |
18 | 18 | import java.util.Comparator; |
| 19 | +import java.util.HashMap; |
19 | 20 | import java.util.Iterator; |
20 | 21 | import java.util.List; |
21 | 22 | import java.util.Map; |
@@ -74,6 +75,7 @@ public class HistogramDataProvider extends AbstractTmfTraceDataProvider implemen |
74 | 75 | private final long fTraceId = TRACE_IDS.getAndIncrement(); |
75 | 76 | private final long fTotalId = TRACE_IDS.getAndIncrement(); |
76 | 77 | private final long fLostId = TRACE_IDS.getAndIncrement(); |
| 78 | + private final Map<String, Long> fEventTypeIds = new HashMap<>(); |
77 | 79 |
|
78 | 80 | /** |
79 | 81 | * Constructor |
@@ -101,6 +103,21 @@ public TmfModelResponse<TmfTreeModel<TmfTreeDataModel>> fetchTree(Map<String, Ob |
101 | 103 | if (eventsSs.optQuarkAbsolute(Attributes.LOST_EVENTS) != ITmfStateSystem.INVALID_ATTRIBUTE) { |
102 | 104 | builder.add(new TmfXyTreeDataModel(fLostId, fTraceId, Collections.singletonList(Objects.requireNonNull(Messages.HistogramDataProvider_Lost)), true, null, true)); |
103 | 105 | } |
| 106 | + |
| 107 | + // Add event type children |
| 108 | + int eventTypesQuark = eventsSs.optQuarkAbsolute(Attributes.EVENT_TYPES); |
| 109 | + if (eventTypesQuark != ITmfStateSystem.INVALID_ATTRIBUTE) { |
| 110 | + List<Integer> eventTypeQuarks = eventsSs.getSubAttributes(eventTypesQuark, false); |
| 111 | + for (Integer quark : eventTypeQuarks) { |
| 112 | + String eventTypeName = eventsSs.getAttributeName(quark); |
| 113 | + if (!"Lost event".equals(eventTypeName)) { //$NON-NLS-1$ |
| 114 | + long eventTypeId = TRACE_IDS.getAndIncrement(); |
| 115 | + fEventTypeIds.put(eventTypeName, eventTypeId); |
| 116 | + builder.add(new TmfXyTreeDataModel(eventTypeId, fTraceId, Collections.singletonList(eventTypeName), true, null, true)); |
| 117 | + } |
| 118 | + } |
| 119 | + } |
| 120 | + |
104 | 121 | if (eventsSs.waitUntilBuilt(0)) { |
105 | 122 | TmfModelResponse<TmfTreeModel<TmfTreeDataModel>> response = new TmfModelResponse<>(new TmfTreeModel<>(Collections.emptyList(), builder.build()), ITmfResponse.Status.COMPLETED, CommonStatusMessage.COMPLETED); |
106 | 123 | fCached = response; |
@@ -145,6 +162,21 @@ public TmfModelResponse<TmfTreeModel<TmfTreeDataModel>> fetchTree(Map<String, Ob |
145 | 162 | return TmfXyResponseFactory.createFailedResponse(CommonStatusMessage.STATE_SYSTEM_FAILED); |
146 | 163 | } |
147 | 164 | } |
| 165 | + |
| 166 | + // Handle event type requests |
| 167 | + if (eventsSs != null) { |
| 168 | + for (Map.Entry<String, Long> entry : fEventTypeIds.entrySet()) { |
| 169 | + if (selected.contains(entry.getValue())) { |
| 170 | + try { |
| 171 | + YModel series = getEventTypeHistogram(eventsSs, entry.getKey(), entry.getValue(), xValues); |
| 172 | + builder.add(series); |
| 173 | + } catch (StateSystemDisposedException e) { |
| 174 | + return TmfXyResponseFactory.createFailedResponse(CommonStatusMessage.STATE_SYSTEM_FAILED); |
| 175 | + } |
| 176 | + } |
| 177 | + } |
| 178 | + } |
| 179 | + |
148 | 180 | boolean completed = eventsSs != null ? eventsSs.waitUntilBuilt(0) || eventsSs.getCurrentEndTime() >= filter.getEnd() : false; |
149 | 181 |
|
150 | 182 | return TmfXyResponseFactory.create(TITLE, xValues, builder.build(), completed); |
@@ -212,6 +244,58 @@ private YModel getLostEvents(ITmfStateSystem ss, long[] times) throws StateSyste |
212 | 244 | return new YModel(fLostId, lostName, leY); |
213 | 245 | } |
214 | 246 |
|
| 247 | + private YModel getEventTypeHistogram(ITmfStateSystem eventsSs, String eventTypeName, long eventTypeId, long[] times) throws StateSystemDisposedException { |
| 248 | + int eventTypeQuark = eventsSs.optQuarkAbsolute(Attributes.EVENT_TYPES, eventTypeName); |
| 249 | + if (eventTypeQuark == ITmfStateSystem.INVALID_ATTRIBUTE) { |
| 250 | + return new YModel(eventTypeId, getTrace().getName() + '/' + eventTypeName, new double[times.length]); |
| 251 | + } |
| 252 | + |
| 253 | + List<Long> timesList = new ArrayList<>(); |
| 254 | + for (long time : times) { |
| 255 | + timesList.add(time); |
| 256 | + } |
| 257 | + |
| 258 | + List<Long> values = new ArrayList<>(); |
| 259 | + try { |
| 260 | + List<ITmfStateInterval> rawValues = new ArrayList<>(); |
| 261 | + |
| 262 | + Iterable<ITmfStateInterval> intervals = eventsSs.query2D(Collections.singletonList(eventTypeQuark), timesList); |
| 263 | + for (ITmfStateInterval interval : intervals) { |
| 264 | + rawValues.add(interval); |
| 265 | + } |
| 266 | + rawValues.sort(new Comparator<ITmfStateInterval>() { |
| 267 | + @Override |
| 268 | + public int compare(ITmfStateInterval arg0, ITmfStateInterval arg1) { |
| 269 | + return Long.compare(arg0.getStartTime(), arg1.getStartTime()); |
| 270 | + } |
| 271 | + }); |
| 272 | + long prevValue = rawValues.get(0).getValueLong(); |
| 273 | + for (ITmfStateInterval interval : rawValues) { |
| 274 | + Object value = interval.getValue(); |
| 275 | + long currentValue = (value instanceof Number) ? ((Number) value).longValue() : 0; |
| 276 | + values.add(currentValue - prevValue); |
| 277 | + prevValue = currentValue; |
| 278 | + } |
| 279 | + } catch (StateSystemDisposedException e) { |
| 280 | + // Return empty data if state system is disposed |
| 281 | + for (int i = 0; i < times.length; i++) { |
| 282 | + values.add(0L); |
| 283 | + } |
| 284 | + } |
| 285 | + |
| 286 | + // Pad with zeros if needed |
| 287 | + while (values.size() < times.length) { |
| 288 | + values.add(0L); |
| 289 | + } |
| 290 | + |
| 291 | + double[] y = new double[times.length]; |
| 292 | + for (int i = 0; i < Math.min(times.length, values.size()); i++) { |
| 293 | + y[i] = values.get(i).doubleValue(); |
| 294 | + } |
| 295 | + |
| 296 | + return new YModel(eventTypeId, getTrace().getName() + '/' + eventTypeName, y); |
| 297 | + } |
| 298 | + |
215 | 299 | private class LostEventInterval { |
216 | 300 | private final long fStartTime; |
217 | 301 | private final long fEndTime; |
|
0 commit comments