diff --git a/exebuf.c b/exebuf.c index 3fad44f1..15d347dd 100644 --- a/exebuf.c +++ b/exebuf.c @@ -243,6 +243,8 @@ int exeBufProcessErrList(pExeBuf self, SicsInterp *pSics, static int weWantLogging = 1; char *cmd; char cmdName[128]; + char *error; + char msg[132]; char *ende; int l; @@ -260,6 +262,9 @@ int exeBufProcessErrList(pExeBuf self, SicsInterp *pSics, status = Tcl_Eval(pTcl,cmd); if(status != TCL_OK){ LLDstringAppend(errList,cmd); + error = (char *)Tcl_GetStringResult(pTcl); + snprintf(msg, sizeof msg, "#ERR: %s\n", error); + LLDstringAppend(errList,msg); } DeleteDynString(command); if(SCGetInterrupt(pCon) >= eAbortBatch){ diff --git a/logger.c b/logger.c new file mode 100644 index 00000000..a6132b57 --- /dev/null +++ b/logger.c @@ -0,0 +1,372 @@ +/*--------------------------------------------------------------------------- +logger.c + +Markus Zolliker, Sept 2004 +---------------------------------------------------------------------------- +*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/logger.h b/logger.h new file mode 100644 index 00000000..170f1635 --- /dev/null +++ b/logger.h @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------- +logger.h + +Markus Zolliker, Sept 2004 +---------------------------------------------------------------------------- +*/ + +#ifndef LOGGER_H +#define LOGGER_H + +#include + +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 diff --git a/logreader.c b/logreader.c new file mode 100644 index 00000000..c45708ea --- /dev/null +++ b/logreader.c @@ -0,0 +1,492 @@ +#include +#include +#include +#include +#include +#include +#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 [ none ] np [ ...] + graph text + graph [ ...] + + and are seconds since epoch (unix time) or, if the value + is below one day, a time relative to the actual time + + The is optional. if not given, unknown values are returned as empty strings + + 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. + + 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 + = ( - ) / + 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 . + + At the very end * is returned. + is 1, when the data had to be reduced, 0 else + 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 + is 1 when the value is exact, i.e. an integer. + 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= 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); +} diff --git a/logsetup.c b/logsetup.c new file mode 100644 index 00000000..3eef2d92 --- /dev/null +++ b/logsetup.c @@ -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 [ []]"); + 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); +} diff --git a/ofac.c b/ofac.c index 68ee73e7..6dd5fed3 100644 --- a/ofac.c +++ b/ofac.c @@ -281,7 +281,6 @@ AddCommand(pInter,"MakeCounter",MakeCounter,NULL,NULL); AddCommand(pInter,"MakeO2T",CreateO2T,NULL,NULL); AddCommand(pInter,"SicsAlias",SicsAlias,NULL,NULL); - AddCommand(pInter,"SicsAlias",DefineAlias,NULL,NULL); AddCommand(pInter,"DefineAlias",DefineAlias,NULL,NULL); /* M.Z. */ AddCommand(pInter,"MakeHM",MakeHistMemory,NULL,NULL); AddCommand(pInter,"VelocitySelector",VelSelFactory,NULL,NULL); @@ -343,6 +342,7 @@ AddCommand(pInter,"MakeAsyncProtocol",AsyncProtocolFactory,NULL,NULL); AddCommand(pInter,"MakeAsyncQueue",AsyncQueueFactory,NULL,NULL); AddCommand(pInter,"MakeSicsObj",InstallSICSOBJ,NULL,NULL); + AddCommand(pInter,"DynSicsObj",InstallSICSOBJ,NULL,NULL); AddCommand(pInter,"MakeHdbQueue",MakeHDBQueue,NULL,NULL); AddCommand(pInter,"MakeGenController",GenControllerFactory,NULL,NULL); AddCommand(pInter,"genconfigure",GenControllerConfigure,NULL,NULL); @@ -435,11 +435,15 @@ /* insert here initialization routines ... */ - INIT(SiteInit); /* site specific initializations */ INIT(StatisticsInit); + INIT(InitializerInit); + INIT(SaveHdbInit); /* must be after InitializerInit */ INIT(SctStartup); + INIT(LogReaderInit); + INIT(LogSetupInit); - } + INIT(SiteInit); /* site specific initializations */ + } /*--------------------------------------------------------------------------*/ int InitObjectCommands(pServer pServ, char *file) { diff --git a/savehdb.c b/savehdb.c new file mode 100644 index 00000000..73919f70 --- /dev/null +++ b/savehdb.c @@ -0,0 +1,91 @@ +#include +#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 ", 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); +}