2010-11-05 Francois Chouinard <fchouinard@gmail.com> Fix for Bug329473
[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;
550d787e 170 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "created");
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 */
8c8bf09f 275 /**
0ab46cd3
FC
276 * Handle a block of incoming data. This method is called every time
277 * a block of data becomes available.
8c8bf09f
ASL
278 *
279 * - Data items are received in the order they appear in the stream.
280 * - Called by the request processor, in its execution thread, every time a
281 * block of data becomes available.
282 * - Request processor performs a synchronous call to handlePartialResult()
283 * i.e. its execution threads holds until handlePartialData() returns.
284 * - Original data items are disposed of on return i.e. keep a reference
285 * (or a copy) if some persistence is needed between invocations.
286 * - When there is no more data, done() is called.
287 *
f9673903 288 * @param events - an events
8c8bf09f 289 */
d4011df2
FC
290 @Override
291 public void handleData(T data) {
f9673903
FC
292 if (data != null) {
293 fNbRead++;
294 }
295 }
9aae0442 296
d4011df2
FC
297 @Override
298 public void handleStarted() {
550d787e
FC
299 }
300
0ab46cd3
FC
301 /**
302 * Handle the completion of the request. It is called when there is no more
303 * data available either because:
304 * - the request completed normally
305 * - the request failed
306 * - the request was canceled
307 *
308 * As a convenience, handleXXXX methods are provided. They are meant to be
309 * overridden by the application if it needs to handle these conditions.
310 */
d4011df2
FC
311 @Override
312 public void handleCompleted() {
0ab46cd3 313 if (fRequestFailed) {
550d787e 314 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "failed");
0ab46cd3
FC
315 handleFailure();
316 }
317 else if (fRequestCanceled) {
550d787e 318 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "cancelled");
0ab46cd3
FC
319 handleCancel();
320 }
37c8b509 321 else {
550d787e 322 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "succeeded");
36548af3 323 handleSuccess();
37c8b509 324 }
0ab46cd3
FC
325 }
326
d4011df2
FC
327 @Override
328 public void handleSuccess() {
0ab46cd3
FC
329 }
330
d4011df2
FC
331 @Override
332 public void handleFailure() {
0ab46cd3
FC
333 }
334
d4011df2
FC
335 @Override
336 public void handleCancel() {
8c8bf09f
ASL
337 }
338
0c2a2e08
FC
339 /**
340 * To suspend the client thread until the request starts (or is
341 * canceled).
342 *
343 * @throws InterruptedException
344 */
345 public void waitForStart() throws InterruptedException {
1a971e96
FC
346 while (!fRequestRunning) {
347 startedLatch.await();
348 }
0c2a2e08
FC
349 }
350
8c8bf09f
ASL
351 /**
352 * To suspend the client thread until the request completes (or is
353 * canceled).
354 *
355 * @throws InterruptedException
356 */
d4011df2
FC
357 @Override
358 public void waitForCompletion() throws InterruptedException {
1a971e96
FC
359 while (!fRequestCompleted) {
360 completedLatch.await();
361 }
9aae0442
ASL
362 }
363
550d787e
FC
364 /**
365 * Called by the request processor upon starting to service the request.
366 */
d4011df2
FC
367 @Override
368 public void start() {
550d787e 369 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "starting");
1a971e96 370 synchronized(this) {
550d787e 371 fRequestRunning = true;
550d787e
FC
372 }
373 handleStarted();
1a971e96 374 startedLatch.countDown();
9b635e61 375 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "started");
550d787e
FC
376 }
377
8c8bf09f 378 /**
0ab46cd3 379 * Called by the request processor upon completion.
8c8bf09f 380 */
d4011df2
FC
381 @Override
382 public void done() {
550d787e 383 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "completing");
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
FC
437 @Override
438 public String toString() {
1a971e96
FC
439 return "[TmfDataRequest(" + fRequestId + "," + fDataType.getSimpleName() +
440 "," + fIndex + "," + fNbRequested + ")]";
2fb2eb37 441 }
8c8bf09f 442}
This page took 0.053057 seconds and 5 git commands to generate.