2010-10-26 Francois Chouinard <fchouinard@gmail.com> Contribution for Bug309042
[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 */
2fb2eb37 188 public int getRequestId() {
fc6ccf6f
FC
189 return fRequestId;
190 }
191
28b94d61 192 /**
951d134a 193 * @return the index of the first event requested
28b94d61 194 */
951d134a 195 public int getIndex() {
28b94d61
FC
196 return fIndex;
197 }
198
550d787e
FC
199 /**
200 * @return the index of the first event requested
201 */
202 public ExecutionType getExecType() {
203 return fExecType;
204 }
205
8c8bf09f 206 /**
e31e01e8 207 * @return the number of requested events (ALL_DATA = all)
8c8bf09f 208 */
e31e01e8
FC
209 public int getNbRequested() {
210 return fNbRequested;
8c8bf09f
ASL
211 }
212
660c9e60
FC
213 /**
214 * @return the number of events read so far
215 */
2fb2eb37 216 public synchronized int getNbRead() {
e31e01e8 217 return fNbRead;
660c9e60
FC
218 }
219
550d787e
FC
220 /**
221 * @return indicates if the request is completed
222 */
223 public boolean isRunning() {
224 return fRequestRunning;
225 }
226
8c8bf09f
ASL
227 /**
228 * @return indicates if the request is completed
229 */
230 public boolean isCompleted() {
231 return fRequestCompleted;
232 }
233
0ab46cd3
FC
234 /**
235 * @return indicates if the request is canceled
236 */
237 public boolean isFailed() {
238 return fRequestFailed;
239 }
240
8c8bf09f
ASL
241 /**
242 * @return indicates if the request is canceled
243 */
244 public boolean isCancelled() {
245 return fRequestCanceled;
246 }
247
e31e01e8
FC
248 /**
249 * @return the requested data type
250 */
951d134a 251 public Class<T> getDataType() {
e31e01e8
FC
252 return fDataType;
253 }
254
255 // ------------------------------------------------------------------------
8c8bf09f 256 // Operators
e31e01e8 257 // ------------------------------------------------------------------------
8c8bf09f
ASL
258
259 /**
660c9e60 260 * Sets the data object to specified value. To be called by the
8c8bf09f 261 * asynchronous method implementor.
f9673903 262 *
8c8bf09f
ASL
263 * @param data Data value to set.
264 */
8c8bf09f 265 /**
0ab46cd3
FC
266 * Handle a block of incoming data. This method is called every time
267 * a block of data becomes available.
8c8bf09f
ASL
268 *
269 * - Data items are received in the order they appear in the stream.
270 * - Called by the request processor, in its execution thread, every time a
271 * block of data becomes available.
272 * - Request processor performs a synchronous call to handlePartialResult()
273 * i.e. its execution threads holds until handlePartialData() returns.
274 * - Original data items are disposed of on return i.e. keep a reference
275 * (or a copy) if some persistence is needed between invocations.
276 * - When there is no more data, done() is called.
277 *
f9673903 278 * @param events - an events
8c8bf09f 279 */
f9673903
FC
280 public void handleData(T data) {
281 if (data != null) {
282 fNbRead++;
283 }
284 }
9aae0442 285
550d787e
FC
286 public void handleStarted() {
287 }
288
0ab46cd3
FC
289 /**
290 * Handle the completion of the request. It is called when there is no more
291 * data available either because:
292 * - the request completed normally
293 * - the request failed
294 * - the request was canceled
295 *
296 * As a convenience, handleXXXX methods are provided. They are meant to be
297 * overridden by the application if it needs to handle these conditions.
298 */
8c8bf09f 299 public void handleCompleted() {
0ab46cd3 300 if (fRequestFailed) {
550d787e 301 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "failed");
0ab46cd3
FC
302 handleFailure();
303 }
304 else if (fRequestCanceled) {
550d787e 305 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "cancelled");
0ab46cd3
FC
306 handleCancel();
307 }
37c8b509 308 else {
550d787e 309 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "succeeded");
36548af3 310 handleSuccess();
37c8b509 311 }
0ab46cd3
FC
312 }
313
314 public void handleSuccess() {
315 }
316
317 public void handleFailure() {
318 }
319
320 public void handleCancel() {
8c8bf09f
ASL
321 }
322
0c2a2e08
FC
323 /**
324 * To suspend the client thread until the request starts (or is
325 * canceled).
326 *
327 * @throws InterruptedException
328 */
329 public void waitForStart() throws InterruptedException {
1a971e96
FC
330 while (!fRequestRunning) {
331 startedLatch.await();
332 }
0c2a2e08
FC
333 }
334
8c8bf09f
ASL
335 /**
336 * To suspend the client thread until the request completes (or is
337 * canceled).
338 *
339 * @throws InterruptedException
340 */
2fb2eb37 341 public void waitForCompletion() throws InterruptedException {
1a971e96
FC
342 while (!fRequestCompleted) {
343 completedLatch.await();
344 }
9aae0442
ASL
345 }
346
550d787e
FC
347 /**
348 * Called by the request processor upon starting to service the request.
349 */
350 public void start() {
351 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "starting");
1a971e96 352 synchronized(this) {
550d787e 353 fRequestRunning = true;
550d787e
FC
354 }
355 handleStarted();
1a971e96 356 startedLatch.countDown();
9b635e61 357 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "started");
550d787e
FC
358 }
359
8c8bf09f 360 /**
0ab46cd3 361 * Called by the request processor upon completion.
8c8bf09f
ASL
362 */
363 public void done() {
550d787e 364 if (Tracer.isRequestTraced()) Tracer.traceRequest(this, "completing");
1a971e96 365 synchronized(this) {
9b635e61
FC
366 if (!fRequestCompleted) {
367 fRequestRunning = false;
368 fRequestCompleted = true;
369 }
8c8bf09f 370 }
1a971e96
FC
371 handleCompleted();
372 completedLatch.countDown();
8c8bf09f
ASL
373 }
374
375 /**
0ab46cd3
FC
376 * Called by the request processor upon failure.
377 */
1a971e96
FC
378 public synchronized void fail() {
379 fRequestFailed = true;
380 done();
0ab46cd3
FC
381 }
382
383 /**
384 * Called by the request processor upon cancellation.
8c8bf09f 385 */
1a971e96
FC
386 public synchronized void cancel() {
387 fRequestCanceled = true;
388 done();
8c8bf09f
ASL
389 }
390
cbd4ad82
FC
391 // ------------------------------------------------------------------------
392 // Object
393 // ------------------------------------------------------------------------
394
395 @Override
2fb2eb37 396 // All requests have a unique id
cbd4ad82 397 public int hashCode() {
2fb2eb37 398 return getRequestId();
cbd4ad82
FC
399 }
400
401 @Override
402 public boolean equals(Object other) {
403 if (other instanceof TmfDataRequest<?>) {
404 TmfDataRequest<?> request = (TmfDataRequest<?>) other;
405 return (request.fDataType == fDataType) &&
406 (request.fIndex == fIndex) &&
407 (request.fNbRequested == fNbRequested);
408 }
409 return false;
410 }
411
2fb2eb37
FC
412 @Override
413 public String toString() {
1a971e96
FC
414 return "[TmfDataRequest(" + fRequestId + "," + fDataType.getSimpleName() +
415 "," + fIndex + "," + fNbRequested + ")]";
2fb2eb37 416 }
8c8bf09f 417}
This page took 0.050305 seconds and 5 git commands to generate.