1 /*******************************************************************************
2 * Copyright (c) 2009, 2015 Ericsson
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
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 *******************************************************************************/
15 package org
.eclipse
.tracecompass
.internal
.tmf
.core
.request
;
17 import java
.util
.ArrayList
;
18 import java
.util
.HashMap
;
19 import java
.util
.HashSet
;
20 import java
.util
.List
;
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
;
32 * The TMF coalesced event request
34 * @author Francois Chouinard
36 public class TmfCoalescedEventRequest
extends TmfEventRequest
{
38 // ------------------------------------------------------------------------
40 // ------------------------------------------------------------------------
42 /** The list of coalesced requests */
43 private final List
<ITmfEventRequest
> fRequests
= new ArrayList
<>();
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.
49 private TmfTimeRange fRange
;
52 * The requests cache to avoid iterating over all requests for each event.
54 private Map
<String
, Set
<ITmfEventRequest
>> fRequestsCache
= new HashMap
<>();
56 // ------------------------------------------------------------------------
58 // ------------------------------------------------------------------------
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.
65 * The requested data type
67 * The range of the request. You can use
68 * {@link TmfTimeRange#ETERNITY} to request all events.
70 * The index of the first event to retrieve. Use '0' to start at
73 * The number of events requested. You can use
74 * {@link TmfEventRequest#ALL_DATA} to request all events.
76 * The requested execution priority
78 public TmfCoalescedEventRequest(Class
<?
extends ITmfEvent
> dataType
,
82 ExecutionType priority
) {
83 super(ITmfEvent
.class, null, index
, nbRequested
, priority
);
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
);
100 public TmfTimeRange
getRange() {
104 // ------------------------------------------------------------------------
106 // ------------------------------------------------------------------------
109 * Add a request to this one.
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
);
123 fRequests
.add(request
);
129 * Check if a request is compatible with the current coalesced one
132 * The request to verify
133 * @return If the request is compatible, true or false
135 public boolean isCompatible(ITmfEventRequest request
) {
136 if (request
.getExecType() == getExecType() &&
137 ranksOverlap(request
) &&
138 timeRangesOverlap(request
)) {
144 private boolean ranksOverlap(ITmfEventRequest request
) {
145 long start
= request
.getIndex();
146 long end
= start
+ request
.getNbRequested();
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));
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);
160 private void merge(ITmfEventRequest request
) {
161 long start
= request
.getIndex();
162 long end
= Math
.min(start
+ request
.getNbRequested(), ITmfEventRequest
.ALL_DATA
);
164 if (start
< fIndex
) {
165 if (fNbRequested
!= ITmfEventRequest
.ALL_DATA
) {
166 fNbRequested
+= (fIndex
- start
);
170 if ((request
.getNbRequested() == ITmfEventRequest
.ALL_DATA
) ||
171 (fNbRequested
== ITmfEventRequest
.ALL_DATA
)) {
172 fNbRequested
= ITmfEventRequest
.ALL_DATA
;
174 fNbRequested
= (int) Math
.max(end
- fIndex
, fNbRequested
);
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());
182 if (!fRange
.contains(endTime
) && fRange
.getEndTime().compareTo(endTime
) < 0) {
183 fRange
= new TmfTimeRange(fRange
.getStartTime(), endTime
);
188 * @return The list of IDs of the sub-requests
190 @SuppressWarnings("nls")
191 public String
getSubRequestIds() {
192 StringBuffer result
= new StringBuffer("[");
193 for (int i
= 0; i
< fRequests
.size(); i
++) {
197 result
.append(fRequests
.get(i
).getRequestId());
200 return result
.toString();
203 // ------------------------------------------------------------------------
205 // ------------------------------------------------------------------------
208 public void handleData(ITmfEvent data
) {
209 super.handleData(data
);
211 long index
= getIndex() + getNbRead() - 1;
213 String traceName
= data
.getTrace().getName();
214 Set
<ITmfEventRequest
> requests
= fRequestsCache
.get(traceName
);
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
);
224 fRequestsCache
.put(traceName
, requests
);
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
);
242 public void start() {
243 for (ITmfEventRequest request
: fRequests
) {
244 if (!request
.isCompleted()) {
253 for (ITmfEventRequest request
: fRequests
) {
254 if (!request
.isCompleted()) {
263 for (ITmfEventRequest request
: fRequests
) {
270 public void cancel() {
271 for (ITmfEventRequest request
: fRequests
) {
272 if (!request
.isCompleted()) {
280 public synchronized boolean isCompleted() {
281 // Firstly, check if coalescing request is completed
282 if (super.isCompleted()) {
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()) {
298 // Coalescing request is not finished if there are no sub-requests
303 public synchronized boolean isCancelled() {
304 // Firstly, check if coalescing request is canceled
305 if (super.isCancelled()) {
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()) {
321 // Coalescing request is not canceled if there are no sub-requests
326 // ------------------------------------------------------------------------
328 // ------------------------------------------------------------------------
331 @SuppressWarnings("nls")
332 public String
toString() {
333 return "[TmfCoalescedEventRequest(" + getRequestId() + "," + getDataType().getSimpleName()
334 + "," + getExecType() + "," + getRange() + "," + getIndex() + "," + getNbRequested()
335 + ", " + fRequests
.toString() + ")]";