new version

This commit is contained in:
zolliker
2005-09-02 12:58:59 +00:00
parent 0cb07da373
commit 42747dc024
2 changed files with 403 additions and 120 deletions

512
logger.c
View File

@ -12,28 +12,49 @@ Markus Zolliker, Sept 2004
#include <assert.h>
#include <fortify.h>
#include <errno.h>
#include <ctype.h>
#include <dirent.h>
#include "splitter.h"
#include "sics.h"
#include "logger.h"
#ifndef TECS_LOG
#include "sics.h"
#endif
#define LOGGER_NAN -999999.
#define ONE_YEAR (366*24*3600)
struct Logger {
char *name;
char old[256];
char *old;
int oldsize;
int period;
time_t last;
long pos;
int lastLn; /* 0 or the number chars counted from the second
last newline character. */
int overwrite; /* overwrite last line when value has not changed */
int oldValue; /* old value to be overwritten */
int numeric;
int exact;
Logger *next;
};
static char *dir = NULL;
static Logger *vars = NULL;
static Logger *list;
static time_t lastLife = 0;
/*--------------------------------------------------------------------------*/
Logger *LoggerFind(char *name) {
char *LoggerName(Logger *log) {
return log->name;
}
/*--------------------------------------------------------------------------*/
void LoggerSetNumeric(Logger *log, int numeric) {
if (log) {
log->numeric = numeric;
}
}
/*--------------------------------------------------------------------------*/
Logger *LoggerFind(const char *name) {
Logger *p;
p = list;
while (p != NULL) {
@ -45,38 +66,42 @@ Logger *LoggerFind(char *name) {
return NULL;
}
/*--------------------------------------------------------------------------*/
char *LoggerGetDir(void) {
#define LASTLOGTXT "#last logging entry at:\n"
void LoggerSetDir(char *dirarg) {
char path[256], line[32];
FILE *fil;
dir = dirarg;
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", (long)lastLife);
}
}
fclose(fil);
} else {
perror("open read error \n");
}
}
/*--------------------------------------------------------------------------*/
char *LoggerGetDir(void) {
char path[256];
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);
fprintf(fil, "%s%ld\n", LASTLOGTXT, (long)now);
fclose(fil);
} else {
printf("can not open %s\n", path);
@ -87,14 +112,32 @@ char *LoggerGetDir(void) {
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;
int LoggerVarPath(char *dir, char *path, int pathLen, char *name) {
int l;
int newday;
l = strlen(dir);
if (l + strlen(name) + 2 >= pathLen) {
path[0]='\0';
return 0;
}
strcpy(path, dir);
path[l] = '/'; l++;
for (;*name != '\0'; name++, l++) {
path[l] = tolower(*name);
}
path[l] = '/'; l++;
path[l] = '\0';
return l;
}
/*--------------------------------------------------------------------------*/
int LoggerWrite0(Logger *log, time_t now, int period, char *value) {
char path[256], stim[32], buf[32], chr;
struct tm *tm;
int yday;
int isdst;
int l, ext, skip, changed;
FILE *fil;
long pos;
long endPos, pos1, p;
LoggerGetDir();
if (dir == NULL) return 0;
@ -102,76 +145,193 @@ int LoggerWrite(Logger *log, time_t now, int period, char *value) {
printf("now==0\n");
}
tm = localtime(&log->last);
isdst = tm->tm_isdst;
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))) {
return 0;
log->period = -1;
}
log->last = now;
snprintf(path, sizeof path, "%s/%s/", dir, log->name);
l = strlen(path);
l = LoggerVarPath(dir, path, sizeof path, log->name);
strftime(path + l, sizeof path - l, "%m-%d.log", tm);
strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S\n", tm);
strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S", tm);
fil = fopen(path, "r+");
skip = 0;
if (fil == NULL) { /* create new file */
fil = fopen(path, "w+");
if (fil == NULL) return 0;
fputs(stim, fil);
} else { /* check if file is actual */
fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm->tm_isdst, period, log->exact);
endPos = ftell(fil);
fseek(fil, -1, SEEK_CUR);
} else { /* check if file is from today */
fgets(buf, sizeof buf, fil);
if (0 != strncmp(buf, stim, 11)) {
fclose(fil);
fil=fopen(path, "w+"); /* overwrite old logfile */
if (fil == NULL) return 0;
fputs(stim, fil);
endPos = ftell(fil);
fseek(fil, -1, SEEK_CUR);
log->period = -1;
} else {
fseek(fil, 0, SEEK_END); /* set position to end */
fseek(fil, -log->lastLn, SEEK_END); /* set position to last line */
endPos = ftell(fil) + log->lastLn;
if (endPos > 0 && log->lastLn == 0) {
/* find last newline in newly opened file */
fseek(fil, -1, SEEK_CUR);
chr = fgetc(fil);
while (chr != '\n' && ftell(fil) >= 2) {
fseek(fil, -2, SEEK_CUR);
chr = fgetc(fil);
}
fseek(fil, -1, SEEK_CUR);
} else if (now != log->last) {
skip = 1;
}
}
}
changed = (0 != strcmp(value, log->old));
if (period != log->period) {
log->period = period;
snprintf(buf, sizeof buf, "\t%d", period);
log->pos = 0;
if (log->numeric) {
snprintf(buf, sizeof buf, "\t%d", period);
} else {
strcpy(buf, "\t0");
}
changed = 1;
} else {
buf[0]='\0';
if (log->overwrite && !changed) {
skip = 0;
}
}
/*
if (log->pos > 0) {
fseek(fil, log->pos, SEEK_SET);
pos1 = 0;
chr = fgetc(fil);
while (chr != EOF) {
if (chr == '\n') {
skip--;
if (skip < 0) break;
}
chr = fgetc(fil);
}
log->pos = ftell(fil);
*/
if (chr == EOF) {
if (pos1 == 0) {
fputs("\n#no newline found\n", fil);
} else {
fseek(fil, pos1, SEEK_SET);
}
}
if (tm->tm_isdst != isdst) {
fprintf(fil, "#isdst %d\n", tm->tm_isdst);
}
pos1 = ftell(fil);
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;
for (p = ftell(fil); p < endPos; p++) { /* overwrite dirt after last line */
fprintf(fil, " ");
}
strncpy(log->old, value, l);
log->old[l] = '\0';
endPos = ftell(fil);
fclose(fil);
log->lastLn = (endPos - pos1) + 1;
/* overwrite next time when value has not changed */
log->overwrite = ! changed;
l = strlen(value);
if (l >= log->oldsize) {
ext = ((l - log->oldsize)/16 + 1) * 16;
if (ext < log->oldsize / 4) ext += (log->oldsize / 64) * 16;
log->oldsize += ext;
free(log->old);
log->old = calloc(1, log->oldsize);
assert(log->old);
assert(l < log->oldsize);
}
strcpy(log->old, value);
log->old[l] = '\0';
log->last = now;
return 1;
}
/*--------------------------------------------------------------------------*/
int LoggerWrite(Logger *log, time_t now, int period, char *value) {
Logger *p;
time_t h0;
static int yday = -1;
struct tm *tm;
int l;
FILE *fil;
char path[PATH_MAX];
char tim[256];
tm = localtime(&now);
if (tm->tm_yday != yday) {
tm->tm_hour = 0;
tm->tm_min = 0;
tm->tm_sec = 0;
h0 = mktime(tm);
yday = tm->tm_yday;
l = LoggerVarPath(dir, path, sizeof path, "debug");
strftime(path + l, sizeof path - l, "%m-%d.log", tm);
fil=fopen(path, "a");
if (fil) {
strftime(tim, sizeof tim, "h0 %m-%d %H:%M:%S\n", localtime(&h0));
fputs(tim, fil);
}
/* log old values (forced midnight log) */
p = list;
while (p != NULL) {
if (fil) {
strftime(tim, sizeof tim, "last %m-%d %H:%M:%S, ", localtime(&p->last));
fputs(tim, fil);
fprintf(fil, "period %d, name %s, old %s\n", p->period, p->name, p->old);
}
if (p->last < h0 && p->last != 0 &&
p->period >= 0 && p->old[0] != '\0') {
LoggerWrite0(p, h0, p->period, p->old);
p->overwrite = 0;
}
p = p->next;
}
if (fil) fclose(fil);
}
return LoggerWrite0(log, now, period, value);
}
/*--------------------------------------------------------------------------*/
time_t LoggerLastTime(Logger *log) {
if (log->last != 0 && log->period > 0) {
return log->last;
}
return 0;
}
/*--------------------------------------------------------------------------*/
int LoggerGetValue(void *data, char *value, int size) {
Logger *log = data;
value[0]='\0';
strncat(value, log->old, size - 1);
return 1;
}
/*--------------------------------------------------------------------------*/
void LoggerKill(Logger *log) {
/* 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, "");
if (list != NULL) { /* LoggerFreeAll not yet called */
LoggerWrite(log, time(NULL), 0, "");
}
}
/*--------------------------------------------------------------------------*/
Logger *LoggerMake(char *name, int period) {
Logger *log, *p;
Logger *LoggerMake(char *name, int period, int exact) {
Logger *log;
char path[256];
struct stat st;
int i;
time_t t;
LoggerGetDir();
if (dir == NULL) return NULL;
snprintf(path, sizeof path, "%s/%s", dir, name);
LoggerVarPath(dir, path, sizeof path, name);
i = stat(path, &st);
if (i >= 0) {
if (((st.st_mode >> 12) & 15) != 4) { /* exists, but is no directory */
@ -183,17 +343,20 @@ Logger *LoggerMake(char *name, int period) {
}
log = LoggerFind(name); /* look if logger already exists */
if (log == NULL) {
log = malloc(sizeof *log);
log = calloc(1, 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->period = -1;
log->exact = exact;
log->old = calloc(1,12);
log->oldsize = 12;
log->last = 0;
log->pos = 0;
log->lastLn = 0;
log->numeric = 1;
log->next = list;
list = log;
t = time(NULL) -1;
@ -205,10 +368,13 @@ Logger *LoggerMake(char *name, int period) {
return log;
}
/*--------------------------------------------------------------------------*/
typedef enum { numeric, text } CompType;
#ifndef TECS_LOG
typedef enum { NUMERIC, TEXT } CompType;
typedef struct {
SConnection *pCon;
char *var;
int exact;
CompType type;
time_t step;
time_t tlim;
@ -216,9 +382,12 @@ typedef struct {
float ymin, ymax, ylast, yold;
char slast[256];
char set[256];
int np;
} Compressor;
static void LoggerInit(Compressor *c, SConnection *pCon, time_t step) {
static char *dir2 = NULL;
static void LoggerInitC(Compressor *c, SConnection *pCon, time_t step) {
c->pCon = pCon;
c->step = step;
c->tmin = -2;
@ -226,6 +395,7 @@ static void LoggerInit(Compressor *c, SConnection *pCon, time_t step) {
c->tlast = 0;
c->tlim = 0;
c->told = 0;
c->slast[0]='\0';
c->ylast = LOGGER_NAN;
}
@ -234,11 +404,12 @@ static void LoggerOutStr(Compressor *c, time_t t, char *str) {
/* printf("out %ld %g\n", t, y); */
if (0 != strcmp(str, c->slast)) {
snprintf(line, sizeof line, "%ld %s\n", t - c->tlast, str);
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, eStatus);
SCWrite(c->pCon, line, eWarning);
c->np--;
}
}
@ -249,13 +420,14 @@ static void LoggerOut(Compressor *c, time_t t, float y) {
if (y != c->ylast) {
c->ylast = y;
if (y == LOGGER_NAN) {
snprintf(line, sizeof line, "%ld\n", t - c->tlast);
snprintf(line, sizeof line, "%ld\n", (long)(t - c->tlast));
} else {
snprintf(line, sizeof line, "%ld %g\n", t - c->tlast, y);
snprintf(line, sizeof line, "%ld %g\n", (long)(t - c->tlast), y);
}
/* printf("-%s\n", line); */
c->tlast = t;
SCWrite(c->pCon, line, eStatus);
SCWrite(c->pCon, line, eWarning);
c->np--;
}
}
@ -263,7 +435,11 @@ static void LoggerPut(Compressor *c, time_t t, char *value) {
char *p;
double y;
if (c->type == numeric) {
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;
@ -314,7 +490,7 @@ static void LoggerPut(Compressor *c, time_t t, char *value) {
c->ymin = y;
c->ymax = y;
return;
} else if (c->type == text) {
} else if (c->type == TEXT) {
if (t != 0) LoggerOutStr(c, t, value);
}
}
@ -324,8 +500,9 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
time_t from, to, step, xs, lastt, now;
long lxs;
char *p;
int i, l, yday, iret, loss;
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];
@ -333,59 +510,93 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
FILE *fil;
Compressor c;
float yy, lasty;
Logger *log;
CompType type0;
DIR *dr;
char *opt;
int isdst;
int overflow;
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);
/* 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 (strcmp(argv[3],"text") == 0) { /* non-numeric values */
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;
c.type = text;
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);
c.type = numeric;
if (step <= 0) step = 1;
type0 = NUMERIC;
np = (from - to) / step + 2;
}
if (p == argv[3]) goto illarg;
if (from <= 0) from += now;
if (to <= 0) to += now;
if (step <= 0) step = 1;
LoggerGetDir();
snprintf(line, sizeof line, "%ld\n", (long)now);
SCWrite(pCon, line, eWarning);
if (dir == NULL) {
SCWrite(pCon, "LoggerDir not found", eError);
return 0;
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;
for (i=4; i<argc; i++) {
overflow = 0;
for (i=iarg0; i<argc; i++) {
startim = from;
t = 0;
lastt = 0;
inRange = 0;
xs = step;
LoggerInit(&c, pCon, step);
snprintf(path, sizeof path, "%s/%s/", dir, argv[i]);
l = strlen(path);
LoggerInitC(&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;
snprintf(line, sizeof line, "*%s\n", argv[i]);
SCWrite(pCon, line, eStatus);
while (startim <= to) {
while (startim <= to && c.tlast <= to) {
tm = *localtime(&startim);
if (tm.tm_yday != yday) {
if (fil != NULL) { /* close file if day changed */
@ -397,24 +608,68 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
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 */
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 {
opt = strstr(line, "isdst");
if (opt) {
sscanf(opt, "isdst %d", &isdst);
}
opt = strstr(line, "exact");
if (opt) {
sscanf(opt, "exact %d", &c.exact);
}
opt = strstr(line, "period");
if (opt) {
sscanf(opt, "period %ld", &lxs);
if (lxs == 0) {
c.type = TEXT;
} else {
c.type = type0;
xs = lxs;
}
if (xs < step) {
loss = 1;
xs = step;
}
}
}
}
}
if (fil == NULL) {
lin == 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';
if (strncmp(line, "#isdst", 6) == 0) {
sscanf(line, "#isdst %d", &isdst);
lin[0]='\0';
} else if (strncmp(line, "#exact", 6) == 0) {
sscanf(line, "#exact %d", &c.exact);
lin[0]='\0';
} else if (strncmp(line, "#period", 7) == 0) {
sscanf(line, "#period %ld", &lxs);
lin[0]='\0';
if (lxs == 0) {
c.type = TEXT;
} else {
c.type = type0;
xs = lxs;
}
if (xs < step) {
loss = 1;
xs = step;
}
} else {
p = strchr(line, '\n'); if (p) *p='\0';
p = strchr(line, '#'); if (p) *p='\0';
}
} while (lin[0] == '\0');
}
if (lin != NULL) {
@ -430,8 +685,14 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
if (p) {
stp = p+1;
*p='\0';
iret = sscanf(stp, "%ld", &lxs); xs = lxs;
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;
@ -442,7 +703,7 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
if (iret != 3) {
lin = NULL;
} else {
tm.tm_isdst = -1;
tm.tm_isdst = isdst;
t=mktime(&tm);
if (!inRange) {
if (t < startim) {
@ -475,23 +736,38 @@ int LoggerGraph(SConnection *pCon, SicsInterp *pSics, void *pData,
LoggerPut(&c, lastt, lastval);
}
}
c.ylast = LOGGER_NAN; /* force output of last value */
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;
}
if (c.np < 0) overflow = 1;
}
snprintf(line, sizeof line, "*%d %ld %ld\n", loss, from, to);
SCWrite(pCon, line, eStatus);
snprintf(line, sizeof line, "*%d %d\n", loss, overflow);
SCWrite(pCon, line, eWarning);
return 1;
illarg:
SCWrite(pCon, "illegal argument(s)", eError);
return 0;
}
/*--------------------------------------------------------------------------*/
void LoggerFreeAll(void *data) {
Logger *p, *next;
KillDummy(data);
p = list;
while (p != NULL) {
next = p->next;
if (p->name) free(p->name);
if (p->old) free(p->old);
free(p);
p = next;
}
list = NULL;
}
/*--------------------------------------------------------------------------*/
void LoggerInit(void) {
AddCommand(pServ->pSics,"Graph",LoggerGraph,LoggerFreeAll,NULL);
}
#endif /* TECS_LOG */

View File

@ -1,5 +1,5 @@
/*---------------------------------------------------------------------------
logger.c
logger.h
Markus Zolliker, Sept 2004
----------------------------------------------------------------------------
@ -12,8 +12,15 @@ Markus Zolliker, Sept 2004
typedef struct Logger Logger;
Logger *LoggerMake(char *name, int period);
Logger *LoggerMake(char *name, int period, int exact);
void LoggerKill(Logger *log);
int LoggerWrite(Logger *log, time_t now, int period, char *value);
char *LoggerName(Logger *log);
void LoggerSetNumeric(Logger *log, int numeric);
void LoggerSetDir(char *dirarg);
void LoggerWriteOld(Logger *log, time_t now);
time_t LoggerLastTime(Logger *log);
int LoggerGetStatus(Logger *log);
void LoggerSetStatus(Logger *log, int status);
#endif