Port ovnidump using the trace and player modules

The -t option is now dropped as only the binary streams found in the
specified directory are dumped. A single binary stream can be also
dumped in the same way.

The relative path is prefixed, so we avoid the collision problem when
filtering TIDs from multiple nodes.
This commit is contained in:
Rodrigo Arias 2023-02-13 11:24:58 +01:00 committed by Rodrigo Arias Mallo
parent 1ac276a220
commit 09f58610ec
2 changed files with 66 additions and 121 deletions

View File

@ -56,8 +56,8 @@ add_library(emu STATIC
add_executable(ovniemu ovniemu.c) add_executable(ovniemu ovniemu.c)
target_link_libraries(ovniemu emu parson-static ovni-static) target_link_libraries(ovniemu emu parson-static ovni-static)
#add_executable(ovnidump ovnidump.c) add_executable(ovnidump ovnidump.c)
#target_link_libraries(ovnidump emu trace) target_link_libraries(ovnidump emu parson-static ovni-static)
# #
#add_executable(ovnisort ovnisort.c) #add_executable(ovnisort ovnisort.c)
#target_link_libraries(ovnisort emu trace) #target_link_libraries(ovnisort emu trace)

View File

@ -1,124 +1,54 @@
/* Copyright (c) 2021 Barcelona Supercomputing Center (BSC) /* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */ * SPDX-License-Identifier: GPL-3.0-or-later */
#define _GNU_SOURCE #define _GNU_SOURCE
#include <dirent.h>
#include <errno.h>
#include <linux/limits.h>
#include <stdatomic.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
#include "emu.h" #include "player.h"
#include "ovni.h"
#include "trace.h" #include "trace.h"
int filter_tid = -1;
char *tracedir; char *tracedir;
static void static void
emit(struct ovni_stream *stream, struct ovni_ev *ev) emit(struct player *player)
{ {
uint64_t clock = ovni_ev_get_clock(ev); static int64_t c = 0;
printf("%s.%d.%d %ld %c%c%c", struct emu_ev *ev = player_ev(player);
stream->loom->hostname, struct stream *stream = player_stream(player);
stream->proc->pid,
stream->thread->tid,
clock,
ev->header.model,
ev->header.category,
ev->header.value);
int payloadsize = ovni_payload_size(ev); /* Use raw clock in the ovni event */
if (payloadsize > 0) { int64_t rel = ev->rclock - c;
c = ev->rclock;
printf("%s %10ld %+10ld %c%c%c",
stream->relpath,
c,
rel,
ev->m,
ev->c,
ev->v);
if (ev->has_payload) {
printf(" "); printf(" ");
for (int i = 0; i < payloadsize; i++) for (size_t i = 0; i < ev->payload_size; i++)
printf(":%02x", ev->payload.u8[i]); printf(":%02x", ev->payload->u8[i]);
} }
printf("\n"); printf("\n");
stream->lastclock = clock;
}
static void
dump_events(struct ovni_trace *trace)
{
/* Load events */
for (size_t i = 0; i < trace->nstreams; i++) {
struct ovni_stream *stream = &trace->stream[i];
/* It can be inactive if it has been disabled by the
* thread TID filter */
if (stream->active)
ovni_load_next_event(stream);
}
uint64_t lastclock = 0;
while (1) {
ssize_t f = -1;
uint64_t minclock = 0;
struct ovni_stream *stream = NULL;
/* Select next event based on the clock */
for (size_t i = 0; i < trace->nstreams; i++) {
stream = &trace->stream[i];
if (!stream->active)
continue;
struct ovni_ev *ev = stream->cur_ev;
if (f < 0 || ovni_ev_get_clock(ev) < minclock) {
f = i;
minclock = ovni_ev_get_clock(ev);
}
}
// fprintf(stderr, "f=%d minclock=%u\n", f, minclock);
if (f < 0)
break;
stream = &trace->stream[f];
if (lastclock > ovni_ev_get_clock(stream->cur_ev)) {
fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n",
lastclock, ovni_ev_get_clock(stream->cur_ev));
}
/* Emit current event */
emit(stream, stream->cur_ev);
lastclock = ovni_ev_get_clock(stream->cur_ev);
/* Read the next one */
ovni_load_next_event(stream);
/* Unset the index */
f = -1;
minclock = 0;
}
} }
static void static void
usage(void) usage(void)
{ {
err("Usage: ovnidump [-t TID] tracedir\n"); rerr("Usage: ovnidump DIR\n");
err("\n"); rerr("\n");
err("Dumps the events of the trace to the standard output.\n"); rerr("Dumps the events of the trace to the standard output.\n");
err("\n"); rerr("\n");
err("Options:\n"); rerr(" DIR Directory containing ovni traces (%s) or single stream.\n",
err(" -t TID Only events from the given TID are shown\n"); OVNI_STREAM_EXT);
err("\n"); rerr("\n");
err(" tracedir The trace directory generated by ovni.\n");
err("\n");
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
@ -128,18 +58,16 @@ parse_args(int argc, char *argv[])
{ {
int opt; int opt;
while ((opt = getopt(argc, argv, "t:")) != -1) { while ((opt = getopt(argc, argv, "h")) != -1) {
switch (opt) { switch (opt) {
case 't': case 'h':
filter_tid = atoi(optarg);
break;
default: /* '?' */ default: /* '?' */
usage(); usage();
} }
} }
if (optind >= argc) { if (optind >= argc) {
err("missing tracedir\n"); err("bad usage: missing directory\n");
usage(); usage();
} }
@ -149,30 +77,47 @@ parse_args(int argc, char *argv[])
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
progname_set("ovnidump");
parse_args(argc, argv); parse_args(argc, argv);
struct ovni_trace *trace = calloc(1, sizeof(struct ovni_trace)); struct trace *trace = calloc(1, sizeof(struct trace));
if (ovni_load_trace(trace, tracedir)) if (trace == NULL) {
err("calloc failed:");
return 1; return 1;
if (ovni_load_streams(trace))
return 1;
if (filter_tid != -1) {
for (size_t i = 0; i < trace->nstreams; i++) {
struct ovni_stream *stream;
stream = &trace->stream[i];
if (stream->tid != filter_tid)
stream->active = 0;
}
} }
dump_events(trace); if (trace_load(trace, tracedir) != 0) {
err("failed to load trace: %s", tracedir);
return 1;
}
ovni_free_streams(trace); struct player *player = calloc(1, sizeof(struct player));
if (player == NULL) {
err("calloc failed:");
return 1;
}
if (player_init(player, trace) != 0) {
err("player_init failed");
return 1;
}
int ret;
while ((ret = player_step(player)) == 0) {
emit(player);
}
/* Error happened */
if (ret < 0) {
err("player_step failed");
return 1;
}
free(trace); free(trace);
free(player);
return 0; return 0;
} }