Commit | Line | Data |
---|---|---|
e73a4ba5 GB |
1 | /******************************************************************************* |
2 | * Copyright (c) 2013 École Polytechnique de Montréal | |
3 | * | |
4 | * All rights reserved. This program and the accompanying materials are made | |
5 | * 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 | * Geneviève Bastien - Initial implementation and API | |
11 | *******************************************************************************/ | |
12 | ||
13 | package org.eclipse.linuxtools.tmf.core.event.matching; | |
14 | ||
15 | import java.util.ArrayList; | |
16 | import java.util.HashMap; | |
17 | import java.util.List; | |
18 | import java.util.Map; | |
19 | ||
20 | import org.eclipse.linuxtools.internal.tmf.core.Activator; | |
21 | import org.eclipse.linuxtools.tmf.core.ctfadaptor.CtfTmfEvent; | |
22 | import org.eclipse.linuxtools.tmf.core.event.ITmfEvent; | |
23 | import org.eclipse.linuxtools.tmf.core.request.ITmfDataRequest; | |
24 | import org.eclipse.linuxtools.tmf.core.request.TmfDataRequest; | |
25 | import org.eclipse.linuxtools.tmf.core.request.TmfEventRequest; | |
26 | import org.eclipse.linuxtools.tmf.core.timestamp.TmfTimeRange; | |
27 | import org.eclipse.linuxtools.tmf.core.trace.ITmfTrace; | |
28 | ||
29 | /** | |
30 | * Abstract class to extend to match certain type of events in a trace | |
31 | * | |
32 | * @author Geneviève Bastien | |
33 | * @since 3.0 | |
34 | */ | |
35 | public abstract class TmfEventMatching implements ITmfEventMatching { | |
36 | ||
37 | /** | |
38 | * The matching type | |
39 | * | |
40 | * FIXME Not the best place to put this. Have an array of match types as a | |
41 | * parameter of each trace? | |
42 | */ | |
43 | public enum MatchingType { | |
44 | /** | |
45 | * NETWORK, match network events | |
46 | */ | |
47 | NETWORK | |
48 | } | |
49 | ||
50 | /** | |
51 | * The array of traces to match | |
52 | */ | |
53 | private final ITmfTrace[] fTraces; | |
54 | ||
55 | /** | |
56 | * The class to call once a match is found | |
57 | */ | |
58 | private final IMatchProcessingUnit fMatches; | |
59 | ||
60 | private static final Map<MatchingType, List<ITmfMatchEventDefinition>> fMatchDefinitions = new HashMap<MatchingType, List<ITmfMatchEventDefinition>>(); | |
61 | ||
62 | private final Map<ITmfTrace, ITmfMatchEventDefinition> fMatchMap = new HashMap<ITmfTrace, ITmfMatchEventDefinition>(); | |
63 | ||
64 | /** | |
65 | * Constructor with multiple traces and a match processing object | |
66 | * | |
67 | * @param traces | |
68 | * The set of traces for which to match events | |
69 | * @param tmfEventMatches | |
70 | * The match processing class | |
71 | */ | |
72 | public TmfEventMatching(ITmfTrace[] traces, IMatchProcessingUnit tmfEventMatches) { | |
73 | if (tmfEventMatches == null) { | |
74 | throw new IllegalArgumentException(); | |
75 | } | |
76 | fTraces = traces; | |
77 | fMatches = tmfEventMatches; | |
78 | } | |
79 | ||
80 | /** | |
81 | * Returns the traces to process | |
82 | * | |
83 | * @return The traces | |
84 | */ | |
85 | protected ITmfTrace[] getTraces() { | |
86 | return fTraces; | |
87 | } | |
88 | ||
89 | /** | |
90 | * Returns the match processing unit | |
91 | * | |
92 | * @return The match processing unit | |
93 | */ | |
94 | protected IMatchProcessingUnit getProcessingUnit() { | |
95 | return fMatches; | |
96 | } | |
97 | ||
98 | /** | |
99 | * Returns the match event definition corresponding to the trace | |
100 | * | |
101 | * @param trace | |
102 | * The trace | |
103 | * @return The match event definition object | |
104 | */ | |
105 | protected ITmfMatchEventDefinition getEventDefinition(ITmfTrace trace) { | |
106 | return fMatchMap.get(trace); | |
107 | } | |
108 | ||
109 | /** | |
110 | * Method that initializes any data structure for the event matching. It | |
111 | * also assigns to each trace an event matching definition instance that | |
112 | * applies to the trace | |
113 | */ | |
114 | protected void initMatching() { | |
115 | fMatches.init(fTraces); | |
116 | List<ITmfMatchEventDefinition> deflist = fMatchDefinitions.get(getMatchingType()); | |
117 | if (deflist == null) { | |
118 | return; | |
119 | } | |
120 | for (ITmfTrace trace : fTraces) { | |
121 | for (ITmfMatchEventDefinition def : deflist) { | |
122 | if (def.canMatchTrace(trace)) { | |
123 | fMatchMap.put(trace, def); | |
124 | break; | |
125 | } | |
126 | } | |
127 | } | |
128 | } | |
129 | ||
130 | /** | |
131 | * Calls any post matching methods of the processing class | |
132 | */ | |
133 | protected void finalizeMatching() { | |
134 | fMatches.matchingEnded(); | |
135 | } | |
136 | ||
137 | /** | |
138 | * Prints stats from the matching | |
139 | * | |
140 | * @return string of statistics | |
141 | */ | |
142 | @SuppressWarnings("nls") | |
143 | @Override | |
144 | public String toString() { | |
145 | return getClass().getSimpleName() + " [ " + fMatches + " ]"; | |
146 | } | |
147 | ||
148 | /** | |
149 | * Matches one event | |
150 | * | |
151 | * @param event | |
152 | * The event to match | |
153 | * @param traceno | |
154 | * The number of the trace this event belongs to | |
155 | */ | |
156 | protected abstract void matchEvent(ITmfEvent event, int traceno); | |
157 | ||
158 | /** | |
159 | * Returns the matching type this class implements | |
160 | * | |
161 | * @return A matching type | |
162 | */ | |
163 | protected abstract MatchingType getMatchingType(); | |
164 | ||
165 | /** | |
166 | * Method that start the process of matching events | |
167 | * | |
168 | * @return Whether the match was completed correctly or not | |
169 | */ | |
170 | @Override | |
171 | public boolean matchEvents() { | |
172 | ||
173 | /* Are there traces to match? If no, return false */ | |
174 | if (!(fTraces.length > 0)) { | |
175 | return false; | |
176 | } | |
177 | ||
178 | // TODO Start a new thread here? | |
179 | initMatching(); | |
180 | ||
181 | /** | |
182 | * For each trace, get the events and for each event, call the | |
183 | * MatchEvent method | |
184 | * | |
185 | * FIXME This would use a lot of memory if the traces are big, because | |
186 | * all involved events from first trace will have to be kept before a | |
187 | * first match is possible with second trace. | |
188 | * | |
189 | * <pre> | |
190 | * Other possible matching strategy: | |
191 | * Incremental: | |
192 | * Sliding window: | |
193 | * Other strategy: start with the shortest trace, take a few events | |
194 | * at the beginning and at the end | |
195 | * Experiment strategy: have the experiment do the request, then events will | |
196 | * come from both traces chronologically, but then instead of ITmfTrace[], it | |
197 | * would be preferable to have experiment | |
198 | * </pre> | |
199 | */ | |
200 | for (int i = 0; i < fTraces.length; i++) { | |
201 | ||
202 | EventMatchingBuildRequest request = new EventMatchingBuildRequest(this, i); | |
203 | ||
204 | /* | |
205 | * Send the request to the trace here, since there is probably no | |
206 | * experiment. | |
207 | */ | |
208 | fTraces[i].sendRequest(request); | |
209 | try { | |
210 | request.waitForCompletion(); | |
211 | } catch (InterruptedException e) { | |
212 | Activator.logInfo(e.getMessage()); | |
213 | } | |
214 | } | |
215 | ||
216 | finalizeMatching(); | |
217 | ||
218 | return true; | |
219 | } | |
220 | ||
221 | /** | |
222 | * Registers an event match definition to be used for a certain match type | |
223 | * | |
224 | * @param match | |
225 | * The event matching definition | |
226 | */ | |
227 | public static void registerMatchObject(ITmfMatchEventDefinition match) { | |
228 | for (MatchingType type : match.getApplicableMatchingTypes()) { | |
229 | if (!fMatchDefinitions.containsKey(type)) { | |
230 | fMatchDefinitions.put(type, new ArrayList<ITmfMatchEventDefinition>()); | |
231 | } | |
232 | fMatchDefinitions.get(type).add(match); | |
233 | } | |
234 | } | |
235 | ||
236 | } | |
237 | ||
238 | class EventMatchingBuildRequest extends TmfEventRequest { | |
239 | ||
240 | private final TmfEventMatching matching; | |
241 | private final int traceno; | |
242 | ||
243 | EventMatchingBuildRequest(TmfEventMatching matching, int traceno) { | |
244 | super(CtfTmfEvent.class, | |
245 | TmfTimeRange.ETERNITY, | |
246 | 0, | |
247 | TmfDataRequest.ALL_DATA, | |
248 | ITmfDataRequest.ExecutionType.FOREGROUND); | |
249 | this.matching = matching; | |
250 | this.traceno = traceno; | |
251 | } | |
252 | ||
253 | @Override | |
254 | public void handleData(final ITmfEvent event) { | |
255 | super.handleData(event); | |
256 | if (event != null) { | |
257 | matching.matchEvent(event, traceno); | |
258 | } | |
259 | } | |
260 | ||
261 | @Override | |
262 | public void handleSuccess() { | |
263 | super.handleSuccess(); | |
264 | } | |
265 | ||
266 | @Override | |
267 | public void handleCancel() { | |
268 | super.handleCancel(); | |
269 | } | |
270 | ||
271 | @Override | |
272 | public void handleFailure() { | |
273 | super.handleFailure(); | |
274 | } | |
275 | } |