- introduced logsetup and savehdb
- moved logger.c and logreader.c for sics/psi/ to sics/ - make comments in status file
This commit is contained in:
5
exebuf.c
5
exebuf.c
@ -243,6 +243,8 @@ int exeBufProcessErrList(pExeBuf self, SicsInterp *pSics,
|
|||||||
static int weWantLogging = 1;
|
static int weWantLogging = 1;
|
||||||
char *cmd;
|
char *cmd;
|
||||||
char cmdName[128];
|
char cmdName[128];
|
||||||
|
char *error;
|
||||||
|
char msg[132];
|
||||||
char *ende;
|
char *ende;
|
||||||
int l;
|
int l;
|
||||||
|
|
||||||
@ -260,6 +262,9 @@ int exeBufProcessErrList(pExeBuf self, SicsInterp *pSics,
|
|||||||
status = Tcl_Eval(pTcl,cmd);
|
status = Tcl_Eval(pTcl,cmd);
|
||||||
if(status != TCL_OK){
|
if(status != TCL_OK){
|
||||||
LLDstringAppend(errList,cmd);
|
LLDstringAppend(errList,cmd);
|
||||||
|
error = (char *)Tcl_GetStringResult(pTcl);
|
||||||
|
snprintf(msg, sizeof msg, "#ERR: %s\n", error);
|
||||||
|
LLDstringAppend(errList,msg);
|
||||||
}
|
}
|
||||||
DeleteDynString(command);
|
DeleteDynString(command);
|
||||||
if(SCGetInterrupt(pCon) >= eAbortBatch){
|
if(SCGetInterrupt(pCon) >= eAbortBatch){
|
||||||
|
372
logger.c
Normal file
372
logger.c
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
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 <ctype.h>
|
||||||
|
#include "logger.h"
|
||||||
|
|
||||||
|
struct Logger {
|
||||||
|
char *name;
|
||||||
|
char *old;
|
||||||
|
int oldsize;
|
||||||
|
int period;
|
||||||
|
time_t last;
|
||||||
|
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 numeric;
|
||||||
|
int exact;
|
||||||
|
double oldFloat, newFloat;
|
||||||
|
time_t newTime;
|
||||||
|
Logger *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
static char *dir = NULL;
|
||||||
|
static Logger *list;
|
||||||
|
static time_t lastLife = 0;
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
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) {
|
||||||
|
if (0==strcasecmp(name, p->name)) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
p = p->next;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
#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 {
|
||||||
|
printf("can not read %s\n", path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
char *LoggerGetDir(void) {
|
||||||
|
char path[256];
|
||||||
|
FILE *fil;
|
||||||
|
time_t now;
|
||||||
|
static time_t last;
|
||||||
|
|
||||||
|
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, (long)now);
|
||||||
|
fclose(fil);
|
||||||
|
} else {
|
||||||
|
printf("can not write %s\n", path);
|
||||||
|
}
|
||||||
|
last = now;
|
||||||
|
}
|
||||||
|
return dir;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
int LoggerVarPath(char *dir, char *path, int pathLen, char *name) {
|
||||||
|
int l;
|
||||||
|
|
||||||
|
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 endPos, pos1, p;
|
||||||
|
char info[80];
|
||||||
|
|
||||||
|
LoggerGetDir();
|
||||||
|
if (dir == NULL) return 0;
|
||||||
|
if (now == 0) {
|
||||||
|
printf("now==0\n");
|
||||||
|
}
|
||||||
|
tm = localtime(&log->last);
|
||||||
|
isdst = tm->tm_isdst; /* last isdst */
|
||||||
|
yday = tm->tm_yday; /* last day */
|
||||||
|
tm = localtime(&now);
|
||||||
|
if (tm->tm_yday != yday) {
|
||||||
|
log->period = -1;
|
||||||
|
}
|
||||||
|
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", tm);
|
||||||
|
|
||||||
|
fil = fopen(path, "r+");
|
||||||
|
skip = 0;
|
||||||
|
if (period <= 0) period = 1;
|
||||||
|
if (fil == NULL) { /* create new file */
|
||||||
|
fil = fopen(path, "w+");
|
||||||
|
if (fil == NULL) return 0;
|
||||||
|
fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm->tm_isdst, period, log->exact);
|
||||||
|
log->period = period;
|
||||||
|
isdst = tm->tm_isdst;
|
||||||
|
endPos = ftell(fil);
|
||||||
|
fseek(fil, -1, SEEK_CUR); /* position to newline */
|
||||||
|
} 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;
|
||||||
|
fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm->tm_isdst, period, log->exact);
|
||||||
|
log->period = period;
|
||||||
|
isdst = tm->tm_isdst;
|
||||||
|
endPos = ftell(fil);
|
||||||
|
fseek(fil, -1, SEEK_CUR); /* position to newline */
|
||||||
|
} else {
|
||||||
|
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); /* position to newline */
|
||||||
|
} else if (now != log->last) {
|
||||||
|
skip = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
changed = (0 != strcmp(value, log->old));
|
||||||
|
info[0]='\0';
|
||||||
|
if (period != log->period) {
|
||||||
|
log->period = period;
|
||||||
|
if (log->numeric) {
|
||||||
|
changed = 1;
|
||||||
|
snprintf(info, sizeof info, "period %d exact %d ", period, log->exact);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (log->overwrite && !changed) {
|
||||||
|
skip = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* go to next newline */
|
||||||
|
chr = fgetc(fil);
|
||||||
|
while (chr != EOF) {
|
||||||
|
if (chr == '\n') {
|
||||||
|
skip--;
|
||||||
|
if (skip < 0) break;
|
||||||
|
}
|
||||||
|
chr = fgetc(fil);
|
||||||
|
}
|
||||||
|
if (chr == EOF) {
|
||||||
|
fputs("\n#no newline found\n", fil);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tm->tm_isdst != isdst || info[0] != '\0') {
|
||||||
|
fprintf(fil, "#isdst %d %s\n", tm->tm_isdst, info);
|
||||||
|
}
|
||||||
|
pos1 = ftell(fil);
|
||||||
|
strftime(stim, sizeof stim,"%H:%M:%S", tm);
|
||||||
|
fprintf(fil, "%s\t%s\n", stim, value);
|
||||||
|
for (p = ftell(fil); p < endPos; p++) { /* overwrite dirt after last line */
|
||||||
|
fprintf(fil, " ");
|
||||||
|
}
|
||||||
|
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[256];
|
||||||
|
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 LoggerPeriod(Logger *log) {
|
||||||
|
return log->period;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
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 */
|
||||||
|
|
||||||
|
if (list != NULL) { /* LoggerFreeAll not yet called */
|
||||||
|
LoggerWrite(log, time(NULL), 0, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
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;
|
||||||
|
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 */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
i = mkdir(path, S_IRWXU+S_IRGRP+S_IXGRP+S_IROTH+S_IXOTH);
|
||||||
|
if (i < 0) return NULL; /* mkdir failed */
|
||||||
|
}
|
||||||
|
log = LoggerFind(name); /* look if logger already exists */
|
||||||
|
if (log == NULL) {
|
||||||
|
log = calloc(1, sizeof *log);
|
||||||
|
if (log == NULL) return NULL;
|
||||||
|
log->name = strdup(name);
|
||||||
|
if (log->name == NULL) {
|
||||||
|
free(log);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
log->period = -1;
|
||||||
|
log->exact = exact;
|
||||||
|
log->old = calloc(1,12);
|
||||||
|
log->oldsize = 12;
|
||||||
|
log->last = 0;
|
||||||
|
log->lastLn = 0;
|
||||||
|
log->numeric = 1;
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
return log;
|
||||||
|
}
|
||||||
|
/*--------------------------------------------------------------------------*/
|
||||||
|
void LoggerFreeAll(void) {
|
||||||
|
Logger *p, *next;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
27
logger.h
Normal file
27
logger.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
logger.h
|
||||||
|
|
||||||
|
Markus Zolliker, Sept 2004
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef LOGGER_H
|
||||||
|
#define LOGGER_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
typedef struct Logger Logger;
|
||||||
|
|
||||||
|
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 LoggerPeriod(Logger *log);
|
||||||
|
int LoggerVarPath(char *dir, char *path, int pathLen, char *name);
|
||||||
|
void LoggerFreeAll(void);
|
||||||
|
|
||||||
|
#endif
|
492
logreader.c
Normal file
492
logreader.c
Normal file
@ -0,0 +1,492 @@
|
|||||||
|
#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)
|
||||||
|
#define LLEN 1024
|
||||||
|
|
||||||
|
typedef enum { NUMERIC, TEXT } CompType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SConnection *pCon;
|
||||||
|
char var[1024];
|
||||||
|
int exact;
|
||||||
|
CompType type;
|
||||||
|
time_t step;
|
||||||
|
time_t tlim;
|
||||||
|
time_t tmin, tmax, tlast, told;
|
||||||
|
float ymin, ymax, ylast, yold;
|
||||||
|
char slast[LLEN];
|
||||||
|
/* char set[LLEN]; */
|
||||||
|
int np;
|
||||||
|
char *none;
|
||||||
|
} 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[LLEN];
|
||||||
|
|
||||||
|
/* 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 && t != c->tlast)) {
|
||||||
|
c->ylast = y;
|
||||||
|
if (y == LOGGER_NAN) {
|
||||||
|
if (c->none) {
|
||||||
|
snprintf(line, sizeof line, "%ld %s\n", (long)(t - c->tlast), c->none);
|
||||||
|
} else {
|
||||||
|
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[0]) {
|
||||||
|
SCPrintf(c->pCon, eWarning, "*%s exact %d\n", c->var, c->exact);
|
||||||
|
c->var[0] = 0;
|
||||||
|
}
|
||||||
|
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[]) {
|
||||||
|
/* Usage:
|
||||||
|
graph <start time> <end time> [ none <none value> ] np <number of points> <variable> [<variable> ...]
|
||||||
|
graph <start time> <end time> text <variable>
|
||||||
|
graph <start time> <end time> <step> <variable> [<variable> ...]
|
||||||
|
|
||||||
|
<start time> and <end time> are seconds since epoch (unix time) or, if the value
|
||||||
|
is below one day, a time relative to the actual time
|
||||||
|
|
||||||
|
The <none value> is optional. if not given, unknown values are returned as empty strings
|
||||||
|
|
||||||
|
<number of points> is the maximal number of points to be returned. If more values
|
||||||
|
are present and the values are numeric, the data is reduced. If the data is not
|
||||||
|
numeric, the last values may be skipped in order to avoid overflow.
|
||||||
|
|
||||||
|
<variable> is the name of a variable (several vaiables may be given).
|
||||||
|
Note that slashes are converted to dots, and that the first slash is ignored.
|
||||||
|
|
||||||
|
The seconds variant is for text values, which can not be reduced. In any case, all values
|
||||||
|
are returned.
|
||||||
|
|
||||||
|
The third variant is old style and can be replaced by the first variant, where
|
||||||
|
<number of points> = (<start time> - <end time>) / <step> + 2
|
||||||
|
|
||||||
|
|
||||||
|
Output format:
|
||||||
|
First line: returning the actual time on the server (this time is used for relative times)
|
||||||
|
|
||||||
|
For each variable which has data in the given interval,
|
||||||
|
the variable name is returned preceeded by a '*', followed by some options* separated with
|
||||||
|
blanks.
|
||||||
|
After the header line for every data point a line follows with
|
||||||
|
a time relative to the last point and the value.
|
||||||
|
The first time value relative to zero, e.g. absolute.
|
||||||
|
The data value is valid until the next datapoint. Empty values are returned as an
|
||||||
|
empty string or as the <none value>.
|
||||||
|
|
||||||
|
At the very end *<loss> <overflow> is returned.
|
||||||
|
<loss> is 1, when the data had to be reduced, 0 else
|
||||||
|
<overflow> is 1, when overflow occured, 0 else. Overflow may happen only
|
||||||
|
when np is given and a text variable was demanded.
|
||||||
|
|
||||||
|
*actually only one option exists (you might ignore it):
|
||||||
|
exact <value>
|
||||||
|
<value> is 1 when the value is exact, i.e. an integer.
|
||||||
|
<value> is 0 else.
|
||||||
|
*/
|
||||||
|
time_t from, to, step, xs, lastt, now;
|
||||||
|
long lxs;
|
||||||
|
char *p, *varp;
|
||||||
|
int i, j, iarg, l, iret, loss, np;
|
||||||
|
int inRange;
|
||||||
|
int yday=0;
|
||||||
|
time_t t, startim;
|
||||||
|
struct tm tm;
|
||||||
|
char stim[32], path[LLEN], line[LLEN], lastval[LLEN];
|
||||||
|
char *lin, *val, *stp;
|
||||||
|
FILE *fil;
|
||||||
|
Compressor c={0};
|
||||||
|
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], &p, 0);
|
||||||
|
if (p == argv[2]) goto illarg;
|
||||||
|
if (from < ONE_YEAR) {
|
||||||
|
from += now;
|
||||||
|
}
|
||||||
|
if (to < ONE_YEAR) {
|
||||||
|
to += now;
|
||||||
|
}
|
||||||
|
iarg = 3;
|
||||||
|
while (1) {
|
||||||
|
if (iarg>=argc) goto illarg;
|
||||||
|
if (strcasecmp(argv[iarg],"text") == 0) { /* non-numeric values */
|
||||||
|
iarg++;
|
||||||
|
step = 1;
|
||||||
|
type0 = TEXT;
|
||||||
|
np = to - from + 2;
|
||||||
|
break;
|
||||||
|
} else if (strcasecmp(argv[iarg],"none") == 0) { /* none */
|
||||||
|
iarg++;
|
||||||
|
if (iarg >= argc) goto illarg;
|
||||||
|
c.none = argv[iarg];
|
||||||
|
iarg++;
|
||||||
|
} else if (strcasecmp(argv[iarg],"np") == 0) { /* max. number of points */
|
||||||
|
iarg++;
|
||||||
|
if (iarg >= argc) goto illarg;
|
||||||
|
type0 = NUMERIC;
|
||||||
|
np = strtol(argv[iarg], &p, 0);
|
||||||
|
if (p == argv[iarg]) goto illarg;
|
||||||
|
iarg++;
|
||||||
|
if (to <= from) {
|
||||||
|
step = 1;
|
||||||
|
} else if (np <= 2) {
|
||||||
|
step = to - from;
|
||||||
|
} else {
|
||||||
|
step = (to - from) / (np - 2) + 1;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
step = strtol(argv[iarg], &p, 0);
|
||||||
|
if (p == argv[iarg]) goto illarg;
|
||||||
|
iarg++;
|
||||||
|
if (step <= 0) step = 1;
|
||||||
|
type0 = NUMERIC;
|
||||||
|
np = (from - to) / step + 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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, "ERROR: 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=iarg; i<argc; i++) {
|
||||||
|
startim = from;
|
||||||
|
t = 0;
|
||||||
|
lastt = 0;
|
||||||
|
inRange = 0;
|
||||||
|
xs = step;
|
||||||
|
InitCompressor(&c, pCon, step);
|
||||||
|
|
||||||
|
/* convert slashes to dots */
|
||||||
|
varp = argv[i];
|
||||||
|
if (*varp == '/') varp++;
|
||||||
|
for (j = 0; j < sizeof(c.var) && *varp != 0; j++, varp++) {
|
||||||
|
if (*varp == '/') {
|
||||||
|
c.var[j] = '.';
|
||||||
|
} else {
|
||||||
|
c.var[j] = *varp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
86
logsetup.c
Normal file
86
logsetup.c
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#include "logger.h"
|
||||||
|
#include "sics.h"
|
||||||
|
#include "sicshipadaba.h"
|
||||||
|
|
||||||
|
static int LoggerUpdateCallback(void *user, void *conn, pHdb node, hdbValue value) {
|
||||||
|
Logger *logger = user;
|
||||||
|
pDynString str;
|
||||||
|
|
||||||
|
str = formatValue(value, node);
|
||||||
|
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str));
|
||||||
|
DeleteDynString(str);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int LogSetup(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||||
|
int argc, char *argv[]) {
|
||||||
|
pHdb node;
|
||||||
|
pHdbCallback cb;
|
||||||
|
static char basepath[1024]="/";
|
||||||
|
char buf[1024];
|
||||||
|
char *p, *name;
|
||||||
|
static char *loggerDir=NULL;
|
||||||
|
int numeric, period;
|
||||||
|
Logger *logger;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
SCPrintf(pCon, eError, "ERROR: should be: logsetup <node> [<period> [<filename>]]");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (strcasecmp(argv[1], "basepath") == 0) {
|
||||||
|
if (argc > 2) {
|
||||||
|
snprintf(basepath, sizeof basepath, "%s", argv[2]);
|
||||||
|
}
|
||||||
|
SCPrintf(pCon, eValue, "%s", basepath);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (loggerDir == NULL) {
|
||||||
|
loggerDir = IFindOption(pSICSOptions, "LoggerDir");
|
||||||
|
if (loggerDir == NULL) loggerDir="./";
|
||||||
|
LoggerSetDir(loggerDir);
|
||||||
|
}
|
||||||
|
if (strcasecmp(argv[1], "directory") == 0) {
|
||||||
|
if (argc > 2) {
|
||||||
|
loggerDir = strdup(argv[2]);
|
||||||
|
}
|
||||||
|
SCPrintf(pCon, eValue, "%s", loggerDir);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
node = FindHdbNode(basepath, argv[1], pCon);
|
||||||
|
if (node == NULL) {
|
||||||
|
SCPrintf(pCon, eError, "ERROR: %s not found", argv[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
period = 0;
|
||||||
|
if (argc > 2) {
|
||||||
|
period = atoi(argv[2]);
|
||||||
|
}
|
||||||
|
if (argc > 3) {
|
||||||
|
snprintf(buf, sizeof buf, "%s", argv[3]);
|
||||||
|
} else {
|
||||||
|
snprintf(buf, sizeof buf, "%s", argv[1]);
|
||||||
|
}
|
||||||
|
for (p = buf; *p != '\0'; p++) {
|
||||||
|
if (*p =='/') *p = '.';
|
||||||
|
}
|
||||||
|
if (buf[0] == '.') {
|
||||||
|
name = buf+1;
|
||||||
|
} else {
|
||||||
|
name = buf;
|
||||||
|
}
|
||||||
|
if (node->value.dataType == HIPFLOAT) {
|
||||||
|
numeric = 1;
|
||||||
|
} else {
|
||||||
|
numeric = 0;
|
||||||
|
}
|
||||||
|
logger = LoggerMake(name, period, !numeric);
|
||||||
|
LoggerSetNumeric(logger, numeric);
|
||||||
|
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger, (void (*)(void *))LoggerKill, -1, NULL);
|
||||||
|
assert(cb);
|
||||||
|
AppendHipadabaCallback(node, HCBUPDATE, cb);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void LogSetupInit(void) {
|
||||||
|
AddCmd("LogSetup",LogSetup);
|
||||||
|
}
|
10
ofac.c
10
ofac.c
@ -281,7 +281,6 @@
|
|||||||
AddCommand(pInter,"MakeCounter",MakeCounter,NULL,NULL);
|
AddCommand(pInter,"MakeCounter",MakeCounter,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeO2T",CreateO2T,NULL,NULL);
|
AddCommand(pInter,"MakeO2T",CreateO2T,NULL,NULL);
|
||||||
AddCommand(pInter,"SicsAlias",SicsAlias,NULL,NULL);
|
AddCommand(pInter,"SicsAlias",SicsAlias,NULL,NULL);
|
||||||
AddCommand(pInter,"SicsAlias",DefineAlias,NULL,NULL);
|
|
||||||
AddCommand(pInter,"DefineAlias",DefineAlias,NULL,NULL); /* M.Z. */
|
AddCommand(pInter,"DefineAlias",DefineAlias,NULL,NULL); /* M.Z. */
|
||||||
AddCommand(pInter,"MakeHM",MakeHistMemory,NULL,NULL);
|
AddCommand(pInter,"MakeHM",MakeHistMemory,NULL,NULL);
|
||||||
AddCommand(pInter,"VelocitySelector",VelSelFactory,NULL,NULL);
|
AddCommand(pInter,"VelocitySelector",VelSelFactory,NULL,NULL);
|
||||||
@ -343,6 +342,7 @@
|
|||||||
AddCommand(pInter,"MakeAsyncProtocol",AsyncProtocolFactory,NULL,NULL);
|
AddCommand(pInter,"MakeAsyncProtocol",AsyncProtocolFactory,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeAsyncQueue",AsyncQueueFactory,NULL,NULL);
|
AddCommand(pInter,"MakeAsyncQueue",AsyncQueueFactory,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeSicsObj",InstallSICSOBJ,NULL,NULL);
|
AddCommand(pInter,"MakeSicsObj",InstallSICSOBJ,NULL,NULL);
|
||||||
|
AddCommand(pInter,"DynSicsObj",InstallSICSOBJ,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeHdbQueue",MakeHDBQueue,NULL,NULL);
|
AddCommand(pInter,"MakeHdbQueue",MakeHDBQueue,NULL,NULL);
|
||||||
AddCommand(pInter,"MakeGenController",GenControllerFactory,NULL,NULL);
|
AddCommand(pInter,"MakeGenController",GenControllerFactory,NULL,NULL);
|
||||||
AddCommand(pInter,"genconfigure",GenControllerConfigure,NULL,NULL);
|
AddCommand(pInter,"genconfigure",GenControllerConfigure,NULL,NULL);
|
||||||
@ -435,11 +435,15 @@
|
|||||||
|
|
||||||
/* insert here initialization routines ... */
|
/* insert here initialization routines ... */
|
||||||
|
|
||||||
INIT(SiteInit); /* site specific initializations */
|
|
||||||
INIT(StatisticsInit);
|
INIT(StatisticsInit);
|
||||||
|
INIT(InitializerInit);
|
||||||
|
INIT(SaveHdbInit); /* must be after InitializerInit */
|
||||||
INIT(SctStartup);
|
INIT(SctStartup);
|
||||||
|
INIT(LogReaderInit);
|
||||||
|
INIT(LogSetupInit);
|
||||||
|
|
||||||
}
|
INIT(SiteInit); /* site specific initializations */
|
||||||
|
}
|
||||||
/*--------------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------------*/
|
||||||
int InitObjectCommands(pServer pServ, char *file)
|
int InitObjectCommands(pServer pServ, char *file)
|
||||||
{
|
{
|
||||||
|
91
savehdb.c
Normal file
91
savehdb.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include "dynstring.h"
|
||||||
|
#include "sicshipadaba.h"
|
||||||
|
|
||||||
|
static pDummy creationCommands = NULL;
|
||||||
|
static int saveit = 0;
|
||||||
|
|
||||||
|
static void SaveHdbBranch(pHdb node, FILE *fil) {
|
||||||
|
pHdb child;
|
||||||
|
char prop[16];
|
||||||
|
pDynString dyn;
|
||||||
|
char path[1024];
|
||||||
|
|
||||||
|
if (GetHdbProperty(node, "save", prop, sizeof prop)) {
|
||||||
|
if (strcmp(prop, "me") == 0) {
|
||||||
|
dyn = formatValue(node->value, node);
|
||||||
|
GetHdbPath(node, path, sizeof path);
|
||||||
|
fprintf(fil, "hupdate %s %s\n", path, GetCharArray(dyn));
|
||||||
|
DeleteDynString(dyn);
|
||||||
|
}
|
||||||
|
for (child = node->child; child != NULL; child = child->next) {
|
||||||
|
SaveHdbBranch(child, fil);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SaveHdbTree(void *object, char *name, FILE *fil) {
|
||||||
|
pHdb node;
|
||||||
|
|
||||||
|
SaveHdbBranch(GetHipadabaRoot(), fil);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SaveHdbCallback(void *user, void *conn, pHdb node, hdbValue value) {
|
||||||
|
saveit = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int SaveHdbEnable(SConnection *con, SicsInterp *sics,
|
||||||
|
void *data, int argc, char *argv[]) {
|
||||||
|
pHdb node;
|
||||||
|
char prop[16];
|
||||||
|
pHdbCallback cb;
|
||||||
|
|
||||||
|
if (argc < 2) {
|
||||||
|
SCPrintf(con, eError, "ERROR: should be: %s <path>", argv[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = FindHdbNode(NULL, argv[1], con);
|
||||||
|
if (!node) {
|
||||||
|
SCPrintf(con, eError, "ERROR: %s not found", argv[1]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
cb = MakeHipadabaCallback(SaveHdbCallback, NULL, NULL, -1, NULL);
|
||||||
|
assert(cb);
|
||||||
|
AppendHipadabaCallback(node, HCBUPDATE, cb);
|
||||||
|
|
||||||
|
SetHdbProperty(node, "save", "me");
|
||||||
|
for (node = node->mama; node != NULL; node = node->mama) {
|
||||||
|
if (!GetHdbProperty(node, "save", prop, sizeof prop)) {
|
||||||
|
SetHdbProperty(node, "save", "kids");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
saveit = 1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SaveHdbTask(void *data) {
|
||||||
|
char *pFile = NULL;
|
||||||
|
|
||||||
|
if (saveit) {
|
||||||
|
saveit = 0;
|
||||||
|
|
||||||
|
assert(pServ->pSics);
|
||||||
|
pFile = IFindOption(pSICSOptions,"statusfile");
|
||||||
|
if (pFile) {
|
||||||
|
WriteSicsStatus(pServ->pSics,pFile,0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SaveHdbInit(void) {
|
||||||
|
pDummy hs = NULL;
|
||||||
|
|
||||||
|
hs = CreateDummy("hdb saver");
|
||||||
|
hs->pDescriptor->SaveStatus = SaveHdbTree;
|
||||||
|
AddCommandWithFlag(pServ->pSics, "hsave", SaveHdbEnable, KillDummy, hs, 0);
|
||||||
|
TaskRegister(pServ->pTasker, SaveHdbTask, NULL, NULL, NULL, 0);
|
||||||
|
}
|
Reference in New Issue
Block a user