Commit 99d1328d authored by Cedric Roux's avatar Cedric Roux
Browse files

add a very basic replay tracer

to be used in conjunction with another tracer
so conceptually it's more a tracee than a tracer
parent 97d1dcbc
...@@ -5,11 +5,14 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I. ...@@ -5,11 +5,14 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I.
LIBS=-lX11 -lm -lpng -lXft LIBS=-lX11 -lm -lpng -lXft
all: record textlog enb vcd all: record replay textlog enb vcd
record: utils.o record.o database.o config.o record: utils.o record.o database.o config.o
$(CC) $(CFLAGS) -o record $^ $(LIBS) $(CC) $(CFLAGS) -o record $^ $(LIBS)
replay: utils.o replay.o
$(CC) $(CFLAGS) -o replay $^ $(LIBS)
textlog: utils.o textlog.o database.o event.o handler.o config.o \ textlog: utils.o textlog.o database.o event.o handler.o config.o \
event_selector.o view/view.a gui/gui.a logger/logger.a \ event_selector.o view/view.a gui/gui.a logger/logger.a \
filter/filter.a filter/filter.a
...@@ -43,7 +46,7 @@ filter/filter.a: ...@@ -43,7 +46,7 @@ filter/filter.a:
$(CC) $(CFLAGS) -c -o $@ $< $(CC) $(CFLAGS) -c -o $@ $<
clean: clean:
rm -f *.o core tracer_remote textlog enb vcd record rm -f *.o core tracer_remote textlog enb vcd record replay
cd gui && make clean cd gui && make clean
cd view && make clean cd view && make clean
cd logger && make clean cd logger && make clean
......
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "utils.h"
#include "../T_defs.h"
#define DEFAULT_REMOTE_PORT 2021
/* replay.c does not know anything about events - it just has the array
* is_on that grows each time replay.c sees a type that does not fit in
* there (the idea is to isolate replay.c as maximum by not using unneeded
* information)
*/
int *is_on;
int is_on_size;
/* this lock is used to protect access to is_on/is_on_size */
pthread_mutex_t biglock = PTHREAD_MUTEX_INITIALIZER;
void set_is_on_size(int size)
{
is_on = realloc(is_on, size * sizeof(int)); if (is_on == NULL) abort();
memset(is_on + is_on_size, 0, (size - is_on_size) * sizeof(int));
is_on_size = size;
}
void lock(void)
{
if (pthread_mutex_lock(&biglock)) abort();
}
void unlock(void)
{
if (pthread_mutex_unlock(&biglock)) abort();
}
#define QUIT(x) do { printf("%s\n", x); exit(1); } while(0)
void get_message(int s)
{
char t;
int l;
int id;
int on;
if (read(s, &t, 1) != 1) QUIT("get_message fails");
lock();
switch (t) {
case 0:
/* toggle all those IDs */
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
while (l) {
if (read(s, &id, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
if (id > is_on_size - 1) set_is_on_size(id + 1);
is_on[id] = 1 - is_on[id];
l--;
}
break;
case 1:
/* set IDs as given */
/* optimize? */
if (read(s, &l, sizeof(int)) != sizeof(int)) QUIT("get_message fails");
if (l > is_on_size) set_is_on_size(l);
id = 0;
while (l) {
if (read(s, &on, sizeof(int)) != sizeof(int))
QUIT("get_message fails");
is_on[id] = on;
id++;
l--;
}
break;
case 2: break; /* do nothing, this message is to wait for local tracer */
default: abort();
}
unlock();
}
void *get_message_thread(void *_socket)
{
int socket = *(int *)_socket;
while (1) get_message(socket);
return NULL;
}
void usage(void)
{
printf(
"options:\n"
" -i <input file> this option is mandatory\n"
" -p <port> wait connection on given port (default %d)\n",
DEFAULT_REMOTE_PORT
);
exit(1);
}
#define ERR printf("ERROR: read file %s failed\n", input_filename)
int main(int n, char **v)
{
int port = DEFAULT_REMOTE_PORT;
char *input_filename = NULL;
int i;
int socket;
FILE *in;
int do_send;
for (i = 1; i < n; i++) {
if (!strcmp(v[i], "-h") || !strcmp(v[i], "--help")) usage();
if (!strcmp(v[i], "-i"))
{ if (i > n-2) usage(); input_filename = v[++i]; continue; }
if (!strcmp(v[i], "-p"))
{ if (i > n-2) usage(); port = atoi(v[++i]); continue; }
usage();
}
if (input_filename == NULL) {
printf("ERROR: provide an input file (-i)\n");
exit(1);
}
in = fopen(input_filename, "r");
if (in == NULL) { perror(input_filename); abort(); }
socket = get_connection("0.0.0.0", port);
/* get first message to activate selected traces */
get_message(socket);
new_thread(get_message_thread, &socket);
while (1) {
int type;
int32_t length;
char v[T_BUFFER_MAX];
int vpos = 0;
/* read event from file */
if (fread(&length, 4, 1, in) != 1) break;
memcpy(v+vpos, &length, 4);
vpos += 4;
#ifdef T_SEND_TIME
if (length < sizeof(struct timespec)) { ERR; break; }
if (fread(v+vpos, sizeof(struct timespec), 1, in) != 1) { ERR; break; }
vpos += sizeof(struct timespec);
length -= sizeof(struct timespec);
#endif
if (length < sizeof(int)) { ERR; break; }
if (fread(&type, sizeof(int), 1, in) != 1) { ERR; break; }
memcpy(v+vpos, &type, sizeof(int));
vpos += sizeof(int);
length -= sizeof(int);
if (length) if (fread(v+vpos, length, 1, in) != 1) { ERR; break; }
vpos += length;
/* only send if configured to do so */
lock();
if (type < 0) do_send = 1;
else {
if (type > is_on_size - 1) set_is_on_size(type+1);
do_send = is_on[type];
}
unlock();
if (do_send)
if (socket_send(socket, v, vpos) != 0)
{ printf("ERROR: socket writing failed\n"); abort(); }
}
fclose(in);
close(socket);
return 0;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment