From 6322010e0aa0eed14c7ac0b313f5d31c1ea8c119 Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Fri, 27 Oct 2017 16:01:33 +0200
Subject: [PATCH] T: add a tracer: extract

This tracer extracts the content of a buffer field of an event
that was previously saved using the tracer 'record'.

For example, to extract the channel estimation done in
frame 924 and subframe 2 as saved in the file input_record.raw
and to store it in the file output.raw, do:

./extract -d ../T_messages.txt -o output.raw input_record.raw ENB_PHY_UL_CHANNEL_ESTIMATE chest_t -f frame 924 -f subframe 2
---
 common/utils/T/.gitignore       |   1 +
 common/utils/T/tracer/Makefile  |   7 +-
 common/utils/T/tracer/extract.c | 124 ++++++++++++++++++++++++++++++++
 3 files changed, 130 insertions(+), 2 deletions(-)
 create mode 100644 common/utils/T/tracer/extract.c

diff --git a/common/utils/T/.gitignore b/common/utils/T/.gitignore
index f5724e6ff8..532e083e15 100644
--- a/common/utils/T/.gitignore
+++ b/common/utils/T/.gitignore
@@ -10,4 +10,5 @@ tracer/replay
 tracer/textlog
 tracer/vcd
 tracer/macpdu2wireshark
+tracer/extract
 tracee/tracee
diff --git a/common/utils/T/tracer/Makefile b/common/utils/T/tracer/Makefile
index 6546345968..a7d3bf561b 100644
--- a/common/utils/T/tracer/Makefile
+++ b/common/utils/T/tracer/Makefile
@@ -6,7 +6,7 @@ CFLAGS=-Wall -g -pthread -DT_TRACER -I.
 LIBS=-lX11 -lm -lpng -lXft
 
 all: record replay extract_config textlog enb ue vcd macpdu2wireshark \
-     extract_input_subframe
+     extract_input_subframe extract
 
 record: utils.o record.o database.o config.o
 	$(CC) $(CFLAGS) -o record $^ $(LIBS)
@@ -21,6 +21,9 @@ extract_input_subframe: extract_input_subframe.o database.o event.o utils.o \
     config.o
 	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
 
+extract: extract.o database.o event.o utils.o config.o
+	$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
+
 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 \
          filter/filter.a
@@ -64,7 +67,7 @@ filter/filter.a:
 
 clean:
 	rm -f *.o core tracer_remote textlog enb ue vcd record replay
-	rm -f extract_config macpdu2wireshark extract_input_subframe
+	rm -f extract_config macpdu2wireshark extract_input_subframe extract
 	cd gui && make clean
 	cd view && make clean
 	cd logger && make clean
diff --git a/common/utils/T/tracer/extract.c b/common/utils/T/tracer/extract.c
new file mode 100644
index 0000000000..b9fca959ed
--- /dev/null
+++ b/common/utils/T/tracer/extract.c
@@ -0,0 +1,124 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include "database.h"
+#include "event.h"
+#include "config.h"
+
+void usage(void)
+{
+  printf(
+"usage: [options] <file> <event> <buffer name>\n"
+"options:\n"
+"    -d <database file>        this option is mandatory\n"
+"    -o <output file>          this option is mandatory\n"
+"    -f <name> <value>         field 'name' of 'event' has to match 'value'\n"
+"                              type of 'name' must be int\n"
+"                              (you can use several -f options)\n"
+  );
+  exit(1);
+}
+
+int get_filter_arg(database_event_format *f, char *field, char *type)
+{
+  int i;
+  for (i = 0; i < f->count; i++)
+    if (!strcmp(f->name[i], field)) {
+      if (strcmp(f->type[i], type)) break;
+      return i;
+    }
+  printf("bad field %s, check that it exists and has type '%s'\n",field,type);
+  exit(1);
+}
+
+int main(int n, char **v)
+{
+  char *database_filename = NULL;
+  void *database;
+  int i;
+  int input_event_id;
+  database_event_format f;
+  char *file = NULL;
+  char *output_file = NULL;
+  FILE *out;
+  int fd;
+  char *event_name = NULL;
+  char *buffer_name = NULL;
+  char *filter[n];
+  int filter_arg[n];
+  int filter_value[n];
+  int filter_count = 0;
+  int buffer_arg;
+  int found;
+
+  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], "-o"))
+      { if (i > n-2) usage(); output_file = v[++i]; continue; }
+    if (!strcmp(v[i], "-f")) { if (i>n-3) usage();
+      filter[filter_count]         = v[++i];
+      filter_value[filter_count++] = atoi(v[++i]);
+      continue;
+    }
+    if (file == NULL) { file = v[i]; continue; }
+    if (event_name == NULL) { event_name = v[i]; continue; }
+    if (buffer_name == NULL) { buffer_name = v[i]; continue; }
+    usage();
+  }
+  if (file == NULL || event_name == NULL || buffer_name == NULL) usage();
+
+  if (database_filename == NULL) {
+    printf("ERROR: provide a database file (-d)\n");
+    exit(1);
+  }
+
+  if (output_file == NULL) {
+    printf("gimme -o <output file>, thanks\n");
+    exit(1);
+  }
+
+  out = fopen(output_file, "w"); if(out==NULL){perror(output_file);exit(1);}
+
+  database = parse_database(database_filename);
+
+  load_config_file(database_filename);
+
+  input_event_id = event_id_from_name(database, event_name);
+  f = get_format(database, input_event_id);
+
+  buffer_arg = get_filter_arg(&f, buffer_name, "buffer");
+
+  for (i = 0; i < filter_count; i++)
+    filter_arg[i] = get_filter_arg(&f, filter[i], "int");
+
+  fd = open(file, O_RDONLY);
+  if (fd == -1) { perror(file); exit(1); }
+
+  found = 0;
+
+  while (1) {
+    char v[T_BUFFER_MAX];
+    event e;
+    e = get_event(fd, v, database);
+    if (e.type == -1) break;
+    if (e.type != input_event_id) continue;
+    for (i = 0; i < filter_count; i++)
+      if (filter_value[i] != e.e[filter_arg[i]].i)
+        break;
+    if (i != filter_count)
+      continue;
+    if (fwrite(e.e[buffer_arg].b, e.e[buffer_arg].bsize, 1, out) != 1)
+      { perror(output_file); exit(1); }
+    found = 1;
+    break;
+  }
+
+  if (found == 0) printf("ERROR: event not found\n");
+
+  fclose(out);
+
+  return 0;
+}
-- 
GitLab