From: Marc-Andre Laperle Date: Thu, 25 Aug 2016 22:23:57 +0000 (-0400) Subject: ctf: Make LttngKernelTraceGenerator also generate UST test traces X-Git-Url: http://git.efficios.com/?a=commitdiff_plain;h=4eebea10fc57f4a28c45fcce0ce4f5a76b3d7932;p=deliverable%2Ftracecompass.git ctf: Make LttngKernelTraceGenerator also generate UST test traces LttngKernelTraceGenerator can currently only generate Kernel traces but with a few changes, it can generate a UST trace. The events do not make much sense for a UST trace but this is good enough for trace type validation, etc. Change-Id: I9826383c6d3cb2bdcb24895bbfa9990a75312a4b Signed-off-by: Marc-Andre Laperle Reviewed-on: https://git.eclipse.org/r/79780 Reviewed-by: Hudson CI Reviewed-by: Matthew Khouzam Tested-by: Matthew Khouzam --- diff --git a/ctf/org.eclipse.tracecompass.ctf.core.tests/shared/org/eclipse/tracecompass/ctf/core/tests/shared/LttngKernelTraceGenerator.java b/ctf/org.eclipse.tracecompass.ctf.core.tests/shared/org/eclipse/tracecompass/ctf/core/tests/shared/LttngKernelTraceGenerator.java deleted file mode 100644 index 27df0b9e30..0000000000 --- a/ctf/org.eclipse.tracecompass.ctf.core.tests/shared/org/eclipse/tracecompass/ctf/core/tests/shared/LttngKernelTraceGenerator.java +++ /dev/null @@ -1,490 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2013, 2015 Ericsson - * - * All rights reserved. This program and the accompanying materials are - * made available under the terms of the Eclipse Public License v1.0 which - * accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Matthew Khouzam - Initial API and implementation - * Marc-Andre Laperle - Move generation to traces folder - *******************************************************************************/ - -package org.eclipse.tracecompass.ctf.core.tests.shared; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.channels.FileChannel; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.Arrays; -import java.util.List; -import java.util.Random; - -import org.eclipse.tracecompass.ctf.core.tests.CtfCoreTestPlugin; - -/** - * Generate a kernel trace - * - * @author Matthew Khouzam - */ -public class LttngKernelTraceGenerator { - - private static final String metadata = "/* CTF 1.8 */ \n" + - "typealias integer { size = 8; align = 8; signed = false; } := uint8_t;\n" + - "typealias integer { size = 16; align = 8; signed = false; } := uint16_t;\n" + - "typealias integer { size = 32; align = 8; signed = false; } := uint32_t;\n" + - "typealias integer { size = 64; align = 8; signed = false; } := uint64_t;\n" + - "typealias integer { size = 32; align = 8; signed = false; } := unsigned long;\n" + - "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" + - "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" + - "\n" + - "trace {\n" + - " major = 1;\n" + - " minor = 8;\n" + - " uuid = \"11111111-1111-1111-1111-111111111111\";\n" + - " byte_order = le;\n" + - " packet.header := struct {\n" + - " uint32_t magic;\n" + - " uint8_t uuid[16];\n" + - " uint32_t stream_id;\n" + - " };\n" + - "};\n" + - "\n" + - "env {\n" + - " hostname = \"synthetic-host\";\n" + - " domain = \"kernel\";\n" + - " sysname = \"FakeLinux\";\n" + - " kernel_release = \"1.0\";\n" + - " kernel_version = \"Fake Os Synthetic Trace\";\n" + - " tracer_name = \"lttng-modules\";\n" + - " tracer_major = 2;\n" + - " tracer_minor = 1;\n" + - " tracer_patchlevel = 0;\n" + - "};\n" + - "\n" + - "clock {\n" + - " name = monotonic;\n" + - " uuid = \"bbff68f0-c633-4ea1-92cd-bd11024ec4de\";\n" + - " description = \"Monotonic Clock\";\n" + - " freq = 1000000000; /* Frequency, in Hz */\n" + - " /* clock value offset from Epoch is: offset * (1/freq) */\n" + - " offset = 1368000272650993664;\n" + - "};\n" + - "\n" + - "typealias integer {\n" + - " size = 27; align = 1; signed = false;\n" + - " map = clock.monotonic.value;\n" + - "} := uint27_clock_monotonic_t;\n" + - "\n" + - "typealias integer {\n" + - " size = 32; align = 8; signed = false;\n" + - " map = clock.monotonic.value;\n" + - "} := uint32_clock_monotonic_t;\n" + - "\n" + - "typealias integer {\n" + - " size = 64; align = 8; signed = false;\n" + - " map = clock.monotonic.value;\n" + - "} := uint64_clock_monotonic_t;\n" + - "\n" + - "struct packet_context {\n" + - " uint64_clock_monotonic_t timestamp_begin;\n" + - " uint64_clock_monotonic_t timestamp_end;\n" + - " uint64_t content_size;\n" + - " uint64_t packet_size;\n" + - " unsigned long events_discarded;\n" + - " uint32_t cpu_id;\n" + - "};\n" + - "\n" + - "struct event_header_compact {\n" + - " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" + - " variant {\n" + - " struct {\n" + - " uint27_clock_monotonic_t timestamp;\n" + - " } compact;\n" + - " struct {\n" + - " uint32_t id;\n" + - " uint64_clock_monotonic_t timestamp;\n" + - " } extended;\n" + - " } v;\n" + - "} align(8);\n" + - "\n" + - "struct event_header_large {\n" + - " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" + - " variant {\n" + - " struct {\n" + - " uint32_clock_monotonic_t timestamp;\n" + - " } compact;\n" + - " struct {\n" + - " uint32_t id;\n" + - " uint64_clock_monotonic_t timestamp;\n" + - " } extended;\n" + - " } v;\n" + - "} align(8);\n" + - "\n" + - "stream {\n" + - " id = 0;\n" + - " event.header := struct event_header_compact;\n" + - " packet.context := struct packet_context;\n" + - "};\n" + - "\n" + - "event {\n" + - " name = sched_switch;\n" + - " id = 0;\n" + - " stream_id = 0;\n" + - " fields := struct {\n" + - " integer { size = 8; align = 8; signed = 1; encoding = UTF8; base = 10; } _prev_comm[16];\n" + - " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_tid;\n" + - " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_prio;\n" + - " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_state;\n" + - " integer { size = 8; align = 8; signed = 1; encoding = UTF8; base = 10; } _next_comm[16];\n" + - " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _next_tid;\n" + - " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _next_prio;\n" + - " };\n" + - "};\n" + - "\n"; - - private final List fProcesses; - private final long fDuration; - private final long fNbEvents; - private final int fNbChans; - - private static final String[] sfProcesses = { - "IDLE", - "gnuplot", - "starcraft 2:pt3", - "bash", - "smash", - "thrash", - "fireball", - "Half-life 3", - "ST: The game" - }; - - - private static final String TRACES_DIRECTORY = "traces"; - private static final String TRACE_NAME = "synthetic-trace"; - - /** - * Main, not always needed - * - * @param args - * args - */ - public static void main(String[] args) { - // not using createTempFile as this is a directory - String path = CtfCoreTestPlugin.getTemporaryDirPath() + File.separator + TRACE_NAME; - generateLttngKernelTrace(new File(path)); - } - - /** - * Gets the name of the trace (top directory name) - * - * @return the name of the trace - */ - public static String getName() { - return TRACE_NAME; - } - - /** - * Get the path - * - * @return the path - */ - public static String getPath() { - CtfCoreTestPlugin plugin = CtfCoreTestPlugin.getDefault(); - if (plugin == null) { - return null; - } - Path tracePath = Paths.get("..", "..", "ctf", "org.eclipse.tracecompass.ctf.core.tests", TRACES_DIRECTORY, TRACE_NAME); - tracePath = tracePath.toAbsolutePath(); - File file = tracePath.toFile(); - generateLttngKernelTrace(file); - return file.getAbsolutePath(); - } - - /** - * Generate a trace - * - * @param file - * the file to write the trace to - */ - public static void generateLttngKernelTrace(File file) { - final int cpus = 25; - LttngKernelTraceGenerator gt = new LttngKernelTraceGenerator(2l * Integer.MAX_VALUE - 100, 500000, cpus); - gt.writeTrace(file); - } - - /** - * Make a kernel trace - * - * @param duration - * the duration of the trace - * @param events - * the number of events in a trace - * @param nbChannels - * the number of channels in the trace - */ - public LttngKernelTraceGenerator(long duration, long events, int nbChannels) { - fProcesses = Arrays.asList(sfProcesses); - fDuration = duration; - fNbEvents = events; - fNbChans = nbChannels; - } - - /** - * Write the trace to a file - * - * @param file - * the file to write the trace to - */ - public void writeTrace(File file) { - - if (file.exists()) { - deleteDirectory(file); - } - file.mkdir(); - - File metadataFile = new File(file.getPath() + File.separator + "metadata"); - File[] streams = new File[fNbChans]; - FileChannel[] channels = new FileChannel[fNbChans]; - - try { - for (int i = 0; i < fNbChans; i++) { - streams[i] = new File(file.getPath() + File.separator + "channel" + i); - channels[i] = new FileOutputStream(streams[i]).getChannel(); - } - } catch (FileNotFoundException e) { - } - // determine the number of events per channel - long evPerChan = fNbEvents / fNbChans; - final int evPerPacket = PacketWriter.CONTENT_SIZE / EventWriter.SIZE; - long delta = (int) (fDuration / evPerChan); - long offsetTime = 0; - Random rndLost = new Random(1337); - for (int chan = 0; chan < fNbChans; chan++) { - int currentSpace = 0; - ByteBuffer bb = ByteBuffer.allocate(65536); - bb.order(ByteOrder.LITTLE_ENDIAN); - Random rnd = new Random(1337); - int rnd0 = rnd.nextInt(fProcesses.size()); - String prevComm = fProcesses.get(rnd0); - int prevPID = rnd0 + chan * fProcesses.size(); - if (rnd0 == 0) { - prevPID = 0; - } - int prevPrio = 0; - int prevPos = -1; - int discarded = 0; - int discardedTotal = 0; - for (int eventNb = 0; eventNb < evPerChan; eventNb++) { - if (EventWriter.SIZE > currentSpace) { - eventNb += discarded; - } - long ts = eventNb * delta + delta / (fNbChans + 1) * chan; - - int pos = rnd.nextInt((int) (fProcesses.size() * 1.5)); - if (pos >= fProcesses.size()) { - pos = 0; - } - while (pos == prevPos) { - pos = rnd.nextInt((int) (fProcesses.size() * 1.5)); - if (pos >= fProcesses.size()) { - pos = 0; - } - } - String nextComm = fProcesses.get(pos); - int nextPID = pos + fProcesses.size() * chan; - if (pos == 0) { - nextPID = 0; - } - int nextPrio = 0; - if (EventWriter.SIZE > currentSpace) { - // pad to end - for (int i = 0; i < currentSpace; i++) { - bb.put((byte) 0x00); - } - // write new packet - PacketWriter pw = new PacketWriter(bb); - long tsBegin = ts; - offsetTime = ts; - int eventCount = Math.min(evPerPacket, (int) evPerChan - eventNb); - discarded = rndLost.nextInt(10 * fNbChans) == 0 ? rndLost.nextInt(evPerPacket) : 0; - discarded = Math.min(discarded, (int) evPerChan - eventNb - eventCount); - discardedTotal += discarded; - long tsEnd = (eventNb + eventCount + discarded) * delta; - pw.writeNewHeader(tsBegin, tsEnd, chan, eventCount, discardedTotal); - currentSpace = PacketWriter.CONTENT_SIZE; - } - EventWriter ew = new EventWriter(bb); - int prev_state = rnd.nextInt(100); - if (prev_state != 0) { - prev_state = 1; - } - final long shrunkenTimestamp = ts - offsetTime; - final int tsMask = (1 << 27) - 1; - if (shrunkenTimestamp > ((1 << 27) + tsMask)) { - /* allow only one compact timestamp overflow per packet */ - throw new IllegalStateException("Invalid timestamp overflow:" + shrunkenTimestamp); - } - final int clampedTs = (int) (ts & tsMask); - int evSize = ew.writeEvent(clampedTs, prevComm, prevPID, prevPrio, prev_state, nextComm, nextPID, nextPrio); - currentSpace -= evSize; - prevComm = nextComm; - prevPID = nextPID; - prevPrio = nextPrio; - if (bb.position() > 63000) { - writeToDisk(channels, chan, bb); - } - } - for (int i = 0; i < currentSpace; i++) { - bb.put((byte) 0x00); - } - writeToDisk(channels, chan, bb); - try { - channels[chan].close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - try (FileOutputStream fos = new FileOutputStream(metadataFile);) { - fos.write(metadata.getBytes()); - } catch (IOException e) { - } - } - - private static void deleteDirectory(File directory) { - try { - Files.walkFileTree(directory.toPath(), new SimpleFileVisitor() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Files.delete(file); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - }); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private static void writeToDisk(FileChannel[] channels, int chan, ByteBuffer bb) { - try { - bb.flip(); - channels[chan].write(bb); - bb.clear(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private class EventWriter { - public static final int SIZE = - 4 + // timestamp - 16 + // prev_comm - 4 + // prev_tid - 4 + // prev_prio - 4 + // prev_state - 16 + // current_comm - 4 + // next_tid - 4; // next_prio - private final ByteBuffer data; - - public EventWriter(ByteBuffer bb) { - data = bb; - } - - 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) { - byte[] bOut = new byte[16]; - byte[] bIn = new byte[16]; - byte[] temp = prev_comm.getBytes(); - for (int i = 0; i < Math.min(temp.length, 16); i++) { - bOut[i] = temp[i]; - } - temp = next_comm.getBytes(); - for (int i = 0; i < Math.min(temp.length, 16); i++) { - bIn[i] = temp[i]; - } - - int timestamp = ts << 5; - - data.putInt(timestamp); - data.put(bOut); - data.putInt(prev_tid); - data.putInt(prev_prio); - data.putInt(prev_state); - data.put(bIn); - data.putInt(next_tid); - data.putInt(next_prio); - return SIZE; - } - - } - - private class PacketWriter { - private static final int SIZE = 4096; - private static final int HEADER_SIZE = 64; - private static final int CONTENT_SIZE = SIZE - HEADER_SIZE; - - private final ByteBuffer data; - - public PacketWriter(ByteBuffer bb) { - data = bb; - } - - public void writeNewHeader(long tsBegin, long tsEnd, int cpu, int eventCount, int discarded) { - final int magicLE = 0xC1FC1FC1; - byte uuid[] = { - 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11, - 0x11, 0x11, 0x11, 0x11 }; - // packet header - - // magic number 4 - data.putInt(magicLE); - // uuid 16 - data.put(uuid); - // stream ID 4 - data.putInt(0); - - // packet context - // timestamp_begin 8 - data.putLong(tsBegin); - - // timestamp_end 8 - data.putLong(tsEnd); - - // content_size 8 - data.putLong((eventCount * EventWriter.SIZE + HEADER_SIZE)* 8); - - // packet_size 8 - data.putLong((SIZE) * 8); - - // events_discarded 4 - data.putInt(discarded); - - // cpu_id 4 - data.putInt(cpu); - - } - - } - - - -} diff --git a/ctf/org.eclipse.tracecompass.ctf.core.tests/shared/org/eclipse/tracecompass/ctf/core/tests/shared/LttngTraceGenerator.java b/ctf/org.eclipse.tracecompass.ctf.core.tests/shared/org/eclipse/tracecompass/ctf/core/tests/shared/LttngTraceGenerator.java new file mode 100644 index 0000000000..a953787437 --- /dev/null +++ b/ctf/org.eclipse.tracecompass.ctf.core.tests/shared/org/eclipse/tracecompass/ctf/core/tests/shared/LttngTraceGenerator.java @@ -0,0 +1,514 @@ +/******************************************************************************* + * Copyright (c) 2013, 2017 Ericsson + * + * All rights reserved. This program and the accompanying materials are + * made available under the terms of the Eclipse Public License v1.0 which + * accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthew Khouzam - Initial API and implementation + * Marc-Andre Laperle - Move generation to traces folder + *******************************************************************************/ + +package org.eclipse.tracecompass.ctf.core.tests.shared; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.channels.FileChannel; +import java.nio.file.FileVisitResult; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.SimpleFileVisitor; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import org.eclipse.tracecompass.ctf.core.tests.CtfCoreTestPlugin; + +/** + * Generate a lttng trace (kernel or ust) + * + * @author Matthew Khouzam + */ +public class LttngTraceGenerator { + + private static final String metadataKernel = "/* CTF 1.8 */ \n" + + "typealias integer { size = 8; align = 8; signed = false; } := uint8_t;\n" + + "typealias integer { size = 16; align = 8; signed = false; } := uint16_t;\n" + + "typealias integer { size = 32; align = 8; signed = false; } := uint32_t;\n" + + "typealias integer { size = 64; align = 8; signed = false; } := uint64_t;\n" + + "typealias integer { size = 32; align = 8; signed = false; } := unsigned long;\n" + + "typealias integer { size = 5; align = 1; signed = false; } := uint5_t;\n" + + "typealias integer { size = 27; align = 1; signed = false; } := uint27_t;\n" + + "\n" + + "trace {\n" + + " major = 1;\n" + + " minor = 8;\n" + + " uuid = \"11111111-1111-1111-1111-111111111111\";\n" + + " byte_order = le;\n" + + " packet.header := struct {\n" + + " uint32_t magic;\n" + + " uint8_t uuid[16];\n" + + " uint32_t stream_id;\n" + + " };\n" + + "};\n" + + "\n" + + "env {\n" + + " hostname = \"synthetic-host\";\n" + + " domain = \"kernel\";\n" + + " sysname = \"FakeLinux\";\n" + + " kernel_release = \"1.0\";\n" + + " kernel_version = \"Fake Os Synthetic Trace\";\n" + + " tracer_name = \"lttng-modules\";\n" + + " tracer_major = 2;\n" + + " tracer_minor = 1;\n" + + " tracer_patchlevel = 0;\n" + + "};\n" + + "\n" + + "clock {\n" + + " name = monotonic;\n" + + " uuid = \"bbff68f0-c633-4ea1-92cd-bd11024ec4de\";\n" + + " description = \"Monotonic Clock\";\n" + + " freq = 1000000000; /* Frequency, in Hz */\n" + + " /* clock value offset from Epoch is: offset * (1/freq) */\n" + + " offset = 1368000272650993664;\n" + + "};\n" + + "\n" + + "typealias integer {\n" + + " size = 27; align = 1; signed = false;\n" + + " map = clock.monotonic.value;\n" + + "} := uint27_clock_monotonic_t;\n" + + "\n" + + "typealias integer {\n" + + " size = 32; align = 8; signed = false;\n" + + " map = clock.monotonic.value;\n" + + "} := uint32_clock_monotonic_t;\n" + + "\n" + + "typealias integer {\n" + + " size = 64; align = 8; signed = false;\n" + + " map = clock.monotonic.value;\n" + + "} := uint64_clock_monotonic_t;\n" + + "\n" + + "struct packet_context {\n" + + " uint64_clock_monotonic_t timestamp_begin;\n" + + " uint64_clock_monotonic_t timestamp_end;\n" + + " uint64_t content_size;\n" + + " uint64_t packet_size;\n" + + " unsigned long events_discarded;\n" + + " uint32_t cpu_id;\n" + + "};\n" + + "\n" + + "struct event_header_compact {\n" + + " enum : uint5_t { compact = 0 ... 30, extended = 31 } id;\n" + + " variant {\n" + + " struct {\n" + + " uint27_clock_monotonic_t timestamp;\n" + + " } compact;\n" + + " struct {\n" + + " uint32_t id;\n" + + " uint64_clock_monotonic_t timestamp;\n" + + " } extended;\n" + + " } v;\n" + + "} align(8);\n" + + "\n" + + "struct event_header_large {\n" + + " enum : uint16_t { compact = 0 ... 65534, extended = 65535 } id;\n" + + " variant {\n" + + " struct {\n" + + " uint32_clock_monotonic_t timestamp;\n" + + " } compact;\n" + + " struct {\n" + + " uint32_t id;\n" + + " uint64_clock_monotonic_t timestamp;\n" + + " } extended;\n" + + " } v;\n" + + "} align(8);\n" + + "\n" + + "stream {\n" + + " id = 0;\n" + + " event.header := struct event_header_compact;\n" + + " packet.context := struct packet_context;\n" + + "};\n" + + "\n" + + "event {\n" + + " name = sched_switch;\n" + + " id = 0;\n" + + " stream_id = 0;\n" + + " fields := struct {\n" + + " integer { size = 8; align = 8; signed = 1; encoding = UTF8; base = 10; } _prev_comm[16];\n" + + " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_tid;\n" + + " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_prio;\n" + + " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _prev_state;\n" + + " integer { size = 8; align = 8; signed = 1; encoding = UTF8; base = 10; } _next_comm[16];\n" + + " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _next_tid;\n" + + " integer { size = 32; align = 8; signed = 1; encoding = none; base = 10; } _next_prio;\n" + + " };\n" + + "};\n" + + "\n"; + + private final List fProcesses; + private final long fDuration; + private final long fNbEvents; + private final int fNbChans; + + private final String metadata; + + private static final String[] sfProcesses = { + "IDLE", + "gnuplot", + "starcraft 2:pt3", + "bash", + "smash", + "thrash", + "fireball", + "Half-life 3", + "ST: The game" + }; + + + private static final String TRACES_DIRECTORY = "traces"; + private static final String TRACE_NAME = "synthetic-trace"; + + /** + * Main, not always needed + * + * @param args + * args + */ + public static void main(String[] args) { + // not using createTempFile as this is a directory + String path = CtfCoreTestPlugin.getTemporaryDirPath() + File.separator + TRACE_NAME; + generateLttngTrace(new File(path)); + } + + /** + * Gets the name of the trace (top directory name) + * + * @return the name of the trace + */ + public static String getName() { + return TRACE_NAME; + } + + /** + * Get the path + * + * @return the path + */ + public static String getPath() { + CtfCoreTestPlugin plugin = CtfCoreTestPlugin.getDefault(); + if (plugin == null) { + return null; + } + Path tracePath = Paths.get("..", "..", "ctf", "org.eclipse.tracecompass.ctf.core.tests", TRACES_DIRECTORY, TRACE_NAME); + tracePath = tracePath.toAbsolutePath(); + File file = tracePath.toFile(); + generateLttngTrace(file); + return file.getAbsolutePath(); + } + + /** + * Generate a trace + * + * @param file + * the file to write the trace to + */ + public static void generateLttngTrace(File file) { + final int cpus = 25; + LttngTraceGenerator gt = new LttngTraceGenerator(2l * Integer.MAX_VALUE - 100, 500000, cpus); + gt.writeTrace(file); + } + + /** + * Make a lttng trace + * + * @param duration + * the duration of the trace + * @param events + * the number of events in a trace + * @param nbChannels + * the number of channels in the trace + */ + public LttngTraceGenerator(long duration, long events, int nbChannels) { + this(duration, events, nbChannels, true); + } + + /** + * Make a lttng trace + * + * @param duration + * the duration of the trace + * @param events + * the number of events in a trace + * @param nbChannels + * the number of channels in the trace + * @param isKernel + * true for kernel, false for ust + */ + public LttngTraceGenerator(long duration, long events, int nbChannels, boolean isKernel) { + fProcesses = Arrays.asList(sfProcesses); + fDuration = duration; + fNbEvents = events; + fNbChans = nbChannels; + metadata = isKernel ? metadataKernel : getMetadataUST(); + } + + /** + * Write the trace to a file + * + * @param file + * the file to write the trace to + */ + public void writeTrace(File file) { + + if (file.exists()) { + deleteDirectory(file); + } + file.mkdir(); + + File metadataFile = new File(file.getPath() + File.separator + "metadata"); + File[] streams = new File[fNbChans]; + FileChannel[] channels = new FileChannel[fNbChans]; + + try { + for (int i = 0; i < fNbChans; i++) { + streams[i] = new File(file.getPath() + File.separator + "channel" + i); + channels[i] = new FileOutputStream(streams[i]).getChannel(); + } + } catch (FileNotFoundException e) { + } + // determine the number of events per channel + long evPerChan = fNbEvents / fNbChans; + final int evPerPacket = PacketWriter.CONTENT_SIZE / EventWriter.SIZE; + long delta = (int) (fDuration / evPerChan); + long offsetTime = 0; + Random rndLost = new Random(1337); + for (int chan = 0; chan < fNbChans; chan++) { + int currentSpace = 0; + ByteBuffer bb = ByteBuffer.allocate(65536); + bb.order(ByteOrder.LITTLE_ENDIAN); + Random rnd = new Random(1337); + int rnd0 = rnd.nextInt(fProcesses.size()); + String prevComm = fProcesses.get(rnd0); + int prevPID = rnd0 + chan * fProcesses.size(); + if (rnd0 == 0) { + prevPID = 0; + } + int prevPrio = 0; + int prevPos = -1; + int discarded = 0; + int discardedTotal = 0; + for (int eventNb = 0; eventNb < evPerChan; eventNb++) { + if (EventWriter.SIZE > currentSpace) { + eventNb += discarded; + } + long ts = eventNb * delta + delta / (fNbChans + 1) * chan; + + int pos = rnd.nextInt((int) (fProcesses.size() * 1.5)); + if (pos >= fProcesses.size()) { + pos = 0; + } + while (pos == prevPos) { + pos = rnd.nextInt((int) (fProcesses.size() * 1.5)); + if (pos >= fProcesses.size()) { + pos = 0; + } + } + String nextComm = fProcesses.get(pos); + int nextPID = pos + fProcesses.size() * chan; + if (pos == 0) { + nextPID = 0; + } + int nextPrio = 0; + if (EventWriter.SIZE > currentSpace) { + // pad to end + for (int i = 0; i < currentSpace; i++) { + bb.put((byte) 0x00); + } + // write new packet + PacketWriter pw = new PacketWriter(bb); + long tsBegin = ts; + offsetTime = ts; + int eventCount = Math.min(evPerPacket, (int) evPerChan - eventNb); + discarded = rndLost.nextInt(10 * fNbChans) == 0 ? rndLost.nextInt(evPerPacket) : 0; + discarded = Math.min(discarded, (int) evPerChan - eventNb - eventCount); + discardedTotal += discarded; + long tsEnd = (eventNb + eventCount + discarded) * delta; + pw.writeNewHeader(tsBegin, tsEnd, chan, eventCount, discardedTotal); + currentSpace = PacketWriter.CONTENT_SIZE; + } + EventWriter ew = new EventWriter(bb); + int prev_state = rnd.nextInt(100); + if (prev_state != 0) { + prev_state = 1; + } + final long shrunkenTimestamp = ts - offsetTime; + final int tsMask = (1 << 27) - 1; + if (shrunkenTimestamp > ((1 << 27) + tsMask)) { + /* allow only one compact timestamp overflow per packet */ + throw new IllegalStateException("Invalid timestamp overflow:" + shrunkenTimestamp); + } + final int clampedTs = (int) (ts & tsMask); + int evSize = ew.writeEvent(clampedTs, prevComm, prevPID, prevPrio, prev_state, nextComm, nextPID, nextPrio); + currentSpace -= evSize; + prevComm = nextComm; + prevPID = nextPID; + prevPrio = nextPrio; + if (bb.position() > 63000) { + writeToDisk(channels, chan, bb); + } + } + for (int i = 0; i < currentSpace; i++) { + bb.put((byte) 0x00); + } + writeToDisk(channels, chan, bb); + try { + channels[chan].close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + try (FileOutputStream fos = new FileOutputStream(metadataFile);) { + fos.write(metadata.getBytes()); + } catch (IOException e) { + } + } + + private static void deleteDirectory(File directory) { + try { + Files.walkFileTree(directory.toPath(), new SimpleFileVisitor() { + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + Files.delete(file); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + Files.delete(dir); + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static void writeToDisk(FileChannel[] channels, int chan, ByteBuffer bb) { + try { + bb.flip(); + channels[chan].write(bb); + bb.clear(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + private static String getMetadataUST() { + String metadata = metadataKernel.replace("\"kernel\"", "\"ust\""); + return metadata.replace("lttng-modules", "lttng-ust"); + } + + private class EventWriter { + public static final int SIZE = + 4 + // timestamp + 16 + // prev_comm + 4 + // prev_tid + 4 + // prev_prio + 4 + // prev_state + 16 + // current_comm + 4 + // next_tid + 4; // next_prio + private final ByteBuffer data; + + public EventWriter(ByteBuffer bb) { + data = bb; + } + + 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) { + byte[] bOut = new byte[16]; + byte[] bIn = new byte[16]; + byte[] temp = prev_comm.getBytes(); + for (int i = 0; i < Math.min(temp.length, 16); i++) { + bOut[i] = temp[i]; + } + temp = next_comm.getBytes(); + for (int i = 0; i < Math.min(temp.length, 16); i++) { + bIn[i] = temp[i]; + } + + int timestamp = ts << 5; + + data.putInt(timestamp); + data.put(bOut); + data.putInt(prev_tid); + data.putInt(prev_prio); + data.putInt(prev_state); + data.put(bIn); + data.putInt(next_tid); + data.putInt(next_prio); + return SIZE; + } + + } + + private class PacketWriter { + private static final int SIZE = 4096; + private static final int HEADER_SIZE = 64; + private static final int CONTENT_SIZE = SIZE - HEADER_SIZE; + + private final ByteBuffer data; + + public PacketWriter(ByteBuffer bb) { + data = bb; + } + + public void writeNewHeader(long tsBegin, long tsEnd, int cpu, int eventCount, int discarded) { + final int magicLE = 0xC1FC1FC1; + byte uuid[] = { + 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11 }; + // packet header + + // magic number 4 + data.putInt(magicLE); + // uuid 16 + data.put(uuid); + // stream ID 4 + data.putInt(0); + + // packet context + // timestamp_begin 8 + data.putLong(tsBegin); + + // timestamp_end 8 + data.putLong(tsEnd); + + // content_size 8 + data.putLong((eventCount * EventWriter.SIZE + HEADER_SIZE)* 8); + + // packet_size 8 + data.putLong((SIZE) * 8); + + // events_discarded 4 + data.putInt(discarded); + + // cpu_id 4 + data.putInt(cpu); + + } + + } + + + +} diff --git a/ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFTraceGrowingTest.java b/ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFTraceGrowingTest.java index b2a721a4e2..2ee963e89d 100644 --- a/ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFTraceGrowingTest.java +++ b/ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFTraceGrowingTest.java @@ -25,7 +25,7 @@ import java.io.InputStreamReader; import org.eclipse.tracecompass.ctf.core.CTFException; import org.eclipse.tracecompass.ctf.core.event.IEventDefinition; -import org.eclipse.tracecompass.ctf.core.tests.shared.LttngKernelTraceGenerator; +import org.eclipse.tracecompass.ctf.core.tests.shared.LttngTraceGenerator; import org.eclipse.tracecompass.ctf.core.trace.CTFTrace; import org.eclipse.tracecompass.ctf.core.trace.CTFTraceReader; import org.eclipse.tracecompass.ctf.core.trace.Metadata; @@ -40,7 +40,7 @@ import org.junit.Test; */ public class CTFTraceGrowingTest { - private final String fPathName = LttngKernelTraceGenerator.getPath(); + private final String fPathName = LttngTraceGenerator.getPath(); private final CTFTrace fixture = new CTFTrace(); /** diff --git a/ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/shared/org/eclipse/tracecompass/tmf/ctf/core/tests/shared/CtfTmfTestTraceUtils.java b/ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/shared/org/eclipse/tracecompass/tmf/ctf/core/tests/shared/CtfTmfTestTraceUtils.java index f29f919f22..d627c675f1 100644 --- a/ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/shared/org/eclipse/tracecompass/tmf/ctf/core/tests/shared/CtfTmfTestTraceUtils.java +++ b/ctf/org.eclipse.tracecompass.tmf.ctf.core.tests/shared/org/eclipse/tracecompass/tmf/ctf/core/tests/shared/CtfTmfTestTraceUtils.java @@ -15,7 +15,7 @@ import java.util.Map; import org.eclipse.core.runtime.FileLocator; import org.eclipse.jdt.annotation.NonNullByDefault; -import org.eclipse.tracecompass.ctf.core.tests.shared.LttngKernelTraceGenerator; +import org.eclipse.tracecompass.ctf.core.tests.shared.LttngTraceGenerator; import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace; import org.eclipse.tracecompass.tmf.core.exceptions.TmfTraceException; import org.eclipse.tracecompass.tmf.ctf.core.event.CtfTmfEvent; @@ -87,7 +87,7 @@ public final class CtfTmfTestTraceUtils { public static CtfTmfTrace getSyntheticTrace() { CtfTmfTrace trace = new CtfTmfTrace(); try { - trace.initTrace(null, LttngKernelTraceGenerator.getPath(), CtfTmfEvent.class); + trace.initTrace(null, LttngTraceGenerator.getPath(), CtfTmfEvent.class); } catch (TmfTraceException e) { throw new IllegalStateException(); } diff --git a/lttng/org.eclipse.tracecompass.lttng2.control.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/control/ui/swtbot/tests/ControlViewTest.java b/lttng/org.eclipse.tracecompass.lttng2.control.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/control/ui/swtbot/tests/ControlViewTest.java index 9079678778..8343f95374 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.control.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/control/ui/swtbot/tests/ControlViewTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.control.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/control/ui/swtbot/tests/ControlViewTest.java @@ -40,7 +40,7 @@ import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; -import org.eclipse.tracecompass.ctf.core.tests.shared.LttngKernelTraceGenerator; +import org.eclipse.tracecompass.ctf.core.tests.shared.LttngTraceGenerator; import org.eclipse.tracecompass.internal.lttng2.control.core.model.TargetNodeState; import org.eclipse.tracecompass.internal.lttng2.control.core.model.TraceSessionState; import org.eclipse.tracecompass.internal.lttng2.control.stubs.service.TestRemoteSystemProxy; @@ -651,7 +651,7 @@ public class ControlViewTest { private static void generateTrace(IPath path) { File traceParent = path.toFile(); traceParent.mkdirs(); - LttngKernelTraceGenerator.generateLttngKernelTrace(path.append(ControlViewSwtBotUtil.KERNEL_TRACE_NAME).toFile()); + LttngTraceGenerator.generateLttngTrace(path.append(ControlViewSwtBotUtil.KERNEL_TRACE_NAME).toFile()); } private static void closeImportWizard(SWTBotShell shell, String buttonName) { diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java index 46121f8f11..1ce0a6cb48 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/ControlFlowViewTest.java @@ -31,7 +31,7 @@ import org.eclipse.swtbot.swt.finder.widgets.SWTBotLabel; import org.eclipse.swtbot.swt.finder.widgets.SWTBotToolbarButton; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; -import org.eclipse.tracecompass.ctf.core.tests.shared.LttngKernelTraceGenerator; +import org.eclipse.tracecompass.ctf.core.tests.shared.LttngTraceGenerator; import org.eclipse.tracecompass.tmf.core.signal.TmfSelectionRangeUpdatedSignal; import org.eclipse.tracecompass.tmf.core.signal.TmfSignalManager; import org.eclipse.tracecompass.tmf.core.signal.TmfWindowRangeUpdatedSignal; @@ -275,7 +275,7 @@ public class ControlFlowViewTest extends KernelTestBase { checked = UIThreadRunnable.syncExec(treeCheckCounter); assertEquals(UNCHECK_INACTIVE, 69, checked.intValue()); // test check selected - treeBot.getTreeItem(LttngKernelTraceGenerator.getName()).select("gnuplot"); + treeBot.getTreeItem(LttngTraceGenerator.getName()).select("gnuplot"); bot.button(UNCHECK_ALL).click(); bot.button(CHECK_SELECTED).click(); checked = UIThreadRunnable.syncExec(treeCheckCounter); @@ -300,7 +300,7 @@ public class ControlFlowViewTest extends KernelTestBase { checked = UIThreadRunnable.syncExec(treeCheckCounter); assertEquals(0, checked.intValue()); bot.text().setText("half-life 3"); - SWTBotTreeItem treeItem = treeBot.getTreeItem(LttngKernelTraceGenerator.getName()); + SWTBotTreeItem treeItem = treeBot.getTreeItem(LttngTraceGenerator.getName()); treeItem.rowCount(); fBot.waitUntil(ConditionHelpers.treeItemCount(treeItem, 25)); bot.button(CHECK_ALL).click(); @@ -308,7 +308,7 @@ public class ControlFlowViewTest extends KernelTestBase { assertEquals("Filtered", 26, checked.intValue()); bot.button("OK").click(); treeBot = fViewBot.bot().tree(); - treeItem = treeBot.getTreeItem(LttngKernelTraceGenerator.getName()); + treeItem = treeBot.getTreeItem(LttngTraceGenerator.getName()); for (int i = 0; i < 25; i++) { assertEquals("Filtered Control flow view", "Half-life 3", treeItem.cell(i, 0)); } diff --git a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelTestBase.java b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelTestBase.java index 1e3605f6d4..4d3d6b9e57 100644 --- a/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelTestBase.java +++ b/lttng/org.eclipse.tracecompass.lttng2.kernel.ui.swtbot.tests/src/org/eclipse/tracecompass/lttng2/kernel/ui/swtbot/tests/KernelTestBase.java @@ -30,7 +30,7 @@ import org.eclipse.swtbot.swt.finder.results.BoolResult; import org.eclipse.swtbot.swt.finder.results.Result; import org.eclipse.swtbot.swt.finder.utils.SWTBotPreferences; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; -import org.eclipse.tracecompass.ctf.core.tests.shared.LttngKernelTraceGenerator; +import org.eclipse.tracecompass.ctf.core.tests.shared.LttngTraceGenerator; import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.ConditionHelpers; import org.eclipse.tracecompass.tmf.ui.swtbot.tests.shared.SWTBotUtils; import org.eclipse.ui.PlatformUI; @@ -125,8 +125,8 @@ public abstract class KernelTestBase { */ @Before public void before() { - SWTBotUtils.openTrace(TRACE_PROJECT_NAME, LttngKernelTraceGenerator.getPath(), KERNEL_TRACE_TYPE); - SWTBotUtils.activateEditor(fBot, LttngKernelTraceGenerator.getName()); + SWTBotUtils.openTrace(TRACE_PROJECT_NAME, LttngTraceGenerator.getPath(), KERNEL_TRACE_TYPE); + SWTBotUtils.activateEditor(fBot, LttngTraceGenerator.getName()); } /** diff --git a/tmf/org.eclipse.tracecompass.tmf.remote.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/remote/ui/swtbot/tests/fetch/FetchRemoteTracesTest.java b/tmf/org.eclipse.tracecompass.tmf.remote.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/remote/ui/swtbot/tests/fetch/FetchRemoteTracesTest.java index a2360967ac..7e6654bf0d 100644 --- a/tmf/org.eclipse.tracecompass.tmf.remote.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/remote/ui/swtbot/tests/fetch/FetchRemoteTracesTest.java +++ b/tmf/org.eclipse.tracecompass.tmf.remote.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/remote/ui/swtbot/tests/fetch/FetchRemoteTracesTest.java @@ -42,7 +42,7 @@ import org.eclipse.swtbot.swt.finder.widgets.SWTBotShell; import org.eclipse.swtbot.swt.finder.widgets.SWTBotText; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTree; import org.eclipse.swtbot.swt.finder.widgets.SWTBotTreeItem; -import org.eclipse.tracecompass.ctf.core.tests.shared.LttngKernelTraceGenerator; +import org.eclipse.tracecompass.ctf.core.tests.shared.LttngTraceGenerator; import org.eclipse.tracecompass.tmf.remote.ui.swtbot.tests.TmfRemoteUISWTBotTestPlugin; import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectElement; import org.eclipse.tracecompass.tmf.ui.project.model.TmfProjectRegistry; @@ -87,7 +87,7 @@ public class FetchRemoteTracesTest { IPath generatedTraceFullPath = subDirFullPath.append("synthetic-trace"); File generatedTraceFile = new File(generatedTraceFullPath.toOSString()); - LttngKernelTraceGenerator.generateLttngKernelTrace(generatedTraceFile); + LttngTraceGenerator.generateLttngTrace(generatedTraceFile); traceLocation = new Path(resourcesFile.getAbsolutePath()).toString(); } catch (IOException e) { e.printStackTrace();