Commit | Line | Data |
---|---|---|
38e2a2e9 JCK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2016 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 | package org.eclipse.tracecompass.internal.tmf.analysis.xml.core.pattern.stateprovider; | |
10 | ||
11 | import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull; | |
12 | ||
13 | import java.io.IOException; | |
14 | import java.io.ObjectInputStream; | |
15 | import java.util.concurrent.CountDownLatch; | |
16 | ||
17 | import org.eclipse.core.runtime.IProgressMonitor; | |
18 | import org.eclipse.jdt.annotation.NonNull; | |
19 | import org.eclipse.jdt.annotation.Nullable; | |
20 | import org.eclipse.tracecompass.analysis.timing.core.segmentstore.AbstractSegmentStoreAnalysisModule; | |
21 | import org.eclipse.tracecompass.analysis.timing.core.segmentstore.IAnalysisProgressListener; | |
22 | import org.eclipse.tracecompass.segmentstore.core.ISegment; | |
23 | import org.eclipse.tracecompass.segmentstore.core.ISegmentStore; | |
24 | import org.eclipse.tracecompass.segmentstore.core.treemap.TreeMapStore; | |
25 | import org.eclipse.tracecompass.tmf.core.exceptions.TmfAnalysisException; | |
26 | import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; | |
27 | ||
28 | /** | |
29 | * Segment store module for pattern analysis defined in XML. This module will | |
30 | * receive all the segments provided by an external source and will build a | |
31 | * segment store | |
32 | * | |
33 | * @author Jean-Christian Kouame | |
34 | */ | |
35 | public class XmlPatternSegmentStoreModule extends AbstractSegmentStoreAnalysisModule implements ISegmentListener { | |
36 | ||
37 | /** | |
38 | * Fake segment indicated that the last segment have been received | |
39 | */ | |
40 | public static final @NonNull EndSegment END_SEGMENT = new EndSegment(); | |
41 | private final ISegmentStore<@NonNull ISegment> fSegments = new TreeMapStore<>(); | |
42 | private final CountDownLatch fFinished = new CountDownLatch(1); | |
43 | private final @NonNull XmlPatternAnalysis fParent; | |
44 | private boolean fSegmentStoreCompleted; | |
45 | ||
46 | /** | |
47 | * Constructor | |
48 | * | |
49 | * @param parent | |
50 | * The parent analysis | |
51 | */ | |
52 | public XmlPatternSegmentStoreModule(@NonNull XmlPatternAnalysis parent) { | |
53 | super(); | |
54 | fParent = parent; | |
55 | } | |
56 | ||
57 | @Override | |
58 | protected Object @NonNull [] readObject(@NonNull ObjectInputStream ois) throws ClassNotFoundException, IOException { | |
59 | return checkNotNull((Object[]) ois.readObject()); | |
60 | } | |
61 | ||
62 | @Override | |
63 | protected boolean buildAnalysisSegments(@NonNull ISegmentStore<@NonNull ISegment> segments, @NonNull IProgressMonitor monitor) throws TmfAnalysisException { | |
64 | final @Nullable ITmfTrace trace = getTrace(); | |
65 | if (trace == null) { | |
66 | /* This analysis was cancelled in the meantime */ | |
67 | segmentStoreReady(false); | |
68 | return false; | |
69 | } | |
70 | waitForSegmentStoreCompletion(); | |
71 | segments.addAll(getSegments()); | |
72 | return true; | |
73 | } | |
74 | ||
75 | @Override | |
76 | protected void canceling() { | |
77 | super.cancel(); | |
78 | segmentStoreReady(false); | |
79 | } | |
80 | ||
81 | @Override | |
82 | protected @Nullable String getDataFileName() { | |
83 | return getId() + XmlPatternAnalysis.SEGMENT_STORE_EXTENSION; | |
84 | } | |
85 | ||
86 | /** | |
87 | * Broadcast the segment store to its listeners. Since this analysis is not | |
88 | * directly register to the trace, the parent analysis is used as the source. | |
89 | * | |
90 | * @param store | |
91 | * The store to broadcast | |
92 | */ | |
93 | @Override | |
94 | protected void sendUpdate(final ISegmentStore<@NonNull ISegment> store) { | |
95 | for (IAnalysisProgressListener listener : getListeners()) { | |
96 | listener.onComplete(fParent, store); | |
97 | } | |
98 | } | |
99 | ||
100 | @Override | |
101 | public void onNewSegment(@NonNull ISegment segment) { | |
102 | // We can accept segments until the first END_SEGMENT arrives. Nothing | |
103 | // should be accept after it. This prevents to receive new segments if | |
104 | // the analysis that generates the segments is rescheduled | |
105 | if (!fSegmentStoreCompleted) { | |
106 | if (segment == END_SEGMENT) { | |
107 | segmentStoreReady(true); | |
108 | return; | |
109 | } | |
110 | getSegments().add(segment); | |
111 | } | |
112 | } | |
113 | ||
114 | /** | |
115 | * Get the internal segment store of this module | |
116 | * | |
117 | * @return The segment store | |
118 | */ | |
119 | private synchronized ISegmentStore<@NonNull ISegment> getSegments() { | |
120 | return fSegments; | |
121 | } | |
122 | ||
123 | /** | |
124 | * Wait until internal segment store of the module is fully filled. If all | |
125 | * the segments have been received, the completion succeeded, otherwise it | |
126 | * is not. | |
127 | * | |
128 | * @return True if the completion succeeded, false otherwise | |
129 | */ | |
130 | public boolean waitForSegmentStoreCompletion() { | |
131 | try { | |
132 | fFinished.await(); | |
133 | } catch (InterruptedException e) { | |
134 | return false; | |
135 | } | |
136 | return fSegmentStoreCompleted; | |
137 | } | |
138 | ||
139 | /** | |
140 | * Make the module available and set whether the segment store completion | |
141 | * succeeded or not. If not, no segment store is available and | |
142 | * {@link #waitForSegmentStoreCompletion()} should return false. | |
143 | * | |
144 | * @param success | |
145 | * True if the segment store completion succeeded, false | |
146 | * otherwise | |
147 | */ | |
148 | private void segmentStoreReady(boolean succeeded) { | |
149 | fSegmentStoreCompleted = succeeded; | |
150 | fFinished.countDown(); | |
151 | } | |
152 | ||
153 | /** | |
154 | * Fake segment indicating the build is over, and the segment store is fully | |
155 | * filled | |
156 | */ | |
157 | public static class EndSegment implements ISegment { | |
158 | /** | |
159 | * The serial version UID | |
160 | */ | |
161 | private static final long serialVersionUID = 7834984029618274707L; | |
162 | ||
163 | @Override | |
164 | public long getStart() { | |
165 | return Long.MIN_VALUE; | |
166 | } | |
167 | ||
168 | @Override | |
169 | public long getEnd() { | |
170 | return Long.MIN_VALUE; | |
171 | } | |
172 | } | |
173 | } |