From 38e2a2e92cb412738b9e3fcfefb32c86851183c7 Mon Sep 17 00:00:00 2001 From: Jean-Christian Kouame Date: Tue, 1 Mar 2016 14:38:03 -0500 Subject: [PATCH] tmf : Introduce the modules for the XML pattern analysis This patch introduces the XmlPatternAnalysis and its sub-modules Change-Id: If27ed6816316752c405f14a31b9b91dcfad877c7 Signed-off-by: Jean-Christian Kouame Reviewed-on: https://git.eclipse.org/r/65750 Reviewed-by: Genevieve Bastien Tested-by: Genevieve Bastien Reviewed-by: Matthew Khouzam Reviewed-by: Hudson CI --- .../AbstractSegmentStoreAnalysisModule.java | 20 +- .../META-INF/MANIFEST.MF | 3 +- .../core/pattern/stateprovider/Messages.java | 43 +++ .../stateprovider/XmlPatternAnalysis.java | 305 ++++++++++++++++++ .../XmlPatternSegmentStoreModule.java | 173 ++++++++++ .../XmlPatternStateProvider.java | 122 +++++++ .../XmlPatternStateSystemModule.java | 58 ++++ .../pattern/stateprovider/messages.properties | 12 + .../model/TmfXmlPatternSegmentBuilder.java | 7 +- .../module/TmfAnalysisModuleHelperXml.java | 23 +- .../core/module/XmlAnalysisModuleSource.java | 9 + .../analysis/xml/core/module/XmlUtils.java | 6 + 12 files changed, 772 insertions(+), 9 deletions(-) create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/Messages.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternAnalysis.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternSegmentStoreModule.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternStateProvider.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternStateSystemModule.java create mode 100644 tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/messages.properties diff --git a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/analysis/timing/core/segmentstore/AbstractSegmentStoreAnalysisModule.java b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/analysis/timing/core/segmentstore/AbstractSegmentStoreAnalysisModule.java index ece3c75d89..5426b07077 100644 --- a/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/analysis/timing/core/segmentstore/AbstractSegmentStoreAnalysisModule.java +++ b/analysis/org.eclipse.tracecompass.analysis.timing.core/src/org/eclipse/tracecompass/analysis/timing/core/segmentstore/AbstractSegmentStoreAnalysisModule.java @@ -151,9 +151,7 @@ public abstract class AbstractSegmentStoreAnalysisModule extends TmfAbstractAnal } } fSegmentStore = store; - for (IAnalysisProgressListener listener : getListeners()) { - listener.onComplete(this, store); - } + sendUpdate(store); return true; } catch (IOException | ClassNotFoundException | ClassCastException e) { /* @@ -190,10 +188,20 @@ public abstract class AbstractSegmentStoreAnalysisModule extends TmfAbstractAnal } } - for (IAnalysisProgressListener listener : getListeners()) { - listener.onComplete(this, segmentStore); - } + sendUpdate(segmentStore); return true; } + + /** + * Send the segment store to all its listener + * + * @param store + * The segment store to broadcast + */ + protected void sendUpdate(final ISegmentStore store) { + for (IAnalysisProgressListener listener : getListeners()) { + listener.onComplete(this, store); + } + } } \ No newline at end of file diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF index a24da4c8da..9cdefedc66 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/META-INF/MANIFEST.MF @@ -11,7 +11,8 @@ Bundle-ActivationPolicy: lazy Require-Bundle: org.eclipse.core.runtime, org.eclipse.tracecompass.common.core, org.eclipse.tracecompass.tmf.core, - org.eclipse.tracecompass.segmentstore.core + org.eclipse.tracecompass.segmentstore.core, + org.eclipse.tracecompass.analysis.timing.core Export-Package: org.eclipse.tracecompass.internal.tmf.analysis.xml.core;x-friends:="org.eclipse.tracecompass.tmf.analysis.xml.core.tests", org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider;x-internal:=true, org.eclipse.tracecompass.tmf.analysis.xml.core.model, diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/Messages.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/Messages.java new file mode 100644 index 0000000000..c86331f00b --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/Messages.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * Copyright (c) 2016 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 + *******************************************************************************/ +package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider; + +import org.eclipse.osgi.util.NLS; + +/** + * Externalized messages for the XML analysis state provider package + * + * @author Jean-Christian Kouame + */ +public class Messages extends NLS { + private static final String BUNDLE_NAME = "org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.messages"; //$NON-NLS-1$ + /** + * The string content + */ + public static String PatternSegmentContentAspect_Content; + /** + * Help text of the segment content aspect + */ + public static String PatternSegmentContentAspect_HelpText; + /** + * Help text of the segment name aspect + */ + public static String PatternSegmentNameAspect_HelpText; + /** + * The string name + */ + public static String PatternSegmentNameAspect_Name; + static { + // initialize resource bundle + NLS.initializeMessages(BUNDLE_NAME, Messages.class); + } + + private Messages() { + } +} diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternAnalysis.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternAnalysis.java new file mode 100644 index 0000000000..85c580ace7 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternAnalysis.java @@ -0,0 +1,305 @@ +/******************************************************************************* + * Copyright (c) 2016 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 + ******************************************************************************/ +package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider; + +import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; + +import java.io.File; +import java.util.Comparator; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener; +import org.eclipse.tracecompass.analysis.timing.core.segmentstore.ISegmentStoreProvider; +import org.eclipse.tracecompass.segmentstore.core.ISegment; +import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; +import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; +import org.eclipse.tracecompass.tmf.analysis.xml.core.model.TmfXmlPatternSegmentBuilder; +import org.eclipse.tracecompass.tmf.analysis.xml.core.segment.TmfXmlPatternSegment; +import org.eclipse.tracecompass.tmf.core.analysis.TmfAbstractAnalysisModule; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.tracecompass.tmf.core.segment.ISegmentAspect; +import org.eclipse.tracecompass.tmf.core.statesystem.ITmfAnalysisModuleWithStateSystems; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.eclipse.tracecompass.tmf.core.trace.TmfTraceManager; + +import com.google.common.collect.ImmutableList; + +/** + * Analysis module for pattern matching within traces. This module creates two + * sub-analyses : A state system analysis that will execute the pattern on the + * trace and a segment store analysis that will build a segment store with the + * segments generated by the state system analysis. + * + * @author Jean-Christian Kouame + */ +public class XmlPatternAnalysis extends TmfAbstractAnalysisModule implements ITmfAnalysisModuleWithStateSystems, ISegmentStoreProvider { + + /** + * Segment store supplementary file extension + */ + public static final @NonNull String SEGMENT_STORE_EXTENSION = ".dat"; //$NON-NLS-1$ + /** + * state system supplementary file extension + */ + private static final @NonNull String STATE_SYSTEM_EXTENSION = ".ht"; //$NON-NLS-1$ + private static final String SEGMENT_STORE_SUFFIX = " segment store"; //$NON-NLS-1$ + private static final String STATE_SYSTEM_SUFFIX = " state system"; //$NON-NLS-1$ + private final CountDownLatch fInitialized = new CountDownLatch(1); + private XmlPatternStateSystemModule fStateSystemModule; + private XmlPatternSegmentStoreModule fSegmentStoreModule; + private boolean fInitializationSucceeded; + + /** + * Constructor + */ + public XmlPatternAnalysis() { + super(); + fSegmentStoreModule = new XmlPatternSegmentStoreModule(this); + fStateSystemModule = new XmlPatternStateSystemModule(fSegmentStoreModule); + } + + @Override + public @Nullable ISegmentStore<@NonNull ISegment> getSegmentStore() { + return fSegmentStoreModule.getSegmentStore(); + } + + @Override + public @Nullable ITmfStateSystem getStateSystem(@NonNull String id) { + return fStateSystemModule.getStateSystem(id); + } + + @Override + public @NonNull Iterable<@NonNull ITmfStateSystem> getStateSystems() { + return fStateSystemModule.getStateSystems(); + } + + @Override + public boolean waitForInitialization() { + try { + fInitialized.await(); + } catch (InterruptedException e) { + return false; + } + return fInitializationSucceeded; + } + + @Override + protected boolean executeAnalysis(@NonNull IProgressMonitor monitor) throws TmfAnalysisException { + ITmfTrace trace = getTrace(); + if (trace == null) { + /* This analysis was cancelled in the meantime */ + analysisReady(false); + return false; + } + + File segmentStoreFile = getSupplementaryFile(getSegmentStoreFileName()); + File stateSystemFile = getSupplementaryFile(getStateSystemFileName()); + if (segmentStoreFile == null || stateSystemFile == null) { + analysisReady(false); + return false; + } + + if (!segmentStoreFile.exists()) { + fStateSystemModule.cancel(); + stateSystemFile.delete(); + } + + IStatus segmentStoreStatus = fSegmentStoreModule.schedule(); + IStatus stateSystemStatus = fStateSystemModule.schedule(); + if (!(segmentStoreStatus.isOK() && stateSystemStatus.isOK())) { + cancelSubAnalyses(); + analysisReady(false); + return false; + } + + /* Wait until the state system module is initialized */ + if (!fStateSystemModule.waitForInitialization()) { + analysisReady(false); + cancelSubAnalyses(); + return false; + } + + ITmfStateSystem stateSystem = fStateSystemModule.getStateSystem(); + if (stateSystem == null) { + analysisReady(false); + throw new IllegalStateException("Initialization of the state system module succeeded but the statesystem is null"); //$NON-NLS-1$ + } + + analysisReady(true); + + return fStateSystemModule.waitForCompletion(monitor) && fSegmentStoreModule.waitForCompletion(monitor); + } + + @Override + protected void canceling() { + cancelSubAnalyses(); + } + + private void cancelSubAnalyses() { + fStateSystemModule.cancel(); + fSegmentStoreModule.cancel(); + } + + @Override + public void dispose() { + /* + * The sub-analyses are not registered to the trace directly, so we need + * to tell them when the trace is disposed. + */ + super.dispose(); + fStateSystemModule.dispose(); + fSegmentStoreModule.dispose(); + } + + @Override + public void setId(@NonNull String id) { + super.setId(id); + fStateSystemModule.setId(id); + fSegmentStoreModule.setId(id); + } + + @Override + public void setName(@NonNull String name) { + super.setName(name); + fStateSystemModule.setName(name + STATE_SYSTEM_SUFFIX); + fSegmentStoreModule.setName(name + SEGMENT_STORE_SUFFIX); + } + + @Override + public boolean setTrace(ITmfTrace trace) throws TmfAnalysisException { + if (!super.setTrace(trace)) { + return false; + } + + /* + * Since these sub-analyzes are not built from an extension point, we + * have to assign the trace ourselves. Very important to do so before + * calling schedule()! + */ + return fSegmentStoreModule.setTrace(trace) && fStateSystemModule.setTrace(trace); + } + + /** + * Sets the file path of the XML file and the id of pattern analysis in the + * file + * + * @param file + * The full path to the XML file + */ + public void setXmlFile(IPath file) { + fStateSystemModule.setXmlFile(file); + } + + /** + * Make the module available and set whether the initialization succeeded or + * not. If not, no state system is available and + * {@link #waitForInitialization()} should return false. + * + * @param success + * True if the initialization went well, false otherwise + */ + private void analysisReady(boolean succeeded) { + fInitializationSucceeded = succeeded; + fInitialized.countDown(); + } + + private @Nullable File getSupplementaryFile(String filename) { + ITmfTrace trace = getTrace(); + if (trace == null) { + return null; + } + String directory = TmfTraceManager.getSupplementaryFileDir(trace); + File file = new File(directory + filename); + return file; + } + + private String getStateSystemFileName() { + return fStateSystemModule.getId() + STATE_SYSTEM_EXTENSION; + } + + private String getSegmentStoreFileName() { + return fSegmentStoreModule.getId() + SEGMENT_STORE_EXTENSION; + } + + @Override + public void addListener(@NonNull IAnalysisProgressListener listener) { + fSegmentStoreModule.addListener(listener); + } + + @Override + public void removeListener(@NonNull IAnalysisProgressListener listener) { + fSegmentStoreModule.removeListener(listener); + } + + @Override + public Iterable getSegmentAspects() { + return ImmutableList.of(PatternSegmentNameAspect.INSTANCE, PatternSegmentContentAspect.INSTANCE); + } + + private static class PatternSegmentNameAspect implements ISegmentAspect { + public static final @NonNull ISegmentAspect INSTANCE = new PatternSegmentNameAspect(); + + private PatternSegmentNameAspect() {} + + @Override + public String getHelpText() { + return checkNotNull(Messages.PatternSegmentNameAspect_HelpText); + } + @Override + public String getName() { + return checkNotNull(Messages.PatternSegmentNameAspect_Name); + } + @Override + public @Nullable Comparator getComparator() { + return null; + } + @Override + public @Nullable String resolve(ISegment segment) { + if (segment instanceof TmfXmlPatternSegment) { + return ((TmfXmlPatternSegment) segment).getName() + .substring(TmfXmlPatternSegmentBuilder.PATTERN_SEGMENT_NAME_PREFIX.length()); + } + return EMPTY_STRING; + } + } + + private static class PatternSegmentContentAspect implements ISegmentAspect { + public static final @NonNull ISegmentAspect INSTANCE = new PatternSegmentContentAspect(); + + private PatternSegmentContentAspect() {} + + @Override + public String getHelpText() { + return checkNotNull(Messages.PatternSegmentContentAspect_HelpText); + } + @Override + public String getName() { + return checkNotNull(Messages.PatternSegmentContentAspect_Content); + } + @Override + public @Nullable Comparator getComparator() { + return null; + } + @Override + public @Nullable String resolve(ISegment segment) { + if (segment instanceof TmfXmlPatternSegment) { + List values = ((TmfXmlPatternSegment) segment).getContent().entrySet().stream().map(c -> c.getKey() + '=' + c.getValue()).collect(Collectors.toList()); + return String.join(", ", values); //$NON-NLS-1$ + } + return EMPTY_STRING; + } + } +} diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternSegmentStoreModule.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternSegmentStoreModule.java new file mode 100644 index 0000000000..97037ac904 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternSegmentStoreModule.java @@ -0,0 +1,173 @@ +/******************************************************************************* + * Copyright (c) 2016 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 + ******************************************************************************/ +package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider; + +import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; + +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.concurrent.CountDownLatch; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule; +import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener; +import org.eclipse.tracecompass.segmentstore.core.ISegment; +import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; +import org.eclipse.tracecompass.segmentstore.core.treemap.TreeMapStore; +import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; + +/** + * Segment store module for pattern analysis defined in XML. This module will + * receive all the segments provided by an external source and will build a + * segment store + * + * @author Jean-Christian Kouame + */ +public class XmlPatternSegmentStoreModule extends AbstractSegmentStoreAnalysisModule implements ISegmentListener { + + /** + * Fake segment indicated that the last segment have been received + */ + public static final @NonNull EndSegment END_SEGMENT = new EndSegment(); + private final ISegmentStore<@NonNull ISegment> fSegments = new TreeMapStore<>(); + private final CountDownLatch fFinished = new CountDownLatch(1); + private final @NonNull XmlPatternAnalysis fParent; + private boolean fSegmentStoreCompleted; + + /** + * Constructor + * + * @param parent + * The parent analysis + */ + public XmlPatternSegmentStoreModule(@NonNull XmlPatternAnalysis parent) { + super(); + fParent = parent; + } + + @Override + protected Object @NonNull [] readObject(@NonNull ObjectInputStream ois) throws ClassNotFoundException, IOException { + return checkNotNull((Object[]) ois.readObject()); + } + + @Override + protected boolean buildAnalysisSegments(@NonNull ISegmentStore<@NonNull ISegment> segments, @NonNull IProgressMonitor monitor) throws TmfAnalysisException { + final @Nullable ITmfTrace trace = getTrace(); + if (trace == null) { + /* This analysis was cancelled in the meantime */ + segmentStoreReady(false); + return false; + } + waitForSegmentStoreCompletion(); + segments.addAll(getSegments()); + return true; + } + + @Override + protected void canceling() { + super.cancel(); + segmentStoreReady(false); + } + + @Override + protected @Nullable String getDataFileName() { + return getId() + XmlPatternAnalysis.SEGMENT_STORE_EXTENSION; + } + + /** + * Broadcast the segment store to its listeners. Since this analysis is not + * directly register to the trace, the parent analysis is used as the source. + * + * @param store + * The store to broadcast + */ + @Override + protected void sendUpdate(final ISegmentStore<@NonNull ISegment> store) { + for (IAnalysisProgressListener listener : getListeners()) { + listener.onComplete(fParent, store); + } + } + + @Override + public void onNewSegment(@NonNull ISegment segment) { + // We can accept segments until the first END_SEGMENT arrives. Nothing + // should be accept after it. This prevents to receive new segments if + // the analysis that generates the segments is rescheduled + if (!fSegmentStoreCompleted) { + if (segment == END_SEGMENT) { + segmentStoreReady(true); + return; + } + getSegments().add(segment); + } + } + + /** + * Get the internal segment store of this module + * + * @return The segment store + */ + private synchronized ISegmentStore<@NonNull ISegment> getSegments() { + return fSegments; + } + + /** + * Wait until internal segment store of the module is fully filled. If all + * the segments have been received, the completion succeeded, otherwise it + * is not. + * + * @return True if the completion succeeded, false otherwise + */ + public boolean waitForSegmentStoreCompletion() { + try { + fFinished.await(); + } catch (InterruptedException e) { + return false; + } + return fSegmentStoreCompleted; + } + + /** + * Make the module available and set whether the segment store completion + * succeeded or not. If not, no segment store is available and + * {@link #waitForSegmentStoreCompletion()} should return false. + * + * @param success + * True if the segment store completion succeeded, false + * otherwise + */ + private void segmentStoreReady(boolean succeeded) { + fSegmentStoreCompleted = succeeded; + fFinished.countDown(); + } + + /** + * Fake segment indicating the build is over, and the segment store is fully + * filled + */ + public static class EndSegment implements ISegment { + /** + * The serial version UID + */ + private static final long serialVersionUID = 7834984029618274707L; + + @Override + public long getStart() { + return Long.MIN_VALUE; + } + + @Override + public long getEnd() { + return Long.MIN_VALUE; + } + } +} diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternStateProvider.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternStateProvider.java new file mode 100644 index 0000000000..d87a09a2fd --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternStateProvider.java @@ -0,0 +1,122 @@ +/******************************************************************************* + * Copyright (c) 2016 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 + ******************************************************************************/ +package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider; + +import java.util.HashSet; +import java.util.Set; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator; +import org.eclipse.tracecompass.statesystem.core.ITmfStateSystem; +import org.eclipse.tracecompass.tmf.analysis.xml.core.model.TmfXmlLocation; +import org.eclipse.tracecompass.tmf.analysis.xml.core.module.IXmlStateSystemContainer; +import org.eclipse.tracecompass.tmf.analysis.xml.core.module.XmlUtils; +import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; +import org.eclipse.tracecompass.tmf.core.event.ITmfEvent; +import org.eclipse.tracecompass.tmf.core.statesystem.AbstractTmfStateProvider; +import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider; +import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; +import org.w3c.dom.Element; + +/** + * State provider for the pattern analysis + * + * @author Jean-Christian Kouame + */ +public class XmlPatternStateProvider extends AbstractTmfStateProvider implements IXmlStateSystemContainer { + + private final IPath fFilePath; + + private final @NonNull String fStateId; + + /** List of all Locations */ + private final @NonNull Set<@NonNull TmfXmlLocation> fLocations; + + private final ISegmentListener fListener; + + /** + * @param trace + * The active trace + * @param stateid + * The state id, which corresponds to the id of the analysis + * defined in the XML file + * @param file + * The XML file + * @param listener + * Listener for segment creation + */ + public XmlPatternStateProvider(@NonNull ITmfTrace trace, @NonNull String stateid, @Nullable IPath file, ISegmentListener listener) { + super(trace, stateid); + fStateId = stateid; + fFilePath = file; + fListener = listener; + final String pathString = fFilePath.makeAbsolute().toOSString(); + Element doc = XmlUtils.getElementInFile(pathString, TmfXmlStrings.PATTERN, fStateId); + fLocations = new HashSet<>(); + if (doc == null) { + Activator.logError("Failed to find a pattern in " + pathString); //$NON-NLS-1$ + return; + } + } + + @Override + public String getAttributeValue(String name) { + return null; + } + + @Override + public int getVersion() { + return 0; + } + + @Override + public @NonNull ITmfStateProvider getNewInstance() { + return new XmlPatternStateProvider(getTrace(), getStateId(), fFilePath, fListener); + } + + /** + * Get the state ID of the provider. It corresponds to the analysis ID. + * + * @return the state Id + */ + public @NonNull String getStateId() { + return fStateId; + } + + @Override + public ITmfStateSystem getStateSystem() { + return getStateSystemBuilder(); + } + + @Override + public @NonNull Iterable<@NonNull TmfXmlLocation> getLocations() { + return fLocations; + } + + @Override + protected void eventHandle(@NonNull ITmfEvent event) { + } + + /** + * Get the listerner for segments creation + * + * @return The segment listener + */ + public ISegmentListener getListener() { + return fListener; + } + + @Override + public void dispose() { + fListener.onNewSegment(XmlPatternSegmentStoreModule.END_SEGMENT); + super.dispose(); + } +} diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternStateSystemModule.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternStateSystemModule.java new file mode 100644 index 0000000000..4facff270f --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/XmlPatternStateSystemModule.java @@ -0,0 +1,58 @@ +/******************************************************************************* + * Copyright (c) 2016 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 + ******************************************************************************/ +package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider; + +import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; + +import org.eclipse.core.runtime.IPath; +import org.eclipse.jdt.annotation.NonNull; +import org.eclipse.jdt.annotation.Nullable; +import org.eclipse.tracecompass.tmf.core.statesystem.ITmfStateProvider; +import org.eclipse.tracecompass.tmf.core.statesystem.TmfStateSystemAnalysisModule; + +/** + * State system analysis for pattern matching analysis described in XML. This + * module will parse the XML description of the analyses and execute it against + * the trace and will execute all required action + * + * @author Jean-Christian Kouame + */ +public class XmlPatternStateSystemModule extends TmfStateSystemAnalysisModule { + + private @Nullable IPath fXmlFile; + private final ISegmentListener fListener; + + /** + * Constructor + * + * @param listener + * Listener for segments that will be created + */ + public XmlPatternStateSystemModule(ISegmentListener listener) { + super(); + fListener = listener; + } + + @Override + protected @NonNull ITmfStateProvider createStateProvider() { + String id = getId(); + return new XmlPatternStateProvider(checkNotNull(getTrace()), id, fXmlFile, fListener); + } + + /** + * Sets the file path of the XML file containing the state provider + * + * @param file + * The full path to the XML file + */ + public void setXmlFile(IPath file) { + fXmlFile = file; + } + +} diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/messages.properties b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/messages.properties new file mode 100644 index 0000000000..3de3225412 --- /dev/null +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/internal/tmf/analysis/xml/core/pattern/stateprovider/messages.properties @@ -0,0 +1,12 @@ +############################################################################### +# Copyright (c) 2016 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 +############################################################################### +PatternSegmentContentAspect_Content=Content +PatternSegmentContentAspect_HelpText=The content of the segment +PatternSegmentNameAspect_HelpText=The name of the segment +PatternSegmentNameAspect_Name=Name diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/model/TmfXmlPatternSegmentBuilder.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/model/TmfXmlPatternSegmentBuilder.java index ba651fb1ea..6c445cadf6 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/model/TmfXmlPatternSegmentBuilder.java +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/model/TmfXmlPatternSegmentBuilder.java @@ -17,6 +17,7 @@ import java.util.Map; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator; +import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternStateProvider; import org.eclipse.tracecompass.statesystem.core.exceptions.AttributeNotFoundException; import org.eclipse.tracecompass.statesystem.core.exceptions.StateValueTypeException; import org.eclipse.tracecompass.statesystem.core.statevalue.ITmfStateValue; @@ -102,7 +103,11 @@ public class TmfXmlPatternSegmentBuilder { String segmentName = getPatternSegmentName(event); Map fields = new HashMap<>(); setPatternSegmentContent(event, start, end, fields); - return new TmfXmlPatternSegment(startValue, endValue, scale, segmentName, fields); + TmfXmlPatternSegment segment = new TmfXmlPatternSegment(startValue, endValue, scale, segmentName, fields); + if (fContainer instanceof XmlPatternStateProvider) { + ((XmlPatternStateProvider) fContainer).getListener().onNewSegment(segment); + } + return segment; } /** diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/TmfAnalysisModuleHelperXml.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/TmfAnalysisModuleHelperXml.java index 8f88f33837..bd0b97d7bb 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/TmfAnalysisModuleHelperXml.java +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/TmfAnalysisModuleHelperXml.java @@ -19,6 +19,7 @@ import org.eclipse.core.runtime.Path; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.tracecompass.common.core.NonNullUtils; import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.Activator; +import org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider.XmlPatternAnalysis; import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.TmfXmlStrings; import org.eclipse.tracecompass.tmf.analysis.xml.core.stateprovider.XmlStateSystemModule; import org.eclipse.tracecompass.tmf.core.analysis.IAnalysisModule; @@ -46,7 +47,14 @@ public class TmfAnalysisModuleHelperXml implements IAnalysisModuleHelper, ITmfPr */ public enum XmlAnalysisModuleType { /** Analysis will be of type XmlStateSystemModule */ - STATE_SYSTEM + STATE_SYSTEM, + + /** + * Analysis will be of type XmlPatternAnalysisModule + * + * @since 2.0 + */ + PATTERN } private final File fSourceFile; @@ -182,6 +190,19 @@ public class TmfAnalysisModuleHelperXml implements IAnalysisModuleHelper, ITmfPr */ ssModule.setAutomatic(true); + break; + case PATTERN: + module = new XmlPatternAnalysis(); + module.setName(getName()); + module.setId(analysisid); + XmlPatternAnalysis paModule = (XmlPatternAnalysis) module; + paModule.setXmlFile(new Path(fSourceFile.getAbsolutePath())); + + /* + * FIXME: Maybe the pattern analysis should not be automatic. + */ + paModule.setAutomatic(true); + break; default: break; diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/XmlAnalysisModuleSource.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/XmlAnalysisModuleSource.java index c9eb4346a1..e058e1b0be 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/XmlAnalysisModuleSource.java +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/XmlAnalysisModuleSource.java @@ -108,6 +108,15 @@ public class XmlAnalysisModuleSource implements IAnalysisModuleSource { IAnalysisModuleHelper helper = new TmfAnalysisModuleHelperXml(xmlFile, node, XmlAnalysisModuleType.STATE_SYSTEM); fModules.add(helper); } + + /* get pattern modules */ + NodeList patternNodes = doc.getElementsByTagName(TmfXmlStrings.PATTERN); + for (int i = 0; i < patternNodes.getLength(); i++) { + Element node = (Element) patternNodes.item(i); + + IAnalysisModuleHelper helper = new TmfAnalysisModuleHelperXml(xmlFile, node, XmlAnalysisModuleType.PATTERN); + fModules.add(helper); + } } catch (ParserConfigurationException | SAXException | IOException e) { Activator.logError("Error opening XML file", e); //$NON-NLS-1$ } diff --git a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/XmlUtils.java b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/XmlUtils.java index 175e9235f6..601266e7ca 100644 --- a/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/XmlUtils.java +++ b/tmf/org.eclipse.tracecompass.tmf.analysis.xml.core/src/org/eclipse/tracecompass/tmf/analysis/xml/core/module/XmlUtils.java @@ -262,6 +262,12 @@ public class XmlUtils { for (int i = 0; i < stateproviderNodes.getLength(); i++) { ids.add(nullToEmptyString(((Element) stateproviderNodes.item(i)).getAttribute(TmfXmlStrings.ID))); } + + /* get patterns modules */ + NodeList patternNodes = doc.getElementsByTagName(TmfXmlStrings.PATTERN); + for (int i = 0; i < patternNodes.getLength(); i++) { + ids.add(nullToEmptyString(((Element) patternNodes.item(i)).getAttribute(TmfXmlStrings.ID))); + } } catch (ParserConfigurationException | SAXException | IOException e) { Activator.logError("Failed to get analyses IDs from " + fileName); //$NON-NLS-1$ } -- 2.34.1