353 lines
8.7 KiB
C
353 lines
8.7 KiB
C
/*---------------------------------------------------------------------------
|
|
logger.c
|
|
|
|
Markus Zolliker, Sept 2004
|
|
----------------------------------------------------------------------------
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <assert.h>
|
|
#include <fortify.h>
|
|
#include <errno.h>
|
|
#include "sics.h"
|
|
#include "logger.h"
|
|
|
|
#define LOGGER_NAN -999999.
|
|
|
|
struct Logger {
|
|
char *name;
|
|
char old[132];
|
|
int period;
|
|
time_t last;
|
|
};
|
|
|
|
static char *dir = NULL;
|
|
|
|
/*--------------------------------------------------------------------------*/
|
|
void LoggerWrite(Logger *log, time_t now, int period, char *value) {
|
|
char path[256], stim[32], buf[32];
|
|
struct tm *tm;
|
|
int yday, isdst;
|
|
int l;
|
|
int newday;
|
|
FILE *fil;
|
|
|
|
if (dir == NULL) return;
|
|
if (now == 0) {
|
|
printf("now==0\n");
|
|
}
|
|
tm = localtime(&log->last);
|
|
yday = tm->tm_yday;
|
|
tm = localtime(&now);
|
|
if (tm->tm_yday != yday) {
|
|
log->period = 0;
|
|
} else if (0 == strncmp(value, log->old, sizeof(log->old))) { /* value has not changed */
|
|
return;
|
|
}
|
|
log->last = now;
|
|
snprintf(path, sizeof path, "%s/%s/", dir, log->name);
|
|
l = strlen(path);
|
|
|
|
strftime(path + l, sizeof path - l, "%m-%d.log", tm);
|
|
fil = fopen(path, "a+");
|
|
if (fil == NULL) return;
|
|
fseek(fil, 0, SEEK_SET);
|
|
fgets(buf, sizeof buf, fil);
|
|
|
|
strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S\n", tm);
|
|
if (0 != strncmp(buf, stim, 11)) {
|
|
fclose(fil);
|
|
fil=fopen(path, "w+"); /* overwrite old logfile */
|
|
if (fil == NULL) return;
|
|
fputs(stim, fil);
|
|
} else {
|
|
fseek(fil, 0, SEEK_END); /* set position to end */
|
|
}
|
|
if (period != log->period) {
|
|
log->period = period;
|
|
snprintf(buf, sizeof buf, "\t%d", period);
|
|
} else {
|
|
buf[0]='\0';
|
|
}
|
|
strftime(stim, sizeof stim,"%H:%M:%S", tm);
|
|
fprintf(fil, "%s\t%s%s\n", stim, value, buf);
|
|
l = strlen(value);
|
|
if (l >= sizeof(log->old)) {
|
|
l = sizeof(log->old) - 1;
|
|
}
|
|
strncpy(log->old, value, l);
|
|
log->old[l] = '\0';
|
|
fclose(fil);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
void LoggerKill(Logger *log) {
|
|
if (!log) return;
|
|
LoggerWrite(log, time(NULL), 0, "");
|
|
free(log->name);
|
|
free(log);
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
char *LoggerGetDir(void) {
|
|
if (dir == NULL) {
|
|
dir = IFindOption(pSICSOptions, "LoggerDir");
|
|
}
|
|
return dir;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
Logger *LoggerMake(char *name, int period) {
|
|
Logger *log, *p;
|
|
char path[256];
|
|
struct stat st;
|
|
int i;
|
|
char *dir;
|
|
|
|
dir = LoggerGetDir();
|
|
if (dir == NULL) return NULL;
|
|
snprintf(path, sizeof path, "%s/%s", dir, name);
|
|
i = stat(path, &st);
|
|
if (i >= 0) {
|
|
if (((st.st_mode >> 12) & 15) != 4) { /* exists, but is no directory */
|
|
return NULL;
|
|
}
|
|
} else {
|
|
i = mkdir(path, S_IRWXU+S_IRGRP+S_IXGRP+S_IROTH+S_IXOTH);
|
|
if (i < 0) return NULL; /* mkdir failed */
|
|
}
|
|
log = malloc(sizeof *log);
|
|
if (log == NULL) return NULL;
|
|
log->name = strdup(name);
|
|
if (log->name == NULL) {
|
|
free(log);
|
|
return NULL;
|
|
}
|
|
log->period = 0;
|
|
log->old[0] = '\0';
|
|
log->last = 0;
|
|
LoggerWrite(log, time(NULL) - 1, period, "");
|
|
return log;
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
typedef struct {
|
|
SConnection *pCon;
|
|
time_t step;
|
|
time_t t0, tmin, tmax;
|
|
time_t tlast;
|
|
float ymin, ymax;
|
|
float ylast;
|
|
long cnt;
|
|
} Compressor;
|
|
|
|
static void LoggerInit(Compressor *c, SConnection *pCon, time_t step) {
|
|
c->pCon = pCon;
|
|
c->step = step;
|
|
c->tmin = -1;
|
|
c->tmax = 0;
|
|
c->tlast = 0;
|
|
c->t0 = 0;
|
|
c->ylast = LOGGER_NAN;
|
|
}
|
|
|
|
static void LoggerOut(Compressor *c, time_t t, float y) {
|
|
char line[80];
|
|
|
|
/* printf("out %ld %g\n", t, y); */
|
|
if (y != c->ylast) {
|
|
c->ylast = y;
|
|
if (y == LOGGER_NAN) {
|
|
snprintf(line, sizeof line, "%ld\n", t - c->tlast);
|
|
} else {
|
|
snprintf(line, sizeof line, "%ld %g\n", t - c->tlast, y);
|
|
}
|
|
/* printf("-%s\n", line); */
|
|
c->cnt--;
|
|
c->tlast = t;
|
|
SCWrite(c->pCon, line, eStatus);
|
|
}
|
|
}
|
|
|
|
static void LoggerSum(Compressor *c) {
|
|
if (c->tmin < 0 || c->tmin==0 && c->tmax==0) {
|
|
/* printf("nos %ld %ld %f %f\n", c->tmin, c->tmax, c->ymin, c->ymax); */
|
|
LoggerOut(c, c->t0, LOGGER_NAN);
|
|
c->tmin = -1;
|
|
} else {
|
|
/* printf("sum %ld %ld %f %f\n", c->tmin, c->tmax, c->ymin, c->ymax); */
|
|
if (c->tmin > c->tmax) {
|
|
if (c->tmax >= c->t0) {
|
|
LoggerOut(c, c->tmax, c->ymax);
|
|
}
|
|
LoggerOut(c, c->tmin, c->ymin);
|
|
} else if (c->tmin < c->tmax) {
|
|
if (c->tmin >= c->t0) {
|
|
LoggerOut(c, c->tmin, c->ymin);
|
|
}
|
|
LoggerOut(c, c->tmax, c->ymax);
|
|
} else {
|
|
LoggerOut(c, c->tmax, c->ymax);
|
|
}
|
|
if (c->ylast != LOGGER_NAN) {
|
|
c->ymin = c->ylast;
|
|
c->ymax = c->ylast;
|
|
c->tmin = 0;
|
|
c->tmax = 0;
|
|
} else {
|
|
c->tmin = -1;
|
|
}
|
|
/* printf("end %ld %ld %f %f\n", c->tmin, c->tmax, c->ymin, c->ymax); */
|
|
}
|
|
}
|
|
|
|
static void LoggerPut(Compressor *c, time_t t, float y) {
|
|
/* printf("put %ld %g\n", t, y); */
|
|
if (t >= c->t0 + c->step) {
|
|
LoggerSum(c);
|
|
c->t0 = t;
|
|
}
|
|
if (y == LOGGER_NAN) return;
|
|
if (c->tmin < 0) {
|
|
c->tmin = t;
|
|
c->tmax = t;
|
|
c->ymin = y;
|
|
c->ymax = y;
|
|
} else if (y <= c->ymin) {
|
|
c->ymin = y;
|
|
c->tmin = t;
|
|
} else if (y >= c->ymax) {
|
|
c->ymax = y;
|
|
c->tmax = t;
|
|
}
|
|
}
|
|
/*--------------------------------------------------------------------------*/
|
|
int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|
int argc, char *argv[]) {
|
|
time_t from, to, step, xs, lastx, now;
|
|
char *p;
|
|
int i, l, yday, iret, loss;
|
|
time_t tim, tr;
|
|
struct tm tm;
|
|
char path[256], line[80];
|
|
char *lin, *val, *stp;
|
|
FILE *fil;
|
|
Compressor c;
|
|
float yy, lasty;
|
|
|
|
if (argc < 4) {
|
|
SCWrite(pCon, "illegal number of arguments", eError);
|
|
return 0;
|
|
}
|
|
now = time(NULL);
|
|
from = strtol(argv[1], &p, 0); /* unix time, not year 2038 safe */
|
|
if (p == argv[1]) goto illarg;
|
|
to = strtol(argv[2], NULL, 0);
|
|
if (p == argv[2]) goto illarg;
|
|
step = strtol(argv[3], NULL, 0);
|
|
if (p == argv[3]) goto illarg;
|
|
if (from <= 0) from += now;
|
|
if (to <= 0) to += now;
|
|
if (step <= 0) step = 1;
|
|
|
|
dir = LoggerGetDir();
|
|
if (dir == NULL) {
|
|
SCWrite(pCon, "LoggerDir not found", eError);
|
|
return 0;
|
|
}
|
|
|
|
loss = 0;
|
|
for (i=4; i<argc; i++) {
|
|
tim = from;
|
|
xs = step;
|
|
LoggerInit(&c, pCon, step);
|
|
c.cnt = (to - from) / step + 1;
|
|
lastx = 0;
|
|
lasty = LOGGER_NAN;
|
|
snprintf(path, sizeof path, "%s/%s/", dir, argv[i]);
|
|
l = strlen(path);
|
|
fil = NULL;
|
|
snprintf(line, sizeof line, "*%s\n", argv[i]);
|
|
SCWrite(pCon, line, eStatus);
|
|
while (tim <= to) {
|
|
tm = *localtime(&tim);
|
|
if (fil == NULL || tm.tm_yday != yday) {
|
|
yday = tm.tm_yday;
|
|
strftime(path + l, sizeof path - l, "%m-%d.log", &tm);
|
|
fil = fopen(path, "r");
|
|
}
|
|
if (fil == NULL) {
|
|
lin == NULL;
|
|
} else {
|
|
do {
|
|
lin = fgets(line, sizeof line, fil);
|
|
/* printf("%s\n", line); */
|
|
if (lin == NULL) break;
|
|
p = strchr(line, '\n'); if (p) *p='\0';
|
|
p = strchr(line, '#'); if (p) *p='\0';
|
|
} while (lin[0] == '\0');
|
|
}
|
|
if (lin != NULL) {
|
|
/* printf(" %s\n", line); */
|
|
p = strchr(line, '\t');
|
|
if (p) {
|
|
*p='\0';
|
|
val = p+1;
|
|
} else {
|
|
val = "";
|
|
}
|
|
p = strchr(val, '\t');
|
|
if (p) {
|
|
*p='\0';
|
|
stp = val+1;
|
|
iret = sscanf(stp, "%ld", &xs);
|
|
if (xs < step) {
|
|
loss = 1;
|
|
xs = step;
|
|
}
|
|
}
|
|
iret = sscanf(line, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
|
|
if (iret != 3) {
|
|
lin = NULL;
|
|
} else {
|
|
tm.tm_isdst = -1;
|
|
tr=mktime(&tm);
|
|
iret = sscanf(val, "%f", &yy);
|
|
if (iret <= 0) {
|
|
yy = LOGGER_NAN;
|
|
} else {
|
|
if (yy == LOGGER_NAN) yy *= 1.0000002;
|
|
}
|
|
if (tr >= tim) {
|
|
if (lastx != 0) {
|
|
lastx += xs;
|
|
while (lastx < tr) {
|
|
LoggerPut(&c, lastx, lasty);
|
|
lastx += xs;
|
|
}
|
|
}
|
|
LoggerPut(&c, tr, yy);
|
|
}
|
|
lastx = tr;
|
|
lasty = yy;
|
|
}
|
|
}
|
|
if (lin == NULL) {
|
|
tm.tm_hour = 24; /* try next day */
|
|
tm.tm_min = 0;
|
|
tm.tm_sec = 0;
|
|
tm.tm_isdst = -1;
|
|
tim=mktime(&tm);
|
|
continue;
|
|
}
|
|
}
|
|
c.ylast = LOGGER_NAN;
|
|
LoggerSum(&c);
|
|
}
|
|
snprintf(line, sizeof line, "*%d\n", loss);
|
|
SCWrite(pCon, line, eStatus);
|
|
return 1;
|
|
illarg:
|
|
SCWrite(pCon, "illegal argument", eError);
|
|
return 0;
|
|
}
|