Commit | Line | Data |
---|---|---|
8c8bf09f | 1 | /******************************************************************************* |
ed902a2b | 2 | * Copyright (c) 2009, 2015 Ericsson |
0283f7ff | 3 | * |
8c8bf09f ASL |
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 | |
0283f7ff | 8 | * |
8c8bf09f | 9 | * Contributors: |
fd3f1eff AM |
10 | * Francois Chouinard - Initial API and implementation, replace background |
11 | * requests by preemptable requests | |
12 | * Alexandre Montplaisir - Merge with TmfDataProvider | |
8967c8c0 | 13 | * Bernd Hufmann - Add timer based coalescing for background requests |
8c8bf09f ASL |
14 | *******************************************************************************/ |
15 | ||
2bdf0193 | 16 | package org.eclipse.tracecompass.tmf.core.component; |
8c8bf09f | 17 | |
aa353506 AM |
18 | import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; |
19 | ||
d77f31da BH |
20 | import java.util.ArrayList; |
21 | import java.util.Collections; | |
8967c8c0 | 22 | import java.util.Iterator; |
f45257df | 23 | import java.util.LinkedList; |
fd3f1eff | 24 | import java.util.List; |
8967c8c0 BH |
25 | import java.util.Timer; |
26 | import java.util.TimerTask; | |
fd3f1eff | 27 | |
6ae0ee68 | 28 | import org.eclipse.jdt.annotation.NonNull; |
5db5a3a4 | 29 | import org.eclipse.tracecompass.common.core.NonNullUtils; |
2bdf0193 AM |
30 | import org.eclipse.tracecompass.internal.tmf.core.TmfCoreTracer; |
31 | import org.eclipse.tracecompass.internal.tmf.core.component.TmfEventThread; | |
32 | import org.eclipse.tracecompass.internal.tmf.core.component.TmfProviderManager; | |
33 | import org.eclipse.tracecompass.internal.tmf.core.request.TmfCoalescedEventRequest; | |
34 | import org.eclipse.tracecompass.internal.tmf.core.request.TmfRequestExecutor; | |
35 | import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; | |
8a580390 | 36 | import org.eclipse.tracecompass.tmf.core.filter.ITmfFilter; |
2bdf0193 AM |
37 | import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest; |
38 | import org.eclipse.tracecompass.tmf.core.request.ITmfEventRequest.ExecutionType; | |
39 | import org.eclipse.tracecompass.tmf.core.signal.TmfEndSynchSignal; | |
40 | import org.eclipse.tracecompass.tmf.core.signal.TmfSignalHandler; | |
41 | import org.eclipse.tracecompass.tmf.core.signal.TmfStartSynchSignal; | |
42 | import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp; | |
43 | import org.eclipse.tracecompass.tmf.core.trace.ITmfContext; | |
8c8bf09f ASL |
44 | |
45 | /** | |
fd3f1eff AM |
46 | * An abstract base class that implements ITmfEventProvider. |
47 | * <p> | |
48 | * This abstract class implements the housekeeping methods to register/ | |
49 | * de-register the event provider and to handle generically the event requests. | |
50 | * </p> | |
0283f7ff | 51 | * |
8fd82db5 | 52 | * @author Francois Chouinard |
8c8bf09f | 53 | */ |
8a580390 | 54 | public abstract class TmfEventProvider extends TmfComponent implements ITmfEventProvider, ITmfFilter { |
fd3f1eff AM |
55 | |
56 | // ------------------------------------------------------------------------ | |
57 | // Constants | |
58 | // ------------------------------------------------------------------------ | |
59 | ||
ae09c4ad | 60 | /** Default amount of events per request "chunk" */ |
fd3f1eff AM |
61 | public static final int DEFAULT_BLOCK_SIZE = 50000; |
62 | ||
8967c8c0 BH |
63 | /** Delay for coalescing background requests (in milli-seconds) */ |
64 | private static final long DELAY = 1000; | |
65 | ||
fd3f1eff AM |
66 | // ------------------------------------------------------------------------ |
67 | // Attributes | |
68 | // ------------------------------------------------------------------------ | |
69 | ||
f45257df AM |
70 | /** List of coalesced requests */ |
71 | private final List<TmfCoalescedEventRequest> fPendingCoalescedRequests = new LinkedList<>(); | |
fd3f1eff | 72 | |
f45257df AM |
73 | /** The type of event handled by this provider */ |
74 | private Class<? extends ITmfEvent> fType; | |
fd3f1eff AM |
75 | |
76 | private final TmfRequestExecutor fExecutor; | |
77 | ||
78 | private final Object fLock = new Object(); | |
79 | ||
80 | private int fSignalDepth = 0; | |
81 | ||
82 | private int fRequestPendingCounter = 0; | |
8c8bf09f | 83 | |
506219d0 | 84 | private Timer fTimer; |
8967c8c0 | 85 | |
6ae0ee68 BH |
86 | /** Current timer task */ |
87 | @NonNull private TimerTask fCurrentTask = new TimerTask() { @Override public void run() {} }; | |
88 | ||
2b5c3b7e | 89 | private boolean fIsTimerEnabled; |
8967c8c0 | 90 | |
d77f31da BH |
91 | /** |
92 | * The parent event provider. | |
93 | */ | |
94 | private TmfEventProvider fParent = null; | |
95 | /** | |
96 | * The list if children event provider. | |
97 | */ | |
98 | private final List<TmfEventProvider> fChildren = Collections.synchronizedList(new ArrayList<TmfEventProvider>()); | |
99 | ||
00641a97 FC |
100 | // ------------------------------------------------------------------------ |
101 | // Constructors | |
102 | // ------------------------------------------------------------------------ | |
103 | ||
063f0d27 AM |
104 | /** |
105 | * Default constructor | |
106 | */ | |
12c155f5 | 107 | public TmfEventProvider() { |
00641a97 | 108 | super(); |
2b5c3b7e | 109 | setTimerEnabled(true); |
fd3f1eff | 110 | fExecutor = new TmfRequestExecutor(); |
12c155f5 | 111 | } |
8c8bf09f | 112 | |
063f0d27 | 113 | /** |
f45257df | 114 | * Standard constructor. Instantiate and initialize at the same time. |
063f0d27 AM |
115 | * |
116 | * @param name | |
fd3f1eff | 117 | * Name of the provider |
063f0d27 | 118 | * @param type |
fd3f1eff | 119 | * The type of events that will be handled |
063f0d27 | 120 | */ |
f45257df | 121 | public TmfEventProvider(String name, Class<? extends ITmfEvent> type) { |
fd3f1eff | 122 | this(); |
fd3f1eff | 123 | init(name, type); |
12c155f5 FC |
124 | } |
125 | ||
063f0d27 | 126 | /** |
f45257df | 127 | * Initialize this data provider |
fd3f1eff AM |
128 | * |
129 | * @param name | |
130 | * Name of the provider | |
131 | * @param type | |
132 | * The type of events that will be handled | |
133 | */ | |
f45257df AM |
134 | public void init(String name, Class<? extends ITmfEvent> type) { |
135 | super.init(name); | |
136 | fType = type; | |
137 | fExecutor.init(); | |
138 | ||
139 | fSignalDepth = 0; | |
506219d0 BH |
140 | |
141 | synchronized (fLock) { | |
142 | fTimer = new Timer(); | |
143 | } | |
144 | ||
f45257df | 145 | TmfProviderManager.register(fType, this); |
fd3f1eff AM |
146 | } |
147 | ||
148 | @Override | |
149 | public void dispose() { | |
150 | TmfProviderManager.deregister(fType, this); | |
151 | fExecutor.stop(); | |
506219d0 BH |
152 | synchronized (fLock) { |
153 | if (fTimer != null) { | |
154 | fTimer.cancel(); | |
155 | } | |
156 | fTimer = null; | |
157 | } | |
d77f31da BH |
158 | |
159 | synchronized (fChildren) { | |
160 | for (TmfEventProvider child : fChildren) { | |
161 | child.dispose(); | |
162 | } | |
163 | fChildren.clear(); | |
164 | } | |
2b5c3b7e | 165 | clearPendingRequests(); |
fd3f1eff | 166 | super.dispose(); |
12c155f5 FC |
167 | } |
168 | ||
00641a97 | 169 | // ------------------------------------------------------------------------ |
fd3f1eff AM |
170 | // Accessors |
171 | // ------------------------------------------------------------------------ | |
172 | ||
fd3f1eff | 173 | /** |
ea652979 | 174 | * @since 2.0 |
fd3f1eff | 175 | */ |
ea652979 AM |
176 | @Override |
177 | public Class<? extends ITmfEvent> getEventType() { | |
fd3f1eff AM |
178 | return fType; |
179 | } | |
180 | ||
181 | // ------------------------------------------------------------------------ | |
182 | // ITmfRequestHandler | |
00641a97 FC |
183 | // ------------------------------------------------------------------------ |
184 | ||
5419a136 | 185 | @Override |
fd3f1eff AM |
186 | public void sendRequest(final ITmfEventRequest request) { |
187 | synchronized (fLock) { | |
5a597798 GB |
188 | |
189 | if (TmfCoreTracer.isRequestTraced()) { | |
190 | TmfCoreTracer.traceRequest(request.getRequestId(), "SENT to provider " + getName()); //$NON-NLS-1$ | |
191 | } | |
192 | ||
8a580390 BH |
193 | if (request.getProviderFilter() == null) { |
194 | request.setProviderFilter(this); | |
6badfac0 BH |
195 | } |
196 | ||
6ae0ee68 BH |
197 | if (sendWithParent(request)) { |
198 | return; | |
199 | } | |
200 | ||
8967c8c0 BH |
201 | if (request.getExecType() == ExecutionType.FOREGROUND) { |
202 | if ((fSignalDepth > 0) || (fRequestPendingCounter > 0)) { | |
203 | coalesceEventRequest(request); | |
204 | } else { | |
f45257df | 205 | queueRequest(request); |
8967c8c0 BH |
206 | } |
207 | return; | |
208 | } | |
209 | ||
506219d0 BH |
210 | /* |
211 | * Dispatch request in case timer is not running. | |
212 | */ | |
213 | if (fTimer == null) { | |
214 | queueRequest(request); | |
215 | return; | |
216 | } | |
217 | ||
8967c8c0 | 218 | coalesceEventRequest(request); |
6ae0ee68 | 219 | |
2b5c3b7e BH |
220 | if (fIsTimerEnabled) { |
221 | fCurrentTask.cancel(); | |
222 | fCurrentTask = new TimerTask() { | |
223 | @Override | |
224 | public void run() { | |
225 | synchronized (fLock) { | |
226 | fireRequest(true); | |
227 | } | |
8967c8c0 | 228 | } |
2b5c3b7e BH |
229 | }; |
230 | fTimer.schedule(fCurrentTask, DELAY); | |
231 | } | |
fd3f1eff AM |
232 | } |
233 | } | |
234 | ||
2b5c3b7e | 235 | private void fireRequest(boolean isTimeout) { |
fd3f1eff AM |
236 | synchronized (fLock) { |
237 | if (fRequestPendingCounter > 0) { | |
238 | return; | |
239 | } | |
8967c8c0 | 240 | |
fd3f1eff | 241 | if (fPendingCoalescedRequests.size() > 0) { |
8967c8c0 BH |
242 | Iterator<TmfCoalescedEventRequest> iter = fPendingCoalescedRequests.iterator(); |
243 | while (iter.hasNext()) { | |
2b5c3b7e | 244 | ExecutionType type = (isTimeout ? ExecutionType.BACKGROUND : ExecutionType.FOREGROUND); |
8967c8c0 BH |
245 | ITmfEventRequest request = iter.next(); |
246 | if (type == request.getExecType()) { | |
f45257df | 247 | queueRequest(request); |
8967c8c0 BH |
248 | iter.remove(); |
249 | } | |
fd3f1eff | 250 | } |
fd3f1eff | 251 | } |
5419a136 | 252 | } |
5419a136 AM |
253 | } |
254 | ||
fd3f1eff AM |
255 | /** |
256 | * Increments/decrements the pending requests counters and fires the request | |
257 | * if necessary (counter == 0). Used for coalescing requests across multiple | |
258 | * TmfDataProvider's. | |
259 | * | |
260 | * @param isIncrement | |
261 | * Should we increment (true) or decrement (false) the pending | |
262 | * counter | |
263 | */ | |
5419a136 | 264 | @Override |
fd3f1eff AM |
265 | public void notifyPendingRequest(boolean isIncrement) { |
266 | synchronized (fLock) { | |
267 | if (isIncrement) { | |
8967c8c0 | 268 | fRequestPendingCounter++; |
fd3f1eff AM |
269 | } else { |
270 | if (fRequestPendingCounter > 0) { | |
271 | fRequestPendingCounter--; | |
272 | } | |
273 | ||
274 | // fire request if all pending requests are received | |
275 | if (fRequestPendingCounter == 0) { | |
2b5c3b7e | 276 | fireRequest(false); |
6badfac0 | 277 | fireRequest(true); |
fd3f1eff AM |
278 | } |
279 | } | |
280 | } | |
281 | } | |
282 | ||
283 | // ------------------------------------------------------------------------ | |
284 | // Coalescing | |
285 | // ------------------------------------------------------------------------ | |
286 | ||
287 | /** | |
288 | * Create a new request from an existing one, and add it to the coalesced | |
289 | * requests | |
290 | * | |
291 | * @param request | |
292 | * The request to copy | |
293 | */ | |
8967c8c0 BH |
294 | protected void newCoalescedEventRequest(ITmfEventRequest request) { |
295 | synchronized (fLock) { | |
672a642a | 296 | TmfCoalescedEventRequest coalescedRequest = new TmfCoalescedEventRequest( |
fd3f1eff AM |
297 | request.getDataType(), |
298 | request.getRange(), | |
299 | request.getIndex(), | |
300 | request.getNbRequested(), | |
6eaea67d BH |
301 | request.getExecType(), |
302 | request.getDependencyLevel()); | |
fd3f1eff | 303 | coalescedRequest.addRequest(request); |
8a580390 | 304 | coalescedRequest.setProviderFilter(this); |
5419a136 | 305 | if (TmfCoreTracer.isRequestTraced()) { |
8b56808c GB |
306 | TmfCoreTracer.traceRequest(request.getRequestId(), "COALESCED with " + coalescedRequest.getRequestId()); //$NON-NLS-1$ |
307 | TmfCoreTracer.traceRequest(coalescedRequest.getRequestId(), "now contains " + coalescedRequest.getSubRequestIds()); //$NON-NLS-1$ | |
5419a136 | 308 | } |
6ae0ee68 | 309 | coalesceChildrenRequests(coalescedRequest); |
5419a136 | 310 | fPendingCoalescedRequests.add(coalescedRequest); |
8967c8c0 | 311 | } |
fd3f1eff AM |
312 | } |
313 | ||
314 | /** | |
315 | * Add an existing requests to the list of coalesced ones | |
316 | * | |
317 | * @param request | |
318 | * The request to add to the list | |
319 | */ | |
320 | protected void coalesceEventRequest(ITmfEventRequest request) { | |
321 | synchronized (fLock) { | |
2b5c3b7e | 322 | for (TmfCoalescedEventRequest coalescedRequest : getPendingRequests()) { |
fd3f1eff AM |
323 | if (coalescedRequest.isCompatible(request)) { |
324 | coalescedRequest.addRequest(request); | |
325 | if (TmfCoreTracer.isRequestTraced()) { | |
8b56808c GB |
326 | TmfCoreTracer.traceRequest(request.getRequestId(), "COALESCED with " + coalescedRequest.getRequestId()); //$NON-NLS-1$ |
327 | TmfCoreTracer.traceRequest(coalescedRequest.getRequestId(), "now contains " + coalescedRequest.getSubRequestIds()); //$NON-NLS-1$ | |
fd3f1eff | 328 | } |
6ae0ee68 | 329 | coalesceChildrenRequests(coalescedRequest); |
fd3f1eff AM |
330 | return; |
331 | } | |
332 | } | |
333 | newCoalescedEventRequest(request); | |
334 | } | |
335 | } | |
336 | ||
6ae0ee68 BH |
337 | /* |
338 | * Sends a request with the parent if compatible. | |
339 | */ | |
340 | private boolean sendWithParent(final ITmfEventRequest request) { | |
341 | ITmfEventProvider parent = getParent(); | |
342 | if (parent instanceof TmfEventProvider) { | |
343 | return ((TmfEventProvider) parent).sendIfCompatible(request); | |
344 | } | |
345 | return false; | |
346 | } | |
347 | ||
348 | /* | |
349 | * Sends a request if compatible with a pending coalesced request. | |
8967c8c0 | 350 | */ |
6ae0ee68 | 351 | private boolean sendIfCompatible(ITmfEventRequest request) { |
8967c8c0 | 352 | synchronized (fLock) { |
2b5c3b7e | 353 | for (TmfCoalescedEventRequest coalescedRequest : getPendingRequests()) { |
6ae0ee68 BH |
354 | if (coalescedRequest.isCompatible(request)) { |
355 | // Send so it can be coalesced with the parent(s) | |
356 | sendRequest(request); | |
357 | return true; | |
358 | } | |
359 | } | |
360 | } | |
361 | return sendWithParent(request); | |
362 | } | |
363 | ||
364 | /* | |
365 | * Coalesces children requests with given request if compatible. | |
366 | */ | |
367 | private void coalesceChildrenRequests(final TmfCoalescedEventRequest request) { | |
368 | synchronized (fChildren) { | |
369 | for (TmfEventProvider child : fChildren) { | |
370 | child.coalesceCompatibleRequests(request); | |
371 | } | |
372 | } | |
373 | } | |
374 | ||
375 | ||
376 | /* | |
377 | * Coalesces all pending requests that are compatible with coalesced request. | |
378 | */ | |
379 | private void coalesceCompatibleRequests(TmfCoalescedEventRequest request) { | |
2b5c3b7e | 380 | Iterator<TmfCoalescedEventRequest> iter = getPendingRequests().iterator(); |
6ae0ee68 BH |
381 | while (iter.hasNext()) { |
382 | TmfCoalescedEventRequest pendingRequest = iter.next(); | |
383 | if (request.isCompatible(pendingRequest)) { | |
384 | request.addRequest(pendingRequest); | |
385 | if (TmfCoreTracer.isRequestTraced()) { | |
386 | TmfCoreTracer.traceRequest(pendingRequest.getRequestId(), "COALESCED with " + request.getRequestId()); //$NON-NLS-1$ | |
387 | TmfCoreTracer.traceRequest(request.getRequestId(), "now contains " + request.getSubRequestIds()); //$NON-NLS-1$ | |
8967c8c0 | 388 | } |
6ae0ee68 | 389 | iter.remove(); |
8967c8c0 BH |
390 | } |
391 | } | |
8967c8c0 BH |
392 | } |
393 | ||
fd3f1eff AM |
394 | // ------------------------------------------------------------------------ |
395 | // Request processing | |
396 | // ------------------------------------------------------------------------ | |
397 | ||
fd3f1eff AM |
398 | /** |
399 | * Queue a request. | |
400 | * | |
401 | * @param request | |
402 | * The data request | |
403 | */ | |
404 | protected void queueRequest(final ITmfEventRequest request) { | |
405 | ||
406 | if (fExecutor.isShutdown()) { | |
407 | request.cancel(); | |
408 | return; | |
409 | } | |
410 | ||
411 | TmfEventThread thread = new TmfEventThread(this, request); | |
412 | ||
413 | if (TmfCoreTracer.isRequestTraced()) { | |
8b56808c | 414 | TmfCoreTracer.traceRequest(request.getRequestId(), "QUEUED"); //$NON-NLS-1$ |
fd3f1eff AM |
415 | } |
416 | ||
417 | fExecutor.execute(thread); | |
418 | } | |
419 | ||
fd3f1eff AM |
420 | /** |
421 | * Initialize the provider based on the request. The context is provider | |
422 | * specific and will be updated by getNext(). | |
423 | * | |
424 | * @param request | |
425 | * The request | |
426 | * @return An application specific context; null if request can't be | |
427 | * serviced | |
fd3f1eff AM |
428 | */ |
429 | public abstract ITmfContext armRequest(ITmfEventRequest request); | |
430 | ||
431 | /** | |
432 | * Checks if the data meets the request completion criteria. | |
433 | * | |
434 | * @param request | |
435 | * The request | |
436 | * @param event | |
437 | * The data to verify | |
438 | * @param nbRead | |
439 | * The number of events read so far | |
440 | * @return true if completion criteria is met | |
441 | */ | |
442 | public boolean isCompleted(ITmfEventRequest request, ITmfEvent event, int nbRead) { | |
443 | boolean requestCompleted = isCompleted2(request, nbRead); | |
444 | if (!requestCompleted) { | |
445 | ITmfTimestamp endTime = request.getRange().getEndTime(); | |
065cc19b | 446 | return event.getTimestamp().compareTo(endTime) > 0; |
fd3f1eff AM |
447 | } |
448 | return requestCompleted; | |
449 | } | |
450 | ||
451 | private static boolean isCompleted2(ITmfEventRequest request,int nbRead) { | |
452 | return request.isCompleted() || nbRead >= request.getNbRequested(); | |
453 | } | |
454 | ||
455 | // ------------------------------------------------------------------------ | |
456 | // Pass-through's to the request executor | |
457 | // ------------------------------------------------------------------------ | |
458 | ||
459 | /** | |
460 | * @return the shutdown state (i.e. if it is accepting new requests) | |
fd3f1eff AM |
461 | */ |
462 | protected boolean executorIsShutdown() { | |
463 | return fExecutor.isShutdown(); | |
464 | } | |
465 | ||
466 | /** | |
467 | * @return the termination state | |
fd3f1eff AM |
468 | */ |
469 | protected boolean executorIsTerminated() { | |
470 | return fExecutor.isTerminated(); | |
471 | } | |
472 | ||
473 | // ------------------------------------------------------------------------ | |
474 | // Signal handlers | |
475 | // ------------------------------------------------------------------------ | |
476 | ||
477 | /** | |
478 | * Handler for the start synch signal | |
479 | * | |
480 | * @param signal | |
481 | * Incoming signal | |
482 | */ | |
483 | @TmfSignalHandler | |
484 | public void startSynch(TmfStartSynchSignal signal) { | |
485 | synchronized (fLock) { | |
486 | fSignalDepth++; | |
487 | } | |
488 | } | |
489 | ||
490 | /** | |
491 | * Handler for the end synch signal | |
492 | * | |
493 | * @param signal | |
494 | * Incoming signal | |
495 | */ | |
496 | @TmfSignalHandler | |
497 | public void endSynch(TmfEndSynchSignal signal) { | |
498 | synchronized (fLock) { | |
499 | fSignalDepth--; | |
500 | if (fSignalDepth == 0) { | |
2b5c3b7e | 501 | fireRequest(false); |
fd3f1eff | 502 | } |
5419a136 AM |
503 | } |
504 | } | |
951d134a | 505 | |
d77f31da BH |
506 | @Override |
507 | public ITmfEventProvider getParent() { | |
508 | synchronized (fLock) { | |
509 | return fParent; | |
510 | } | |
511 | } | |
512 | ||
513 | @Override | |
514 | public void setParent(ITmfEventProvider parent) { | |
515 | if (!(parent instanceof TmfEventProvider)) { | |
516 | throw new IllegalArgumentException(); | |
517 | } | |
518 | ||
519 | synchronized (fLock) { | |
520 | fParent = (TmfEventProvider) parent; | |
521 | } | |
522 | } | |
523 | ||
524 | @Override | |
525 | public List<ITmfEventProvider> getChildren() { | |
526 | synchronized (fChildren) { | |
527 | List<ITmfEventProvider> list = new ArrayList<>(); | |
528 | list.addAll(fChildren); | |
529 | return list; | |
530 | } | |
531 | } | |
532 | ||
533 | @Override | |
534 | public <T extends ITmfEventProvider> List<T> getChildren(Class<T> clazz) { | |
aa353506 | 535 | List<@NonNull T> list = new ArrayList<>(); |
d77f31da BH |
536 | synchronized (fChildren) { |
537 | for (TmfEventProvider child : fChildren) { | |
538 | if (clazz.isAssignableFrom(child.getClass())) { | |
aa353506 | 539 | list.add(checkNotNull(clazz.cast(child))); |
d77f31da BH |
540 | } |
541 | } | |
542 | } | |
543 | return list; | |
544 | } | |
545 | ||
546 | @Override | |
547 | public ITmfEventProvider getChild(String name) { | |
548 | synchronized (fChildren) { | |
549 | for (TmfEventProvider child : fChildren) { | |
550 | if (child.getName().equals(name)) { | |
551 | return child; | |
552 | } | |
553 | } | |
554 | } | |
555 | return null; | |
556 | } | |
557 | ||
d77f31da BH |
558 | @Override |
559 | public ITmfEventProvider getChild(int index) { | |
5db5a3a4 | 560 | return NonNullUtils.checkNotNull(fChildren.get(index)); |
d77f31da BH |
561 | } |
562 | ||
563 | @Override | |
564 | public void addChild(ITmfEventProvider child) { | |
565 | if (!(child instanceof TmfEventProvider)) { | |
566 | throw new IllegalArgumentException(); | |
567 | } | |
fa62dc1d | 568 | child.setParent(this); |
d77f31da BH |
569 | fChildren.add((TmfEventProvider)child); |
570 | } | |
571 | ||
572 | @Override | |
573 | public int getNbChildren() { | |
574 | return fChildren.size(); | |
575 | } | |
2b5c3b7e | 576 | |
8a580390 BH |
577 | /** |
578 | * Returns true if an event was provided by this event provider or one of | |
579 | * its children event providers else false. | |
580 | * | |
581 | * @param event | |
582 | * the event to check | |
583 | * @return <code>true</code> if event was provided by this provider or one | |
584 | * of its children else <code>false</code> | |
585 | */ | |
6badfac0 | 586 | @Override |
8a580390 | 587 | public boolean matches(ITmfEvent event) { |
6badfac0 BH |
588 | if ((event.getTrace() == this)) { |
589 | return true; | |
590 | } | |
591 | if (fChildren.size() > 0) { | |
592 | synchronized (fLock) { | |
593 | List <TmfEventProvider> children = getChildren(TmfEventProvider.class); | |
594 | for (TmfEventProvider child : children) { | |
8a580390 | 595 | if (child.matches(event)) { |
6badfac0 BH |
596 | return true; |
597 | } | |
598 | } | |
599 | } | |
600 | } | |
601 | return false; | |
602 | } | |
603 | ||
2b5c3b7e BH |
604 | // ------------------------------------------------------------------------ |
605 | // Debug code (will also used in tests using reflection) | |
606 | // ------------------------------------------------------------------------ | |
607 | ||
608 | /** | |
609 | * Gets a list of all pending requests. Debug code. | |
610 | * | |
611 | * @return a list of all pending requests | |
612 | */ | |
613 | private List<TmfCoalescedEventRequest> getPendingRequests() { | |
614 | return fPendingCoalescedRequests; | |
615 | } | |
616 | ||
617 | /** | |
618 | * Clears all pending requests. Debug code. | |
619 | */ | |
620 | private void clearPendingRequests() { | |
621 | fPendingCoalescedRequests.clear(); | |
622 | } | |
623 | ||
624 | /** | |
625 | * Enables/disables the timer. Debug code. | |
626 | * | |
627 | * @param enabled | |
628 | * the enable flag to set | |
629 | */ | |
630 | private void setTimerEnabled(Boolean enabled) { | |
631 | fIsTimerEnabled = enabled; | |
632 | } | |
8c8bf09f | 633 | } |