separated logger.c and logreader.c
This commit is contained in:
414
logreader.c
Normal file
414
logreader.c
Normal file
@ -0,0 +1,414 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <fortify.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include "logger.h"
|
||||||
|
#include "sics.h"
|
||||||
|
|
||||||
|
#define LOGGER_NAN -999999.
|
||||||
|
#define ONE_YEAR (366*24*3600)
|
||||||
|
|
||||||
|
typedef enum { NUMERIC, TEXT } CompType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SConnection *pCon;
|
||||||
|
char *var;
|
||||||
|
int exact;
|
||||||
|
CompType type;
|
||||||
|
time_t step;
|
||||||
|
time_t tlim;
|
||||||
|
time_t tmin, tmax, tlast, told;
|
||||||
|
float ymin, ymax, ylast, yold;
|
||||||
|
char slast[256];
|
||||||
|
char set[256];
|
||||||
|
int np;
|
||||||
|
} Compressor;
|
||||||
|
|
||||||
|
static char *dir = NULL;
|
||||||
|
static char *dir2 = NULL;
|
||||||
|
|
||||||
|
static void InitCompressor(Compressor *c, SConnection *pCon, time_t step) {
|
||||||
|
c->pCon = pCon;
|
||||||
|
c->step = step;
|
||||||
|
c->tmin = -2;
|
||||||
|
c->tmax = 0;
|
||||||
|
c->tlast = 0;
|
||||||
|
c->tlim = 0;
|
||||||
|
c->told = 0;
|
||||||
|
c->slast[0]='\0';
|
||||||
|
c->ylast = LOGGER_NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OutString(Compressor *c, time_t t, char *str) {
|
||||||
|
char line[256];
|
||||||
|
|
||||||
|
/* printf("out %ld %g\n", t, y); */
|
||||||
|
if (0 != strcmp(str, c->slast)) {
|
||||||
|
snprintf(line, sizeof line, "%ld %s\n", (long)(t - c->tlast), str);
|
||||||
|
c->tlast = t;
|
||||||
|
c->slast[0]='\0';
|
||||||
|
strncat(c->slast, str, sizeof c->slast - 1);
|
||||||
|
SCWrite(c->pCon, line, eWarning);
|
||||||
|
c->np--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void OutFloat(Compressor *c, time_t t, float y) {
|
||||||
|
char line[80];
|
||||||
|
|
||||||
|
/* printf("out %ld %g\n", t, y); */
|
||||||
|
if (y != c->ylast || !c->exact) {
|
||||||
|
c->ylast = y;
|
||||||
|
if (y == LOGGER_NAN) {
|
||||||
|
snprintf(line, sizeof line, "%ld\n", (long)(t - c->tlast));
|
||||||
|
} else {
|
||||||
|
snprintf(line, sizeof line, "%ld %g\n", (long)(t - c->tlast), y);
|
||||||
|
}
|
||||||
|
/* printf("-%s\n", line); */
|
||||||
|
c->tlast = t;
|
||||||
|
SCWrite(c->pCon, line, eWarning);
|
||||||
|
c->np--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PutValue(Compressor *c, time_t t, char *value) {
|
||||||
|
char *p;
|
||||||
|
double y;
|
||||||
|
|
||||||
|
if (c->var) {
|
||||||
|
SCPrintf(c->pCon, eWarning, "*%s exact %d\n", c->var, c->exact);
|
||||||
|
c->var = NULL;
|
||||||
|
}
|
||||||
|
if (c->type == NUMERIC) {
|
||||||
|
if (t == 0) { /* finish */
|
||||||
|
t = c->tlim + 3 * c->step;
|
||||||
|
y = 0;
|
||||||
|
} else {
|
||||||
|
y = strtod(value, &p);
|
||||||
|
if (p == value) {
|
||||||
|
y = LOGGER_NAN;
|
||||||
|
} else {
|
||||||
|
if (y == LOGGER_NAN) y *= 1.0000002;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* printf("put %ld %g\n", t, y); */
|
||||||
|
if (c->tlim == 0) goto first;
|
||||||
|
if (t >= c->tlim) {
|
||||||
|
c->tlim += c->step;
|
||||||
|
if (c->tmin > c->tmax) {
|
||||||
|
OutFloat(c, c->tmax, c->ymax);
|
||||||
|
c->ymax = c->ymin;
|
||||||
|
c->tmax = c->tmin;
|
||||||
|
} else {
|
||||||
|
OutFloat(c, c->tmin, c->ymin);
|
||||||
|
if (c->tmin == c->tmax) goto first;
|
||||||
|
c->ymin = c->ymax;
|
||||||
|
c->tmin = c->tmax;
|
||||||
|
}
|
||||||
|
if (t >= c->tlim) {
|
||||||
|
OutFloat(c, c->tmin, c->ymin);
|
||||||
|
if (t >= c->tlim + c->step) {
|
||||||
|
OutFloat(c, c->told, c->yold);
|
||||||
|
}
|
||||||
|
goto first;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (y <= c->ymin) {
|
||||||
|
c->ymin = y;
|
||||||
|
c->tmin = t;
|
||||||
|
} else if (y > c->ymax) {
|
||||||
|
c->ymax = y;
|
||||||
|
c->tmax = t;
|
||||||
|
}
|
||||||
|
c->yold = y;
|
||||||
|
c->told = t;
|
||||||
|
return;
|
||||||
|
first:
|
||||||
|
c->tlim = t + 2 * c->step;
|
||||||
|
c->tmin = t;
|
||||||
|
c->tmax = t;
|
||||||
|
c->ymin = y;
|
||||||
|
c->ymax = y;
|
||||||
|
return;
|
||||||
|
} else if (c->type == TEXT) {
|
||||||
|
if (t != 0) OutString(c, t, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static long getOpt(char *line, int *isdst, int *exact) {
|
||||||
|
long lxs;
|
||||||
|
char *opt;
|
||||||
|
|
||||||
|
opt = strstr(line, "isdst");
|
||||||
|
if (opt) {
|
||||||
|
sscanf(opt, "isdst %d", isdst);
|
||||||
|
}
|
||||||
|
opt = strstr(line, "exact");
|
||||||
|
if (opt) {
|
||||||
|
sscanf(opt, "exact %d", exact);
|
||||||
|
}
|
||||||
|
opt = strstr(line, "period");
|
||||||
|
if (opt) {
|
||||||
|
sscanf(opt, "period %ld", &lxs);
|
||||||
|
return lxs;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]) {
|
||||||
|
time_t from, to, step, xs, lastt, now;
|
||||||
|
long lxs;
|
||||||
|
char *p;
|
||||||
|
int i, iarg0, l, iret, loss, np;
|
||||||
|
int inRange;
|
||||||
|
int yday=0;
|
||||||
|
time_t t, startim;
|
||||||
|
struct tm tm;
|
||||||
|
char stim[32], path[256], line[256], lastval[256];
|
||||||
|
char *lin, *val, *stp;
|
||||||
|
FILE *fil;
|
||||||
|
Compressor c;
|
||||||
|
float yy, lasty;
|
||||||
|
CompType type0;
|
||||||
|
DIR *dr;
|
||||||
|
char *opt;
|
||||||
|
int isdst;
|
||||||
|
int overflow;
|
||||||
|
|
||||||
|
/* argtolower(argc, argv); */
|
||||||
|
if (argc < 4) goto illarg;
|
||||||
|
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;
|
||||||
|
if (from < ONE_YEAR) {
|
||||||
|
from += now;
|
||||||
|
}
|
||||||
|
if (to < ONE_YEAR) {
|
||||||
|
to += now;
|
||||||
|
}
|
||||||
|
iarg0 = 4;
|
||||||
|
if (strcasecmp(argv[3],"text") == 0) { /* non-numeric values */
|
||||||
|
step = 1;
|
||||||
|
type0 = TEXT;
|
||||||
|
np = from - to + 2;
|
||||||
|
} else if (strcasecmp(argv[3],"np") == 0) { /* max. number of points */
|
||||||
|
type0 = NUMERIC;
|
||||||
|
iarg0 = 5;
|
||||||
|
np = strtol(argv[4], NULL, 0);
|
||||||
|
if (to <= from) {
|
||||||
|
step = 1;
|
||||||
|
} else if (np <= 2) {
|
||||||
|
step = to - from;
|
||||||
|
} else {
|
||||||
|
step = (to - from) / (np - 2) + 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
step = strtol(argv[3], NULL, 0);
|
||||||
|
if (step <= 0) step = 1;
|
||||||
|
type0 = NUMERIC;
|
||||||
|
np = (from - to) / step + 2;
|
||||||
|
}
|
||||||
|
if (p == argv[3]) goto illarg;
|
||||||
|
if (step <= 0) step = 1;
|
||||||
|
|
||||||
|
snprintf(line, sizeof line, "%ld\n", (long)now);
|
||||||
|
SCWrite(pCon, line, eWarning);
|
||||||
|
|
||||||
|
if (dir == NULL) {
|
||||||
|
dir = IFindOption(pSICSOptions, "LoggerDir");
|
||||||
|
if (dir == NULL) {
|
||||||
|
SCWrite(pCon, "LoggerDir not found", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
LoggerSetDir(dir);
|
||||||
|
}
|
||||||
|
if (dir2 == NULL) {
|
||||||
|
dir2 = IFindOption(pSICSOptions, "LoggerDir2");
|
||||||
|
if (dir2 == NULL) dir2="";
|
||||||
|
}
|
||||||
|
|
||||||
|
loss = 0;
|
||||||
|
overflow = 0;
|
||||||
|
for (i=iarg0; i<argc; i++) {
|
||||||
|
startim = from;
|
||||||
|
t = 0;
|
||||||
|
lastt = 0;
|
||||||
|
inRange = 0;
|
||||||
|
xs = step;
|
||||||
|
InitCompressor(&c, pCon, step);
|
||||||
|
c.var = argv[i];
|
||||||
|
c.type = type0;
|
||||||
|
c.np = np;
|
||||||
|
l = LoggerVarPath(dir, path, sizeof path, c.var);
|
||||||
|
dr = opendir(path);
|
||||||
|
if (dr) {
|
||||||
|
closedir(dr);
|
||||||
|
} else {
|
||||||
|
l = LoggerVarPath(dir2, path, sizeof path, c.var);
|
||||||
|
dr = opendir(path);
|
||||||
|
if (dr) {
|
||||||
|
closedir(dr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isdst = -1;
|
||||||
|
fil = NULL;
|
||||||
|
while (startim <= to && c.tlast <= to) {
|
||||||
|
tm = *localtime(&startim);
|
||||||
|
if (tm.tm_yday != yday) {
|
||||||
|
if (fil != NULL) { /* close file if day changed */
|
||||||
|
fclose(fil);
|
||||||
|
fil=NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fil == NULL) {
|
||||||
|
yday = tm.tm_yday;
|
||||||
|
strftime(path + l, sizeof path - l, "%m-%d.log", &tm);
|
||||||
|
fil = fopen(path, "r");
|
||||||
|
if (fil != NULL) { /* check if file is from the given year */
|
||||||
|
strftime(stim, sizeof stim, "#%Y-%m-%d", &tm);
|
||||||
|
fgets(line, sizeof line, fil);
|
||||||
|
if (0 != strncmp(line, stim, 11)) {
|
||||||
|
fclose(fil);
|
||||||
|
fil = NULL;
|
||||||
|
} else {
|
||||||
|
lxs = getOpt(line, &isdst, &c.exact);
|
||||||
|
if (lxs >= 0) {
|
||||||
|
if (lxs == 0) {
|
||||||
|
c.type = TEXT;
|
||||||
|
} else {
|
||||||
|
c.type = type0;
|
||||||
|
xs = lxs;
|
||||||
|
}
|
||||||
|
if (xs < step) {
|
||||||
|
loss = 1;
|
||||||
|
xs = step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fil == NULL) {
|
||||||
|
lin = NULL;
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
lin = fgets(line, sizeof line, fil);
|
||||||
|
/* printf("%s\n", line); */
|
||||||
|
if (lin == NULL) break;
|
||||||
|
if (line[0] == '#') {
|
||||||
|
lxs = getOpt(line, &isdst, &c.exact);
|
||||||
|
if (lxs >= 0) {
|
||||||
|
if (lxs == 0) {
|
||||||
|
c.type = TEXT;
|
||||||
|
} else {
|
||||||
|
c.type = type0;
|
||||||
|
xs = lxs;
|
||||||
|
}
|
||||||
|
if (xs < step) {
|
||||||
|
loss = 1;
|
||||||
|
xs = step;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lin[0]='\0';
|
||||||
|
} else {
|
||||||
|
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) {
|
||||||
|
stp = p+1;
|
||||||
|
*p='\0';
|
||||||
|
iret = sscanf(stp, "%ld", &lxs);
|
||||||
|
if (iret == 1) {
|
||||||
|
if (lxs == 0) {
|
||||||
|
c.type = TEXT;
|
||||||
|
} else {
|
||||||
|
c.type = type0;
|
||||||
|
xs = lxs;
|
||||||
|
}
|
||||||
|
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 = isdst;
|
||||||
|
t=mktime(&tm);
|
||||||
|
if (!inRange) {
|
||||||
|
if (t < startim) {
|
||||||
|
lastval[0]='\0';
|
||||||
|
strncat(lastval, val, sizeof lastval - 1);
|
||||||
|
lastt = t;
|
||||||
|
} else {
|
||||||
|
inRange=1;
|
||||||
|
if (lastt != 0) {
|
||||||
|
PutValue(&c, lastt, lastval);
|
||||||
|
}
|
||||||
|
PutValue(&c, t, val);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
PutValue(&c, t, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lin == NULL) {
|
||||||
|
tm.tm_hour = 24; /* try next day */
|
||||||
|
tm.tm_min = 0;
|
||||||
|
tm.tm_sec = 0;
|
||||||
|
tm.tm_isdst = -1;
|
||||||
|
startim=mktime(&tm);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inRange) {
|
||||||
|
if (lastt != 0) {
|
||||||
|
PutValue(&c, lastt, lastval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.ylast = LOGGER_NAN; /* force output of last value */
|
||||||
|
PutValue(&c, 0, ""); /* finish */
|
||||||
|
if (fil) {
|
||||||
|
fclose(fil);
|
||||||
|
fil = NULL;
|
||||||
|
}
|
||||||
|
if (c.np < 0) overflow = 1;
|
||||||
|
}
|
||||||
|
snprintf(line, sizeof line, "*%d %d\n", loss, overflow);
|
||||||
|
SCWrite(pCon, line, eWarning);
|
||||||
|
return 1;
|
||||||
|
illarg:
|
||||||
|
SCWrite(pCon, "illegal argument(s)", eError);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
static void KillLogReader(void *data) {
|
||||||
|
Logger *p, *next;
|
||||||
|
|
||||||
|
KillDummy(data);
|
||||||
|
LoggerFreeAll();
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
void LogReaderInit(void) {
|
||||||
|
AddCommand(pServ->pSics,"Graph",LogReader,KillLogReader,NULL);
|
||||||
|
}
|
Reference in New Issue
Block a user