bug fixes and enhancements related to evcontroller
This commit is contained in:
385
logger.c
385
logger.c
@@ -19,16 +19,74 @@ Markus Zolliker, Sept 2004
|
||||
|
||||
struct Logger {
|
||||
char *name;
|
||||
char old[132];
|
||||
char old[256];
|
||||
int period;
|
||||
time_t last;
|
||||
long pos;
|
||||
Logger *next;
|
||||
};
|
||||
|
||||
static char *dir = NULL;
|
||||
static Logger *vars = NULL;
|
||||
static Logger *list;
|
||||
static time_t lastLife = 0;
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void LoggerWrite(Logger *log, time_t now, int period, char *value) {
|
||||
Logger *LoggerFind(char *name) {
|
||||
Logger *p;
|
||||
p = list;
|
||||
while (p != NULL) {
|
||||
if (0==strcasecmp(name, p->name)) {
|
||||
return p;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
char *LoggerGetDir(void) {
|
||||
char path[256], line[32];
|
||||
FILE *fil;
|
||||
time_t now;
|
||||
static time_t last;
|
||||
|
||||
#define LASTLOGTXT "#last logging entry at:\n"
|
||||
|
||||
if (dir == NULL) {
|
||||
dir = IFindOption(pSICSOptions, "LoggerDir");
|
||||
snprintf(path, sizeof path, "%s/lastlife.dat", dir);
|
||||
fil = fopen(path, "r");
|
||||
if (fil) {
|
||||
fgets(line, sizeof line, fil);
|
||||
if (strcmp(line, LASTLOGTXT) == 0) {
|
||||
fgets(line, sizeof line, fil);
|
||||
lastLife = atol(line);
|
||||
if (lastLife < 1000000000) {
|
||||
printf("bad lastLife %ld\n", lastLife);
|
||||
}
|
||||
}
|
||||
fclose(fil);
|
||||
} else {
|
||||
perror("open read error \n");
|
||||
}
|
||||
}
|
||||
now = time(NULL);
|
||||
if (now != last) {
|
||||
snprintf(path, sizeof path, "%s/lastlife.dat", dir);
|
||||
fil = fopen(path, "w");
|
||||
if (fil) {
|
||||
fprintf(fil, "%s%ld\n", LASTLOGTXT, now);
|
||||
fclose(fil);
|
||||
} else {
|
||||
printf("can not open %s\n", path);
|
||||
perror("open write error \n");
|
||||
}
|
||||
last = now;
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int LoggerWrite(Logger *log, time_t now, int period, char *value) {
|
||||
char path[256], stim[32], buf[32];
|
||||
struct tm *tm;
|
||||
int yday, isdst;
|
||||
@@ -37,7 +95,8 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) {
|
||||
FILE *fil;
|
||||
long pos;
|
||||
|
||||
if (dir == NULL) return;
|
||||
LoggerGetDir();
|
||||
if (dir == NULL) return 0;
|
||||
if (now == 0) {
|
||||
printf("now==0\n");
|
||||
}
|
||||
@@ -46,6 +105,8 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) {
|
||||
tm = localtime(&now);
|
||||
if (tm->tm_yday != yday) {
|
||||
log->period = 0;
|
||||
} else if (0 == strncmp(value, log->old, sizeof(log->old))) {
|
||||
return 0;
|
||||
}
|
||||
log->last = now;
|
||||
snprintf(path, sizeof path, "%s/%s/", dir, log->name);
|
||||
@@ -56,14 +117,14 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) {
|
||||
fil = fopen(path, "r+");
|
||||
if (fil == NULL) { /* create new file */
|
||||
fil = fopen(path, "w+");
|
||||
if (fil == NULL) return;
|
||||
if (fil == NULL) return 0;
|
||||
fputs(stim, fil);
|
||||
} else { /* check if file is actual */
|
||||
fgets(buf, sizeof buf, fil);
|
||||
if (0 != strncmp(buf, stim, 11)) {
|
||||
fclose(fil);
|
||||
fil=fopen(path, "w+"); /* overwrite old logfile */
|
||||
if (fil == NULL) return;
|
||||
if (fil == NULL) return 0;
|
||||
fputs(stim, fil);
|
||||
} else {
|
||||
fseek(fil, 0, SEEK_END); /* set position to end */
|
||||
@@ -76,16 +137,17 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) {
|
||||
} else {
|
||||
buf[0]='\0';
|
||||
}
|
||||
/*
|
||||
if (log->pos > 0) {
|
||||
fseek(fil, log->pos, SEEK_SET);
|
||||
}
|
||||
log->pos = ftell(fil);
|
||||
*/
|
||||
strftime(stim, sizeof stim,"%H:%M:%S", tm);
|
||||
fprintf(fil, "%s\t%s%s\n", stim, value, buf);
|
||||
if (0 != strncmp(value, log->old, sizeof(log->old)) || buf[0]!='\0') { /* value has changed */
|
||||
log->pos = ftell(fil); /* next time append to the end */
|
||||
}
|
||||
|
||||
// if (0 != strncmp(value, log->old, sizeof(log->old)) || buf[0]!='\0') { /* value has changed */
|
||||
// log->pos = ftell(fil); /* next time append to the end */
|
||||
// }
|
||||
l = strlen(value);
|
||||
if (l >= sizeof(log->old)) {
|
||||
l = sizeof(log->old) - 1;
|
||||
@@ -93,20 +155,13 @@ void LoggerWrite(Logger *log, time_t now, int period, char *value) {
|
||||
strncpy(log->old, value, l);
|
||||
log->old[l] = '\0';
|
||||
fclose(fil);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
void LoggerKill(Logger *log) {
|
||||
if (!log) return;
|
||||
/* we do not really free the logger, it might be reused
|
||||
for the same variable later. We set the value to undefined */
|
||||
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) {
|
||||
@@ -114,9 +169,9 @@ Logger *LoggerMake(char *name, int period) {
|
||||
char path[256];
|
||||
struct stat st;
|
||||
int i;
|
||||
char *dir;
|
||||
time_t t;
|
||||
|
||||
dir = LoggerGetDir();
|
||||
LoggerGetDir();
|
||||
if (dir == NULL) return NULL;
|
||||
snprintf(path, sizeof path, "%s/%s", dir, name);
|
||||
i = stat(path, &st);
|
||||
@@ -128,41 +183,67 @@ Logger *LoggerMake(char *name, int period) {
|
||||
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 = LoggerFind(name); /* look if logger already exists */
|
||||
if (log == NULL) {
|
||||
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;
|
||||
log->pos = 0;
|
||||
log->next = list;
|
||||
list = log;
|
||||
t = time(NULL) -1;
|
||||
if (lastLife != 0 && lastLife + period < t) {
|
||||
t = lastLife + period;
|
||||
}
|
||||
LoggerWrite(log, t, period, ""); /* value was undefined since last life of server */
|
||||
}
|
||||
log->period = 0;
|
||||
log->old[0] = '\0';
|
||||
log->last = 0;
|
||||
log->pos = 0;
|
||||
LoggerWrite(log, time(NULL) - 1, period, "");
|
||||
return log;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef enum { numeric, text } CompType;
|
||||
|
||||
typedef struct {
|
||||
SConnection *pCon;
|
||||
CompType type;
|
||||
time_t step;
|
||||
time_t t0, tmin, tmax;
|
||||
time_t tlast;
|
||||
float ymin, ymax;
|
||||
float ylast;
|
||||
long cnt;
|
||||
time_t tlim;
|
||||
time_t tmin, tmax, tlast, told;
|
||||
float ymin, ymax, ylast, yold;
|
||||
char slast[256];
|
||||
char set[256];
|
||||
} Compressor;
|
||||
|
||||
static void LoggerInit(Compressor *c, SConnection *pCon, time_t step) {
|
||||
c->pCon = pCon;
|
||||
c->step = step;
|
||||
c->tmin = -1;
|
||||
c->tmin = -2;
|
||||
c->tmax = 0;
|
||||
c->tlast = 0;
|
||||
c->t0 = 0;
|
||||
c->tlim = 0;
|
||||
c->told = 0;
|
||||
c->ylast = LOGGER_NAN;
|
||||
}
|
||||
|
||||
static void LoggerOutStr(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", t - c->tlast, str);
|
||||
c->tlast = t;
|
||||
c->slast[0]='\0';
|
||||
strncat(c->slast, str, sizeof c->slast - 1);
|
||||
SCWrite(c->pCon, line, eStatus);
|
||||
}
|
||||
}
|
||||
|
||||
static void LoggerOut(Compressor *c, time_t t, float y) {
|
||||
char line[80];
|
||||
|
||||
@@ -175,94 +256,118 @@ static void LoggerOut(Compressor *c, time_t t, float y) {
|
||||
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) {
|
||||
static void LoggerPut(Compressor *c, time_t t, char *value) {
|
||||
char *p;
|
||||
double y;
|
||||
|
||||
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) {
|
||||
LoggerOut(c, c->tmax, c->ymax);
|
||||
}
|
||||
LoggerOut(c, c->tmin, c->ymin);
|
||||
} else if (c->tmin < c->tmax) {
|
||||
if (c->tmin >= c->t0) {
|
||||
c->ymax = c->ymin;
|
||||
c->tmax = c->tmin;
|
||||
} else {
|
||||
LoggerOut(c, c->tmin, c->ymin);
|
||||
if (c->tmin == c->tmax) goto first;
|
||||
c->ymin = c->ymax;
|
||||
c->tmin = c->tmax;
|
||||
}
|
||||
LoggerOut(c, c->tmax, c->ymax);
|
||||
} else {
|
||||
LoggerOut(c, c->tmax, c->ymax);
|
||||
if (t >= c->tlim) {
|
||||
LoggerOut(c, c->tmin, c->ymin);
|
||||
if (t >= c->tlim + c->step) {
|
||||
LoggerOut(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;
|
||||
}
|
||||
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); */
|
||||
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) LoggerOutStr(c, t, value);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
time_t from, to, step, xs, lastt, now;
|
||||
char *p;
|
||||
int i, l, yday, iret, loss;
|
||||
time_t tim, tr;
|
||||
int inRange;
|
||||
time_t t, startim;
|
||||
struct tm tm;
|
||||
char path[256], line[80];
|
||||
char stim[32], path[256], line[256], lastval[256];
|
||||
char *lin, *val, *stp;
|
||||
FILE *fil;
|
||||
Compressor c;
|
||||
float yy, lasty;
|
||||
Logger *log;
|
||||
|
||||
if (argc < 4) {
|
||||
SCWrite(pCon, "illegal number of arguments", eError);
|
||||
return 0;
|
||||
if (argc < 2) goto illarg;
|
||||
strtolower(argv[1]);
|
||||
if (strcmp(argv[1], "vars") == 0) { /* default variables on a graph */
|
||||
if (vars == NULL) {
|
||||
vars = LoggerMake("vars", 1);
|
||||
if (vars == NULL) return 0;
|
||||
}
|
||||
Arg2Text(argc-2, argv+2, line, sizeof line);
|
||||
LoggerWrite(vars, time(NULL), 1, line);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
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;
|
||||
step = strtol(argv[3], NULL, 0);
|
||||
if (strcmp(argv[3],"text") == 0) { /* non-numeric values */
|
||||
step = 1;
|
||||
c.type = text;
|
||||
} else {
|
||||
step = strtol(argv[3], NULL, 0);
|
||||
c.type = numeric;
|
||||
}
|
||||
if (p == argv[3]) goto illarg;
|
||||
if (from <= 0) from += now;
|
||||
if (to <= 0) to += now;
|
||||
if (step <= 0) step = 1;
|
||||
|
||||
dir = LoggerGetDir();
|
||||
LoggerGetDir();
|
||||
if (dir == NULL) {
|
||||
SCWrite(pCon, "LoggerDir not found", eError);
|
||||
return 0;
|
||||
@@ -270,23 +375,37 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
|
||||
loss = 0;
|
||||
for (i=4; i<argc; i++) {
|
||||
tim = from;
|
||||
startim = from;
|
||||
t = 0;
|
||||
lastt = 0;
|
||||
inRange = 0;
|
||||
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) {
|
||||
while (startim <= 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 this year */
|
||||
strftime(stim, sizeof stim, "#%Y-%m-%d", &tm);
|
||||
fgets(line, sizeof line, fil);
|
||||
if (0 != strncmp(line, stim, 11)) {
|
||||
fclose(fil);
|
||||
fil = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fil == NULL) {
|
||||
lin == NULL;
|
||||
@@ -310,12 +429,14 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
}
|
||||
p = strchr(val, '\t');
|
||||
if (p) {
|
||||
stp = p+1;
|
||||
*p='\0';
|
||||
stp = val+1;
|
||||
iret = sscanf(stp, "%ld", &xs);
|
||||
if (xs < step) {
|
||||
loss = 1;
|
||||
xs = step;
|
||||
if (iret == 1) {
|
||||
if (xs < step) {
|
||||
loss = 1;
|
||||
xs = step;
|
||||
}
|
||||
}
|
||||
}
|
||||
iret = sscanf(line, "%d:%d:%d", &tm.tm_hour, &tm.tm_min, &tm.tm_sec);
|
||||
@@ -323,25 +444,22 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
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;
|
||||
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) {
|
||||
LoggerPut(&c, lastt, lastval);
|
||||
}
|
||||
LoggerPut(&c, t, val);
|
||||
}
|
||||
LoggerPut(&c, tr, yy);
|
||||
} else {
|
||||
LoggerPut(&c, t, val);
|
||||
}
|
||||
lastx = tr;
|
||||
lasty = yy;
|
||||
}
|
||||
}
|
||||
if (lin == NULL) {
|
||||
@@ -349,17 +467,32 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
tm.tm_min = 0;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_isdst = -1;
|
||||
tim=mktime(&tm);
|
||||
startim=mktime(&tm);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
c.ylast = LOGGER_NAN;
|
||||
LoggerSum(&c);
|
||||
if (!inRange) {
|
||||
if (lastt != 0) {
|
||||
LoggerPut(&c, lastt, lastval);
|
||||
}
|
||||
}
|
||||
LoggerPut(&c, 0, ""); /* finish */
|
||||
log = LoggerFind(argv[i]);
|
||||
if (log) { /* add actual value if it is within range */
|
||||
if (to >= log->last) {
|
||||
c.slast[0]='\0';
|
||||
LoggerOutStr(&c, now, log->old);
|
||||
}
|
||||
}
|
||||
if (fil) {
|
||||
fclose(fil);
|
||||
fil = NULL;
|
||||
}
|
||||
}
|
||||
snprintf(line, sizeof line, "*%d\n", loss);
|
||||
snprintf(line, sizeof line, "*%d %ld %ld\n", loss, from, to);
|
||||
SCWrite(pCon, line, eStatus);
|
||||
return 1;
|
||||
illarg:
|
||||
SCWrite(pCon, "illegal argument", eError);
|
||||
SCWrite(pCon, "illegal argument(s)", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user