1 /*******************************************************************************
2 * Copyright (c) 2012 Ericsson
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
10 * Francois Chouinard - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.linuxtools
.tmf
.core
.trace
;
15 import java
.util
.Collections
;
16 import java
.util
.Vector
;
18 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
19 import org
.eclipse
.core
.runtime
.IStatus
;
20 import org
.eclipse
.core
.runtime
.Status
;
21 import org
.eclipse
.core
.runtime
.jobs
.Job
;
22 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfEvent
;
23 import org
.eclipse
.linuxtools
.tmf
.core
.event
.ITmfTimestamp
;
24 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimeRange
;
25 import org
.eclipse
.linuxtools
.tmf
.core
.event
.TmfTimestamp
;
26 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfDataRequest
;
27 import org
.eclipse
.linuxtools
.tmf
.core
.request
.ITmfEventRequest
;
28 import org
.eclipse
.linuxtools
.tmf
.core
.request
.TmfDataRequest
;
29 import org
.eclipse
.linuxtools
.tmf
.core
.request
.TmfEventRequest
;
30 import org
.eclipse
.linuxtools
.tmf
.core
.signal
.TmfTraceUpdatedSignal
;
33 * <b><u>TmfTraceIndexer</u></b>
35 * A simple trace indexer that builds an array of trace checkpoints. Checkpoints
36 * are stored at fixed intervals (event rank) in ascending timestamp order.
38 * The goal being to access a random trace event reasonably fast from the user's
39 * standpoint, picking the right interval value becomes a trade-off between speed
40 * and memory usage (a shorter inter-event interval is faster but requires more
43 * Locating a specific checkpoint is trivial for both rank (rank % interval) and
44 * timestamp (bsearch in the array).
46 public class TmfTraceIndexer
<T
extends ITmfTrace
<ITmfEvent
>> implements ITmfTraceIndexer
<T
> {
48 // ------------------------------------------------------------------------
50 // ------------------------------------------------------------------------
53 * The event trace to index
55 private final ITmfTrace
<ITmfEvent
> fTrace
;
58 * The interval between checkpoints
60 protected final int fCheckpointInterval
;
63 * The trace index. It is composed of checkpoints taken at intervals of
64 * fCheckpointInterval events.
66 protected final Vector
<TmfCheckpoint
> fTraceIndex
;
68 // ------------------------------------------------------------------------
70 // ------------------------------------------------------------------------
73 * Basic constructor that uses the default trace block size as checkpoints
76 * @param trace the trace to index
78 public TmfTraceIndexer(final ITmfTrace
<ITmfEvent
> trace
) {
79 this(trace
, TmfTrace
.DEFAULT_BLOCK_SIZE
);
85 * @param trace the trace to index
86 * @param interval the checkpoints interval
88 public TmfTraceIndexer(final ITmfTrace
<ITmfEvent
> trace
, final int interval
) {
90 fCheckpointInterval
= interval
;
91 fTraceIndex
= new Vector
<TmfCheckpoint
>();
94 // ------------------------------------------------------------------------
96 // ------------------------------------------------------------------------
99 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#indexTrace(boolean)
101 * The index is a list of contexts that point to events at regular interval
102 * (rank-wise) in the trace. After it is built, the index can be used to
103 * quickly access any event by rank or timestamp (using seekIndex()).
105 * The index is built simply by reading the trace
108 public void buildIndex(final boolean waitForCompletion
) {
110 // The monitoring job
111 final Job job
= new Job("Indexing " + fTrace
.getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$
113 protected IStatus
run(final IProgressMonitor monitor
) {
114 while (!monitor
.isCanceled()) {
117 } catch (final InterruptedException e
) {
118 return Status
.OK_STATUS
;
122 return Status
.OK_STATUS
;
127 // Clear the checkpoints
130 // Build a background request for all the trace data. The index is
131 // updated as we go by getNextEvent().
132 final ITmfEventRequest
<ITmfEvent
> request
= new TmfEventRequest
<ITmfEvent
>(ITmfEvent
.class, TmfTimeRange
.ETERNITY
,
133 TmfDataRequest
.ALL_DATA
, fCheckpointInterval
, ITmfDataRequest
.ExecutionType
.BACKGROUND
)
135 ITmfTimestamp startTime
= null;
136 ITmfTimestamp lastTime
= null;
139 public void handleData(final ITmfEvent event
) {
140 super.handleData(event
);
142 final ITmfTimestamp timestamp
= event
.getTimestamp();
143 if (startTime
== null) {
144 startTime
= timestamp
.clone();
146 lastTime
= timestamp
.clone();
148 // Update the trace status at regular intervals
149 if ((getNbRead() % fCheckpointInterval
) == 0) {
156 public void handleSuccess() {
161 public void handleCompleted() {
163 super.handleCompleted();
166 private void updateTraceStatus() {
167 if (getNbRead() != 0) {
168 notifyListeners(startTime
, lastTime
);
173 // Submit the request and wait for completion if required
174 fTrace
.sendRequest(request
);
175 if (waitForCompletion
) {
177 request
.waitForCompletion();
178 } catch (final InterruptedException e
) {
185 * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTraceIndexer#seekIndex(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp)
188 public ITmfContext
seekIndex(final ITmfTimestamp timestamp
) {
189 // Adjust the timestamp if needed
190 ITmfTimestamp ts
= timestamp
;
192 ts
= TmfTimestamp
.BIG_BANG
;
195 // First, find the right checkpoint
196 int index
= Collections
.binarySearch(fTraceIndex
, new TmfCheckpoint(ts
, null));
198 // In the very likely case that the checkpoint was not found, bsearch
199 // returns its negated would-be location (not an offset...). From that
200 // index, we can then position the stream and get figure out the context.
202 index
= Math
.max(0, -(index
+ 2));
205 // Position the trace at the checkpoint
206 ITmfLocation
<?
> location
;
207 synchronized (fTraceIndex
) {
208 if (!fTraceIndex
.isEmpty()) {
209 if (index
>= fTraceIndex
.size()) {
210 index
= fTraceIndex
.size() - 1;
212 location
= fTraceIndex
.elementAt(index
).getLocation();
217 final ITmfContext context
= fTrace
.seekLocation(location
);
218 context
.setRank(index
* fCheckpointInterval
);
224 public ITmfContext
seekIndex(final long rank
) {
226 // Position the stream at the previous checkpoint
227 int index
= (int) rank
/ fCheckpointInterval
;
228 ITmfLocation
<?
> location
;
229 synchronized (fTraceIndex
) {
230 if (fTraceIndex
.isEmpty()) {
233 if (index
>= fTraceIndex
.size()) {
234 index
= fTraceIndex
.size() - 1;
236 location
= fTraceIndex
.elementAt(index
).getLocation();
240 final ITmfContext context
= fTrace
.seekLocation(location
);
241 final long pos
= index
* fCheckpointInterval
;
242 context
.setRank(pos
);
247 private void notifyListeners(final ITmfTimestamp startTime
, final ITmfTimestamp endTime
) {
248 fTrace
.broadcast(new TmfTraceUpdatedSignal(fTrace
, fTrace
, new TmfTimeRange(startTime
, endTime
)));
252 public void updateIndex(final ITmfContext context
, final long rank
, final ITmfTimestamp timestamp
) {
253 if ((rank
% fCheckpointInterval
) == 0) {
254 // Determine the table position
255 final long position
= rank
/ fCheckpointInterval
;
256 // Add new entry at proper location (if empty)
257 if (fTraceIndex
.size() == position
) {
258 final ITmfLocation
<?
> location
= context
.getLocation().clone();
259 fTraceIndex
.add(new TmfCheckpoint(timestamp
.clone(), location
));
260 // System.out.println(getName() + "[" + (fCheckpoints.size() - 1) + "] " + timestamp + ", " + location.toString());
This page took 0.043254 seconds and 5 git commands to generate.