lttng: Fix a test on Windows with file not being able to be deleted
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core.tests / shared / org / eclipse / tracecompass / ctf / core / tests / shared / LttngTraceGenerator.java
CommitLineData
c2fa72bc 1/*******************************************************************************
4eebea10 2 * Copyright (c) 2013, 2017 Ericsson
c2fa72bc
MK
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 * Matthew Khouzam - Initial API and implementation
ea0e5a5b 11 * Marc-Andre Laperle - Move generation to traces folder
c2fa72bc
MK
12 *******************************************************************************/
13
c4d57ac1 14package org.eclipse.tracecompass.ctf.core.tests.shared;
c2fa72bc
MK
15
16import java.io.File;
17import java.io.FileNotFoundException;
18import java.io.FileOutputStream;
19import java.io.IOException;
20import java.nio.ByteBuffer;
21import java.nio.ByteOrder;
22import java.nio.channels.FileChannel;
83967946
PT
23import java.nio.file.FileVisitResult;
24import java.nio.file.Files;
c4d57ac1
AM
25import java.nio.file.Path;
26import java.nio.file.Paths;
83967946
PT
27import java.nio.file.SimpleFileVisitor;
28import java.nio.file.attribute.BasicFileAttributes;
c2fa72bc
MK
29import java.util.Arrays;
30import java.util.List;
31import java.util.Random;
32
f357bcd4 33import org.eclipse.tracecompass.ctf.core.tests.CtfCoreTestPlugin;
ea0e5a5b 34
c2fa72bc 35/**
4eebea10 36 * Generate a lttng trace (kernel or ust)
c2fa72bc
MK
37 *
38 * @author Matthew Khouzam
39 */
4eebea10 40public class LttngTraceGenerator {
c2fa72bc 41
4eebea10 42 private static final String metadataKernel = "/* CTF 1.8 */ \n" +
c2fa72bc
MK
43 "typealias integer { size = 8; align = 8; signed = false; } := uint8_t;\n" +
44 "typealias integer { size = 16; align = 8; signed = false; } := uint16_t;\n" +
45 "typealias integer { size = 32; align = 8; signed = false; } := uint32_t;\n" +
46 "typealias integer { size = 64; align = 8; signed = false; } := uint64_t;\n" +
47 "typealias integer { size = 32; align = 8; signed = false; } := unsigned long;\n" +
48 "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" +
49 "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" +
50 "\n" +
51 "trace {\n" +
52 " major = 1;\n" +
53 " minor = 8;\n" +
54 " uuid = \"11111111-1111-1111-1111-111111111111\";\n" +
55 " byte_order = le;\n" +
56 " packet.header := struct {\n" +
57 " uint32_t magic;\n" +
58 " uint8_t uuid[16];\n" +
59 " uint32_t stream_id;\n" +
60 " };\n" +
61 "};\n" +
62 "\n" +
63 "env {\n" +
64 " hostname = \"synthetic-host\";\n" +
65 " domain = \"kernel\";\n" +
66 " sysname = \"FakeLinux\";\n" +
67 " kernel_release = \"1.0\";\n" +
68 " kernel_version = \"Fake Os Synthetic Trace\";\n" +
69 " tracer_name = \"lttng-modules\";\n" +
70 " tracer_major = 2;\n" +
71 " tracer_minor = 1;\n" +
72 " tracer_patchlevel = 0;\n" +
73 "};\n" +
74 "\n" +
75 "clock {\n" +
76 " name = monotonic;\n" +
77 " uuid = \"bbff68f0-c633-4ea1-92cd-bd11024ec4de\";\n" +
78 " description = \"Monotonic Clock\";\n" +
79 " freq = 1000000000; /* Frequency, in Hz */\n" +
80 " /* clock value offset from Epoch is: offset * (1/freq) */\n" +
81 " offset = 1368000272650993664;\n" +
82 "};\n" +
83 "\n" +
84 "typealias integer {\n" +
85 " size = 27; align = 1; signed = false;\n" +
86 " map = clock.monotonic.value;\n" +
87 "} := uint27_clock_monotonic_t;\n" +
88 "\n" +
89 "typealias integer {\n" +
90 " size = 32; align = 8; signed = false;\n" +
91 " map = clock.monotonic.value;\n" +
92 "} := uint32_clock_monotonic_t;\n" +
93 "\n" +
94 "typealias integer {\n" +
95 " size = 64; align = 8; signed = false;\n" +
96 " map = clock.monotonic.value;\n" +
97 "} := uint64_clock_monotonic_t;\n" +
98 "\n" +
99 "struct packet_context {\n" +
100 " uint64_clock_monotonic_t timestamp_begin;\n" +
101 " uint64_clock_monotonic_t timestamp_end;\n" +
102 " uint64_t content_size;\n" +
103 " uint64_t packet_size;\n" +
104 " unsigned long events_discarded;\n" +
105 " uint32_t cpu_id;\n" +
106 "};\n" +
107 "\n" +
108 "struct event_header_compact {\n" +
109 " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" +
110 " variant <id> {\n" +
111 " struct {\n" +
112 " uint27_clock_monotonic_t timestamp;\n" +
113 " } compact;\n" +
114 " struct {\n" +
115 " uint32_t id;\n" +
116 " uint64_clock_monotonic_t timestamp;\n" +
117 " } extended;\n" +
118 " } v;\n" +
119 "} align(8);\n" +
120 "\n" +
121 "struct event_header_large {\n" +
122 " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" +
123 " variant <id> {\n" +
124 " struct {\n" +
125 " uint32_clock_monotonic_t timestamp;\n" +
126 " } compact;\n" +
127 " struct {\n" +
128 " uint32_t id;\n" +
129 " uint64_clock_monotonic_t timestamp;\n" +
130 " } extended;\n" +
131 " } v;\n" +
132 "} align(8);\n" +
133 "\n" +
134 "stream {\n" +
135 " id = 0;\n" +
136 " event.header := struct event_header_compact;\n" +
137 " packet.context := struct packet_context;\n" +
138 "};\n" +
139 "\n" +
140 "event {\n" +
141 " name = sched_switch;\n" +
142 " id = 0;\n" +
143 " stream_id = 0;\n" +
144 " fields := struct {\n" +
145 " integer { size = 8; align = 8; signed = 1; encoding = UTF8; base = 10; } _prev_comm[16];\n" +
146 " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_tid;\n" +
147 " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_prio;\n" +
148 " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_state;\n" +
149 " integer { size = 8; align = 8; signed = 1; encoding = UTF8; base = 10; } _next_comm[16];\n" +
150 " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _next_tid;\n" +
151 " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _next_prio;\n" +
152 " };\n" +
153 "};\n" +
154 "\n";
155
156 private final List<String> fProcesses;
157 private final long fDuration;
158 private final long fNbEvents;
159 private final int fNbChans;
c2fa72bc 160
4eebea10
MAL
161 private final String metadata;
162
c2fa72bc
MK
163 private static final String[] sfProcesses = {
164 "IDLE",
165 "gnuplot",
166 "starcraft 2:pt3",
167 "bash",
168 "smash",
169 "thrash",
170 "fireball",
171 "Half-life 3",
172 "ST: The game"
173 };
174
175
ea0e5a5b
MAL
176 private static final String TRACES_DIRECTORY = "traces";
177 private static final String TRACE_NAME = "synthetic-trace";
c2fa72bc
MK
178
179 /**
180 * Main, not always needed
181 *
182 * @param args
183 * args
184 */
185 public static void main(String[] args) {
ea0e5a5b 186 // not using createTempFile as this is a directory
3ec38c4c 187 String path = CtfCoreTestPlugin.getTemporaryDirPath() + File.separator + TRACE_NAME;
4eebea10 188 generateLttngTrace(new File(path));
c2fa72bc
MK
189 }
190
191 /**
192 * Gets the name of the trace (top directory name)
193 *
194 * @return the name of the trace
195 */
196 public static String getName() {
ea0e5a5b 197 return TRACE_NAME;
c2fa72bc
MK
198 }
199
200 /**
201 * Get the path
202 *
203 * @return the path
204 */
205 public static String getPath() {
e9504bf6
AM
206 CtfCoreTestPlugin plugin = CtfCoreTestPlugin.getDefault();
207 if (plugin == null) {
208 return null;
209 }
c4d57ac1
AM
210 Path tracePath = Paths.get("..", "..", "ctf", "org.eclipse.tracecompass.ctf.core.tests", TRACES_DIRECTORY, TRACE_NAME);
211 tracePath = tracePath.toAbsolutePath();
212 File file = tracePath.toFile();
4eebea10 213 generateLttngTrace(file);
c2fa72bc
MK
214 return file.getAbsolutePath();
215 }
216
217 /**
218 * Generate a trace
ea0e5a5b
MAL
219 *
220 * @param file
221 * the file to write the trace to
c2fa72bc 222 */
4eebea10 223 public static void generateLttngTrace(File file) {
c2fa72bc 224 final int cpus = 25;
4eebea10 225 LttngTraceGenerator gt = new LttngTraceGenerator(2l * Integer.MAX_VALUE - 100, 500000, cpus);
ea0e5a5b 226 gt.writeTrace(file);
c2fa72bc
MK
227 }
228
229 /**
4eebea10
MAL
230 * Make a lttng trace
231 *
232 * @param duration
233 * the duration of the trace
234 * @param events
235 * the number of events in a trace
236 * @param nbChannels
237 * the number of channels in the trace
238 */
239 public LttngTraceGenerator(long duration, long events, int nbChannels) {
240 this(duration, events, nbChannels, true);
241 }
242
243 /**
244 * Make a lttng trace
c2fa72bc
MK
245 *
246 * @param duration
247 * the duration of the trace
248 * @param events
249 * the number of events in a trace
250 * @param nbChannels
251 * the number of channels in the trace
4eebea10
MAL
252 * @param isKernel
253 * true for kernel, false for ust
c2fa72bc 254 */
4eebea10 255 public LttngTraceGenerator(long duration, long events, int nbChannels, boolean isKernel) {
c2fa72bc
MK
256 fProcesses = Arrays.asList(sfProcesses);
257 fDuration = duration;
258 fNbEvents = events;
259 fNbChans = nbChannels;
4eebea10 260 metadata = isKernel ? metadataKernel : getMetadataUST();
c2fa72bc
MK
261 }
262
263 /**
264 * Write the trace to a file
265 *
ea0e5a5b
MAL
266 * @param file
267 * the file to write the trace to
c2fa72bc 268 */
ea0e5a5b 269 public void writeTrace(File file) {
c2fa72bc 270
83967946
PT
271 if (file.exists()) {
272 deleteDirectory(file);
c2fa72bc 273 }
83967946 274 file.mkdir();
c2fa72bc 275
ea0e5a5b 276 File metadataFile = new File(file.getPath() + File.separator + "metadata");
c2fa72bc
MK
277 File[] streams = new File[fNbChans];
278 FileChannel[] channels = new FileChannel[fNbChans];
c2fa72bc
MK
279
280 try {
281 for (int i = 0; i < fNbChans; i++) {
ea0e5a5b 282 streams[i] = new File(file.getPath() + File.separator + "channel" + i);
c2fa72bc 283 channels[i] = new FileOutputStream(streams[i]).getChannel();
c2fa72bc
MK
284 }
285 } catch (FileNotFoundException e) {
286 }
287 // determine the number of events per channel
288 long evPerChan = fNbEvents / fNbChans;
9709972d 289 final int evPerPacket = PacketWriter.CONTENT_SIZE / EventWriter.SIZE;
6e1f0a91
PT
290 long delta = (int) (fDuration / evPerChan);
291 long offsetTime = 0;
9709972d 292 Random rndLost = new Random(1337);
c2fa72bc
MK
293 for (int chan = 0; chan < fNbChans; chan++) {
294 int currentSpace = 0;
295 ByteBuffer bb = ByteBuffer.allocate(65536);
296 bb.order(ByteOrder.LITTLE_ENDIAN);
297 Random rnd = new Random(1337);
298 int rnd0 = rnd.nextInt(fProcesses.size());
299 String prevComm = fProcesses.get(rnd0);
300 int prevPID = rnd0 + chan * fProcesses.size();
301 if (rnd0 == 0) {
302 prevPID = 0;
303 }
304 int prevPrio = 0;
305 int prevPos = -1;
9709972d
PT
306 int discarded = 0;
307 int discardedTotal = 0;
c2fa72bc 308 for (int eventNb = 0; eventNb < evPerChan; eventNb++) {
9709972d
PT
309 if (EventWriter.SIZE > currentSpace) {
310 eventNb += discarded;
311 }
6e1f0a91 312 long ts = eventNb * delta + delta / (fNbChans + 1) * chan;
c2fa72bc
MK
313
314 int pos = rnd.nextInt((int) (fProcesses.size() * 1.5));
315 if (pos >= fProcesses.size()) {
316 pos = 0;
317 }
318 while (pos == prevPos) {
319 pos = rnd.nextInt((int) (fProcesses.size() * 1.5));
320 if (pos >= fProcesses.size()) {
321 pos = 0;
322 }
323 }
324 String nextComm = fProcesses.get(pos);
325 int nextPID = pos + fProcesses.size() * chan;
326 if (pos == 0) {
327 nextPID = 0;
328 }
329 int nextPrio = 0;
330 if (EventWriter.SIZE > currentSpace) {
331 // pad to end
332 for (int i = 0; i < currentSpace; i++) {
333 bb.put((byte) 0x00);
334 }
335 // write new packet
336 PacketWriter pw = new PacketWriter(bb);
6e1f0a91 337 long tsBegin = ts;
c2fa72bc 338 offsetTime = ts;
9709972d
PT
339 int eventCount = Math.min(evPerPacket, (int) evPerChan - eventNb);
340 discarded = rndLost.nextInt(10 * fNbChans) == 0 ? rndLost.nextInt(evPerPacket) : 0;
341 discarded = Math.min(discarded, (int) evPerChan - eventNb - eventCount);
342 discardedTotal += discarded;
343 long tsEnd = (eventNb + eventCount + discarded) * delta;
344 pw.writeNewHeader(tsBegin, tsEnd, chan, eventCount, discardedTotal);
c2fa72bc
MK
345 currentSpace = PacketWriter.CONTENT_SIZE;
346 }
347 EventWriter ew = new EventWriter(bb);
348 int prev_state = rnd.nextInt(100);
349 if (prev_state != 0) {
350 prev_state = 1;
351 }
6e1f0a91 352 final long shrunkenTimestamp = ts - offsetTime;
c2fa72bc
MK
353 final int tsMask = (1 << 27) - 1;
354 if (shrunkenTimestamp > ((1 << 27) + tsMask)) {
6e1f0a91
PT
355 /* allow only one compact timestamp overflow per packet */
356 throw new IllegalStateException("Invalid timestamp overflow:" + shrunkenTimestamp);
c2fa72bc 357 }
6e1f0a91 358 final int clampedTs = (int) (ts & tsMask);
c2fa72bc
MK
359 int evSize = ew.writeEvent(clampedTs, prevComm, prevPID, prevPrio, prev_state, nextComm, nextPID, nextPrio);
360 currentSpace -= evSize;
361 prevComm = nextComm;
362 prevPID = nextPID;
363 prevPrio = nextPrio;
364 if (bb.position() > 63000) {
365 writeToDisk(channels, chan, bb);
366 }
367 }
368 for (int i = 0; i < currentSpace; i++) {
369 bb.put((byte) 0x00);
370 }
371 writeToDisk(channels, chan, bb);
372 try {
373 channels[chan].close();
374 } catch (IOException e) {
375 e.printStackTrace();
376 }
377 }
05ce5fef 378 try (FileOutputStream fos = new FileOutputStream(metadataFile);) {
c2fa72bc 379 fos.write(metadata.getBytes());
c2fa72bc
MK
380 } catch (IOException e) {
381 }
382 }
383
83967946
PT
384 private static void deleteDirectory(File directory) {
385 try {
386 Files.walkFileTree(directory.toPath(), new SimpleFileVisitor<Path>() {
387 @Override
388 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
389 Files.delete(file);
390 return FileVisitResult.CONTINUE;
391 }
392
393 @Override
394 public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
4bbf01d7
MAL
395 // If a file failed to delete, it's more useful to throw this instead
396 if (exc != null) {
397 throw exc;
398 }
83967946
PT
399 Files.delete(dir);
400 return FileVisitResult.CONTINUE;
401 }
402 });
403 } catch (IOException e) {
404 e.printStackTrace();
405 }
406 }
407
c2fa72bc
MK
408 private static void writeToDisk(FileChannel[] channels, int chan, ByteBuffer bb) {
409 try {
410 bb.flip();
411 channels[chan].write(bb);
412 bb.clear();
413 } catch (IOException e) {
414 e.printStackTrace();
415 }
416 }
417
4eebea10
MAL
418 private static String getMetadataUST() {
419 String metadata = metadataKernel.replace("\"kernel\"", "\"ust\"");
420 return metadata.replace("lttng-modules", "lttng-ust");
421 }
422
c2fa72bc
MK
423 private class EventWriter {
424 public static final int SIZE =
425 4 + // timestamp
426 16 + // prev_comm
427 4 + // prev_tid
428 4 + // prev_prio
429 4 + // prev_state
430 16 + // current_comm
431 4 + // next_tid
432 4; // next_prio
433 private final ByteBuffer data;
434
435 public EventWriter(ByteBuffer bb) {
436 data = bb;
437 }
438
439 public int writeEvent(int ts, String prev_comm, int prev_tid, int prev_prio, int prev_state, String next_comm, int next_tid, int next_prio) {
440 byte[] bOut = new byte[16];
441 byte[] bIn = new byte[16];
442 byte[] temp = prev_comm.getBytes();
443 for (int i = 0; i < Math.min(temp.length, 16); i++) {
444 bOut[i] = temp[i];
445 }
446 temp = next_comm.getBytes();
447 for (int i = 0; i < Math.min(temp.length, 16); i++) {
448 bIn[i] = temp[i];
449 }
450
451 int timestamp = ts << 5;
452
453 data.putInt(timestamp);
454 data.put(bOut);
455 data.putInt(prev_tid);
456 data.putInt(prev_prio);
457 data.putInt(prev_state);
458 data.put(bIn);
459 data.putInt(next_tid);
460 data.putInt(next_prio);
461 return SIZE;
462 }
463
464 }
465
466 private class PacketWriter {
467 private static final int SIZE = 4096;
468 private static final int HEADER_SIZE = 64;
469 private static final int CONTENT_SIZE = SIZE - HEADER_SIZE;
470
471 private final ByteBuffer data;
472
473 public PacketWriter(ByteBuffer bb) {
474 data = bb;
475 }
476
9709972d 477 public void writeNewHeader(long tsBegin, long tsEnd, int cpu, int eventCount, int discarded) {
c2fa72bc
MK
478 final int magicLE = 0xC1FC1FC1;
479 byte uuid[] = {
480 0x11, 0x11, 0x11, 0x11,
481 0x11, 0x11, 0x11, 0x11,
482 0x11, 0x11, 0x11, 0x11,
483 0x11, 0x11, 0x11, 0x11 };
484 // packet header
485
486 // magic number 4
487 data.putInt(magicLE);
488 // uuid 16
489 data.put(uuid);
490 // stream ID 4
491 data.putInt(0);
492
493 // packet context
494 // timestamp_begin 8
495 data.putLong(tsBegin);
496
497 // timestamp_end 8
498 data.putLong(tsEnd);
499
500 // content_size 8
9709972d 501 data.putLong((eventCount * EventWriter.SIZE + HEADER_SIZE)* 8);
c2fa72bc
MK
502
503 // packet_size 8
504 data.putLong((SIZE) * 8);
505
506 // events_discarded 4
9709972d 507 data.putInt(discarded);
c2fa72bc
MK
508
509 // cpu_id 4
510 data.putInt(cpu);
511
512 }
513
514 }
515
516
517
518}
This page took 0.133965 seconds and 5 git commands to generate.