Skip to content

Commit 8533210

Browse files
committed
lttng: Make text metadata detection more lenient
Text CTF metadata files are supposed to start with "/* CTF " followed by the CTF version. https://diamon.org/ctf/v1.8.3/#spec7.1 However, to support opening traces that don't comply with the specification check for some common metadata keywords at the beginning of the metadata file when validating the trace. This will allow to open such traces with Trace Compass. fixes #298 Signed-off-by: Bernd Hufmann <[email protected]>
1 parent dde2974 commit 8533210

File tree

3 files changed

+103
-3
lines changed

3 files changed

+103
-3
lines changed

ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/MetadataPrevalidationTest.java

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,21 +180,103 @@ public void testTraceDirectoryWithJsonMetadata() throws IOException, CTFExceptio
180180
}
181181

182182
/**
183-
* Test a valid trace with text invalid metadata should return false
183+
* Test a valid trace with text metedata missing TSDL header, but with allowed "trace"
184+
* strings should return true
184185
*
185186
* @throws IOException
186187
* A file error occurs, shouldn't happen
187188
* @throws CTFException
188189
* if an exception occurs, shouldn't happen
189190
*/
190191
@Test
191-
public void testTraceDirectoryWithInvalidMetadata() throws IOException, CTFException {
192+
public void testTraceDirectoryWithAllowedStartStringMetadata1() throws IOException, CTFException {
192193
Path dir = Files.createTempDirectory("trace");
193194
Path f = Files.createFile(dir.resolve("metadata"));
194195
try (PrintWriter pw = new PrintWriter(f.toFile())) {
195196
// no header
196197
pw.println("trace { major =1 ; minor = 8 ; byte_order = le;};");
197198
}
199+
assertTrue(Metadata.preValidate(dir.toAbsolutePath().toString()));
200+
}
201+
202+
/**
203+
* Test a valid trace with text metedata missing TSDL header, but with allowed "typealias"
204+
* strings should return true
205+
*
206+
* @throws IOException
207+
* A file error occurs, shouldn't happen
208+
* @throws CTFException
209+
* if an exception occurs, shouldn't happen
210+
*/
211+
@Test
212+
public void testTraceDirectoryWithAllowedStartStringMetadata2() throws IOException, CTFException {
213+
Path dir = Files.createTempDirectory("trace");
214+
Path f = Files.createFile(dir.resolve("metadata"));
215+
try (PrintWriter pw = new PrintWriter(f.toFile())) {
216+
// no header
217+
pw.println("typealias integer { size = 8; align = 8; signed = false; } := uint8_t;");
218+
}
219+
assertTrue(Metadata.preValidate(dir.toAbsolutePath().toString()));
220+
}
221+
222+
/**
223+
* Test a valid trace with text metedata missing TSDL header, but with allowed "typealias"
224+
* strings should return true
225+
*
226+
* @throws IOException
227+
* A file error occurs, shouldn't happen
228+
* @throws CTFException
229+
* if an exception occurs, shouldn't happen
230+
*/
231+
@Test
232+
public void testTraceDirectoryWithAllowedStartStringMetadata3() throws IOException, CTFException {
233+
Path dir = Files.createTempDirectory("trace");
234+
Path f = Files.createFile(dir.resolve("metadata"));
235+
try (PrintWriter pw = new PrintWriter(f.toFile())) {
236+
// no header
237+
pw.println("env {\n"
238+
+ " hostname = \"localhost.localdomain\";\n"
239+
+ " domain = \"kernel\";\n"
240+
+ " sysname = \"Linux\";\n"
241+
+ " kernel_release = \"4.18.16-rt9\";\n"
242+
+ " kernel_version = \"#1 SMP PREEMPT RT Thu Jun 23 10:43:50 EDT 2022\";\n"
243+
+ " tracer_name = \"lttng-modules\";\n"
244+
+ " tracer_major = 2;\n"
245+
+ " tracer_minor = 14;\n"
246+
+ " tracer_patchlevel = 0;\n"
247+
+ " trace_buffering_scheme = \"global\";\n"
248+
+ " trace_name = \"default-k-20250724-093844\";\n"
249+
+ " trace_creation_datetime = \"20250724T093844-0400\";\n"
250+
+ " product_uuid = \"03000200-0400-0500-0006-000700080009\";\n"
251+
+ "};");
252+
}
253+
assertTrue(Metadata.preValidate(dir.toAbsolutePath().toString()));
254+
}
255+
256+
/**
257+
* Test a valid trace with text metedata missing TSDL header, but with allowed "typealias"
258+
* strings should return true
259+
*
260+
* @throws IOException
261+
* A file error occurs, shouldn't happen
262+
* @throws CTFException
263+
* if an exception occurs, shouldn't happen
264+
*/
265+
@Test
266+
public void testTraceDirectoryWithInvalidMetadata() throws IOException, CTFException {
267+
Path dir = Files.createTempDirectory("trace");
268+
Path f = Files.createFile(dir.resolve("metadata"));
269+
try (PrintWriter pw = new PrintWriter(f.toFile())) {
270+
// no header
271+
pw.println("clock {\n"
272+
+ " name = \"monotonic\";\n"
273+
+ " uuid = \"e7602765-7075-4f0b-814a-87c901e6837f\";\n"
274+
+ " description = \"Monotonic Clock\";\n"
275+
+ " freq = 1000000000; /* Frequency, in Hz */\n"
276+
+ " /* clock value offset from Epoch is: offset * (1/freq) */\n"
277+
+ " offset = 1753351888197109407;\n"
278+
+ "};");
279+
}
198280
assertFalse(Metadata.preValidate(dir.toAbsolutePath().toString()));
199281
}
200282

ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/Metadata.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
import org.eclipse.tracecompass.ctf.parser.CTFLexer;
5252
import org.eclipse.tracecompass.ctf.parser.CTFParser;
5353
import org.eclipse.tracecompass.ctf.parser.CTFParser.parse_return;
54+
import org.eclipse.tracecompass.internal.ctf.core.CtfCoreLoggerUtil;
5455
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.CTFAntlrMetadataNode;
5556
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.CTFJsonMetadataNode;
5657
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.CtfAntlrException;
@@ -63,6 +64,7 @@
6364
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.JsonFieldClassAliasMetadataNode;
6465
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.JsonPreambleMetadataNode;
6566
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.JsonTraceMetadataNode;
67+
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
6668
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
6769
import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace.TraceDeclarationParser;
6870
import org.eclipse.tracecompass.internal.ctf.core.event.types.ICTFMetadataNode;
@@ -90,6 +92,8 @@ public class Metadata {
9092

9193
private static final String TEXT_ONLY_METADATA_HEADER_PREFIX = "/* CTF"; //$NON-NLS-1$
9294

95+
private static final List<String> TEXT_ONLY_METADATA_HEADER_PREFIXES = List.of(MetadataStrings.TYPE_ALIAS, MetadataStrings.TRACE, MetadataStrings.ENV);
96+
9397
private static final int PREVALIDATION_SIZE = 8;
9498

9599
private static final int BITS_PER_BYTE = Byte.SIZE;
@@ -349,7 +353,17 @@ public static boolean preValidate(String path) throws CTFException {
349353
}
350354
try (BufferedReader br = new BufferedReader(new FileReader(metadataFile))) {
351355
String text = br.readLine();
352-
return text.startsWith(TEXT_ONLY_METADATA_HEADER_PREFIX);
356+
if (text.startsWith(TEXT_ONLY_METADATA_HEADER_PREFIX)) {
357+
return true;
358+
}
359+
if (TEXT_ONLY_METADATA_HEADER_PREFIXES.stream().anyMatch(text::startsWith)) {
360+
CtfCoreLoggerUtil.logWarning("Text-only metadata of trace " + path + " does not start with the required prefix: " + //$NON-NLS-1$ //$NON-NLS-2$
361+
TEXT_ONLY_METADATA_HEADER_PREFIX + ". Trace will be parsed as CTF because metadata starts with one of the supported keywords: " + //$NON-NLS-1$
362+
TEXT_ONLY_METADATA_HEADER_PREFIXES + "."); //$NON-NLS-1$
363+
return true;
364+
}
365+
return false;
366+
353367
} catch (IOException e) {
354368
throw new CTFException(e.getMessage(), e);
355369
}

ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/MetadataStrings.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,5 +128,9 @@ public interface MetadataStrings {
128128
String VARIANT = "variant";
129129
/** enum */
130130
String ENUM = "enum";
131+
/** typealias */
132+
String TYPE_ALIAS = "typealias";
133+
/** env */
134+
String ENV = "env";
131135

132136
}

0 commit comments

Comments
 (0)