From 1f4f0305810bfecfe39ae33e31f5027932918e6d Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Wed, 16 Mar 2016 11:00:39 +0100
Subject: [PATCH] more work on database

---
 tracer/Makefile                 |   2 +-
 tracer/{t_data.c => database.c} | 115 +++++++++++++++++++++++++-------
 tracer/defs.h                   |   2 +
 tracer/main.c                   |  44 ++++++++++--
 4 files changed, 135 insertions(+), 28 deletions(-)
 rename tracer/{t_data.c => database.c} (59%)

diff --git a/tracer/Makefile b/tracer/Makefile
index 99385f4593..8388ec91e2 100644
--- a/tracer/Makefile
+++ b/tracer/Makefile
@@ -8,7 +8,7 @@ CFLAGS += -DT_USE_SHARED_MEMORY
 LIBS += -lrt
 
 PROG=tracer
-OBJS=main.o plot.o t_data.o
+OBJS=main.o plot.o database.o
 
 $(PROG): $(OBJS)
 	$(CC) $(CFLAGS) -o $(PROG) $(OBJS) $(LIBS)
diff --git a/tracer/t_data.c b/tracer/database.c
similarity index 59%
rename from tracer/t_data.c
rename to tracer/database.c
index dc006e5830..87e793b8c3 100644
--- a/tracer/t_data.c
+++ b/tracer/database.c
@@ -7,6 +7,8 @@
 typedef struct {
   char *name;
   char *desc;
+  char **groups;
+  int size;
 } id;
 
 typedef struct {
@@ -16,6 +18,7 @@ typedef struct {
 } group;
 
 typedef struct {
+  char *name;
   id *i;
   int isize;
   group *g;
@@ -92,31 +95,51 @@ void get_line(parser *p, FILE *f, char **name, char **value)
   *value = p->value.data;
 }
 
-void add_id(database *r, char *id)
+int group_cmp(const void *_p1, const void *_p2)
+{
+  const group *p1 = _p1;
+  const group *p2 = _p2;
+  return strcmp(p1->name, p2->name);
+}
+
+int id_cmp(const void *_p1, const void *_p2)
 {
+  const id *p1 = _p1;
+  const id *p2 = _p2;
+  return strcmp(p1->name, p2->name);
+}
+
+int string_cmp(const void *_p1, const void *_p2)
+{
+  char * const *p1 = _p1;
+  char * const *p2 = _p2;
+  return strcmp(*p1, *p2);
+}
+
+id *add_id(database *r, char *idname)
+{
+  if (bsearch(&(id){name:idname}, r->i, r->isize, sizeof(id), id_cmp) != NULL)
+    { printf("ERROR: ID '%s' declared more than once\n", idname); exit(1); }
   if ((r->isize & 1023) == 0) {
     r->i = realloc(r->i, (r->isize + 1024) * sizeof(id));
     if (r->i == NULL) { printf("out of memory\n"); exit(1); }
   }
-  r->i[r->isize].name = strdup(id);
+  r->i[r->isize].name = strdup(idname);
   if (r->i[r->isize].name == NULL) { printf("out of memory\n"); exit(1); }
+  r->i[r->isize].desc = NULL;
+  r->i[r->isize].groups = NULL;
+  r->i[r->isize].size = 0;
   r->isize++;
-}
-
-int group_cmp(const void *_p1, const void *_p2)
-{
-  const group *p1 = _p1;
-  const group *p2 = _p2;
-  return strcmp(p1->name, p2->name);
+  qsort(r->i, r->isize, sizeof(id), id_cmp);
+  return (id*)bsearch(&(id){name:idname}, r->i, r->isize, sizeof(id), id_cmp);
 }
 
 group *get_group(database *r, char *group_name)
 {
-  group gsearch;
   group *ret;
 
-  gsearch.name = group_name;
-  ret = bsearch(&gsearch, r->g, r->gsize, sizeof(group), group_cmp);
+  ret = bsearch(&(group){name:group_name},
+                r->g, r->gsize, sizeof(group), group_cmp);
   if (ret != NULL) return ret;
 
   if ((r->gsize & 1023) == 0) {
@@ -131,7 +154,8 @@ group *get_group(database *r, char *group_name)
 
   qsort(r->g, r->gsize, sizeof(group), group_cmp);
 
-  return bsearch(&gsearch, r->g, r->gsize, sizeof(group), group_cmp);
+  return bsearch(&(group){name:group_name},
+                 r->g, r->gsize, sizeof(group), group_cmp);
 }
 
 void group_add_id(group *g, char *id)
@@ -144,10 +168,24 @@ void group_add_id(group *g, char *id)
   g->size++;
 }
 
-void add_groups(database *r, char *groups)
+void id_add_group(id *i, char *group)
 {
-  group *g;
+  char *g = bsearch(&group, i->groups, i->size, sizeof(char *), string_cmp);
+  if (g != NULL) return;
+
+  if ((i->size & 1023) == 0) {
+    i->groups = realloc(i->groups, (i->size+1024) * sizeof(char *));
+    if (i->groups == NULL) abort();
+  }
+  i->groups[i->size] = group;
+  i->size++;
+  qsort(i->groups, i->size, sizeof(char *), string_cmp);
+}
 
+void add_groups(database *r, id *i, char *groups)
+{
+  group *g;
+  if (i == NULL) {printf("ERROR: GROUP line before ID line\n");exit(1);}
   while (1) {
     char *start = groups;
     char *end = start;
@@ -159,7 +197,8 @@ void add_groups(database *r, char *groups)
     if (*end == 0) end = NULL; else *end = 0;
 
     g = get_group(r, start);
-    group_add_id(g, r->i[r->isize-1].name);
+    group_add_id(g, i->name);
+    id_add_group(i, g->name);
 
     if (end == NULL) break;
     end++;
@@ -169,24 +208,34 @@ void add_groups(database *r, char *groups)
   }
 }
 
+void add_desc(id *i, char *desc)
+{
+  if (i == NULL) {printf("ERROR: DESC line before ID line\n");exit(1);}
+  i->desc = strdup(desc); if (i->desc == NULL) abort();
+}
+
 void *parse_database(char *filename)
 {
   FILE *in;
   parser p;
   database *r;
   char *name, *value;
+  id *last_id = NULL;
 
   r = calloc(1, sizeof(*r)); if (r == NULL) abort();
   memset(&p, 0, sizeof(p));
 
+  r->name = strdup(filename); if (r->name == NULL) abort();
+
   in = fopen(filename, "r"); if (in == NULL) { perror(filename); abort(); }
 
   while (1) {
     get_line(&p, in, &name, &value);
     if (name == NULL) break;
-    printf("%s %s\n", name, value);
-    if (!strcmp(name, "ID")) add_id(r, value);
-    if (!strcmp(name, "GROUP")) add_groups(r, value);
+//printf("%s %s\n", name, value);
+    if (!strcmp(name, "ID")) last_id = add_id(r, value);
+    if (!strcmp(name, "GROUP")) add_groups(r, last_id, value);
+    if (!strcmp(name, "DESC")) add_desc(last_id, value);
   }
 
   fclose(in);
@@ -201,13 +250,33 @@ void dump_database(void *_d)
   database *d = _d;
   int i;
 
-  printf("database: %d IDs, %d GROUPs\n", d->isize, d->gsize);
-  for (i = 0; i < d->isize; i++)
-    printf("ID %s [%s]\n", d->i[i].name, d->i[i].desc);
+  printf("database %s: %d IDs, %d GROUPs\n", d->name, d->isize, d->gsize);
+  for (i = 0; i < d->isize; i++) {
+    int j;
+    printf("ID %s [%s] [in %d group%s]\n",
+           d->i[i].name, d->i[i].desc ? d->i[i].desc : "",
+           d->i[i].size, d->i[i].size > 1 ? "s" : "");
+    for (j = 0; j < d->i[i].size; j++)
+      printf("    in GROUP: %s\n", d->i[i].groups[j]);
+  }
   for (i = 0; i < d->gsize; i++) {
     int j;
     printf("GROUP %s [size %d]\n", d->g[i].name, d->g[i].size);
     for (j = 0; j < d->g[i].size; j++)
-      printf("  ID %s\n", d->g[i].ids[j]);
+      printf("  contains ID: %s\n", d->g[i].ids[j]);
   }
 }
+
+void list_ids(void *_d)
+{
+  database *d = _d;
+  int i;
+  for (i = 0; i < d->isize; i++) printf("%s\n", d->i[i].name);
+}
+
+void list_groups(void *_d)
+{
+  database *d = _d;
+  int i;
+  for (i = 0; i < d->gsize; i++) printf("%s\n", d->g[i].name);
+}
diff --git a/tracer/defs.h b/tracer/defs.h
index 5ba87131de..6c2a026600 100644
--- a/tracer/defs.h
+++ b/tracer/defs.h
@@ -8,5 +8,7 @@ void iq_plot_set(void *plot, short *data, int len, int pos);
 /* returns an opaque pointer - truly a 'database *', see t_data.c */
 void *parse_database(char *filename);
 void dump_database(void *database);
+void list_ids(void *database);
+void list_groups(void *database);
 
 #endif /* _TRACER_DEFS_H_ */
diff --git a/tracer/main.c b/tracer/main.c
index b045c58652..fb5fcc99d9 100644
--- a/tracer/main.c
+++ b/tracer/main.c
@@ -257,15 +257,53 @@ void init_shm(void)
 
 #endif /* T_USE_SHARED_MEMORY */
 
+void usage(void)
+{
+  printf(
+"options:\n"
+"    -d <database file>        this option is mandatory\n"
+"    -li                       print IDs in the database\n"
+"    -lg                       print GROUPs in the database\n"
+"    -dump                     dump the database\n"
+  );
+  exit(1);
+}
+
 int main(int n, char **v)
 {
+  char *database_filename = NULL;
   void *database;
   int s;
   int l;
   char t;
+  int i;
+  int do_list_ids = 0;
+  int do_list_groups = 0;
+  int do_dump_database = 0;
+
+  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], "-li")) { do_list_ids = 1; continue; }
+    if (!strcmp(v[i], "-lg")) { do_list_groups = 1; continue; }
+    if (!strcmp(v[i], "-dump")) { do_dump_database = 1; continue; }
+    usage();
+  }
+
+  if (database_filename == NULL) {
+    printf("ERROR: provide a database file (-d)\n");
+    exit(1);
+  }
+
+  database = parse_database(database_filename);
+
+  if (do_list_ids + do_list_groups + do_dump_database > 1) usage();
+  if (do_list_ids) { list_ids(database); return 0; }
+  if (do_list_groups) { list_groups(database); return 0; }
+  if (do_dump_database) { dump_database(database); return 0; }
 
-  database = parse_database("../T_messages.txt");
-  dump_database(database);
+  ul_plot = make_plot(512, 100, 7680*2*10);
 
 #ifdef T_USE_SHARED_MEMORY
   init_shm();
@@ -279,8 +317,6 @@ int main(int n, char **v)
   for (l = 0; l < T_NUMBER_OF_IDS; l++)
     if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
 
-  ul_plot = make_plot(512, 100, 7680*2*10);
-
   /* read messages */
   while (1) {
 #ifdef T_USE_SHARED_MEMORY
-- 
GitLab