Commit | Line | Data |
---|---|---|
6e512b93 ASL |
1 | /******************************************************************************* |
2 | * Copyright (c) 2009 Ericsson | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are | |
5 | * made available under the terms of the Eclipse Public License v1.0 which | |
6 | * accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * William Bourque - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | package org.eclipse.linuxtools.lttng.ui.views.histogram; | |
13 | ||
14 | import org.eclipse.linuxtools.lttng.event.LttngEvent; | |
15 | import org.eclipse.linuxtools.tmf.event.TmfEvent; | |
16 | import org.eclipse.linuxtools.tmf.event.TmfTimeRange; | |
17 | import org.eclipse.linuxtools.tmf.request.TmfEventRequest; | |
18 | ||
19 | /** | |
20 | * <b><u>HistogramRequest</u></b> | |
21 | * <p> | |
22 | * Request class, to perform a request to TMF for the histograms. | |
23 | * <p> | |
24 | */ | |
25 | public class HistogramRequest extends TmfEventRequest<LttngEvent> { | |
26 | protected HistogramContent histogramContent = null; | |
27 | ||
28 | protected int lastInterval = 0; | |
29 | protected long lastRangeTime = 0L; | |
30 | protected long nbEventsInInterval = 0L; | |
31 | ||
32 | protected int nbIntervalNotEmpty = 1; | |
33 | protected int nbEventRead = 0; | |
34 | ||
35 | protected int lastDrawPosition = 0; | |
36 | ||
37 | protected HistogramCanvas parentCanvas = null; | |
38 | ||
39 | /** | |
40 | * Constructor for HistogramRequest.<p> | |
41 | * Prepare the request in TMF and reset the histogram content. | |
42 | * | |
43 | * @param range Range of the request. | |
44 | * @param nbRequested Nb events requested. Can be "Infinity" for all. | |
45 | * @param newParentCanvas HistogramCanvas related to the request. | |
46 | * @param timeInterval Time interval to consider (i.e. : 1 interval is 1 bar in the histogram) | |
47 | * | |
48 | * @see org.eclipse.linuxtools.tmf.request.TmfEventRequest | |
49 | */ | |
50 | public HistogramRequest(TmfTimeRange range, int nbRequested, HistogramCanvas newParentCanvas, long timeInterval) { | |
51 | super((Class<LttngEvent>)LttngEvent.class, range, nbRequested, HistogramConstant.MAX_EVENTS_PER_READ); | |
52 | ||
53 | // *** FIXME *** | |
54 | // This does not work! The request won't be processed or the number of events returned is wrong! | |
55 | // We cannot use this ! | |
56 | //super((Class<LttngEvent>)dataType, range); | |
57 | ||
58 | parentCanvas = newParentCanvas; | |
59 | histogramContent = parentCanvas.getHistogramContent(); | |
60 | ||
61 | // Reset the content of the HistogramContent... the given data better be valid or this will fail. | |
62 | histogramContent.clearContentData(); | |
63 | histogramContent.resetTable(range.getStartTime().getValue(), range.getEndTime().getValue(), timeInterval); | |
64 | ||
65 | lastRangeTime = range.getStartTime().getValue(); | |
66 | ||
67 | // Notify the UI even before the request started, so we set the timestamp already. | |
68 | parentCanvas.notifyParentUpdatedInformationAsynchronously(); | |
69 | } | |
70 | ||
71 | /** | |
72 | * HandleData function : will be called by TMF each time a new event is receive for the request.<p> | |
73 | * Calculation for the content is done here. | |
74 | */ | |
75 | @Override | |
76 | public void handleData() { | |
77 | TmfEvent[] result = getData(); | |
78 | TmfEvent[] evt = new TmfEvent[1]; | |
79 | ||
80 | evt[0] = (result.length > 0) ? result[0] : null; | |
81 | ||
82 | // *** FIXME *** | |
83 | // *** EVIL BUG *** | |
84 | // The request by timerange only does not work! (see constructor above) | |
85 | // However, the request with number of events will loop until it reach its number or EOF | |
86 | // We have to filter out ourself the extra useless events! | |
87 | // | |
88 | if (evt[0] != null) { | |
89 | ||
90 | LttngEvent tmpEvent = (LttngEvent)evt[0]; | |
91 | ||
92 | // This check is linked to the evil fix mentionned above | |
93 | if ( ( tmpEvent.getTimestamp().getValue() >= histogramContent.getStartTime() ) && | |
94 | ( tmpEvent.getTimestamp().getValue() <= histogramContent.getEndTime() ) ) | |
95 | { | |
96 | ||
97 | // Distance (in time) between this event and the last one we read | |
98 | long distance = ( tmpEvent.getTimestamp().getValue() - lastRangeTime ); | |
99 | ||
100 | // Check if we changed of interval (the distance is higher than the interval time) | |
101 | if ( distance > histogramContent.getElementsTimeInterval() ) { | |
102 | ||
103 | histogramContent.getElementByIndex(lastInterval).intervalNbEvents = nbEventsInInterval; | |
104 | lastRangeTime = tmpEvent.getTimestamp().getValue(); | |
105 | ||
106 | // * NOTE * | |
107 | // We can skip several interval at once, so we need to find what was our interval now | |
108 | lastInterval = (int)((lastRangeTime - histogramContent.getStartTime()) / histogramContent.getElementsTimeInterval() ); | |
109 | ||
110 | // *** HACK *** | |
111 | // Because of the threads, weird phenomenons seem to happen here, like a position after the | |
112 | // element range because another request was issued. | |
113 | // This enforce the position but may result in slightly inconsistent result (i.e. a weird misplaced bar sometime). | |
114 | if ( lastInterval < 0 ) { | |
115 | lastInterval = 0; | |
116 | } | |
117 | else if ( lastInterval >= histogramContent.getNbElement() ) { | |
118 | lastInterval = (histogramContent.getNbElement()-1); | |
119 | } | |
120 | ||
121 | // * NOTE * | |
122 | // We save the time we have here. This mean only the FIRST time read in an interval will be saved. | |
123 | histogramContent.getElementByIndex(lastInterval).firstIntervalTimestamp = lastRangeTime; | |
124 | histogramContent.setReadyUpToPosition(lastInterval); | |
125 | ||
126 | nbIntervalNotEmpty++; | |
127 | nbEventsInInterval = 1L; | |
128 | } | |
129 | // We are still in the same interval, just keep counting | |
130 | else { | |
131 | nbEventsInInterval++; | |
132 | } | |
133 | ||
134 | if ( nbEventsInInterval > histogramContent.getHeighestEventCount() ) { | |
135 | histogramContent.setHeighestEventCount(nbEventsInInterval); | |
136 | } | |
137 | nbEventRead++; | |
138 | ||
139 | // Call an asynchronous redraw every REDRAW_EVERY_NB_EVENTS events | |
140 | // That way we don't need to wait until to end to have something on the screen | |
141 | if ( nbEventRead % HistogramConstant.REDRAW_EVERY_NB_EVENTS == 0 ) { | |
142 | redrawAsyncronously(); | |
143 | } | |
144 | } | |
145 | } | |
146 | // We got a null event! This mean we reach the end of the request. | |
147 | // Save the last interval we had, so we won't miss the very last events at the end. | |
148 | else { | |
149 | // Save the last events | |
150 | histogramContent.getElementByIndex(lastInterval).intervalNbEvents = nbEventsInInterval; | |
151 | // We reached the end of the request, so assume we fill up the content as well | |
152 | histogramContent.setReadyUpToPosition(histogramContent.getNbElement()); | |
153 | ||
154 | // If the interval wasn't null, count this as a "non empty" interval | |
155 | if (nbEventsInInterval > 0) { | |
156 | nbIntervalNotEmpty++; | |
157 | } | |
158 | } | |
159 | } | |
160 | ||
161 | /** | |
162 | * Function that is called when the request completed (successful or not).<p> | |
163 | * Update information and redraw the screen. | |
164 | */ | |
165 | @Override | |
166 | public void handleCompleted() { | |
167 | parentCanvas.notifyParentUpdatedInformationAsynchronously(); | |
168 | redrawAsyncronously(); | |
169 | } | |
170 | ||
171 | /** | |
172 | * Function that is called when the request completed successfully.<p> | |
173 | */ | |
174 | @Override | |
175 | public void handleSuccess() { | |
176 | // Nothing different from completed. | |
177 | } | |
178 | ||
179 | /** | |
180 | * Function that is called when the request completed in failure.<p> | |
181 | */ | |
182 | @Override | |
183 | public void handleFailure() { | |
184 | // Nothing different from cancel. | |
185 | } | |
186 | ||
187 | /** | |
188 | * Function that is called when the request was cancelled.<p> | |
189 | * Redraw and set the requestCompleted flag to true; | |
190 | */ | |
191 | @Override | |
192 | public void handleCancel() { | |
193 | redrawAsyncronously(); | |
194 | } | |
195 | ||
196 | /** | |
197 | * Update the HistogramContent with the latest information.<p> | |
198 | * This will perform some calculation that might be a bit harsh so it should'nt be called too often. | |
199 | */ | |
200 | public void updateEventsInfo() { | |
201 | // *** Note *** | |
202 | // The average number of event is calculated while skipping empty interval if asked | |
203 | int averageNumberOfEvents = 0; | |
204 | if ( HistogramConstant.SKIP_EMPTY_INTERVALS_WHEN_CALCULATING_AVERAGE ) { | |
205 | averageNumberOfEvents = (int)Math.ceil((double)nbEventRead / (double)nbIntervalNotEmpty); | |
206 | } | |
207 | else { | |
208 | averageNumberOfEvents = (int)Math.ceil((double)nbEventRead / (double)histogramContent.getNbElement()); | |
209 | } | |
210 | ||
211 | histogramContent.setAverageNumberOfEvents(averageNumberOfEvents); | |
212 | ||
213 | // It is possible that the height factor didn't change; | |
214 | // If not, we only need to redraw the updated section, no the whole content | |
215 | // Save the actual height, recalculate the height and check if there was any changes | |
216 | double previousHeightFactor = histogramContent.getHeightFactor(); | |
217 | histogramContent.recalculateHeightFactor(); | |
218 | if ( histogramContent.getHeightFactor() != previousHeightFactor ) { | |
219 | histogramContent.recalculateEventHeight(); | |
220 | } | |
221 | else { | |
222 | histogramContent.recalculateEventHeightInInterval(lastDrawPosition, histogramContent.getReadyUpToPosition()); | |
223 | } | |
224 | ||
225 | lastDrawPosition = histogramContent.getReadyUpToPosition(); | |
226 | } | |
227 | ||
228 | /** | |
229 | * Perform an asynchonous redraw of the screen. | |
230 | */ | |
231 | public void redrawAsyncronously() { | |
232 | updateEventsInfo(); | |
233 | // Canvas redraw is already asynchronous | |
234 | parentCanvas.redrawAsynchronously(); | |
235 | } | |
236 | ||
237 | } |