X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=org.eclipse.linuxtools.tmf.core%2Fsrc%2Forg%2Feclipse%2Flinuxtools%2Ftmf%2Fcore%2Ftrace%2FTmfTrace.java;h=ea18b442fd081056e97b60f3b34293dd22f89a34;hb=6f4e8ec0ae816788e83accc0de316f7bd783c35c;hp=a558eae126cb07786c4b0e85dc33cd60f605b5b5;hpb=1b70b6dcd623cbb0cf78cc5ab20e62d7ea082a99;p=deliverable%2Ftracecompass.git diff --git a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java index a558eae126..ea18b442fd 100644 --- a/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java +++ b/org.eclipse.linuxtools.tmf.core/src/org/eclipse/linuxtools/tmf/core/trace/TmfTrace.java @@ -1,552 +1,634 @@ /******************************************************************************* - * Copyright (c) 2009, 2010 Ericsson - * + * Copyright (c) 2009, 2010, 2012 Ericsson + * * All rights reserved. This program and the accompanying materials are * made available under the terms of the Eclipse Public License v1.0 which * accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html - * + * * Contributors: * Francois Chouinard - Initial API and implementation + * Francois Chouinard - Updated as per TMF Trace Model 1.0 *******************************************************************************/ package org.eclipse.linuxtools.tmf.core.trace; import java.io.File; -import java.io.FileNotFoundException; -import java.util.Collections; -import java.util.Vector; - -import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; + +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.IPath; import org.eclipse.linuxtools.tmf.core.component.TmfEventProvider; -import org.eclipse.linuxtools.tmf.core.event.TmfEvent; +import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; +import org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp; import org.eclipse.linuxtools.tmf.core.event.TmfTimeRange; import org.eclipse.linuxtools.tmf.core.event.TmfTimestamp; +import org.eclipse.linuxtools.tmf.core.exceptions.TmfTraceException; import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest; import org.eclipse.linuxtools.tmf.core.request.ITmfEventRequest; -import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest; -import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest; -import org.eclipse.linuxtools.tmf.core.signal.TmfTraceUpdatedSignal; +import org.eclipse.linuxtools.tmf.core.statesystem.ITmfStateSystem; +import org.eclipse.linuxtools.tmf.core.statistics.ITmfStatistics; +import org.eclipse.linuxtools.tmf.core.statistics.TmfStateStatistics; /** - * TmfTrace - *

- * Abstract implementation of ITmfTrace. It should be sufficient to extend this class and provide implementation for - * getCurrentLocation() and seekLocation(), as well as a proper parser, to have a working - * concrete implementation. + * Abstract implementation of ITmfTrace. *

- * Note: The notion of event rank is still under heavy discussion. Although used by the Events View and probably useful - * in the general case, there is no easy way to implement it for LTTng (actually a strong case is being made that this - * is useless). + * Since the concept of 'location' is trace specific, the concrete classes have + * to provide the related methods, namely: + *

+ * A concrete trace must provide its corresponding parser. A common way to + * accomplish this is by making the concrete class extend TmfTrace and + * implement ITmfEventParser. *

- * That it is not supported by LTTng does by no mean indicate that it is not useful for (just about) every other tracing - * tool. Therefore, this class provides a minimal (and partial) implementation of rank. However, the current - * implementation should not be relied on in the general case. - * - * TODO: Add support for live streaming (notifications, incremental indexing, ...) + * The concrete class can either specify its own indexer or use the provided + * TmfCheckpointIndexer (default). In this case, the trace cache size will be + * used as checkpoint interval. + * + * @version 1.0 + * @author Francois Chouinard + * + * @see ITmfEvent + * @see ITmfTraceIndexer + * @see ITmfEventParser */ -public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace, Cloneable { - - // ------------------------------------------------------------------------ - // Constants - // ------------------------------------------------------------------------ - - // The default number of events to cache - // TODO: Make the DEFAULT_CACHE_SIZE a preference - public static final int DEFAULT_INDEX_PAGE_SIZE = 50000; +public abstract class TmfTrace extends TmfEventProvider implements ITmfTrace { // ------------------------------------------------------------------------ // Attributes // ------------------------------------------------------------------------ + // The resource used for persistent properties for this trace + private IResource fResource; + // The trace path private String fPath; - // The trace name - private String fTraceName; + // The trace cache page size + private int fCacheSize = ITmfTrace.DEFAULT_TRACE_CACHE_SIZE; - // The cache page size AND checkpoints interval - protected int fIndexPageSize = DEFAULT_INDEX_PAGE_SIZE; + // The number of events collected (so far) + private long fNbEvents = 0; - // The set of event stream checkpoints (for random access) - protected Vector fCheckpoints = new Vector(); + // The time span of the event stream + private ITmfTimestamp fStartTime = TmfTimestamp.BIG_CRUNCH; + private ITmfTimestamp fEndTime = TmfTimestamp.BIG_BANG; - // The number of events collected - protected long fNbEvents = 0; + // The trace streaming interval (0 = no streaming) + private long fStreamingInterval = 0; - // The time span of the event stream - private TmfTimestamp fStartTime = TmfTimestamp.BigCrunch; - private TmfTimestamp fEndTime = TmfTimestamp.BigBang; + // The trace indexer + private ITmfTraceIndexer fIndexer; + + // The trace parser + private ITmfEventParser fParser; + + // The trace's statistics + private ITmfStatistics fStatistics; // ------------------------------------------------------------------------ - // Constructors + // Construction // ------------------------------------------------------------------------ + /** + * The default, parameterless, constructor + */ public TmfTrace() { super(); } - @Override - public void initTrace(String path, Class eventType) throws FileNotFoundException { - initTmfTrace(path, eventType, DEFAULT_INDEX_PAGE_SIZE, false, null); + /** + * The standard constructor (non-live trace). Applicable when the trace + * implements its own parser and if at checkpoint-based index is OK. + * + * @param resource the resource associated to the trace + * @param type the trace event type + * @param path the trace path + * @param cacheSize the trace cache size + * @throws TmfTraceException If something failed during the opening + */ + protected TmfTrace(final IResource resource, final Class type, final String path, final int cacheSize) throws TmfTraceException { + this(resource, type, path, cacheSize, 0); } - @Override - public void initTrace(String path, Class eventType, int cacheSize) throws FileNotFoundException { - initTmfTrace(path, eventType, cacheSize, false, null); + /** + * The standard constructor (live trace). Applicable when the trace + * implements its own parser and if at checkpoint-based index is OK. + * + * @param resource the resource associated to the trace + * @param type the trace event type + * @param path the trace path + * @param cacheSize the trace cache size + * @param interval the trace streaming interval + * @throws TmfTraceException If something failed during the opening + */ + protected TmfTrace(final IResource resource, final Class type, final String path, final int cacheSize, final long interval) throws TmfTraceException { + this(resource, type, path, cacheSize, interval, null); } - @Override - public void initTrace(String path, Class eventType, boolean indexTrace) throws FileNotFoundException { - initTmfTrace(path, eventType, DEFAULT_INDEX_PAGE_SIZE, indexTrace, null); + /** + * The 'non-default indexer' constructor. Allows to provide a trace + * specific indexer. + * + * @param resource the resource associated to the trace + * @param type the trace event type + * @param path the trace path + * @param cacheSize the trace cache size + * @param interval the trace streaming interval + * @param indexer the trace indexer + * @throws TmfTraceException If something failed during the opening + */ + protected TmfTrace(final IResource resource, final Class type, final String path, final int cacheSize, + final long interval, final ITmfTraceIndexer indexer) throws TmfTraceException { + this(resource, type, path, cacheSize, interval, indexer, null); } - @Override - public void initTrace(String path, Class eventType, int cacheSize, boolean indexTrace) throws FileNotFoundException { - initTmfTrace(path, eventType, cacheSize, indexTrace, null); + /** + * The full constructor where trace specific indexer/parser are provided. + * + * @param resource the resource associated to the trace + * @param type the trace event type + * @param path the trace path + * @param cacheSize the trace cache size + * @param interval the trace streaming interval + * @param indexer the trace indexer + * @param parser the trace event parser + * @throws TmfTraceException If something failed during the opening + */ + protected TmfTrace(final IResource resource, final Class type, final String path, final int cacheSize, + final long interval, final ITmfTraceIndexer indexer, final ITmfEventParser parser) throws TmfTraceException { + super(); + fCacheSize = (cacheSize > 0) ? cacheSize : ITmfTrace.DEFAULT_TRACE_CACHE_SIZE; + fStreamingInterval = interval; + fIndexer = (indexer != null) ? indexer : new TmfCheckpointIndexer(this, fCacheSize); + fParser = parser; + initialize(resource, path, type); + } + + /** + * Copy constructor + * + * @param trace the original trace + * @throws TmfTraceException Should not happen usually + */ + public TmfTrace(final TmfTrace trace) throws TmfTraceException { + super(); + if (trace == null) { + throw new IllegalArgumentException(); + } + fCacheSize = trace.getCacheSize(); + fStreamingInterval = trace.getStreamingInterval(); + fIndexer = new TmfCheckpointIndexer(this); + fParser = trace.fParser; + initialize(trace.getResource(), trace.getPath(), trace.getEventType()); } + // ------------------------------------------------------------------------ + // ITmfTrace - Initializers + // ------------------------------------------------------------------------ + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#initTrace(org.eclipse.core.resources.IResource, java.lang.String, java.lang.Class) + */ @Override - public void initTrace(String path, Class eventType, int cacheSize, boolean indexTrace, String name) throws FileNotFoundException { - initTmfTrace(path, eventType, cacheSize, indexTrace, name); + public void initTrace(final IResource resource, final String path, final Class type) throws TmfTraceException { + fIndexer = new TmfCheckpointIndexer(this, fCacheSize); + initialize(resource, path, type); } - private void initTmfTrace(String path, Class eventType, int cacheSize, boolean indexTrace, String name) throws FileNotFoundException { + /** + * Initialize the trace common attributes and the base component. + * + * @param resource the Eclipse resource (trace) + * @param path the trace path + * @param type the trace event type + * + * @throws TmfTraceException If something failed during the initialization + */ + protected void initialize(final IResource resource, final String path, final Class type) throws TmfTraceException { + if (path == null) { + throw new TmfTraceException("Invalid trace path"); //$NON-NLS-1$ + } fPath = path; - if (name != null) { - fTraceName = name; + fResource = resource; + String traceName = (resource != null) ? resource.getName() : null; + // If no resource was provided, extract the display name the trace path + if (traceName == null) { + final int sep = path.lastIndexOf(IPath.SEPARATOR); + traceName = (sep >= 0) ? path.substring(sep + 1) : path; } - if (fTraceName == null) { - fTraceName = ""; //$NON-NLS-1$ - if (path != null) { - int sep = path.lastIndexOf(Path.SEPARATOR); - fTraceName = (sep >= 0) ? path.substring(sep + 1) : path; + if (fParser == null) { + if (this instanceof ITmfEventParser) { + fParser = (ITmfEventParser) this; + } else { + throw new TmfTraceException("Invalid trace parser"); //$NON-NLS-1$ } } - super.init(fTraceName, eventType); - fIndexPageSize = (cacheSize > 0) ? cacheSize : DEFAULT_INDEX_PAGE_SIZE; - if (indexTrace) - indexTrace(false); - } + super.init(traceName, type); - @Override - public boolean validate(IProject project, String path) { - File file = new File(path); - return file.exists(); + buildStatistics(); } /** - * @param path - * @throws FileNotFoundException + * Indicates if the path points to an existing file/directory + * + * @param path the path to test + * @return true if the file/directory exists */ - protected TmfTrace(String name, Class type, String path) throws FileNotFoundException { - this(name, type, path, DEFAULT_INDEX_PAGE_SIZE, true); + protected boolean fileExists(final String path) { + final File file = new File(path); + return file.exists(); } /** - * @param path - * @param cacheSize - * @throws FileNotFoundException + * Index the trace + * + * @param waitForCompletion index synchronously (true) or not (false) */ - protected TmfTrace(String name, Class type, String path, int cacheSize) throws FileNotFoundException { - this(name, type, path, cacheSize, true); + protected void indexTrace(boolean waitForCompletion) { + getIndexer().buildIndex(0, TmfTimeRange.ETERNITY, waitForCompletion); } /** - * @param path - * @param indexTrace - * @throws FileNotFoundException + * The default implementation of TmfTrace uses a TmfStatistics back-end. + * Override this if you want to specify another type (or none at all). + * + * @throws TmfTraceException + * If there was a problem setting up the statistics + * @since 2.0 */ - protected TmfTrace(String name, Class type, String path, boolean indexTrace) throws FileNotFoundException { - this(name, type, path, DEFAULT_INDEX_PAGE_SIZE, indexTrace); + protected void buildStatistics() throws TmfTraceException { + /* + * Initialize the statistics provider, but only if a Resource has been + * set (so we don't build it for experiments, for unit tests, etc.) + */ + fStatistics = (fResource == null ? null : new TmfStateStatistics(this) ); } /** - * @param path - * @param cacheSize - * @param indexTrace - * @throws FileNotFoundException + * Clears the trace */ - protected TmfTrace(String name, Class type, String path, int cacheSize, boolean indexTrace) throws FileNotFoundException { - super(); - fTraceName = name; - initTrace(path, type, cacheSize, indexTrace); - } - - @SuppressWarnings("unchecked") @Override - public TmfTrace clone() throws CloneNotSupportedException { - TmfTrace clone = (TmfTrace) super.clone(); - clone.fCheckpoints = fCheckpoints; - clone.fStartTime = new TmfTimestamp(fStartTime); - clone.fEndTime = new TmfTimestamp(fEndTime); - return clone; + public synchronized void dispose() { + /* Clean up the index if applicable */ + if (getIndexer() != null) { + getIndexer().dispose(); + } + + /* Clean up the statistics */ + if (fStatistics != null) { + fStatistics.dispose(); + } + super.dispose(); } // ------------------------------------------------------------------------ - // Accessors + // ITmfTrace - Basic getters // ------------------------------------------------------------------------ - /** - * @return the trace path + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getEventType() */ @Override - public String getPath() { - return fPath; + public Class getEventType() { + return (Class) super.getType(); } /* (non-Javadoc) - * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getNbEvents() + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getResource() */ @Override - public long getNbEvents() { - return fNbEvents; + public IResource getResource() { + return fResource; } - /** - * @return the size of the cache + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getPath() */ @Override - public int getCacheSize() { - return fIndexPageSize; + public String getPath() { + return fPath; } /* (non-Javadoc) - * @see org.eclipse.linuxtools.tmf.stream.ITmfEventStream#getTimeRange() + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getIndexPageSize() */ @Override - public TmfTimeRange getTimeRange() { - return new TmfTimeRange(fStartTime, fEndTime); + public int getCacheSize() { + return fCacheSize; } /* (non-Javadoc) - * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStartTime() + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getStreamingInterval() */ @Override - public TmfTimestamp getStartTime() { - return fStartTime; + public long getStreamingInterval() { + return fStreamingInterval; + } + + /** + * @return the trace indexer + */ + protected ITmfTraceIndexer getIndexer() { + return fIndexer; + } + + /** + * @return the trace parser + */ + protected ITmfEventParser getParser() { + return fParser; + } + + /** + * @since 2.0 + */ + @Override + public ITmfStatistics getStatistics() { + return fStatistics; + } + + /** + * @since 2.0 + */ + @Override + public ITmfStateSystem getStateSystem() { + /* + * By default, no state system is used. Sub-classes can specify their + * own behaviour. + */ + return null; } + // ------------------------------------------------------------------------ + // ITmfTrace - Trace characteristics getters + // ------------------------------------------------------------------------ + /* (non-Javadoc) - * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getEndTime() + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getNbEvents() */ @Override - public TmfTimestamp getEndTime() { - return fEndTime; + public synchronized long getNbEvents() { + return fNbEvents; } /* (non-Javadoc) - * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getStreamingInterval() + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getTimeRange() */ @Override - public long getStreamingInterval() { - return 0; + public TmfTimeRange getTimeRange() { + return new TmfTimeRange(fStartTime, fEndTime); } - @SuppressWarnings("unchecked") - public Vector getCheckpoints() { - return (Vector) fCheckpoints.clone(); + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getStartTime() + */ + @Override + public ITmfTimestamp getStartTime() { + return fStartTime; } - /** - * Returns the rank of the first event with the requested timestamp. If none, returns the index of the next event - * (if any). - * - * @param timestamp - * @return + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#getEndTime() */ @Override - public long getRank(TmfTimestamp timestamp) { - TmfContext context = seekEvent(timestamp); - return context.getRank(); + public ITmfTimestamp getEndTime() { + return fEndTime; } // ------------------------------------------------------------------------ - // Operators + // Convenience setters/getters // ------------------------------------------------------------------------ - protected void setTimeRange(TmfTimeRange range) { + /** + * Set the trace cache size. Must be done at initialization time. + * + * @param cacheSize The trace cache size + */ + protected void setCacheSize(final int cacheSize) { + fCacheSize = cacheSize; + } + + /** + * Set the trace known number of events. This can be quite dynamic + * during indexing or for live traces. + * + * @param nbEvents The number of events + */ + protected synchronized void setNbEvents(final long nbEvents) { + fNbEvents = (nbEvents > 0) ? nbEvents : 0; + } + + /** + * Update the trace events time range + * + * @param range the new time range + */ + protected void setTimeRange(final TmfTimeRange range) { fStartTime = range.getStartTime(); fEndTime = range.getEndTime(); } - protected void setStartTime(TmfTimestamp startTime) { + /** + * Update the trace chronologically first event timestamp + * + * @param startTime the new first event timestamp + */ + protected void setStartTime(final ITmfTimestamp startTime) { fStartTime = startTime; } - protected void setEndTime(TmfTimestamp endTime) { + /** + * Update the trace chronologically last event timestamp + * + * @param endTime the new last event timestamp + */ + protected void setEndTime(final ITmfTimestamp endTime) { fEndTime = endTime; } - // ------------------------------------------------------------------------ - // TmfProvider - // ------------------------------------------------------------------------ - - @Override - public ITmfContext armRequest(ITmfDataRequest request) { - if (request instanceof ITmfEventRequest - && !TmfTimestamp.BigBang.equals(((ITmfEventRequest) request).getRange().getStartTime()) && request.getIndex() == 0) { - ITmfContext context = seekEvent(((ITmfEventRequest) request).getRange().getStartTime()); - ((ITmfEventRequest) request).setStartIndex((int) context.getRank()); - return context; + /** + * Set the polling interval for live traces (default = 0 = no streaming). + * + * @param interval the new trace streaming interval + */ + protected void setStreamingInterval(final long interval) { + fStreamingInterval = (interval > 0) ? interval : 0; + } - } - return seekEvent(request.getIndex()); + /** + * Set the trace indexer. Must be done at initialization time. + * + * @param indexer the trace indexer + */ + protected void setIndexer(final ITmfTraceIndexer indexer) { + fIndexer = indexer; } /** - * Return the next piece of data based on the context supplied. The context would typically be updated for the - * subsequent read. - * - * @param context - * @return + * Set the trace parser. Must be done at initialization time. + * + * @param parser the new trace parser */ - @SuppressWarnings("unchecked") - @Override - public T getNext(ITmfContext context) { - if (context instanceof TmfContext) { - return (T) getNextEvent((TmfContext) context); - } - return null; + protected void setParser(final ITmfEventParser parser) { + fParser = parser; } // ------------------------------------------------------------------------ - // ITmfTrace + // ITmfTrace - SeekEvent operations (returning a trace context) // ------------------------------------------------------------------------ /* (non-Javadoc) - * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.event.TmfTimestamp) + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(long) */ @Override - public TmfContext seekEvent(TmfTimestamp timestamp) { + public synchronized ITmfContext seekEvent(final long rank) { - if (timestamp == null) { - timestamp = TmfTimestamp.BigBang; + // A rank <= 0 indicates to seek the first event + if (rank <= 0) { + ITmfContext context = seekEvent((ITmfLocation) null); + context.setRank(0); + return context; } - // First, find the right checkpoint - int index = Collections.binarySearch(fCheckpoints, new TmfCheckpoint(timestamp, null)); + // Position the trace at the checkpoint + final ITmfContext context = fIndexer.seekIndex(rank); - // In the very likely case that the checkpoint was not found, bsearch - // returns its negated would-be location (not an offset...). From that - // index, we can then position the stream and get the event. - if (index < 0) { - index = Math.max(0, -(index + 2)); - } - - // Position the stream at the checkpoint - ITmfLocation location; - synchronized (fCheckpoints) { - if (fCheckpoints.size() > 0) { - if (index >= fCheckpoints.size()) { - index = fCheckpoints.size() - 1; - } - location = fCheckpoints.elementAt(index).getLocation(); - } else { - location = null; + // And locate the requested event context + long pos = context.getRank(); + if (pos < rank) { + ITmfEvent event = getNext(context); + while ((event != null) && (++pos < rank)) { + event = getNext(context); } } - TmfContext context = seekLocation(location); - context.setRank(index * fIndexPageSize); - - // And locate the event - TmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype... - TmfEvent event = getNextEvent(nextEventContext); - while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) { - context.setLocation(nextEventContext.getLocation().clone()); - context.updateRank(1); - event = getNextEvent(nextEventContext); - } - return context; } /* (non-Javadoc) - * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#seekEvent(int) + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#seekEvent(org.eclipse.linuxtools.tmf.core.event.ITmfTimestamp) */ @Override - public TmfContext seekEvent(long rank) { - - // Position the stream at the previous checkpoint - int index = (int) rank / fIndexPageSize; - ITmfLocation location; - synchronized (fCheckpoints) { - if (fCheckpoints.size() == 0) { - location = null; - } else { - if (index >= fCheckpoints.size()) { - index = fCheckpoints.size() - 1; - } - location = fCheckpoints.elementAt(index).getLocation(); - } + public synchronized ITmfContext seekEvent(final ITmfTimestamp timestamp) { + + // A null timestamp indicates to seek the first event + if (timestamp == null) { + ITmfContext context = seekEvent((ITmfLocation) null); + context.setRank(0); + return context; } - TmfContext context = seekLocation(location); - long pos = index * fIndexPageSize; - context.setRank(pos); + // Position the trace at the checkpoint + ITmfContext context = fIndexer.seekIndex(timestamp); - if (pos < rank) { - TmfEvent event = getNextEvent(context); - while (event != null && ++pos < rank) { - event = getNextEvent(context); - } + // And locate the requested event context + final ITmfContext nextEventContext = context.clone(); // Must use clone() to get the right subtype... + ITmfEvent event = getNext(nextEventContext); + while (event != null && event.getTimestamp().compareTo(timestamp, false) < 0) { + context.dispose(); + context = nextEventContext.clone(); + event = getNext(nextEventContext); + } + nextEventContext.dispose(); + if (event == null) { + context.setLocation(null); + context.setRank(ITmfContext.UNKNOWN_RANK); } - return context; } - /* - * (non-Javadoc) - * - * @see org.eclipse.linuxtools.tmf.trace.ITmfTrace#getNextEvent(org.eclipse. - * linuxtools.tmf.trace.ITmfTrace.TraceContext) + // ------------------------------------------------------------------------ + // ITmfTrace - Read operations (returning an actual event) + // ------------------------------------------------------------------------ + + /* (non-Javadoc) + * @see org.eclipse.linuxtools.tmf.core.trace.ITmfTrace#readNextEvent(org.eclipse.linuxtools.tmf.core.trace.ITmfContext) */ @Override - public synchronized TmfEvent getNextEvent(TmfContext context) { + public synchronized ITmfEvent getNext(final ITmfContext context) { // parseEvent() does not update the context - TmfEvent event = parseEvent(context); + final ITmfEvent event = fParser.parseEvent(context); if (event != null) { - updateIndex(context, context.getRank(), event.getTimestamp()); + updateAttributes(context, event.getTimestamp()); context.setLocation(getCurrentLocation()); - context.updateRank(1); + context.increaseRank(); processEvent(event); } return event; } - protected synchronized void updateIndex(ITmfContext context, long rank, TmfTimestamp timestamp) { - if (fStartTime.compareTo(timestamp, false) > 0) + /** + * Hook for special event processing by the concrete class + * (called by TmfTrace.getEvent()) + * + * @param event the event + */ + protected void processEvent(final ITmfEvent event) { + // Do nothing + } + + /** + * Update the trace attributes + * + * @param context the current trace context + * @param timestamp the corresponding timestamp + */ + protected synchronized void updateAttributes(final ITmfContext context, final ITmfTimestamp timestamp) { + if (fStartTime.equals(TmfTimestamp.BIG_BANG) || (fStartTime.compareTo(timestamp, false) > 0)) { fStartTime = timestamp; - if (fEndTime.compareTo(timestamp, false) < 0) + } + if (fEndTime.equals(TmfTimestamp.BIG_CRUNCH) || (fEndTime.compareTo(timestamp, false) < 0)) { fEndTime = timestamp; - if (context.isValidRank()) { - if (fNbEvents <= rank) + } + if (context.hasValidRank()) { + long rank = context.getRank(); + if (fNbEvents <= rank) { fNbEvents = rank + 1; - // Build the index as we go along - if ((rank % fIndexPageSize) == 0) { - // Determine the table position - long position = rank / fIndexPageSize; - // Add new entry at proper location (if empty) - if (fCheckpoints.size() == position) { - ITmfLocation location = context.getLocation().clone(); - fCheckpoints.add(new TmfCheckpoint(timestamp.clone(), location)); - // System.out.println(getName() + "[" + (fCheckpoints.size() - // - 1) + "] " + timestamp + ", " + location.toString()); - } + } + if (fIndexer != null) { + fIndexer.updateIndex(context, timestamp); } } } - /** - * Hook for special processing by the concrete class (called by getNextEvent()) - * - * @param event - */ - protected void processEvent(TmfEvent event) { - // Do nothing by default - } - // ------------------------------------------------------------------------ - // toString + // TmfDataProvider // ------------------------------------------------------------------------ /* (non-Javadoc) - * @see java.lang.Object#toString() + * @see org.eclipse.linuxtools.tmf.core.component.TmfDataProvider#armRequest(org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest) */ @Override - @SuppressWarnings("nls") - public String toString() { - return "[TmfTrace (" + getName() + ")]"; + protected ITmfContext armRequest(final ITmfDataRequest request) { + if ((request instanceof ITmfEventRequest) + && !TmfTimestamp.BIG_BANG.equals(((ITmfEventRequest) request).getRange().getStartTime()) + && (request.getIndex() == 0)) + { + final ITmfContext context = seekEvent(((ITmfEventRequest) request).getRange().getStartTime()); + ((ITmfEventRequest) request).setStartIndex((int) context.getRank()); + return context; + + } + return seekEvent(request.getIndex()); } // ------------------------------------------------------------------------ - // Indexing + // toString // ------------------------------------------------------------------------ - /* - * The purpose of the index is to keep the information needed to rapidly - * restore the traces contexts at regular intervals (every INDEX_PAGE_SIZE - * event). + /* (non-Javadoc) + * @see java.lang.Object#toString() */ - - @SuppressWarnings({ "unchecked" }) - protected void indexTrace(boolean waitForCompletion) { - - final Job job = new Job("Indexing " + getName() + "...") { //$NON-NLS-1$ //$NON-NLS-2$ - @Override - protected IStatus run(IProgressMonitor monitor) { - while (!monitor.isCanceled()) { - try { - Thread.sleep(100); - } catch (InterruptedException e) { - return Status.OK_STATUS; - } - } - monitor.done(); - return Status.OK_STATUS; - } - }; - job.schedule(); - - fCheckpoints.clear(); - ITmfEventRequest request = new TmfEventRequest(TmfEvent.class, TmfTimeRange.Eternity, TmfDataRequest.ALL_DATA, - fIndexPageSize, ITmfDataRequest.ExecutionType.BACKGROUND) { - - TmfTimestamp startTime = null; - TmfTimestamp lastTime = null; - - @Override - public void handleData(TmfEvent event) { - super.handleData(event); - if (event != null) { - TmfTimestamp ts = event.getTimestamp(); - if (startTime == null) - startTime = new TmfTimestamp(ts); - lastTime = new TmfTimestamp(ts); - - if ((getNbRead() % fIndexPageSize) == 0) { - updateTrace(); - } - } - } - - @Override - public void handleSuccess() { - updateTrace(); - } - - @Override - public void handleCompleted() { - job.cancel(); - super.handleCompleted(); - } - - private void updateTrace() { - int nbRead = getNbRead(); - if (nbRead != 0) { - fStartTime = startTime; - fEndTime = lastTime; - fNbEvents = nbRead; - notifyListeners(); - } - } - }; - - sendRequest((ITmfDataRequest) request); - if (waitForCompletion) - try { - request.waitForCompletion(); - } catch (InterruptedException e) { - e.printStackTrace(); - } + @Override + @SuppressWarnings("nls") + public synchronized String toString() { + return "TmfTrace [fPath=" + fPath + ", fCacheSize=" + fCacheSize + + ", fNbEvents=" + fNbEvents + ", fStartTime=" + fStartTime + + ", fEndTime=" + fEndTime + ", fStreamingInterval=" + fStreamingInterval + "]"; } - protected void notifyListeners() { - broadcast(new TmfTraceUpdatedSignal(this, this, new TmfTimeRange(fStartTime, fEndTime))); - } }