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