Files
openairinterface5g/common/utils/T/tracer/vcd.c
T
Cedric Roux 51292c2472 event_selector does not deal with socket anymore
It was wrong.
Plus it is starting work so as to make enb.c not crashing if
the tracee goes away (maybe also textlog and vcd, but those are of
less importance).
2016-06-04 23:48:03 +02:00

199 lines
5.3 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "database.h"
#include "event.h"
#include "handler.h"
#include "logger/logger.h"
#include "view/view.h"
#include "gui/gui.h"
#include "utils.h"
#include "../T_defs.h"
#include "event_selector.h"
#include "config.h"
typedef struct {
int socket;
int *is_on;
int nevents;
pthread_mutex_t lock;
} vcd_data;
void is_on_changed(void *_d)
{
vcd_data *d = _d;
char t;
if (pthread_mutex_lock(&d->lock)) abort();
if (d->socket == -1) goto no_connection;
t = 1;
socket_send(d->socket, &t, 1);
socket_send(d->socket, &d->nevents, sizeof(int));
socket_send(d->socket, d->is_on, d->nevents * sizeof(int));
no_connection:
if (pthread_mutex_unlock(&d->lock)) abort();
}
#define DEFAULT_REMOTE_IP "127.0.0.1"
#define DEFAULT_REMOTE_PORT 2021
void usage(void)
{
printf(
"options:\n"
" -d <database file> this option is mandatory\n"
" -on <GROUP or ID> turn log ON for given GROUP or ID\n"
" -off <GROUP or ID> turn log OFF for given GROUP or ID\n"
" -ON turn all logs ON\n"
" -OFF turn all logs OFF\n"
" note: you may pass several -on/-off/-ON/-OFF,\n"
" they will be processed in order\n"
" by default, all is off\n"
" -ip <host> connect to given IP address (default %s)\n"
" -p <port> connect to given port (default %d)\n"
" -debug-gui activate GUI debug logs\n",
DEFAULT_REMOTE_IP,
DEFAULT_REMOTE_PORT
);
exit(1);
}
static void *gui_thread(void *_g)
{
gui *g = _g;
gui_loop(g);
return NULL;
}
static void vcd_main_gui(gui *g, event_handler *h, void *database)
{
int i, j;
int n;
int nb_functions = 0;
char **ids;
widget *win;
widget *container;
widget *w;
view *timeview;
view *subview;
logger *timelog;
/* get number of vcd functions - look for all events VCD_FUNCTION_xxx */
n = database_get_ids(database, &ids);
for (i = 0; i < n; i++) {
if (strncmp(ids[i], "VCD_FUNCTION_", 13) != 0) continue;
nb_functions++;
}
win = new_toplevel_window(g, 1000, 5 * nb_functions, "VCD tracer");
container = new_container(g, VERTICAL);
widget_add_child(g, win, container, -1);
w = new_timeline(g, 1000, nb_functions, 5);
widget_add_child(g, container, w, -1);
for (i = 0; i < nb_functions; i++)
timeline_set_subline_background_color(g, w, i,
new_color(g, i & 1 ? "#ddd" : "#eee"));
timeview = new_view_time(3600, 10, g, w);
i = 0;
for (j = 0; j < n; j++) {
if (strncmp(ids[j], "VCD_FUNCTION_", 13) != 0) continue;
timelog = new_timelog(h, database, ids[j]);
subview = new_subview_time(timeview, i, FOREGROUND_COLOR, 3600*1000);
logger_add_view(timelog, subview);
i++;
}
free(ids);
}
int main(int n, char **v)
{
extern int volatile gui_logd;
char *database_filename = NULL;
void *database;
char *ip = DEFAULT_REMOTE_IP;
int port = DEFAULT_REMOTE_PORT;
char **on_off_name;
int *on_off_action;
int on_off_n = 0;
int *is_on;
int number_of_events;
int i;
event_handler *h;
gui *g;
vcd_data vcd_data;
on_off_name = malloc(n * sizeof(char *)); if (on_off_name == NULL) abort();
on_off_action = malloc(n * sizeof(int)); if (on_off_action == NULL) abort();
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-d"))
{ if (i > n-2) usage(); database_filename = v[++i]; continue; }
if (!strcmp(v[i], "-ip")) { if (i > n-2) usage(); ip = v[++i]; continue; }
if (!strcmp(v[i], "-p"))
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
if (!strcmp(v[i], "-on")) { if (i > n-2) usage();
on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=1; continue; }
if (!strcmp(v[i], "-off")) { if (i > n-2) usage();
on_off_name[on_off_n]=v[++i]; on_off_action[on_off_n++]=0; continue; }
if (!strcmp(v[i], "-ON"))
{ on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=1; continue; }
if (!strcmp(v[i], "-OFF"))
{ on_off_name[on_off_n]=NULL; on_off_action[on_off_n++]=0; continue; }
if (!strcmp(v[i], "-debug-gui")) { gui_logd = 1; continue; }
usage();
}
if (database_filename == NULL) {
printf("ERROR: provide a database file (-d)\n");
exit(1);
}
database = parse_database(database_filename);
store_config_file(database_filename);
number_of_events = number_of_ids(database);
is_on = calloc(number_of_events, sizeof(int));
if (is_on == NULL) abort();
h = new_handler(database);
g = gui_init();
new_thread(gui_thread, g);
vcd_main_gui(g, h, database);
on_off(database, "VCD_FUNCTION", is_on, 1);
for (i = 0; i < on_off_n; i++)
on_off(database, on_off_name[i], is_on, on_off_action[i]);
vcd_data.socket = -1;
vcd_data.is_on = is_on;
vcd_data.nevents = number_of_events;
if (pthread_mutex_init(&vcd_data.lock, NULL)) abort();
setup_event_selector(g, database, is_on, is_on_changed, &vcd_data);
vcd_data.socket = connect_to(ip, port);
/* send the first message - activate selected traces */
is_on_changed(&vcd_data);
/* read messages */
while (1) {
char v[T_BUFFER_MAX];
event e;
e = get_event(vcd_data.socket, v, database);
handle_event(h, e);
}
return 0;
}