tmf: Improved toString methods for debugging
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / request / TmfDataRequest.java
CommitLineData
8c8bf09f 1/*******************************************************************************
61759503 2 * Copyright (c) 2009, 2013 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
ASL
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
12
6c13869b 13package org.eclipse.linuxtools.tmf.core.request;
8c8bf09f 14
5419a136
AM
15import java.util.concurrent.CountDownLatch;
16
5500a7f0 17import org.eclipse.linuxtools.internal.tmf.core.TmfCoreTracer;
72f1e62a 18import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
8c8bf09f
ASL
19
20/**
5419a136
AM
21 * TmfDataRequests are used to obtain blocks of contiguous data from a data provider. Open ranges can be used,
22 * especially for continuous streaming.
8c8bf09f 23 * <p>
5419a136
AM
24 * The request is processed asynchronously by a TmfProvider and, as blocks of data become available, handleData() is
25 * invoked synchronously for each block. Upon return, the data instances go out of scope and become eligible for gc. It
26 * is is thus the responsibility of the requester to either clone or keep a reference to the data it wishes to track
27 * specifically.
8c8bf09f 28 * <p>
5419a136
AM
29 * This data block approach is used to avoid busting the heap for very large trace files. The block size is
30 * configurable.
8c8bf09f 31 * <p>
5419a136
AM
32 * The TmfProvider indicates that the request is completed by calling done(). The request can be canceled at any time
33 * with cancel().
8c8bf09f
ASL
34 * <p>
35 * Typical usage:
0283f7ff 36 *
12c155f5
FC
37 * <pre>
38 * <code><i>TmfTimeWindow range = new TmfTimewindow(...);
39 * TmfDataRequest&lt;DataType[]&gt; request = new TmfDataRequest&lt;DataType[]&gt;(DataType.class, 0, NB_EVENTS, BLOCK_SIZE) {
40 * public void handleData() {
41 * DataType[] data = request.getData();
42 * for (DataType e : data) {
43 * // do something
44 * }
45 * }
46 * public void handleSuccess() {
47 * // do something
48 * }
49 * }
50 * public void handleFailure() {
51 * // do something
52 * }
53 * }
54 * public void handleCancel() {
55 * // do something
56 * }
57 * }
58 * };
59 * fProcessor.process(request, true);
60 * </i></code>
61 * </pre>
0283f7ff 62 *
5419a136
AM
63 * TODO: Consider decoupling from "time range", "rank", etc and for the more generic notion of "criteria". This would
64 * allow to extend for "time range", etc instead of providing specialized constructors. This also means removing the
65 * criteria info from the data structure (with the possible exception of fNbRequested). The nice thing about it is that
66 * it would prepare us well for the coming generation of analysis tools.
0283f7ff 67 *
0ab46cd3 68 * TODO: Implement request failures (codes, etc...)
0283f7ff 69 *
5419a136 70 * @version 1.0
8fd82db5 71 * @author Francois Chouinard
8c8bf09f 72 */
5419a136 73public abstract class TmfDataRequest implements ITmfDataRequest {
8c8bf09f 74
e31e01e8 75 // ------------------------------------------------------------------------
8c8bf09f 76 // Constants
e31e01e8 77 // ------------------------------------------------------------------------
8c8bf09f 78
063f0d27 79 /** The default maximum number of events per chunk */
8c8bf09f
ASL
80 public static final int DEFAULT_BLOCK_SIZE = 1000;
81
063f0d27 82 /** The request count for all the events */
e31e01e8 83 public static final int ALL_DATA = Integer.MAX_VALUE;
12c155f5 84
5419a136
AM
85 private static int fRequestNumber = 0;
86
e31e01e8 87 // ------------------------------------------------------------------------
8c8bf09f 88 // Attributes
e31e01e8 89 // ------------------------------------------------------------------------
8c8bf09f 90
5419a136
AM
91 private final Class<? extends ITmfEvent> fDataType;
92 private final ExecutionType fExecType;
93
94 /** A unique request ID */
95 private final int fRequestId;
96
97 /** The index (rank) of the requested event */
98 protected long fIndex;
99
100 /** The number of requested events (ALL_DATA for all) */
101 protected int fNbRequested;
6f4e8ec0
AM
102
103 /** The block size (for BG requests) */
104 private final int fBlockSize;
105
5419a136
AM
106 /** The number of reads so far */
107 private int fNbRead;
108
109 private final CountDownLatch startedLatch = new CountDownLatch(1);
110 private final CountDownLatch completedLatch = new CountDownLatch(1);
111 private boolean fRequestRunning;
112 private boolean fRequestCompleted;
113 private boolean fRequestFailed;
114 private boolean fRequestCanceled;
115
e31e01e8 116 // ------------------------------------------------------------------------
8c8bf09f 117 // Constructors
e31e01e8 118 // ------------------------------------------------------------------------
8c8bf09f 119
5419a136
AM
120 /**
121 * Resets the request counter (used for testing)
122 */
123 public static void reset() {
124 fRequestNumber = 0;
125 }
126
8c8bf09f 127 /**
0d9a6d76
FC
128 * Request all the events of a given type (high priority)
129 * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
0283f7ff 130 *
0d9a6d76 131 * @param dataType the requested data type
8c8bf09f 132 */
6256d8ad 133 public TmfDataRequest(Class<? extends ITmfEvent> dataType) {
f6b14ce2 134 this(dataType, 0, ALL_DATA, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
550d787e
FC
135 }
136
0d9a6d76
FC
137 /**
138 * Request all the events of a given type (given priority)
139 * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
0283f7ff 140 *
0d9a6d76
FC
141 * @param dataType the requested data type
142 * @param priority the requested execution priority
143 */
6256d8ad 144 public TmfDataRequest(Class<? extends ITmfEvent> dataType, ExecutionType priority) {
0d9a6d76 145 this(dataType, 0, ALL_DATA, DEFAULT_BLOCK_SIZE, priority);
8c8bf09f
ASL
146 }
147
148 /**
0d9a6d76
FC
149 * Request all the events of a given type from the given index (high priority)
150 * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
0283f7ff 151 *
0d9a6d76
FC
152 * @param dataType the requested data type
153 * @param index the index of the first event to retrieve
8c8bf09f 154 */
6256d8ad 155 public TmfDataRequest(Class<? extends ITmfEvent> dataType, long index) {
f6b14ce2 156 this(dataType, index, ALL_DATA, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
550d787e
FC
157 }
158
0d9a6d76
FC
159 /**
160 * Request all the events of a given type from the given index (given priority)
161 * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
0283f7ff 162 *
0d9a6d76
FC
163 * @param dataType the requested data type
164 * @param index the index of the first event to retrieve
165 * @param priority the requested execution priority
166 */
6256d8ad 167 public TmfDataRequest(Class<? extends ITmfEvent> dataType, long index, ExecutionType priority) {
0d9a6d76 168 this(dataType, index, ALL_DATA, DEFAULT_BLOCK_SIZE, priority);
8c8bf09f
ASL
169 }
170
171 /**
0d9a6d76
FC
172 * Request 'n' events of a given type from the given index (high priority)
173 * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
0283f7ff 174 *
0d9a6d76
FC
175 * @param dataType the requested data type
176 * @param index the index of the first event to retrieve
177 * @param nbRequested the number of events requested
8c8bf09f 178 */
6256d8ad 179 public TmfDataRequest(Class<? extends ITmfEvent> dataType, long index, int nbRequested) {
f6b14ce2 180 this(dataType, index, nbRequested, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
550d787e
FC
181 }
182
0d9a6d76
FC
183 /**
184 * Request 'n' events of a given type from the given index (given priority)
185 * Events are returned in blocks of the default size (DEFAULT_BLOCK_SIZE).
0283f7ff 186 *
0d9a6d76
FC
187 * @param dataType the requested data type
188 * @param index the index of the first event to retrieve
189 * @param nbRequested the number of events requested
190 * @param priority the requested execution priority
191 */
6256d8ad 192 public TmfDataRequest(Class<? extends ITmfEvent> dataType, long index, int nbRequested, ExecutionType priority) {
0d9a6d76 193 this(dataType, index, nbRequested, DEFAULT_BLOCK_SIZE, priority);
8c8bf09f
ASL
194 }
195
196 /**
0d9a6d76
FC
197 * Request 'n' events of a given type from the given index (high priority).
198 * Events are returned in blocks of the given size.
0283f7ff 199 *
0d9a6d76
FC
200 * @param dataType the requested data type
201 * @param index the index of the first event to retrieve
202 * @param nbRequested the number of events requested
203 * @param blockSize the number of events per block
8c8bf09f 204 */
6256d8ad 205 public TmfDataRequest(Class<? extends ITmfEvent> dataType, long index, int nbRequested, int blockSize) {
f6b14ce2 206 this(dataType, index, nbRequested, blockSize, ExecutionType.FOREGROUND);
550d787e
FC
207 }
208
0d9a6d76
FC
209 /**
210 * Request 'n' events of a given type from the given index (given priority).
211 * Events are returned in blocks of the given size.
0283f7ff 212 *
0d9a6d76
FC
213 * @param dataType the requested data type
214 * @param index the index of the first event to retrieve
215 * @param nbRequested the number of events requested
216 * @param blockSize the number of events per block
217 * @param priority the requested execution priority
218 */
6256d8ad 219 public TmfDataRequest(Class<? extends ITmfEvent> dataType, long index, int nbRequested, int blockSize, ExecutionType priority) {
5419a136
AM
220 fRequestId = fRequestNumber++;
221 fDataType = dataType;
222 fIndex = index;
223 fNbRequested = nbRequested;
8584dc20 224 fBlockSize = blockSize;
5419a136
AM
225 fExecType = priority;
226 fNbRead = 0;
227
228 fRequestRunning = false;
229 fRequestCompleted = false;
230 fRequestFailed = false;
231 fRequestCanceled = false;
beae214a 232
5500a7f0 233 if (!(this instanceof ITmfEventRequest) && TmfCoreTracer.isRequestTraced()) {
90891c08
FC
234 String type = getClass().getName();
235 type = type.substring(type.lastIndexOf('.') + 1);
236 @SuppressWarnings("nls")
0283f7ff
FC
237 String message = "CREATED "
238 + (getExecType() == ITmfDataRequest.ExecutionType.BACKGROUND ? "(BG)" : "(FG)")
90891c08
FC
239 + " Type=" + type + " Index=" + getIndex() + " NbReq=" + getNbRequested()
240 + " DataType=" + getDataType().getSimpleName();
5500a7f0 241 TmfCoreTracer.traceRequest(this, message);
90891c08 242 }
2fb2eb37
FC
243 }
244
245 /**
246 * Copy constructor
247 */
248 @SuppressWarnings("unused")
6256d8ad 249 private TmfDataRequest(TmfDataRequest other) {
12c155f5 250 this(null, 0, ALL_DATA, DEFAULT_BLOCK_SIZE);
8c8bf09f 251 }
951d134a 252
e31e01e8 253 // ------------------------------------------------------------------------
165c977c 254 // Accessors
e31e01e8 255 // ------------------------------------------------------------------------
8c8bf09f 256
5419a136
AM
257 /**
258 * @return the request ID
259 */
260 @Override
261 public int getRequestId() {
262 return fRequestId;
263 }
264
12c155f5
FC
265 /**
266 * @return the index of the first event requested
267 */
268 @Override
9e0640dc 269 public long getIndex() {
5419a136 270 return fIndex;
12c155f5
FC
271 }
272
273 /**
0d9a6d76 274 * @return the execution type (priority)
12c155f5
FC
275 */
276 @Override
277 public ExecutionType getExecType() {
5419a136 278 return fExecType;
12c155f5 279 }
550d787e 280
5419a136
AM
281 /**
282 * @return the number of requested events (ALL_DATA = all)
8c8bf09f 283 */
d4011df2 284 @Override
5419a136
AM
285 public int getNbRequested() {
286 return fNbRequested;
8c8bf09f
ASL
287 }
288
8016d660
FC
289 /**
290 * @return the block size (for BG requests)
291 */
292 @Override
12c155f5 293 public int getBlockSize() {
8016d660
FC
294 return fBlockSize;
295 }
296
660c9e60
FC
297 /**
298 * @return the number of events read so far
299 */
d4011df2 300 @Override
12c155f5 301 public synchronized int getNbRead() {
5419a136
AM
302 return fNbRead;
303 }
304
305 /**
306 * @return indicates if the request is currently running
307 */
308 @Override
309 public synchronized boolean isRunning() {
310 return fRequestRunning;
311 }
312
313 /**
314 * @return indicates if the request is completed
315 */
316 @Override
317 public synchronized boolean isCompleted() {
318 return fRequestCompleted;
319 }
320
321 /**
322 * @return indicates if the request has failed
323 */
324 @Override
325 public synchronized boolean isFailed() {
326 return fRequestFailed;
327 }
328
329 /**
330 * @return indicates if the request is canceled
331 */
332 @Override
333 public synchronized boolean isCancelled() {
334 return fRequestCanceled;
8c8bf09f
ASL
335 }
336
e31e01e8
FC
337 /**
338 * @return the requested data type
339 */
d4011df2 340 @Override
6256d8ad 341 public Class<? extends ITmfEvent> getDataType() {
5419a136 342 return fDataType;
e31e01e8
FC
343 }
344
a79913eb
FC
345 // ------------------------------------------------------------------------
346 // Setters
347 // ------------------------------------------------------------------------
348
349 /**
350 * this method is called by the event provider to set the index corresponding to the time range start time
0283f7ff 351 *
12c155f5
FC
352 * @param index
353 * the start time index
a79913eb 354 */
12c155f5 355 protected void setIndex(int index) {
5419a136 356 fIndex = index;
a79913eb
FC
357 }
358
e31e01e8 359 // ------------------------------------------------------------------------
5419a136 360 // Operators
e31e01e8 361 // ------------------------------------------------------------------------
8c8bf09f 362
12c155f5 363 /**
0d9a6d76
FC
364 * Handle incoming data, one event at a time i.e. this method is invoked
365 * for every data item obtained by the request.
0283f7ff 366 *
0d9a6d76
FC
367 * - Data items are received in the order they appear in the stream
368 * - Called by the request processor, in its execution thread, every time
369 * a block of data becomes available.
370 * - Request processor performs a synchronous call to handleData() i.e.
371 * its execution threads holds until handleData() returns.
372 * - Original data items are disposed of on return i.e. keep a reference
373 * (or a copy) if some persistence is needed between invocations.
374 * - When there is no more data, done() is called.
0283f7ff 375 *
0d9a6d76 376 * @param data a piece of data
8c8bf09f 377 */
d4011df2 378 @Override
6256d8ad 379 public void handleData(ITmfEvent data) {
5419a136
AM
380 if (data != null) {
381 fNbRead++;
382 }
383 }
384
385 @Override
386 public void handleStarted() {
387 if (TmfCoreTracer.isRequestTraced()) {
388 TmfCoreTracer.traceRequest(this, "STARTED"); //$NON-NLS-1$
389 }
390 }
391
392 /**
393 * Handle the completion of the request. It is called when there is no
394 * more data available either because:
395 * - the request completed normally
396 * - the request failed
397 * - the request was canceled
398 *
399 * As a convenience, handleXXXX methods are provided. They are meant to be
400 * overridden by the application if it needs to handle these conditions.
401 */
402 @Override
403 public void handleCompleted() {
404 boolean requestFailed = false;
405 boolean requestCanceled = false;
406 synchronized (this) {
407 requestFailed = fRequestFailed;
408 requestCanceled = fRequestCanceled;
409 }
410
411 if (requestFailed) {
412 handleFailure();
413 } else if (requestCanceled) {
414 handleCancel();
415 } else {
416 handleSuccess();
417 }
418 if (TmfCoreTracer.isRequestTraced()) {
419 TmfCoreTracer.traceRequest(this, "COMPLETED (" + fNbRead + " events read)"); //$NON-NLS-1$ //$NON-NLS-2$
420 }
0ab46cd3
FC
421 }
422
5419a136
AM
423 @Override
424 public void handleSuccess() {
425 if (TmfCoreTracer.isRequestTraced()) {
426 TmfCoreTracer.traceRequest(this, "SUCCEEDED"); //$NON-NLS-1$
427 }
428 }
429
430 @Override
431 public void handleFailure() {
432 if (TmfCoreTracer.isRequestTraced()) {
433 TmfCoreTracer.traceRequest(this, "FAILED"); //$NON-NLS-1$
434 }
435 }
436
437 @Override
438 public void handleCancel() {
439 if (TmfCoreTracer.isRequestTraced()) {
440 TmfCoreTracer.traceRequest(this, "CANCELLED"); //$NON-NLS-1$
441 }
442 }
443
444 /**
445 * To suspend the client thread until the request starts (or is canceled).
446 *
447 * @throws InterruptedException
448 * If the thread was interrupted while waiting
449 */
450 public void waitForStart() throws InterruptedException {
451 while (!fRequestRunning) {
452 startedLatch.await();
453 }
454 }
455
456 /**
457 * To suspend the client thread until the request completes (or is
458 * canceled).
063f0d27 459 *
5419a136
AM
460 * @throws InterruptedException
461 * If the thread was interrupted while waiting
462 */
463 @Override
464 public void waitForCompletion() throws InterruptedException {
465 while (!fRequestCompleted) {
466 completedLatch.await();
467 }
468 }
469
470 /**
471 * Called by the request processor upon starting to service the request.
550d787e 472 */
d4011df2 473 @Override
5419a136
AM
474 public void start() {
475 synchronized (this) {
476 fRequestRunning = true;
477 }
478 handleStarted();
479 startedLatch.countDown();
480 }
481
482 /**
483 * Called by the request processor upon completion.
484 */
485 @Override
486 public void done() {
487 synchronized (this) {
488 if (!fRequestCompleted) {
489 fRequestRunning = false;
490 fRequestCompleted = true;
491 } else {
492 return;
493 }
494 }
495 try {
496 handleCompleted();
497 } finally {
498 completedLatch.countDown();
499 }
500 }
501
502 /**
503 * Called by the request processor upon failure.
504 */
505 @Override
506 public void fail() {
507 synchronized (this) {
508 fRequestFailed = true;
509 }
510 done();
511 }
512
513 /**
514 * Called by the request processor upon cancellation.
515 */
516 @Override
517 public void cancel() {
518 synchronized (this) {
519 fRequestCanceled = true;
520 }
521 done();
8c8bf09f
ASL
522 }
523
cbd4ad82
FC
524 // ------------------------------------------------------------------------
525 // Object
526 // ------------------------------------------------------------------------
527
528 @Override
2fb2eb37 529 // All requests have a unique id
cbd4ad82 530 public int hashCode() {
12c155f5 531 return getRequestId();
cbd4ad82
FC
532 }
533
534 @Override
535 public boolean equals(Object other) {
6256d8ad
AM
536 if (other instanceof TmfDataRequest) {
537 TmfDataRequest request = (TmfDataRequest) other;
5419a136
AM
538 return (request.fDataType == fDataType) && (request.fIndex == fIndex)
539 && (request.fNbRequested == fNbRequested);
12c155f5
FC
540 }
541 return false;
cbd4ad82
FC
542 }
543
2fb2eb37 544 @Override
3b38ea61 545 @SuppressWarnings("nls")
2fb2eb37 546 public String toString() {
b1b156f3
PT
547 String name = getClass().getName();
548 int dot = name.lastIndexOf('.');
549 if (dot >= 0) {
550 name = name.substring(dot + 1);
551 }
552 return "[" + name + "(" + fRequestId + "," + fDataType.getSimpleName()+ "," + getExecType()
553 + "," + fIndex + "," + fNbRequested + "," + getBlockSize() + ")]";
2fb2eb37 554 }
8c8bf09f 555}
This page took 0.084156 seconds and 5 git commands to generate.