Improve internal signal handling
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf / src / org / eclipse / linuxtools / tmf / request / TmfDataRequest.java
CommitLineData
8c8bf09f 1/*******************************************************************************
e31e01e8 2 * Copyright (c) 2009, 2010 Ericsson
8c8bf09f
ASL
3 *
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
8 *
9 * Contributors:
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.tmf.request;
14
1a971e96
FC
15import java.util.concurrent.CountDownLatch;
16
ce785d7d 17import org.eclipse.linuxtools.tmf.Tracer;
e31e01e8 18import org.eclipse.linuxtools.tmf.event.TmfData;
8c8bf09f
ASL
19
20/**
21 * <b><u>TmfDataRequest</u></b>
22 * <p>
23 * TmfDataRequests are used to obtain blocks of contiguous data from a data
e31e01e8 24 * provider. Open ranges can be used, especially for continuous streaming.
8c8bf09f 25 * <p>
e31e01e8
FC
26 * The request is processed asynchronously by a TmfProvider and, as blocks
27 * of data become available, handleData() is invoked synchronously for each
28 * block. Upon return, the data instances go out of scope and become eligible
29 * for gc. It is is thus the responsibility of the requester to either clone
30 * or keep a reference to the data it wishes to track specifically.
8c8bf09f 31 * <p>
e31e01e8
FC
32 * This data block approach is used to avoid busting the heap for very
33 * large trace files. The block size is configurable.
8c8bf09f 34 * <p>
e31e01e8
FC
35 * The TmfProvider indicates that the request is completed by calling done().
36 * The request can be canceled at any time with cancel().
8c8bf09f
ASL
37 * <p>
38 * Typical usage:
39 *<pre><code><i>TmfTimeWindow range = new TmfTimewindow(...);
e31e01e8 40 *TmfDataRequest&lt;DataType[]&gt; request = new TmfDataRequest&lt;DataType[]&gt;(DataType.class, 0, NB_EVENTS, BLOCK_SIZE) {
0ab46cd3 41 * public void handleData() {
8c8bf09f
ASL
42 * DataType[] data = request.getData();
43 * for (DataType e : data) {
44 * // do something
45 * }
46 * }
0ab46cd3
FC
47 * public void handleSuccess() {
48 * // do something
49 * }
50 * }
51 * public void handleFailure() {
52 * // do something
53 * }
54 * }
55 * public void handleCancel() {
56 * // do something
57 * }
58 * }
8c8bf09f
ASL
59 *};
60 *fProcessor.process(request, true);
61 *</i></code></pre>
62 *
e31e01e8
FC
63 * TODO: Consider decoupling from "time range", "rank", etc and for the more
64 * generic notion of "criteria". This would allow to extend for "time range", etc
65 * instead of providing specialized constructors. This also means removing the
66 * criteria info from the data structure (with the possible exception of fNbRequested).
67 * The nice thing about it is that it would prepare us well for the coming generation
68 * of analysis tools.
0ab46cd3
FC
69 *
70 * TODO: Implement request failures (codes, etc...)
8c8bf09f 71 */
951d134a 72public abstract class TmfDataRequest<T extends TmfData> implements ITmfDataRequest<T> {
8c8bf09f 73
e31e01e8 74 // ------------------------------------------------------------------------
8c8bf09f 75 // Constants
e31e01e8 76 // ------------------------------------------------------------------------
8c8bf09f
ASL
77
78 // The default maximum number of events per chunk
79 public static final int DEFAULT_BLOCK_SIZE = 1000;
80
81 // The request count for all the events
e31e01e8 82 public static final int ALL_DATA = Integer.MAX_VALUE;
8c8bf09f 83
fc6ccf6f
FC
84 private static int fRequestNumber = 0;
85
e31e01e8 86 // ------------------------------------------------------------------------
8c8bf09f 87 // Attributes
e31e01e8 88 // ------------------------------------------------------------------------
8c8bf09f 89
550d787e
FC
90 private final Class<T> fDataType;
91 private final ExecutionType fExecType;
92 private final int fRequestId; // A unique request ID
93 private final int fIndex; // The index (rank) of the requested event
94 private final int fNbRequested; // The number of requested events (ALL_DATA for all)
f9673903 95 private int fNbRead; // The number of reads so far
8c8bf09f 96
1a971e96
FC
97 private CountDownLatch startedLatch = new CountDownLatch(1);
98 private CountDownLatch completedLatch = new CountDownLatch(1);
550d787e
FC
99 private boolean fRequestRunning = false;
100 private boolean fRequestCompleted = false;
101 private boolean fRequestFailed = false;
102 private boolean fRequestCanceled = false;
8c8bf09f 103
e31e01e8 104 // ------------------------------------------------------------------------
8c8bf09f 105 // Constructors
e31e01e8 106 // ------------------------------------------------------------------------
8c8bf09f 107
2fb2eb37
FC
108 /**
109 * Resets the request counter (used for testing)
110 */
111 public static void reset() {
112 fRequestNumber = 0;
113 }
114
8c8bf09f 115 /**
e31e01e8 116 * Default constructor
2fb2eb37
FC
117 *
118 * @param dataType the requested data type
8c8bf09f 119 */
951d134a 120 public TmfDataRequest(Class<T> dataType) {
f6b14ce2 121 this(dataType, 0, ALL_DATA, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
550d787e
FC
122 }
123
124 public TmfDataRequest(Class<T> dataType, ExecutionType execType) {
125 this(dataType, 0, ALL_DATA, DEFAULT_BLOCK_SIZE, execType);
8c8bf09f
ASL
126 }
127
128 /**
2fb2eb37
FC
129 * @param dataType the requested data type
130 * @param nbRequested the number of data items requested
8c8bf09f 131 */
951d134a 132 public TmfDataRequest(Class<T> dataType, int index) {
f6b14ce2 133 this(dataType, index, ALL_DATA, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
550d787e
FC
134 }
135
136 public TmfDataRequest(Class<T> dataType, int index, ExecutionType execType) {
137 this(dataType, index, ALL_DATA, DEFAULT_BLOCK_SIZE, execType);
8c8bf09f
ASL
138 }
139
140 /**
2fb2eb37
FC
141 * @param dataType the requested data type
142 * @param index the index (rank) of the first event requested
143 * @param blockSize the number of data items per block
8c8bf09f 144 */
951d134a 145 public TmfDataRequest(Class<T> dataType, int index, int nbRequested) {
f6b14ce2 146 this(dataType, index, nbRequested, DEFAULT_BLOCK_SIZE, ExecutionType.FOREGROUND);
550d787e
FC
147 }
148
149 public TmfDataRequest(Class<T> dataType, int index, int nbRequested, ExecutionType execType) {
150 this(dataType, index, nbRequested, DEFAULT_BLOCK_SIZE, execType);
8c8bf09f
ASL
151 }
152
153 /**
2fb2eb37
FC
154 * @param dataType the requested data type
155 * @param index the index (rank) of the first event requested
156 * @param nbRequested the number of data items requested
157 * @param blockSize the number of data items per block
8c8bf09f 158 */
951d134a 159 public TmfDataRequest(Class<T> dataType, int index, int nbRequested, int blockSize) {
f6b14ce2 160 this(dataType, index, nbRequested, blockSize, ExecutionType.FOREGROUND);
550d787e
FC
161 }
162
163 public TmfDataRequest(Class<T> dataType, int index, int nbRequested, int blockSize, ExecutionType execType) {
fc6ccf6f 164 fRequestId = fRequestNumber++;
e31e01e8
FC
165 fDataType = dataType;
166 fIndex = index;
167 fNbRequested = nbRequested;
550d787e 168 fExecType = execType;
e31e01e8 169 fNbRead = 0;
3b38ea61 170 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "created"); //$NON-NLS-1$
2fb2eb37
FC
171 }
172
173 /**
174 * Copy constructor
175 */
176 @SuppressWarnings("unused")
177 private TmfDataRequest(TmfDataRequest<T> other) {
550d787e 178 this(null, 0, ALL_DATA, DEFAULT_BLOCK_SIZE);
8c8bf09f 179 }
951d134a 180
e31e01e8 181 // ------------------------------------------------------------------------
165c977c 182 // Accessors
e31e01e8 183 // ------------------------------------------------------------------------
8c8bf09f 184
fc6ccf6f
FC
185 /**
186 * @return the request ID
187 */
d4011df2 188 @Override
2fb2eb37 189 public int getRequestId() {
fc6ccf6f
FC
190 return fRequestId;
191 }
192
28b94d61 193 /**
951d134a 194 * @return the index of the first event requested
28b94d61 195 */
d4011df2 196 @Override
951d134a 197 public int getIndex() {
28b94d61
FC
198 return fIndex;
199 }
200
550d787e
FC
201 /**
202 * @return the index of the first event requested
203 */
d4011df2 204 @Override
550d787e
FC
205 public ExecutionType getExecType() {
206 return fExecType;
207 }
208
8c8bf09f 209 /**
e31e01e8 210 * @return the number of requested events (ALL_DATA = all)
8c8bf09f 211 */
d4011df2
FC
212 @Override
213 public int getNbRequested() {
e31e01e8 214 return fNbRequested;
8c8bf09f
ASL
215 }
216
660c9e60
FC
217 /**
218 * @return the number of events read so far
219 */
d4011df2
FC
220 @Override
221 public synchronized int getNbRead() {
e31e01e8 222 return fNbRead;
660c9e60
FC
223 }
224
550d787e
FC
225 /**
226 * @return indicates if the request is completed
227 */
d4011df2 228 @Override
c1c69938 229 public synchronized boolean isRunning() {
550d787e
FC
230 return fRequestRunning;
231 }
232
8c8bf09f
ASL
233 /**
234 * @return indicates if the request is completed
235 */
d4011df2 236 @Override
c1c69938 237 public synchronized boolean isCompleted() {
8c8bf09f
ASL
238 return fRequestCompleted;
239 }
240
0ab46cd3
FC
241 /**
242 * @return indicates if the request is canceled
243 */
d4011df2 244 @Override
c1c69938 245 public synchronized boolean isFailed() {
0ab46cd3
FC
246 return fRequestFailed;
247 }
248
8c8bf09f
ASL
249 /**
250 * @return indicates if the request is canceled
251 */
d4011df2 252 @Override
c1c69938 253 public synchronized boolean isCancelled() {
8c8bf09f
ASL
254 return fRequestCanceled;
255 }
256
e31e01e8
FC
257 /**
258 * @return the requested data type
259 */
d4011df2
FC
260 @Override
261 public Class<T> getDataType() {
e31e01e8
FC
262 return fDataType;
263 }
264
265 // ------------------------------------------------------------------------
8c8bf09f 266 // Operators
e31e01e8 267 // ------------------------------------------------------------------------
8c8bf09f
ASL
268
269 /**
660c9e60 270 * Sets the data object to specified value. To be called by the
8c8bf09f 271 * asynchronous method implementor.
f9673903 272 *
8c8bf09f
ASL
273 * @param data Data value to set.
274 */
dc299841 275
8c8bf09f 276 /**
0ab46cd3
FC
277 * Handle a block of incoming data. This method is called every time
278 * a block of data becomes available.
8c8bf09f
ASL
279 *
280 * - Data items are received in the order they appear in the stream.
281 * - Called by the request processor, in its execution thread, every time a
282 * block of data becomes available.
283 * - Request processor performs a synchronous call to handlePartialResult()
284 * i.e. its execution threads holds until handlePartialData() returns.
285 * - Original data items are disposed of on return i.e. keep a reference
286 * (or a copy) if some persistence is needed between invocations.
287 * - When there is no more data, done() is called.
288 *
f9673903 289 * @param events - an events
8c8bf09f 290 */
d4011df2
FC
291 @Override
292 public void handleData(T data) {
f9673903
FC
293 if (data != null) {
294 fNbRead++;
295 }
296 }
9aae0442 297
d4011df2
FC
298 @Override
299 public void handleStarted() {
dc299841 300 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "started"); //$NON-NLS-1$
550d787e
FC
301 }
302
0ab46cd3
FC
303 /**
304 * Handle the completion of the request. It is called when there is no more
305 * data available either because:
306 * - the request completed normally
307 * - the request failed
308 * - the request was canceled
309 *
310 * As a convenience, handleXXXX methods are provided. They are meant to be
311 * overridden by the application if it needs to handle these conditions.
312 */
d4011df2
FC
313 @Override
314 public void handleCompleted() {
0ab46cd3
FC
315 if (fRequestFailed) {
316 handleFailure();
317 }
318 else if (fRequestCanceled) {
319 handleCancel();
320 }
37c8b509 321 else {
36548af3 322 handleSuccess();
37c8b509 323 }
dc299841 324 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "completed"); //$NON-NLS-1$
0ab46cd3
FC
325 }
326
d4011df2
FC
327 @Override
328 public void handleSuccess() {
dc299841 329 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "succeeded"); //$NON-NLS-1$
0ab46cd3
FC
330 }
331
d4011df2
FC
332 @Override
333 public void handleFailure() {
dc299841 334 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "failed"); //$NON-NLS-1$
0ab46cd3
FC
335 }
336
d4011df2
FC
337 @Override
338 public void handleCancel() {
dc299841 339 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "cancelled"); //$NON-NLS-1$
8c8bf09f
ASL
340 }
341
0c2a2e08
FC
342 /**
343 * To suspend the client thread until the request starts (or is
344 * canceled).
345 *
346 * @throws InterruptedException
347 */
348 public void waitForStart() throws InterruptedException {
1a971e96
FC
349 while (!fRequestRunning) {
350 startedLatch.await();
351 }
0c2a2e08
FC
352 }
353
8c8bf09f
ASL
354 /**
355 * To suspend the client thread until the request completes (or is
356 * canceled).
357 *
358 * @throws InterruptedException
359 */
d4011df2
FC
360 @Override
361 public void waitForCompletion() throws InterruptedException {
1a971e96
FC
362 while (!fRequestCompleted) {
363 completedLatch.await();
364 }
9aae0442
ASL
365 }
366
550d787e
FC
367 /**
368 * Called by the request processor upon starting to service the request.
369 */
d4011df2
FC
370 @Override
371 public void start() {
1a971e96 372 synchronized(this) {
550d787e 373 fRequestRunning = true;
550d787e
FC
374 }
375 handleStarted();
1a971e96 376 startedLatch.countDown();
550d787e
FC
377 }
378
8c8bf09f 379 /**
0ab46cd3 380 * Called by the request processor upon completion.
8c8bf09f 381 */
d4011df2
FC
382 @Override
383 public void done() {
1a971e96 384 synchronized(this) {
9b635e61
FC
385 if (!fRequestCompleted) {
386 fRequestRunning = false;
387 fRequestCompleted = true;
388 }
8c8bf09f 389 }
1a971e96
FC
390 handleCompleted();
391 completedLatch.countDown();
8c8bf09f
ASL
392 }
393
394 /**
0ab46cd3
FC
395 * Called by the request processor upon failure.
396 */
d4011df2 397 @Override
c1c69938
FC
398 public void fail() {
399 synchronized(this) {
400 fRequestFailed = true;
401 }
1a971e96 402 done();
0ab46cd3
FC
403 }
404
405 /**
406 * Called by the request processor upon cancellation.
8c8bf09f 407 */
d4011df2 408 @Override
c1c69938
FC
409 public void cancel() {
410 synchronized(this) {
411 fRequestCanceled = true;
412 }
1a971e96 413 done();
8c8bf09f
ASL
414 }
415
cbd4ad82
FC
416 // ------------------------------------------------------------------------
417 // Object
418 // ------------------------------------------------------------------------
419
420 @Override
2fb2eb37 421 // All requests have a unique id
cbd4ad82 422 public int hashCode() {
2fb2eb37 423 return getRequestId();
cbd4ad82
FC
424 }
425
426 @Override
427 public boolean equals(Object other) {
428 if (other instanceof TmfDataRequest<?>) {
429 TmfDataRequest<?> request = (TmfDataRequest<?>) other;
430 return (request.fDataType == fDataType) &&
431 (request.fIndex == fIndex) &&
432 (request.fNbRequested == fNbRequested);
433 }
434 return false;
435 }
436
2fb2eb37 437 @Override
3b38ea61 438 @SuppressWarnings("nls")
2fb2eb37 439 public String toString() {
1a971e96
FC
440 return "[TmfDataRequest(" + fRequestId + "," + fDataType.getSimpleName() +
441 "," + fIndex + "," + fNbRequested + ")]";
2fb2eb37 442 }
8c8bf09f 443}
This page took 0.063789 seconds and 5 git commands to generate.