Add ovnitop command

This commit is contained in:
Rodrigo Arias 2023-05-29 13:22:00 +02:00 committed by Rodrigo Arias Mallo
parent f8a15df1b9
commit 553d0a1c62
2 changed files with 161 additions and 1 deletions

View File

@ -66,6 +66,9 @@ target_link_libraries(ovnidump emu parson-static ovni-static)
add_executable(ovnisort ovnisort.c)
target_link_libraries(ovnisort emu parson-static ovni-static)
add_executable(ovnitop ovnitop.c)
target_link_libraries(ovnitop emu parson-static ovni-static)
set(USE_MPI ON CACHE BOOL "Use MPI (required by ovnisync)")
if(USE_MPI)
# Use <PackageName>_ROOT variables if available, commonly used by MPI
@ -81,4 +84,4 @@ else()
message(STATUS "Disabling ovnisync as MPI is disabled")
endif()
install(TARGETS ovniemu ovnidump ovnisort RUNTIME DESTINATION bin)
install(TARGETS ovniemu ovnidump ovnisort ovnitop RUNTIME DESTINATION bin)

157
src/emu/ovnitop.c Normal file
View File

@ -0,0 +1,157 @@
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
#include "emu_ev.h"
#include "emu_stat.h"
#include "ovni.h"
#include "player.h"
#include "trace.h"
#include "uthash.h"
struct entry {
char mcv[4];
long count;
UT_hash_handle hh;
};
char *tracedir;
struct entry *table = NULL;
static void
accum(struct player *player)
{
struct emu_ev *ev = player_ev(player);
struct entry *e = NULL;
HASH_FIND_STR(table, ev->mcv, e);
if (e == NULL) {
e = calloc(1, sizeof(struct entry));
if (e == NULL)
die("calloc failed:");
strcpy(e->mcv, ev->mcv);
e->count = 1;
HASH_ADD_STR(table, mcv, e);
} else {
e->count++;
}
}
static int
by_count(struct entry *a, struct entry *b)
{
if (a->count < b->count)
return +1;
if (a->count > b->count)
return -1;
/* Otherwise they have the same count, sort by mcv */
return strcmp(a->mcv, b->mcv);
}
static void
report(void)
{
HASH_SORT(table, by_count);
for (struct entry *e = table; e; e = e->hh.next)
printf("%s %10ld\n", e->mcv, e->count);
}
static void
usage(void)
{
rerr("Usage: ovnitop DIR\n");
rerr("\n");
rerr("Show most common events in a trace.\n");
rerr("\n");
rerr(" DIR Directory containing ovni traces (%s) or single stream.\n",
OVNI_STREAM_EXT);
rerr("\n");
exit(EXIT_FAILURE);
}
static void
parse_args(int argc, char *argv[])
{
int opt;
while ((opt = getopt(argc, argv, "h")) != -1) {
switch (opt) {
case 'h':
default: /* '?' */
usage();
}
}
if (optind >= argc) {
err("bad usage: missing directory");
usage();
}
tracedir = argv[optind];
}
int
main(int argc, char *argv[])
{
progname_set("ovnitop");
parse_args(argc, argv);
struct trace *trace = calloc(1, sizeof(struct trace));
if (trace == NULL) {
err("calloc failed:");
return 1;
}
if (trace_load(trace, tracedir) != 0) {
err("failed to load trace: %s", tracedir);
return 1;
}
struct player *player = calloc(1, sizeof(struct player));
if (player == NULL) {
err("calloc failed:");
return 1;
}
if (player_init(player, trace, 1) != 0) {
err("player_init failed");
return 1;
}
int ret;
struct emu_stat stat;
emu_stat_init(&stat);
while ((ret = player_step(player)) == 0) {
accum(player);
emu_stat_update(&stat, player);
}
emu_stat_report(&stat, player, 1);
/* Report events */
report();
/* Error happened */
if (ret < 0) {
err("player_step failed");
return 1;
}
free(trace);
free(player);
return 0;
}