|
@@ -0,0 +1,229 @@
|
|
|
+#include <stdio.h>
|
|
|
+#include <stdlib.h>
|
|
|
+#include <string.h>
|
|
|
+#include <sys/stat.h>
|
|
|
+#include <errno.h>
|
|
|
+#include "log.h"
|
|
|
+
|
|
|
+#define PLOT_LINES 6
|
|
|
+
|
|
|
+static void log_add_ent(log_t *l, logent_t *le);
|
|
|
+static void logent_destroy(logent_t *le);
|
|
|
+static void fatal_error(const char *format, ...);
|
|
|
+static f_t *finit(char *name, const char *mode);
|
|
|
+static void fend(f_t *f);
|
|
|
+
|
|
|
+/**
|
|
|
+ * Get the time: function to use as logfunc_t
|
|
|
+ **/
|
|
|
+void gettime(unsigned long long *t) {
|
|
|
+ struct timeval tp;
|
|
|
+ unsigned long long ctime;
|
|
|
+
|
|
|
+ gettimeofday( &tp, NULL );
|
|
|
+ ctime = tp.tv_sec;
|
|
|
+ ctime *= 1000000;
|
|
|
+ ctime += tp.tv_usec;
|
|
|
+
|
|
|
+ *t = ctime;
|
|
|
+}
|
|
|
+
|
|
|
+log_t *log_init(char *fn, const char *mode, char *xlabel, char *ylabel, logfunc_t func) {
|
|
|
+ char buf[256];
|
|
|
+
|
|
|
+ stat_t st;
|
|
|
+ log_t *l = (log_t *) malloc(sizeof(log_t));
|
|
|
+
|
|
|
+ if (l == NULL)
|
|
|
+ fatal_error("Could not allocate memory for the new log [%s].", fn);
|
|
|
+
|
|
|
+ if (stat(LOG_DIR, &st) != 0)
|
|
|
+ if (mkdir(LOG_DIR, 0777))
|
|
|
+ fatal_error("Could not create directory: %s", LOG_DIR);
|
|
|
+
|
|
|
+ sprintf(buf, "%s/%s-%s", LOG_DIR, fn, LOG_PLT);
|
|
|
+ l->file = finit(buf, mode);
|
|
|
+
|
|
|
+ if (l->file->lines == 0)
|
|
|
+ l->file->lines = PLOT_LINES;
|
|
|
+
|
|
|
+ l->entries = 0;
|
|
|
+ l->entry = NULL;
|
|
|
+ l->xlabel = strdup(xlabel);
|
|
|
+ l->ylabel = strdup(ylabel);
|
|
|
+ l->func = func;
|
|
|
+
|
|
|
+ return l;
|
|
|
+}
|
|
|
+
|
|
|
+logent_t *logent_init(log_t *l, char *desc, ...) {
|
|
|
+ char buf[256];
|
|
|
+ char *id;
|
|
|
+ va_list vargs;
|
|
|
+ logent_t *le = (logent_t *)malloc(sizeof(logent_t));
|
|
|
+
|
|
|
+ if (l == NULL)
|
|
|
+ fatal_error("Log is NULL\n");
|
|
|
+
|
|
|
+ if (le == NULL)
|
|
|
+ fatal_error("Could not allocate memory for log entry: %s:%s\n", l->file->fn, desc);
|
|
|
+
|
|
|
+ le->desc = strdup(desc);
|
|
|
+
|
|
|
+ va_start(vargs, desc);
|
|
|
+ id = va_arg(vargs, char*);
|
|
|
+ va_end(vargs);
|
|
|
+
|
|
|
+ if (id != NULL)
|
|
|
+ sprintf(buf, "%s-%d.data", l->file->fn, l->file->lines - PLOT_LINES + l->entries);
|
|
|
+ else
|
|
|
+ sprintf(buf, "%s-%s.data", l->file->fn, id);
|
|
|
+
|
|
|
+ printf("FN: %s\n", buf);
|
|
|
+ le->file = finit(buf, l->file->mode);
|
|
|
+
|
|
|
+ log_add_ent(l, le);
|
|
|
+
|
|
|
+ return le;
|
|
|
+}
|
|
|
+
|
|
|
+void logent_start(logent_t *le, ...) {
|
|
|
+ va_list vargs;
|
|
|
+
|
|
|
+ if (le == NULL)
|
|
|
+ fatal_error("Log entry is NULL\n");
|
|
|
+
|
|
|
+ va_start(vargs, le);
|
|
|
+ le->log->func(&le->t1);
|
|
|
+ va_end(vargs);
|
|
|
+}
|
|
|
+
|
|
|
+void logent_end(logent_t *le, int idx, int ent, ...) {
|
|
|
+ int res;
|
|
|
+ va_list vargs;
|
|
|
+
|
|
|
+ if (le == NULL)
|
|
|
+ fatal_error("Logentry is NULL\n");
|
|
|
+
|
|
|
+ va_start(vargs, ent);
|
|
|
+ le->log->func(&le->t2, vargs);
|
|
|
+ va_end(vargs);
|
|
|
+
|
|
|
+ if (ent <= 0)
|
|
|
+ ent = 1;
|
|
|
+
|
|
|
+ res = (int)(le->t2 - le->t1) / ent;
|
|
|
+
|
|
|
+ fprintf(le->file->f, "%d %d\n", idx, res);
|
|
|
+ fflush(le->file->f);
|
|
|
+}
|
|
|
+
|
|
|
+void log_destroy(log_t *l) {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ if (ftell(l->file->f) == 0) {
|
|
|
+ fprintf(l->file->f, "set terminal postscript color\n");
|
|
|
+ fprintf(l->file->f, "set output \"%s-%s\"\n", l->file->fn, LOG_CMP);
|
|
|
+ fprintf(l->file->f, "set autoscale\n");
|
|
|
+ fprintf(l->file->f, "set xlabel \"%s\"\nset ylabel \"%s\"\n", l->xlabel, l->ylabel);
|
|
|
+ fprintf(l->file->f, "set key right\nplot");
|
|
|
+ }
|
|
|
+
|
|
|
+ for (i = 0; i < l->entries; i++) {
|
|
|
+ if (l->entry[i]->file->lines == 0) {
|
|
|
+ fprintf(l->file->f, " \\\n\"%s\" w linespoints lw 2 t \"%s\",",
|
|
|
+ l->entry[i]->file->fn, l->entry[i]->desc
|
|
|
+ );
|
|
|
+ }
|
|
|
+ logent_destroy(l->entry[i]);
|
|
|
+ }
|
|
|
+
|
|
|
+ fflush(l->file->f);
|
|
|
+ fend(l->file);
|
|
|
+ free(l->xlabel);
|
|
|
+ free(l->ylabel);
|
|
|
+
|
|
|
+ if (l->entry != NULL)
|
|
|
+ free(l->entry);
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * When something bad happens.... we end!
|
|
|
+ **/
|
|
|
+static void fatal_error(const char *format, ...) {
|
|
|
+ va_list vargs;
|
|
|
+ fprintf(stdout, "[FATAL] ");
|
|
|
+ va_start(vargs, format);
|
|
|
+ vfprintf(stdout, format, vargs);
|
|
|
+ va_end(vargs);
|
|
|
+ exit(EXIT_FAILURE);
|
|
|
+}
|
|
|
+
|
|
|
+static f_t *finit(char *name, const char *mode) {
|
|
|
+
|
|
|
+ char c;
|
|
|
+
|
|
|
+ f_t *f = (f_t *)malloc(sizeof(f_t));
|
|
|
+
|
|
|
+ if (f == NULL)
|
|
|
+ fatal_error("Could not allocate memory for %s\n", name);
|
|
|
+
|
|
|
+ f->fn = strdup(name);
|
|
|
+ f->f = fopen(f->fn, mode);
|
|
|
+ f->lines = 0;
|
|
|
+ f->mode = mode;
|
|
|
+
|
|
|
+ if (f->f == NULL)
|
|
|
+ fatal_error("Coult not open %s[%s]\n", name, mode);
|
|
|
+
|
|
|
+ while ((c = fgetc(f->f)) != EOF)
|
|
|
+ if (c == '\n')
|
|
|
+ f->lines++;
|
|
|
+
|
|
|
+ fseek(f->f, 0, SEEK_END);
|
|
|
+
|
|
|
+ return f;
|
|
|
+}
|
|
|
+
|
|
|
+static void fend(f_t *f) {
|
|
|
+ if (f == NULL)
|
|
|
+ fatal_error("Cant close NULL-file\n");
|
|
|
+
|
|
|
+ if (f->f == NULL)
|
|
|
+ return;
|
|
|
+
|
|
|
+ printf("[FILE] stored in: %s\n", f->fn);
|
|
|
+ free(f->fn);
|
|
|
+ fclose(f->f);
|
|
|
+}
|
|
|
+
|
|
|
+static void log_add_ent(log_t *l, logent_t *le) {
|
|
|
+ int i;
|
|
|
+
|
|
|
+ logent_t **entry = (logent_t **)malloc(sizeof(logent_t*) * (l->entries + 1));
|
|
|
+
|
|
|
+ for (i = 0; i < l->entries; i++)
|
|
|
+ entry[i] = l->entry[i];
|
|
|
+
|
|
|
+ entry[l->entries++] = le;
|
|
|
+
|
|
|
+ if (l->entry != NULL)
|
|
|
+ free(l->entry);
|
|
|
+
|
|
|
+ l->entry = entry;
|
|
|
+ le->log = l;
|
|
|
+}
|
|
|
+
|
|
|
+static void logent_destroy(logent_t *le) {
|
|
|
+
|
|
|
+ if (le == NULL)
|
|
|
+ fatal_error("Cant close log entry 0x%p\n", le);
|
|
|
+
|
|
|
+ if (le->file->f != NULL)
|
|
|
+ fend(le->file);
|
|
|
+
|
|
|
+ le->file->f = NULL;
|
|
|
+
|
|
|
+ free(le->desc);
|
|
|
+ free(le);
|
|
|
+}
|