tmf: Make pcap aspects singletons
[deliverable/tracecompass.git] / org.eclipse.tracecompass.tmf.pcap.core / src / org / eclipse / tracecompass / internal / tmf / pcap / core / trace / PcapTrace.java
CommitLineData
b6eb4dce 1/*******************************************************************************
0214cc07 2 * Copyright (c) 2014, 2015 Ericsson
b6eb4dce
VP
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 * Contributors:
10 * Vincent Perot - Initial API and implementation
0214cc07
PT
11 * Alexandre Montplaisir - Update to new ITmfEventAspect API
12 * Patrick Tasse - Make pcap aspects singletons
b6eb4dce
VP
13 *******************************************************************************/
14
2bdf0193 15package org.eclipse.tracecompass.internal.tmf.pcap.core.trace;
b6eb4dce 16
5db5a3a4
AM
17import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
18
b6eb4dce
VP
19import java.io.IOException;
20import java.nio.channels.ClosedChannelException;
333a2acb 21import java.nio.file.Path;
5db5a3a4 22import java.nio.file.Paths;
b04903a2 23import java.util.Collection;
5db5a3a4 24import java.util.Collections;
b6eb4dce
VP
25import java.util.Map;
26
27import org.eclipse.core.resources.IProject;
28import org.eclipse.core.resources.IResource;
29import org.eclipse.core.runtime.IStatus;
30import org.eclipse.core.runtime.Status;
b6eb4dce 31import org.eclipse.jdt.annotation.Nullable;
71f2817f
AM
32import org.eclipse.tracecompass.internal.pcap.core.packet.BadPacketException;
33import org.eclipse.tracecompass.internal.pcap.core.protocol.pcap.PcapPacket;
34import org.eclipse.tracecompass.internal.pcap.core.trace.BadPcapFileException;
35import org.eclipse.tracecompass.internal.pcap.core.trace.PcapFile;
36import org.eclipse.tracecompass.internal.pcap.core.util.LinkTypeHelper;
2bdf0193
AM
37import org.eclipse.tracecompass.internal.tmf.pcap.core.Activator;
38import org.eclipse.tracecompass.internal.tmf.pcap.core.event.PcapEvent;
b04903a2
AM
39import org.eclipse.tracecompass.internal.tmf.pcap.core.event.aspect.PcapDestinationAspect;
40import org.eclipse.tracecompass.internal.tmf.pcap.core.event.aspect.PcapProtocolAspect;
41import org.eclipse.tracecompass.internal.tmf.pcap.core.event.aspect.PcapReferenceAspect;
42import org.eclipse.tracecompass.internal.tmf.pcap.core.event.aspect.PcapSourceAspect;
2bdf0193
AM
43import org.eclipse.tracecompass.internal.tmf.pcap.core.util.PcapEventFactory;
44import org.eclipse.tracecompass.tmf.core.event.ITmfEvent;
b04903a2 45import org.eclipse.tracecompass.tmf.core.event.aspect.ITmfEventAspect;
2bdf0193
AM
46import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException;
47import org.eclipse.tracecompass.tmf.core.trace.ITmfContext;
2bdf0193
AM
48import org.eclipse.tracecompass.tmf.core.trace.ITmfTraceProperties;
49import org.eclipse.tracecompass.tmf.core.trace.TmfContext;
50import org.eclipse.tracecompass.tmf.core.trace.TmfTrace;
51import org.eclipse.tracecompass.tmf.core.trace.TraceValidationStatus;
52import org.eclipse.tracecompass.tmf.core.trace.location.ITmfLocation;
53import org.eclipse.tracecompass.tmf.core.trace.location.TmfLongLocation;
b6eb4dce 54
b04903a2 55import com.google.common.collect.ImmutableList;
b6eb4dce
VP
56import com.google.common.collect.ImmutableMap;
57
58/**
59 * Class that represents a TMF Pcap Trace. It is used to make the glue between
60 * the Pcap parser and TMF.
61 *
62 * TODO handle fields in TmfEventType for the filter view.
63 *
64 * @author Vincent Perot
65 */
5733be39 66public class PcapTrace extends TmfTrace implements ITmfTraceProperties, AutoCloseable {
b6eb4dce 67
5db5a3a4
AM
68 private static final Collection<ITmfEventAspect> PCAP_ASPECTS =
69 checkNotNull(ImmutableList.of(
70 ITmfEventAspect.BaseAspects.TIMESTAMP,
0214cc07
PT
71 PcapSourceAspect.INSTANCE,
72 PcapDestinationAspect.INSTANCE,
73 PcapReferenceAspect.INSTANCE,
74 PcapProtocolAspect.INSTANCE,
5db5a3a4
AM
75 ITmfEventAspect.BaseAspects.CONTENTS
76 ));
b04903a2 77
b6eb4dce
VP
78 private static final String EMPTY_STRING = ""; //$NON-NLS-1$
79 private static final int CONFIDENCE = 50;
80 private @Nullable PcapFile fPcapFile;
5db5a3a4 81 private @Nullable Map<String, String> fTraceProperties = null;
b6eb4dce
VP
82
83 @Override
84 public synchronized ITmfLocation getCurrentLocation() {
85 PcapFile pcap = fPcapFile;
86 if (pcap == null) {
87 return new TmfLongLocation(0);
88 }
89 return new TmfLongLocation(pcap.getCurrentRank());
90 }
91
92 @Override
93 public synchronized double getLocationRatio(@Nullable ITmfLocation location) {
94 TmfLongLocation loc = (TmfLongLocation) location;
95 PcapFile pcap = fPcapFile;
96 if (loc == null || pcap == null) {
97 return 0;
98 }
99 try {
100 return (pcap.getTotalNbPackets() == 0 ? 0 : ((double) loc.getLocationInfo()) / pcap.getTotalNbPackets());
101 } catch (IOException | BadPcapFileException e) {
102 String message = e.getMessage();
103 if (message == null) {
104 message = EMPTY_STRING;
105 }
106 Activator.logError(message, e);
107 return 0;
108 }
109
110 }
111
112 @Override
113 public synchronized void initTrace(@Nullable IResource resource, @Nullable String path, @Nullable Class<? extends ITmfEvent> type) throws TmfTraceException {
114 super.initTrace(resource, path, type);
115 if (path == null) {
116 throw new TmfTraceException("No path has been specified."); //$NON-NLS-1$
117 }
5db5a3a4 118 Path filePath = checkNotNull(Paths.get(path));
b6eb4dce 119 try {
333a2acb 120 fPcapFile = new PcapFile(filePath);
b6eb4dce
VP
121 } catch (IOException | BadPcapFileException e) {
122 throw new TmfTraceException(e.getMessage(), e);
123 }
124 }
125
b04903a2
AM
126 @Override
127 public Iterable<ITmfEventAspect> getEventAspects() {
128 return PCAP_ASPECTS;
129 }
130
b6eb4dce
VP
131 @Override
132 public synchronized @Nullable PcapEvent parseEvent(@Nullable ITmfContext context) {
133 if (context == null) {
134 return null;
135 }
136
137 long rank = context.getRank();
138 PcapPacket packet = null;
139 PcapFile pcap = fPcapFile;
140 if (pcap == null) {
141 return null;
142 }
143 try {
144 pcap.seekPacket(rank);
145 packet = pcap.parseNextPacket();
146 } catch (ClosedChannelException e) {
147 /*
148 * This is handled independently and happens when the user closes
149 * the trace while it is being parsed. It simply stops the parsing.
150 * No need to log a error.
151 */
152 return null;
153 } catch (IOException | BadPcapFileException | BadPacketException e) {
154 String message = e.getMessage();
155 if (message == null) {
156 message = EMPTY_STRING;
157 }
158 Activator.logError(message, e);
159 return null;
160 }
161
162 if (packet == null) {
163 return null;
164 }
165
166 // Generate an event from this packet and return it.
167 return PcapEventFactory.createEvent(packet, pcap, this);
168
169 }
170
171 @Override
172 public synchronized ITmfContext seekEvent(double ratio) {
173 long position;
174 PcapFile pcap = fPcapFile;
175 if (pcap == null) {
176 return new TmfContext(new TmfLongLocation(0), 0);
177 }
178
179 try {
180 /*
181 * The ratio is between 0 and 1. We multiply it by the total number
182 * of packets to get the position.
183 */
184 position = (long) (ratio * pcap.getTotalNbPackets());
185 } catch (IOException | BadPcapFileException e) {
186 String message = e.getMessage();
187 if (message == null) {
188 message = EMPTY_STRING;
189 }
190 Activator.logError(message, e);
191 return new TmfContext(new TmfLongLocation(0), 0);
192 }
193 TmfLongLocation loc = new TmfLongLocation(position);
194 return new TmfContext(loc, loc.getLocationInfo());
195 }
196
197 @Override
198 public synchronized ITmfContext seekEvent(@Nullable ITmfLocation location) {
199 TmfLongLocation loc = (TmfLongLocation) location;
200 if (loc == null) {
201 return new TmfContext(new TmfLongLocation(0));
202 }
203
204 return new TmfContext(loc, loc.getLocationInfo());
205 }
206
207 @Override
208 public IStatus validate(@Nullable IProject project, @Nullable String path) {
209
210 // All validations are made when making a new pcap file.
211 if (path == null) {
212 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, EMPTY_STRING);
213 }
5db5a3a4 214 Path filePath = checkNotNull(Paths.get(path));
333a2acb 215 try (PcapFile file = new PcapFile(filePath)) {
b6eb4dce
VP
216 } catch (IOException | BadPcapFileException e) {
217 return new Status(IStatus.ERROR, Activator.PLUGIN_ID, e.toString());
218 }
219 return new TraceValidationStatus(CONFIDENCE, Activator.PLUGIN_ID);
220 }
221
222 @Override
223 public synchronized void dispose() {
224 super.dispose();
225 PcapFile pcap = fPcapFile;
226 if (pcap == null) {
227 return;
228 }
229 try {
230 pcap.close();
231 fPcapFile = null;
232 } catch (IOException e) {
233 String message = e.getMessage();
234 if (message == null) {
235 message = EMPTY_STRING;
236 }
237 Activator.logError(message, e);
238 return;
239 }
240 }
241
242 @Override
243 public synchronized Map<String, String> getTraceProperties() {
244 PcapFile pcap = fPcapFile;
245 if (pcap == null) {
5db5a3a4 246 return checkNotNull(Collections.<String, String> emptyMap());
b6eb4dce
VP
247 }
248
5db5a3a4 249 Map<String, String> properties = fTraceProperties;
b6eb4dce 250 if (properties == null) {
5db5a3a4
AM
251 ImmutableMap.Builder<String, String> builder = ImmutableMap.<String, String> builder();
252 builder.put(Messages.PcapTrace_Version, String.format("%d%c%d", pcap.getMajorVersion(), '.', pcap.getMinorVersion())); //$NON-NLS-1$
253 builder.put(Messages.PcapTrace_TimeZoneCorrection, pcap.getTimeZoneCorrection() + " s"); //$NON-NLS-1$
254 builder.put(Messages.PcapTrace_TimestampAccuracy, String.valueOf(pcap.getTimeAccuracy()));
255 builder.put(Messages.PcapTrace_MaxSnapLength, pcap.getSnapLength() + " bytes"); //$NON-NLS-1$
256 builder.put(Messages.PcapTrace_LinkLayerHeaderType, LinkTypeHelper.toString((int) pcap.getDataLinkType()) + " (" + pcap.getDataLinkType() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
257 builder.put(Messages.PcapTrace_FileEndianness, pcap.getByteOrder().toString());
258
259 return checkNotNull(builder.build());
b6eb4dce
VP
260
261 }
262
263 return properties;
264 }
265
266 @Override
267 public void close() {
268 dispose();
269 }
270}
This page took 0.050109 seconds and 5 git commands to generate.