Commit | Line | Data |
---|---|---|
6c7592e1 MK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2014 Ericsson | |
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 | * Matthew Khouzam - Initial API and implementation | |
11 | *******************************************************************************/ | |
12 | ||
f357bcd4 | 13 | package org.eclipse.tracecompass.internal.ctf.core.event.types.composite; |
6c7592e1 MK |
14 | |
15 | import java.nio.ByteOrder; | |
16 | ||
f78eb6a7 MK |
17 | import org.eclipse.jdt.annotation.NonNullByDefault; |
18 | import org.eclipse.jdt.annotation.Nullable; | |
f357bcd4 AM |
19 | import org.eclipse.tracecompass.ctf.core.event.io.BitBuffer; |
20 | import org.eclipse.tracecompass.ctf.core.event.scope.IDefinitionScope; | |
21 | import org.eclipse.tracecompass.ctf.core.event.types.Declaration; | |
22 | import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration; | |
23 | import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration; | |
24 | import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration; | |
25 | import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration; | |
26 | import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration; | |
27 | import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration; | |
28 | import org.eclipse.tracecompass.ctf.core.trace.CTFReaderException; | |
6c7592e1 MK |
29 | |
30 | /** | |
31 | * An event header declaration is a declaration of a structure defined in the | |
32 | * CTF spec examples section 6.1.1 . It is used in LTTng traces. This will | |
33 | * accelerate reading of the trace. | |
34 | * | |
35 | * Reminder | |
36 | * | |
37 | * <pre> | |
38 | * struct event_header_compact { | |
39 | * enum : uint5_t { compact = 0 ... 30, extended = 31 } id; | |
40 | * variant <id> { | |
41 | * struct { | |
42 | * uint27_clock_monotonic_t timestamp; | |
43 | * } compact; | |
44 | * struct { | |
45 | * uint32_t id; | |
46 | * uint64_clock_monotonic_t timestamp; | |
47 | * } extended; | |
48 | * } v; | |
49 | * } align(8); | |
50 | * </pre> | |
51 | * | |
52 | * @author Matthew Khouzam | |
53 | */ | |
f78eb6a7 | 54 | @NonNullByDefault |
6c7592e1 MK |
55 | public class EventHeaderCompactDeclaration extends Declaration implements IEventHeaderDeclaration { |
56 | ||
57 | private static final int COMPACT_SIZE = 1; | |
58 | private static final int VARIANT_SIZE = 2; | |
59 | private static final int EXTENDED_FIELD_SIZE = 2; | |
60 | /** | |
61 | * The id is 5 bits | |
62 | */ | |
63 | private static final int COMPACT_ID = 5; | |
64 | private static final int EXTENDED_VALUE = 31; | |
65 | /** | |
66 | * Full sized id is 32 bits | |
67 | */ | |
68 | private static final int ID_SIZE = 32; | |
69 | /** | |
70 | * Full sized timestamp is 64 bits | |
71 | */ | |
72 | private static final int FULL_TS = 64; | |
73 | /** | |
74 | * Compact timestamp is 27 bits, | |
75 | */ | |
76 | private static final int COMPACT_TS = 27; | |
77 | /** | |
78 | * Maximum size = largest this header can be | |
79 | */ | |
80 | private static final int MAX_SIZE = 104; | |
81 | /** | |
82 | * Byte aligned | |
83 | */ | |
84 | private static final int ALIGN = 8; | |
85 | /** | |
86 | * Name of the variant according to the spec | |
87 | */ | |
88 | private static final String V = "v"; //$NON-NLS-1$ | |
89 | ||
90 | private final ByteOrder fByteOrder; | |
91 | ||
f78eb6a7 MK |
92 | /** |
93 | * Big-Endian Large Event Header | |
94 | */ | |
95 | private static final EventHeaderCompactDeclaration EVENT_HEADER_BIG_ENDIAN = new EventHeaderCompactDeclaration(nullCheck(ByteOrder.BIG_ENDIAN)); | |
96 | ||
97 | /** | |
98 | * Little-Endian Large Event Header | |
99 | */ | |
100 | private static final EventHeaderCompactDeclaration EVENT_HEADER_LITTLE_ENDIAN = new EventHeaderCompactDeclaration(nullCheck(ByteOrder.LITTLE_ENDIAN)); | |
101 | ||
6c7592e1 MK |
102 | /** |
103 | * Event Header Declaration | |
104 | * | |
105 | * @param byteOrder | |
106 | * the byteorder | |
107 | */ | |
f78eb6a7 | 108 | private EventHeaderCompactDeclaration(ByteOrder byteOrder) { |
6c7592e1 MK |
109 | fByteOrder = byteOrder; |
110 | } | |
111 | ||
f78eb6a7 MK |
112 | /** |
113 | * Gets an {@link EventHeaderCompactDeclaration} of a given ByteOrder | |
114 | * | |
115 | * @param byteOrder | |
116 | * the byte order | |
117 | * @return the header declaration | |
118 | */ | |
119 | public static EventHeaderCompactDeclaration getEventHeader(@Nullable ByteOrder byteOrder) { | |
120 | if (byteOrder == ByteOrder.BIG_ENDIAN) { | |
121 | return EVENT_HEADER_BIG_ENDIAN; | |
122 | } | |
123 | return EVENT_HEADER_LITTLE_ENDIAN; | |
124 | } | |
125 | ||
6c7592e1 | 126 | @Override |
f78eb6a7 | 127 | public EventHeaderDefinition createDefinition(@Nullable IDefinitionScope definitionScope, String fieldName, BitBuffer input) throws CTFReaderException { |
6c7592e1 MK |
128 | alignRead(input); |
129 | ByteOrder bo = input.getByteOrder(); | |
130 | input.setByteOrder(fByteOrder); | |
131 | int enumId = (int) input.get(COMPACT_ID, false); | |
132 | if (enumId != EXTENDED_VALUE) { | |
133 | long timestamp2 = input.get(COMPACT_TS, false); | |
134 | input.setByteOrder(bo); | |
135 | return new EventHeaderDefinition(this, enumId, timestamp2, COMPACT_TS); | |
136 | } | |
137 | // needed since we read 5 bits | |
138 | input.position(input.position() + 3); | |
733e6767 MK |
139 | long id = input.get(ID_SIZE, false); |
140 | if (id > Integer.MAX_VALUE) { | |
141 | throw new CTFReaderException("ID " + id + " larger than " + Integer.MAX_VALUE + " is currently unsupported by the parser"); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ | |
142 | } | |
6c7592e1 MK |
143 | long timestampLong = input.get(FULL_TS, false); |
144 | input.setByteOrder(bo); | |
733e6767 | 145 | return new EventHeaderDefinition(this, (int) id, timestampLong, FULL_TS); |
6c7592e1 MK |
146 | |
147 | } | |
148 | ||
149 | @Override | |
150 | public long getAlignment() { | |
151 | return ALIGN; | |
152 | } | |
153 | ||
154 | @Override | |
155 | public int getMaximumSize() { | |
156 | return MAX_SIZE; | |
157 | } | |
158 | ||
159 | /** | |
160 | * Check if a given struct declaration is an event header | |
161 | * | |
162 | * @param declaration | |
163 | * the declaration | |
164 | * @return true if the struct is a compact event header | |
165 | */ | |
f78eb6a7 MK |
166 | public static boolean isCompactEventHeader(@Nullable StructDeclaration declaration) { |
167 | if (declaration == null) { | |
168 | return false; | |
169 | } | |
6c7592e1 MK |
170 | |
171 | IDeclaration iDeclaration = declaration.getFields().get(ID); | |
172 | if (!(iDeclaration instanceof EnumDeclaration)) { | |
173 | return false; | |
174 | } | |
175 | EnumDeclaration eId = (EnumDeclaration) iDeclaration; | |
176 | if (eId.getContainerType().getLength() != COMPACT_ID) { | |
177 | return false; | |
178 | } | |
179 | iDeclaration = declaration.getFields().get(V); | |
180 | ||
181 | if (!(iDeclaration instanceof VariantDeclaration)) { | |
182 | return false; | |
183 | } | |
184 | VariantDeclaration vDec = (VariantDeclaration) iDeclaration; | |
185 | if (!vDec.hasField(COMPACT) || !vDec.hasField(EXTENDED)) { | |
186 | return false; | |
187 | } | |
733e6767 | 188 | if (vDec.getFields().size() != VARIANT_SIZE) { |
6c7592e1 MK |
189 | return false; |
190 | } | |
191 | iDeclaration = vDec.getFields().get(COMPACT); | |
733e6767 | 192 | if (!(iDeclaration instanceof StructDeclaration)) { |
6c7592e1 MK |
193 | return false; |
194 | } | |
195 | StructDeclaration compactDec = (StructDeclaration) iDeclaration; | |
196 | if (compactDec.getFields().size() != COMPACT_SIZE) { | |
197 | return false; | |
198 | } | |
199 | if (!compactDec.hasField(TIMESTAMP)) { | |
200 | return false; | |
201 | } | |
202 | iDeclaration = compactDec.getFields().get(TIMESTAMP); | |
733e6767 | 203 | if (!(iDeclaration instanceof IntegerDeclaration)) { |
6c7592e1 MK |
204 | return false; |
205 | } | |
206 | IntegerDeclaration tsDec = (IntegerDeclaration) iDeclaration; | |
207 | if (tsDec.getLength() != COMPACT_TS || tsDec.isSigned()) { | |
208 | return false; | |
209 | } | |
210 | iDeclaration = vDec.getFields().get(EXTENDED); | |
733e6767 | 211 | if (!(iDeclaration instanceof StructDeclaration)) { |
6c7592e1 MK |
212 | return false; |
213 | } | |
214 | StructDeclaration extendedDec = (StructDeclaration) iDeclaration; | |
215 | if (!extendedDec.hasField(TIMESTAMP)) { | |
216 | return false; | |
217 | } | |
218 | if (extendedDec.getFields().size() != EXTENDED_FIELD_SIZE) { | |
219 | return false; | |
220 | } | |
221 | iDeclaration = extendedDec.getFields().get(TIMESTAMP); | |
733e6767 | 222 | if (!(iDeclaration instanceof IntegerDeclaration)) { |
6c7592e1 MK |
223 | return false; |
224 | } | |
225 | tsDec = (IntegerDeclaration) iDeclaration; | |
226 | if (tsDec.getLength() != FULL_TS || tsDec.isSigned()) { | |
227 | return false; | |
228 | } | |
229 | iDeclaration = extendedDec.getFields().get(ID); | |
230 | if (!(iDeclaration instanceof IntegerDeclaration)) { | |
231 | return false; | |
232 | } | |
233 | IntegerDeclaration iId = (IntegerDeclaration) iDeclaration; | |
234 | if (iId.getLength() != ID_SIZE || iId.isSigned()) { | |
235 | return false; | |
236 | } | |
237 | return true; | |
238 | } | |
f78eb6a7 MK |
239 | |
240 | private static ByteOrder nullCheck(@Nullable ByteOrder bo) { | |
241 | if (bo == null) { | |
242 | throw new IllegalStateException("Could not create byteorder"); //$NON-NLS-1$ | |
243 | } | |
244 | return bo; | |
245 | } | |
e00e6663 MK |
246 | |
247 | @Override | |
248 | public int hashCode() { | |
249 | final int prime = 31; | |
250 | int result = 1; | |
251 | result = prime * result + (fByteOrder.equals(ByteOrder.BIG_ENDIAN) ? 4321 : 1234); | |
252 | return result; | |
253 | } | |
254 | ||
255 | @Override | |
256 | public boolean equals(@Nullable Object obj) { | |
257 | if (this == obj) { | |
258 | return true; | |
259 | } | |
260 | if (obj == null) { | |
261 | return false; | |
262 | } | |
263 | if (getClass() != obj.getClass()) { | |
264 | return false; | |
265 | } | |
266 | EventHeaderCompactDeclaration other = (EventHeaderCompactDeclaration) obj; | |
267 | if (!fByteOrder.equals(other.fByteOrder)) { | |
268 | return false; | |
269 | } | |
270 | return true; | |
271 | } | |
272 | ||
6c7592e1 | 273 | } |