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