Commit | Line | Data |
---|---|---|
4ab33d2b AO |
1 | /******************************************************************************* |
2 | * Copyright (c) 2009 Ericsson | |
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 (fchouinard@gmail.com) - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.tmf.eventlog; | |
14 | ||
15 | import java.util.Vector; | |
16 | ||
17 | import org.eclipse.linuxtools.tmf.event.TmfEvent; | |
1f506a43 | 18 | import org.eclipse.linuxtools.tmf.event.TmfTimeRange; |
4ab33d2b AO |
19 | |
20 | /** | |
21 | * <b><u>TmfEventRequest</u></b> | |
22 | * <p> | |
23 | * TmfEventRequests are used to obtain blocks of contiguous events from an | |
24 | * event stream, either all the events within a given time window or n events | |
25 | * starting a a specific timestamp. Open ranges can be used, especially for | |
26 | * continuous streaming. | |
27 | * <p> | |
28 | * The request is processed asynchronously by an ITmfRequestProcessor and, | |
29 | * as blocks of events become available, the callback function newEvents() | |
30 | * is invoked, synchronously, for each block. When returning from newEvents(), | |
31 | * the event instances go out of scope and become eligible for gc. It is | |
32 | * is thus the responsibility of the requester to either copy or keep a | |
33 | * reference to the events it wishes to track specifically. | |
34 | * <p> | |
35 | * This event block approach is necessary to avoid busting the heap for very | |
36 | * large trace files. The block size is configurable. | |
37 | * <p> | |
38 | * The ITmfRequestProcessor indicates that the request is completed by | |
39 | * calling done(). The request can be canceled at any time with cancel(). | |
40 | * <p> | |
41 | * Typical usage: | |
42 | *<pre><code><i>TmfTimeWindow range = new TmfTimewindow(...); | |
43 | *TmfEventRequest request = new TmfEventRequest(range, 0, NB_EVENTS, BLOCK_SIZE) { | |
44 | * @Override | |
45 | * public void newEvents(Vector<TmfEvent> events) { | |
46 | * for (TmfEvent e : events) { | |
47 | * // do something | |
48 | * } | |
49 | * } | |
50 | *}; | |
51 | *fProcessor.process(request, true); | |
52 | *</i></code></pre> | |
53 | * | |
54 | * TODO: Consider extending DataRequestMonitor from DSF concurrency plugin. | |
55 | * The main issue is the slicing of the result in blocks and continuous | |
56 | * streams. | |
57 | */ | |
58 | public class TmfEventRequest { | |
59 | ||
60 | // ======================================================================== | |
61 | // Constants | |
62 | // ======================================================================== | |
63 | ||
64 | // The default maximum number of events per chunk | |
65 | public static final int DEFAULT_BLOCK_SIZE = 1000; | |
66 | ||
67 | // ======================================================================== | |
68 | // Attributes | |
69 | // ======================================================================== | |
70 | ||
1f506a43 | 71 | private final TmfTimeRange fRange; // The requested events timestamp range |
4ab33d2b AO |
72 | private final long fOffset; // The synchronization offset to apply |
73 | private final int fNbRequestedEvents; // The number of events to read (-1 == the whole range) | |
74 | private final int fBlockSize; // The maximum number of events per chunk | |
75 | ||
76 | private Object lock = new Object(); | |
77 | private boolean fRequestCompleted = false; | |
78 | private boolean fRequestCanceled = false; | |
79 | ||
80 | // ======================================================================== | |
81 | // Constructors | |
82 | // ======================================================================== | |
83 | ||
84 | /** | |
85 | * @param range | |
86 | * @param offset | |
87 | * @param nbEvents | |
88 | */ | |
1f506a43 | 89 | public TmfEventRequest(TmfTimeRange range, long offset, int nbEvents) { |
4ab33d2b AO |
90 | this(range, offset, nbEvents, DEFAULT_BLOCK_SIZE); |
91 | } | |
92 | ||
93 | /** | |
94 | * @param range | |
95 | * @param offset | |
96 | * @param nbEvents | |
97 | * @param maxBlockSize Size of the largest blocks expected | |
98 | */ | |
1f506a43 | 99 | public TmfEventRequest(TmfTimeRange range, long offset, int nbEvents, int maxBlockSize) { |
4ab33d2b AO |
100 | fRange = range; |
101 | fOffset = offset; | |
102 | fNbRequestedEvents = nbEvents; | |
103 | fBlockSize = maxBlockSize; | |
104 | } | |
105 | ||
106 | // ======================================================================== | |
107 | // Accessors | |
108 | // ======================================================================== | |
109 | ||
110 | /** | |
111 | * @return the requested time range | |
112 | */ | |
1f506a43 | 113 | public TmfTimeRange getRange() { |
4ab33d2b AO |
114 | return fRange; |
115 | } | |
116 | ||
117 | /** | |
118 | * @return the offset | |
119 | */ | |
120 | public long getOffset() { | |
121 | return fOffset; | |
122 | } | |
123 | ||
124 | /** | |
125 | * @return the number of requested events (-1 = all) | |
126 | */ | |
127 | public int getNbRequestedEvents() { | |
128 | return fNbRequestedEvents; | |
129 | } | |
130 | ||
131 | /** | |
132 | * @return the block size | |
133 | */ | |
134 | public int getBlockize() { | |
135 | return fBlockSize; | |
136 | } | |
137 | ||
138 | /** | |
139 | * @return indicates if the request is completed | |
140 | */ | |
141 | public boolean isCompleted() { | |
142 | return fRequestCompleted; | |
143 | } | |
144 | ||
145 | /** | |
146 | * @return indicates if the request is canceled | |
147 | */ | |
148 | public boolean isCancelled() { | |
149 | return fRequestCanceled; | |
150 | } | |
151 | ||
152 | // ======================================================================== | |
153 | // Operators | |
154 | // ======================================================================== | |
155 | ||
156 | /** | |
157 | * newEvents() | |
158 | * | |
159 | * - Events are received in the order they appear in the stream. | |
160 | * - Called by the request processor, in its execution thread, every time a | |
161 | * block of events becomes available. | |
162 | * - Request processor performs a synchronous call to newEvents() | |
163 | * i.e. its execution threads holds until newEvents() returns. | |
164 | * - Original events are disposed of on return i.e. keep a reference (or a | |
165 | * copy) if some persistence is needed between invocations. | |
166 | * - When there are no more events, | |
167 | * | |
168 | * @param events - an array of events | |
169 | */ | |
170 | public void newEvents(Vector<TmfEvent> events) { | |
171 | } | |
172 | ||
173 | /** | |
174 | * To suspend the client thread until the request completes (or is | |
175 | * canceled). | |
176 | * | |
177 | * @throws InterruptedException | |
178 | */ | |
179 | public void waitForCompletion() { | |
180 | synchronized (lock) { | |
181 | while (!fRequestCompleted) | |
182 | try { | |
183 | lock.wait(); | |
184 | } catch (InterruptedException e) { | |
185 | e.printStackTrace(); | |
186 | } | |
187 | } | |
188 | } | |
189 | ||
190 | /** | |
191 | * Complete the request. Called by the request processor upon completion. | |
192 | */ | |
193 | public void done() { | |
194 | synchronized(lock) { | |
195 | fRequestCompleted = true; | |
196 | lock.notify(); | |
197 | } | |
198 | } | |
199 | ||
200 | /** | |
201 | * Cancel the request. | |
202 | */ | |
203 | public void cancel() { | |
204 | synchronized(lock) { | |
205 | fRequestCanceled = true; | |
206 | fRequestCompleted = true; | |
207 | lock.notify(); | |
208 | } | |
209 | } | |
210 | ||
211 | } |