Refactor TmfTrace and dependencies - finalize ITmfTraceIndexer
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.core / src / org / eclipse / linuxtools / tmf / core / trace / TmfTraceIndexer.java
CommitLineData
20658947
FC
1/*******************************************************************************
2 * Copyright (c) 2012 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 - Initial API and implementation
11 *******************************************************************************/
12
13package org.eclipse.linuxtools.tmf.core.trace;
14
15import java.util.Collections;
16import java.util.Vector;
17
18import org.eclipse.core.runtime.IProgressMonitor;
19import org.eclipse.core.runtime.IStatus;
20import org.eclipse.core.runtime.Status;
21import org.eclipse.core.runtime.jobs.Job;
22import org.eclipse.linuxtools.tmf.core.event.ITmfEvent;
23import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp;
24import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange;
20658947
FC
25import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest;
26import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest;
27import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest;
28import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest;
29import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal;
30
31/**
32 * <b><u>TmfTraceIndexer</u></b>
33 * <p>
34 * A simple trace indexer that builds an array of trace checkpoints. Checkpoints
35 * are stored at fixed intervals (event rank) in ascending timestamp order.
36 * <p>
37 * The goal being to access a random trace event reasonably fast from the user's
38 * standpoint, picking the right interval value becomes a trade-off between speed
39 * and memory usage (a shorter inter-event interval is faster but requires more
40 * checkpoints).
41 * <p>
42 * Locating a specific checkpoint is trivial for both rank (rank % interval) and
43 * timestamp (bsearch in the array).
44 */
45public class TmfTraceIndexer<T extends ITmfTrace<ITmfEvent>> implements ITmfTraceIndexer<T> {
46
47 // ------------------------------------------------------------------------
48 // Attributes
49 // ------------------------------------------------------------------------
50
51 /**
52 * The event trace to index
53 */
54 private final ITmfTrace<ITmfEvent> fTrace;
55
56 /**
57 * The interval between checkpoints
58 */
59 protected final int fCheckpointInterval;
60
61 /**
62 * The trace index. It is composed of checkpoints taken at intervals of
63 * fCheckpointInterval events.
64 */
65 protected final Vector<TmfCheckpoint> fTraceIndex;
66
67 // ------------------------------------------------------------------------
68 // Construction
69 // ------------------------------------------------------------------------
70
71 /**
72 * Basic constructor that uses the default trace block size as checkpoints
73 * intervals
74 *
75 * @param trace the trace to index
76 */
77 public TmfTraceIndexer(final ITmfTrace<ITmfEvent> trace) {
78 this(trace, TmfTrace.DEFAULT_BLOCK_SIZE);
79 }
80
81 /**
82 * Full trace indexer
83 *
84 * @param trace the trace to index
85 * @param interval the checkpoints interval
86 */
87 public TmfTraceIndexer(final ITmfTrace<ITmfEvent> trace, final int interval) {
88 fTrace = trace;
89 fCheckpointInterval = interval;
90 fTraceIndex = new Vector<TmfCheckpoint>();
91 }
92
93 // ------------------------------------------------------------------------
1703b536 94 // ITmfTraceIndexer - buildIndex
20658947
FC
95 // ------------------------------------------------------------------------
96
97 /* (non-Javadoc)
98 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#indexTrace(boolean)
99 *
100 * The index is a list of contexts that point to events at regular interval
101 * (rank-wise) in the trace. After it is built, the index can be used to
102 * quickly access any event by rank or timestamp (using seekIndex()).
103 *
104 * The index is built simply by reading the trace
105 */
106 @Override
107 public void buildIndex(final boolean waitForCompletion) {
108
109 // The monitoring job
110 final Job job = new Job("Indexing " + fTrace.getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
111 @Override
112 protected IStatus run(final IProgressMonitor monitor) {
113 while (!monitor.isCanceled()) {
114 try {
115 Thread.sleep(100);
116 } catch (final InterruptedException e) {
117 return Status.OK_STATUS;
118 }
119 }
120 monitor.done();
121 return Status.OK_STATUS;
122 }
123 };
124 job.schedule();
125
126 // Clear the checkpoints
127 fTraceIndex.clear();
128
129 // Build a background request for all the trace data. The index is
130 // updated as we go by getNextEvent().
131 final ITmfEventRequest<ITmfEvent> request = new TmfEventRequest<ITmfEvent>(ITmfEvent.class, TmfTimeRange.ETERNITY,
132 TmfDataRequest.ALL_DATA, fCheckpointInterval, ITmfDataRequest.ExecutionType.BACKGROUND)
d337369a 133 {
20658947
FC
134 ITmfTimestamp startTime = null;
135 ITmfTimestamp lastTime = null;
136
137 @Override
138 public void handleData(final ITmfEvent event) {
139 super.handleData(event);
140 if (event != null) {
141 final ITmfTimestamp timestamp = event.getTimestamp();
142 if (startTime == null) {
143 startTime = timestamp.clone();
144 }
145 lastTime = timestamp.clone();
146
147 // Update the trace status at regular intervals
148 if ((getNbRead() % fCheckpointInterval) == 0) {
149 updateTraceStatus();
150 }
151 }
152 }
153
154 @Override
155 public void handleSuccess() {
156 updateTraceStatus();
157 }
158
159 @Override
160 public void handleCompleted() {
161 job.cancel();
162 super.handleCompleted();
163 }
164
165 private void updateTraceStatus() {
166 if (getNbRead() != 0) {
167 notifyListeners(startTime, lastTime);
168 }
169 }
d337369a 170 };
20658947 171
d337369a
FC
172 // Submit the request and wait for completion if required
173 fTrace.sendRequest(request);
174 if (waitForCompletion) {
175 try {
176 request.waitForCompletion();
177 } catch (final InterruptedException e) {
178 }
179 }
20658947
FC
180 }
181
1703b536
FC
182 private void notifyListeners(final ITmfTimestamp startTime, final ITmfTimestamp endTime) {
183 fTrace.broadcast(new TmfTraceUpdatedSignal(fTrace, fTrace, new TmfTimeRange(startTime, endTime)));
184 }
185
186 // ------------------------------------------------------------------------
187 // ITmfTraceIndexer - updateIndex
188 // ------------------------------------------------------------------------
189
d337369a
FC
190 /* (non-Javadoc)
191 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTraceIndexer#updateIndex(org.eclipse.linuxtools.tmf.core.trace.ITmfContext, org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
192 */
1703b536 193 @Override
d337369a
FC
194 public synchronized void updateIndex(final ITmfContext context, final ITmfTimestamp timestamp) {
195 final long rank = context.getRank();
1703b536
FC
196 if ((rank % fCheckpointInterval) == 0) {
197 // Determine the table position
198 final long position = rank / fCheckpointInterval;
199 // Add new entry at proper location (if empty)
200 if (fTraceIndex.size() == position) {
201 final ITmfLocation<?> location = context.getLocation().clone();
202 fTraceIndex.add(new TmfCheckpoint(timestamp.clone(), location));
1703b536
FC
203 }
204 }
205 }
206
207 // ------------------------------------------------------------------------
208 // ITmfTraceIndexer - seekIndex
209 // ------------------------------------------------------------------------
20658947
FC
210
211 /* (non-Javadoc)
212 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTraceIndexer#seekIndex(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
213 */
214 @Override
1703b536 215 public synchronized ITmfContext seekIndex(final ITmfTimestamp timestamp) {
20658947 216
1703b536
FC
217 // A null timestamp indicates to seek the first event
218 if (timestamp == null)
219 return fTrace.seekLocation(null);
20658947 220
1703b536
FC
221 // Find the checkpoint at or before the requested timestamp.
222 // In the very likely event that the timestamp is not at a checkpoint
223 // boundary, bsearch will return index = (- (insertion point + 1)).
224 // It is then trivial to compute the index of the previous checkpoint.
225 int index = Collections.binarySearch(fTraceIndex, new TmfCheckpoint(timestamp, null));
20658947
FC
226 if (index < 0) {
227 index = Math.max(0, -(index + 2));
228 }
229
230 // Position the trace at the checkpoint
1703b536 231 return seekCheckpoint(index);
20658947
FC
232 }
233
1703b536
FC
234 /* (non-Javadoc)
235 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTraceIndexer#seekIndex(long)
236 */
20658947
FC
237 @Override
238 public ITmfContext seekIndex(final long rank) {
239
1703b536
FC
240 // A rank <= 0 indicates to seek the first event
241 if (rank <= 0)
242 return fTrace.seekLocation(null);
243
244 // Find the checkpoint at or before the requested rank.
245 final int index = (int) rank / fCheckpointInterval;
246
247 // Position the trace at the checkpoint
248 return seekCheckpoint(index);
249 }
250
251 /**
252 * Position the trace at the given checkpoint
253 *
254 * @param index
255 * the checkpoint index
256 * @return the corresponding context
257 */
258 private ITmfContext seekCheckpoint(int index) {
20658947
FC
259 ITmfLocation<?> location;
260 synchronized (fTraceIndex) {
1703b536 261 if (!fTraceIndex.isEmpty()) {
20658947
FC
262 if (index >= fTraceIndex.size()) {
263 index = fTraceIndex.size() - 1;
264 }
265 location = fTraceIndex.elementAt(index).getLocation();
1703b536
FC
266 } else {
267 location = null;
20658947
FC
268 }
269 }
20658947 270 final ITmfContext context = fTrace.seekLocation(location);
1703b536 271 context.setRank(index * fCheckpointInterval);
20658947
FC
272 return context;
273 }
274
20658947 275}
This page took 0.036767 seconds and 5 git commands to generate.