analysis: Move plugins to their own sub-directory
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.core / src / org / eclipse / tracecompass / internal / tmf / core / request / TmfCoalescedEventRequest.java
1 /*******************************************************************************
2 * Copyright (c) 2009, 2015 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 * Francois Chouinard - Initial API and implementation
11 * Alexandre Montplaisir - Merge with TmfCoalescedDataRequest
12 * Bernd Hufmann - Updated dispatching of events and added requests cache
13 *******************************************************************************/
14
15 package org.eclipse.tracecompass.internal.tmf.core.request;
16
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
21 import java.util.Map;
22 import java.util.Set;
23
24 import org.eclipse.tracecompass.internal.tmf.core.TmfCoreTracer;
25 import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
26 import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest;
27 import org.eclipse.tracecompass.tmf.core.request.TmfEventRequest;
28 import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
29 import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimeRange;
30
31 /**
32 * The TMF coalesced event request
33 *
34 * @author Francois Chouinard
35 */
36 public class TmfCoalescedEventRequest extends TmfEventRequest {
37
38 // ------------------------------------------------------------------------
39 // Attributes
40 // ------------------------------------------------------------------------
41
42 /** The list of coalesced requests */
43 private final List<ITmfEventRequest> fRequests = new ArrayList<>();
44
45 /**
46 * We do not use super.fRange, because in the case of coalesced requests,
47 * the global range can be modified as sub-request are added.
48 */
49 private TmfTimeRange fRange;
50
51 /**
52 * The requests cache to avoid iterating over all requests for each event.
53 */
54 private Map<String, Set<ITmfEventRequest>> fRequestsCache = new HashMap<>();
55
56 // ------------------------------------------------------------------------
57 // Constructor
58 // ------------------------------------------------------------------------
59
60 /**
61 * Request 'n' events of a given type for the given time range (given
62 * priority). Events are returned in blocks of the given size.
63 *
64 * @param dataType
65 * The requested data type
66 * @param range
67 * The range of the request. You can use
68 * {@link TmfTimeRange#ETERNITY} to request all events.
69 * @param index
70 * The index of the first event to retrieve. Use '0' to start at
71 * the beginning.
72 * @param nbRequested
73 * The number of events requested. You can use
74 * {@link TmfEventRequest#ALL_DATA} to request all events.
75 * @param priority
76 * The requested execution priority
77 */
78 public TmfCoalescedEventRequest(Class<? extends ITmfEvent> dataType,
79 TmfTimeRange range,
80 long index,
81 int nbRequested,
82 ExecutionType priority) {
83 super(ITmfEvent.class, null, index, nbRequested, priority);
84 fRange = range;
85
86 if (TmfCoreTracer.isRequestTraced()) {
87 String type = getClass().getName();
88 type = type.substring(type.lastIndexOf('.') + 1);
89 @SuppressWarnings("nls")
90 String message = "CREATED "
91 + (getExecType() == ITmfEventRequest.ExecutionType.BACKGROUND ? "(BG)" : "(FG)")
92 + " Type=" + type + " Index=" + getIndex() + " NbReq=" + getNbRequested()
93 + " Range=" + getRange()
94 + " DataType=" + getDataType().getSimpleName();
95 TmfCoreTracer.traceRequest(getRequestId(), message);
96 }
97 }
98
99 @Override
100 public TmfTimeRange getRange() {
101 return fRange;
102 }
103
104 // ------------------------------------------------------------------------
105 // Management
106 // ------------------------------------------------------------------------
107
108 /**
109 * Add a request to this one.
110 *
111 * @param request
112 * The request to add
113 */
114 public void addRequest(ITmfEventRequest request) {
115 // If it is a coalesced request only add the sub-requests
116 if (request instanceof TmfCoalescedEventRequest) {
117 TmfCoalescedEventRequest otherRequest = (TmfCoalescedEventRequest)request;
118 for (ITmfEventRequest subRequest : otherRequest.fRequests) {
119 fRequests.add(subRequest);
120 merge(subRequest);
121 }
122 } else {
123 fRequests.add(request);
124 merge(request);
125 }
126 }
127
128 /**
129 * Check if a request is compatible with the current coalesced one
130 *
131 * @param request
132 * The request to verify
133 * @return If the request is compatible, true or false
134 */
135 public boolean isCompatible(ITmfEventRequest request) {
136 if (request.getExecType() == getExecType() &&
137 ranksOverlap(request) &&
138 timeRangesOverlap(request)) {
139 return true;
140 }
141 return false;
142 }
143
144 private boolean ranksOverlap(ITmfEventRequest request) {
145 long start = request.getIndex();
146 long end = start + request.getNbRequested();
147
148 // Return true if either the start or end index falls within
149 // the coalesced request boundaries
150 return (start <= (fIndex + fNbRequested + 1) && (end >= fIndex - 1));
151 }
152
153 private boolean timeRangesOverlap(ITmfEventRequest request) {
154 ITmfTimestamp startTime = request.getRange().getStartTime();
155 ITmfTimestamp endTime = request.getRange().getEndTime();
156 return (startTime.compareTo(endTime) <= 0) &&
157 (fRange.getStartTime().compareTo(fRange.getEndTime()) <= 0);
158 }
159
160 private void merge(ITmfEventRequest request) {
161 long start = request.getIndex();
162 long end = Math.min(start + request.getNbRequested(), ITmfEventRequest.ALL_DATA);
163
164 if (start < fIndex) {
165 if (fNbRequested != ITmfEventRequest.ALL_DATA) {
166 fNbRequested += (fIndex - start);
167 }
168 fIndex = start;
169 }
170 if ((request.getNbRequested() == ITmfEventRequest.ALL_DATA) ||
171 (fNbRequested == ITmfEventRequest.ALL_DATA)) {
172 fNbRequested = ITmfEventRequest.ALL_DATA;
173 } else {
174 fNbRequested = (int) Math.max(end - fIndex, fNbRequested);
175 }
176
177 ITmfTimestamp startTime = request.getRange().getStartTime();
178 ITmfTimestamp endTime = request.getRange().getEndTime();
179 if (!fRange.contains(startTime) && fRange.getStartTime().compareTo(startTime) > 0) {
180 fRange = new TmfTimeRange(startTime, fRange.getEndTime());
181 }
182 if (!fRange.contains(endTime) && fRange.getEndTime().compareTo(endTime) < 0) {
183 fRange = new TmfTimeRange(fRange.getStartTime(), endTime);
184 }
185 }
186
187 /**
188 * @return The list of IDs of the sub-requests
189 */
190 @SuppressWarnings("nls")
191 public String getSubRequestIds() {
192 StringBuffer result = new StringBuffer("[");
193 for (int i = 0; i < fRequests.size(); i++) {
194 if (i != 0) {
195 result.append(", ");
196 }
197 result.append(fRequests.get(i).getRequestId());
198 }
199 result.append("]");
200 return result.toString();
201 }
202
203 // ------------------------------------------------------------------------
204 // ITmfEventRequest
205 // ------------------------------------------------------------------------
206
207 @Override
208 public void handleData(ITmfEvent data) {
209 super.handleData(data);
210
211 long index = getIndex() + getNbRead() - 1;
212
213 String traceName = data.getTrace().getName();
214 Set<ITmfEventRequest> requests = fRequestsCache.get(traceName);
215
216 if (requests == null) {
217 // Populate requests cache
218 requests = new HashSet<>();
219 for (ITmfEventRequest myRequest : fRequests) {
220 if (myRequest.getProviderFilter().matches(data)) {
221 requests.add(myRequest);
222 }
223 }
224 fRequestsCache.put(traceName, requests);
225 }
226
227 // dispatch event to relevant requests
228 for (ITmfEventRequest request : requests) {
229 long start = request.getIndex();
230 if (!request.isCompleted() && index >= start && request.getNbRead() < request.getNbRequested()) {
231 ITmfTimestamp ts = data.getTimestamp();
232 if (request.getRange().contains(ts)) {
233 if (request.getDataType().isInstance(data)) {
234 request.handleData(data);
235 }
236 }
237 }
238 }
239 }
240
241 @Override
242 public void start() {
243 for (ITmfEventRequest request : fRequests) {
244 if (!request.isCompleted()) {
245 request.start();
246 }
247 }
248 super.start();
249 }
250
251 @Override
252 public void done() {
253 for (ITmfEventRequest request : fRequests) {
254 if (!request.isCompleted()) {
255 request.done();
256 }
257 }
258 super.done();
259 }
260
261 @Override
262 public void fail() {
263 for (ITmfEventRequest request : fRequests) {
264 request.fail();
265 }
266 super.fail();
267 }
268
269 @Override
270 public void cancel() {
271 for (ITmfEventRequest request : fRequests) {
272 if (!request.isCompleted()) {
273 request.cancel();
274 }
275 }
276 super.cancel();
277 }
278
279 @Override
280 public synchronized boolean isCompleted() {
281 // Firstly, check if coalescing request is completed
282 if (super.isCompleted()) {
283 return true;
284 }
285
286 // Secondly, check if all sub-requests are finished
287 if (fRequests.size() > 0) {
288 // If all sub requests are completed the coalesced request is
289 // treated as completed, too.
290 for (ITmfEventRequest request : fRequests) {
291 if (!request.isCompleted()) {
292 return false;
293 }
294 }
295 return true;
296 }
297
298 // Coalescing request is not finished if there are no sub-requests
299 return false;
300 }
301
302 @Override
303 public synchronized boolean isCancelled() {
304 // Firstly, check if coalescing request is canceled
305 if (super.isCancelled()) {
306 return true;
307 }
308
309 // Secondly, check if all sub-requests are canceled
310 if (fRequests.size() > 0) {
311 // If all sub requests are canceled the coalesced request is
312 // treated as completed, too.
313 for (ITmfEventRequest request : fRequests) {
314 if (!request.isCancelled()) {
315 return false;
316 }
317 }
318 return true;
319 }
320
321 // Coalescing request is not canceled if there are no sub-requests
322 return false;
323
324 }
325
326 // ------------------------------------------------------------------------
327 // Object
328 // ------------------------------------------------------------------------
329
330 @Override
331 @SuppressWarnings("nls")
332 public String toString() {
333 return "[TmfCoalescedEventRequest(" + getRequestId() + "," + getDataType().getSimpleName()
334 + "," + getExecType() + "," + getRange() + "," + getIndex() + "," + getNbRequested()
335 + ", " + fRequests.toString() + ")]";
336 }
337
338 }
This page took 0.075015 seconds and 5 git commands to generate.