diff --git a/SCinter.c b/SCinter.c index c74ac636..38880894 100644 --- a/SCinter.c +++ b/SCinter.c @@ -976,6 +976,11 @@ static void printType(SicsInterp *pSics, SConnection *pCon, char *typeName) if(!pCom->pData) return NULL; + if (cclass == NULL) + { + return pCom->pData; + } + pDum = (pDummy)pCom->pData; if(strcmp(pDum->pDescriptor->name,cclass) == 0) { @@ -983,6 +988,19 @@ static void printType(SicsInterp *pSics, SConnection *pCon, char *typeName) } return NULL; } +/*---------------------------------------------------------------------------*/ + pObjectDescriptor FindCommandDescriptor(SicsInterp *pSics, char *name) + { + CommandList *pCom; + + pCom = FindCommand(pSics,name); + if(pCom == NULL || pCom->pData == NULL) + { + return NULL; + } + + return ((pDummy)pCom->pData)->pDescriptor; + } /*------------------------------------------------------------------------*/ void *FindDrivable(SicsInterp *pSics, char *name){ pIDrivable pDriv; diff --git a/SCinter.h b/SCinter.h index 411cbdef..1b24ce24 100644 --- a/SCinter.h +++ b/SCinter.h @@ -143,10 +143,16 @@ typedef struct __SINTER /*------------------------------------------------------------------------- FindCommandData finds a command with the name given. It tests the name in the ObjectDescriptor to be of name class. If all this succeeds a pointer - to the commands data structure is retuned. Else NULL + to the commands data structure is retuned. Else NULL. + Do not test the Object Descriptor name when comclass == NULL. */ void *FindCommandData(SicsInterp *pSics, char *name, char *comclass); +/*------------------------------------------------------------------------- + FindCommandDescriptor finds the descriptor of a command with the name given. +*/ + pObjectDescriptor FindCommandDescriptor(SicsInterp *pSics, char *name); + /*------------------------------------------------------------------------ FindDrivable tries to find Drivable object by the name given. Returns a pointer to the drivable interface in the case of success, NULL in diff --git a/initializer.c b/initializer.c index c1700ffb..4c8ee024 100644 --- a/initializer.c +++ b/initializer.c @@ -121,29 +121,31 @@ static int DriverList(SConnection *con, SicsInterp *sics, static int RemoveObject(SConnection *con, SicsInterp *sics, void *data, int argc, char *argv[]) { CmdInitializer cmdin; - CommandList *command; + ObjectDescriptor *desc; char *className; char shortClassName[32]; char *p; int removeAllowed; + char *creationCommand; if (argc != 2) { SCPrintf(con, eError, "ERROR: should be: %s ", argv[0]); return 0; } - command = FindCommand(sics, argv[1]); - if (!command) { + desc = FindCommandDescriptor(sics, argv[1]); + if (!desc) { SCPrintf(con, eError, "ERROR: %s not found", argv[1]); return 0; } - if (((pDummy)command->pData)->pDescriptor->creationCommand != NULL) { + creationCommand = GetDescriptorKey(desc, "creationCommand"); + if (creationCommand != NULL) { /* if there is a creationCommand, we are allowed to remove */ removeAllowed = 1; } else { /* if we have an initializer: we are also allowed to remove */ - className = ((pDummy)command->pData)->pDescriptor->name; + className = desc->name; cmdin = (CmdInitializer)GetInitializer("Object", className); if (cmdin == 0) { /* allow also a longer descriptor starting with the initializer name and a blank */ @@ -169,22 +171,33 @@ static int RemoveObject(SConnection *con, SicsInterp *sics, } } -static int SaveCreationCommands(void *object, char *name, FILE *fil) { - CommandList *p; - ObjectDescriptor *desc; - int printHeader = 0; +typedef struct { + int printHeader; + FILE *fil; +} SaveData; + +static int SaveCreationCommand(char *name, pDummy object, void *userData) { + SaveData *saveData = userData; + char *creationCommand; - for (p = pServ->pSics->pCList; p != NULL; p = p->pNext) { - desc = ((pDummy)p->pData)->pDescriptor; - if (desc->creationCommand && strcmp(desc->creationCommand, "0") != 0) { - if (printHeader == 0) { - printHeader = 1; - fprintf(fil, "\n#--- BEGIN creation commands\n"); - } - fprintf(fil, "%s\n", desc->creationCommand); + creationCommand = GetDescriptorKey(object->pDescriptor, "creationCommand"); + if (creationCommand && strcmp(creationCommand, "0") != 0) { + if (saveData->printHeader == 0) { + saveData->printHeader = 1; + fprintf(saveData->fil, "\n#--- BEGIN creation commands\n"); } + fprintf(saveData->fil, "%s\n", creationCommand); } - if (printHeader == 1) { + return 1; +} + +static int SaveCreationCommands(void *object, char *name, FILE *fil) { + SaveData saveData; + + saveData.fil = fil; + saveData.printHeader = 0; + ForEachCommand(SaveCreationCommand, &saveData); + if (saveData.printHeader == 1) { fprintf(fil, "#--- END creation commands\n\n"); } return 1; @@ -193,37 +206,43 @@ static int SaveCreationCommands(void *object, char *name, FILE *fil) { static int CreationCommand(SConnection *con, SicsInterp *sics, void *data, int argc, char *argv[]) { CmdInitializer cmdin; - CommandList *command; char *className; char shortClassName[32]; char *p; int removeAllowed; ObjectDescriptor *desc; + char *creationCommand; + char buf[256]; if (argc < 2) { SCPrintf(con, eError, "ERROR: should be: %s []", argv[0]); return 0; } - command = FindCommand(sics, argv[1]); - if (!command) { + desc = FindCommandDescriptor(sics, argv[1]); + if (!desc) { SCPrintf(con, eError, "ERROR: %s not found", argv[1]); return 0; } - desc = ((pDummy)command->pData)->pDescriptor; + creationCommand = GetDescriptorKey(desc, "creationCommand"); if (argc < 3) { - if (desc->creationCommand != NULL) { - SCPrintf(con, eValue, "%s", desc->creationCommand); + if (creationCommand != NULL) { + SCPrintf(con, eValue, "%s", creationCommand); } else { SCPrintf(con, eValue, ""); } } else { - if (! desc->creationCommand) { + if (!creationCommand) { SCPrintf(con, eValue, "ERROR: %s is a static object", argv[1]); return 0; } - free(desc->creationCommand); - desc->creationCommand = Arg2Tcl(argc - 2, argv + 2, NULL, -1); + creationCommand = Arg2Tcl(argc - 2, argv + 2, buf, sizeof buf); + if (creationCommand) { + SetDescriptorKey(desc, "creationCommand", creationCommand); + if (creationCommand != buf) free(creationCommand); + } else { + SetDescriptorKey(desc, "creationCommand", "0"); + } } return 1; } diff --git a/logger.c b/logger.c index a6132b57..598173e0 100644 --- a/logger.c +++ b/logger.c @@ -20,21 +20,16 @@ struct Logger { 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 */ + time_t last, lastWrite; int numeric; int exact; - double oldFloat, newFloat; - time_t newTime; Logger *next; }; static char *dir = NULL; static Logger *list; static time_t lastLife = 0; - +static time_t lastWritten = 0; /*--------------------------------------------------------------------------*/ char *LoggerName(Logger *log) { return log->name; @@ -60,45 +55,55 @@ Logger *LoggerFind(const char *name) { /*--------------------------------------------------------------------------*/ #define LASTLOGTXT "#last logging entry at:\n" -void LoggerSetDir(char *dirarg) { +time_t LoggerGetLastLife(char *dirarg) { char path[256], line[32]; FILE *fil; - - dir = dirarg; - snprintf(path, sizeof path, "%s/lastlife.dat", dir); + time_t t = 0; + + if (dirarg == NULL) { + return lastWritten; + } + snprintf(path, sizeof path, "%s/lastlife.dat", dirarg); 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); + t = atol(line); + if (t < 1000000000) { + printf("bad lastLife %ld\n", (long)t); } } fclose(fil); } else { printf("can not read %s\n", path); } + return t; +} + +/*--------------------------------------------------------------------------*/ +time_t LoggerSetDir(char *dirarg) { + dir = dirarg; + lastLife = LoggerGetLastLife(dir); + return lastLife; } /*--------------------------------------------------------------------------*/ char *LoggerGetDir(void) { char path[256]; FILE *fil; - time_t now; static time_t last; - now = time(NULL); - if (now != last) { + lastWritten = time(NULL); + if (lastWritten != last) { /* do not write more than once per second */ snprintf(path, sizeof path, "%s/lastlife.dat", dir); fil = fopen(path, "w"); if (fil) { - fprintf(fil, "%s%ld\n", LASTLOGTXT, (long)now); + fprintf(fil, "%s%ld\n", LASTLOGTXT, (long)lastWritten); fclose(fil); } else { printf("can not write %s\n", path); } - last = now; + last = lastWritten; } return dir; } @@ -122,123 +127,80 @@ int LoggerVarPath(char *dir, char *path, int pathLen, char *name) { } /*--------------------------------------------------------------------------*/ 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; + char path[256], stim[32], buf[32]; + struct tm tm, lasttm; + int l, ext, writeInfo; FILE *fil; - long endPos, pos1, p; - char info[80]; + time_t beforenow; 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; - } + lasttm = *localtime(&log->last); + tm = *localtime(&now); 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); + 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 */ + writeInfo = (tm.tm_isdst != lasttm.tm_isdst || + tm.tm_yday != lasttm.tm_yday || + (period != log->period && log->numeric)); + if (strcmp(value, log->old) != 0 || writeInfo) { + + fil = fopen(path, "r+"); + 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 { - 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); + fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm.tm_isdst, period, log->exact); + } else { /* check if file is from today */ + fgets(buf, sizeof buf, fil); + if (0 != strncmp(buf, stim, 11)) { + fclose(fil); /* it was file from an earlier year */ + 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); + } else { + fseek(fil, 0, SEEK_END); /* set position to end */ + if (writeInfo) { + fprintf(fil, "#isdst %d period %d exact %d\n", tm.tm_isdst, period, log->exact); + } + if (log->lastWrite != 0 && now >= log->lastWrite + 2 * period) { + /* this is only useful for direct access of the log files */ + beforenow = now - period; + lasttm = *localtime(&beforenow); + if (lasttm.tm_yday == tm.tm_yday) { + strftime(stim, sizeof stim,"%H:%M:%S", &lasttm); + } else { + snprintf(stim, sizeof stim, "00:00:00"); + } + fprintf(fil, "%s\t%s\n", stim, log->old); } - fseek(fil, -1, SEEK_CUR); /* position to newline */ - } else if (now != log->last) { - skip = 1; } } + strftime(stim, sizeof stim,"%H:%M:%S", &tm); + fprintf(fil, "%s\t%s\n", stim, value); + log->lastWrite = now; + fclose(fil); + } - 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; + log->period = period; + l = strlen(value); - if (l >= log->oldsize) { + if (l >= log->oldsize) { /* increase log->old size, optimized for linux/i386 */ 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); } + assert(log->old); + assert(l < log->oldsize); strcpy(log->old, value); - log->old[l] = '\0'; + assert(log->old[l] == '\0'); log->last = now; return 1; } @@ -263,6 +225,7 @@ int LoggerWrite(Logger *log, time_t now, int period, char *value) { yday = tm->tm_yday; + /* -- debug logging if dir/debug exists */ l = LoggerVarPath(dir, path, sizeof path, "debug"); strftime(path + l, sizeof path - l, "%m-%d.log", tm); fil=fopen(path, "a"); @@ -274,15 +237,16 @@ int LoggerWrite(Logger *log, time_t now, int period, char *value) { /* log old values (forced midnight log) */ p = list; while (p != NULL) { - if (fil) { + + if (fil) { /* debug logging */ 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; } @@ -302,6 +266,10 @@ int LoggerPeriod(Logger *log) { return log->period; } /*--------------------------------------------------------------------------*/ +void LoggerSetPeriod(Logger *log, int period) { + LoggerWrite0(log, time(NULL), period, log->old); +} +/*--------------------------------------------------------------------------*/ 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 */ @@ -344,7 +312,7 @@ Logger *LoggerMake(char *name, int period, int exact) { log->old = calloc(1,12); log->oldsize = 12; log->last = 0; - log->lastLn = 0; + log->lastWrite = 0; log->numeric = 1; log->next = list; list = log; diff --git a/logger.h b/logger.h index 170f1635..f0389ffd 100644 --- a/logger.h +++ b/logger.h @@ -17,10 +17,12 @@ 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); +time_t LoggerSetDir(char *dirarg); +time_t LoggerGetLastLife(char *dirarg); void LoggerWriteOld(Logger *log, time_t now); time_t LoggerLastTime(Logger *log); int LoggerPeriod(Logger *log); +void LoggerSetPeriod(Logger *log, int period); int LoggerVarPath(char *dir, char *path, int pathLen, char *name); void LoggerFreeAll(void); diff --git a/logreader.c b/logreader.c index c45708ea..3bf8083e 100644 --- a/logreader.c +++ b/logreader.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "logger.h" #include "sics.h" @@ -13,19 +14,26 @@ typedef enum { NUMERIC, TEXT } CompType; +typedef struct { + time_t t; + float y; +} Point; + 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]; */ + time_t tlim; /* 0: initial state */ + Point best; /* best point, to be written if tlim > 0 */ + Point written; /* last written point */ + Point last; /* last point */ + char buf[LLEN]; int np; char *none; + char *header; + time_t period; + int omitEqual; } Compressor; static char *dir = NULL; @@ -34,112 +42,103 @@ 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; + c->last.y = LOGGER_NAN; + c->last.t = 0; + c->buf[0]='\0'; + c->written.t = 0; + c->written.y = LOGGER_NAN; + c->omitEqual = 1; } -static void OutString(Compressor *c, time_t t, char *str) { - char line[LLEN]; +static void OutFloat(Compressor *c, Point p) { + char *value; - /* 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)); - } + if (p.y == LOGGER_NAN) { + if (c->omitEqual && c->written.y == LOGGER_NAN) return; + if (c->none) { + value = c->none; } else { - snprintf(line, sizeof line, "%ld %g\n", (long)(t - c->tlast), y); + value = ""; } - /* printf("-%s\n", line); */ - c->tlast = t; - SCWrite(c->pCon, line, eWarning); - c->np--; + } else { + if (c->omitEqual && c->written.y == p.y) return; + snprintf(c->buf, sizeof(c->buf), "%g", p.y); + value = c->buf; + } + SCPrintf(c->pCon, eWarning, "%ld %s", (long)(p.t - c->written.t), value); + c->written = p; + c->np--; +} + +static void WriteHeader(Compressor *c) { + if (c->header) { + SCPrintf(c->pCon, eWarning, "*%s period %ld\n", c->header, c->period); + c->header = NULL; } } 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; - } + Point new; + + WriteHeader(c); if (c->type == NUMERIC) { - if (t == 0) { /* finish */ - t = c->tlim + 3 * c->step; - y = 0; + new.y = strtod(value, &p); + if (p == value) { + new.y = LOGGER_NAN; } else { - y = strtod(value, &p); - if (p == value) { - y = LOGGER_NAN; - } else { - if (y == LOGGER_NAN) y *= 1.0000002; - } + if (new.y == LOGGER_NAN) new.y *= 1.0000002; } - /* printf("put %ld %g\n", t, y); */ - if (c->tlim == 0) goto first; - if (t >= c->tlim) { + new.t = t; + if (t >= c->tlim) { /* a new interval starts */ + if (c->tlim == 0) { + c->tlim = t; + } else if (c->best.y != c->written.y) { + OutFloat(c, c->best); + } + c->best = new; 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); + if (t > c->tlim) { + if (c->last.y != c->written.y) { + OutFloat(c, c->last); } - goto first; + c->tlim = t + c->step; + } + } else { /* not the first point */ + if (fabs(new.y - c->best.y) > fabs(c->written.y - c->best.y)) { + c->best = new; } - } - 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; + c->last = new; } else if (c->type == TEXT) { - if (t != 0) OutString(c, t, value); + if (0 != strncmp(value, c->buf, sizeof(c->buf)-1)) { + snprintf(c->buf, sizeof(c->buf), "%s", value); + SCPrintf(c->pCon, eWarning, "%ld %s\n", (long)(t - c->written.t), value); + c->written.t = t; + c->np--; + } + } +} + +static void PutFinish(Compressor *c, time_t now) { + char value[32]; + + if (c->tlim != 0) { /* there is data already */ + c->omitEqual = 0; + if (c->type == NUMERIC) { + if (now > c->last.t) { /* copy last value to the actual time */ + if (c->last.y != LOGGER_NAN) { + snprintf(value, sizeof value, "%g", c->last.y); + PutValue(c, now, value); + } + if (c->best.t > c->written.t) { + OutFloat(c, c->best); /* write last buffered value */ + } + } + } if (now > c->last.t) { + PutValue(c, now, c->buf); + } } } /*--------------------------------------------------------------------------*/ @@ -194,7 +193,7 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, 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 + the variable name is returned preceeded by a '*', followed by some infos* 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. @@ -207,13 +206,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, 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. + *actually only one info exists: period . This is the update rate in seconds. + As equal values are not transmitted, two points (t1,y1) and (t2,y2) with a distance + (t2 - t1) > period should not be connected directly. The plot software should generate + an intermediate point at (t2-period,y1). + */ - time_t from, to, step, xs, lastt, now; - long lxs; + time_t from, to, step, xs, lastt; char *p, *varp; int i, j, iarg, l, iret, loss, np; int inRange; @@ -230,6 +229,8 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, char *opt; int isdst; int overflow; + time_t now, now1, now2, nowi; + char var[256]; /* argtolower(argc, argv); */ if (argc < 4) goto illarg; @@ -293,12 +294,16 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, SCWrite(pCon, "ERROR: LoggerDir not found", eError); return 0; } - LoggerSetDir(dir); } if (dir2 == NULL) { dir2 = IFindOption(pSICSOptions, "LoggerDir2"); - if (dir2 == NULL) dir2=""; + if (dir2 == NULL) { + dir2=""; + } } + now1 = LoggerGetLastLife(NULL); + if (now1 == 0) now1 = now; + now2 = 0; loss = 0; overflow = 0; @@ -312,23 +317,32 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, /* convert slashes to dots */ varp = argv[i]; + if (*varp == '/') varp++; - for (j = 0; j < sizeof(c.var) && *varp != 0; j++, varp++) { + for (j = 0; j < sizeof(var)-1 && *varp != 0; j++, varp++) { if (*varp == '/') { - c.var[j] = '.'; + var[j] = '.'; } else { - c.var[j] = *varp; + var[j] = *varp; } } - + c.header = argv[i]; + c.period = 0; + var[j] = '\0'; c.type = type0; c.np = np; - l = LoggerVarPath(dir, path, sizeof path, c.var); + l = LoggerVarPath(dir, path, sizeof path, var); dr = opendir(path); if (dr) { + nowi = now1; closedir(dr); } else { - l = LoggerVarPath(dir2, path, sizeof path, c.var); + if (now2 == 0) { + now2 = LoggerGetLastLife(dir2); + if (now2 == 0) now2 = now; + } + l = LoggerVarPath(dir2, path, sizeof path, var); + nowi = now2; dr = opendir(path); if (dr) { closedir(dr); @@ -337,7 +351,7 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, isdst = -1; fil = NULL; - while (startim <= to && c.tlast <= to) { + while (startim <= to && c.last.t <= to) { tm = *localtime(&startim); if (tm.tm_yday != yday) { if (fil != NULL) { /* close file if day changed */ @@ -356,13 +370,14 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, fclose(fil); fil = NULL; } else { - lxs = getOpt(line, &isdst, &c.exact); - if (lxs >= 0) { - if (lxs == 0) { + c.period = getOpt(line, &isdst, &c.exact); + /* if (c.exact) c.period = 0; */ + if (c.period >= 0) { + if (c.period == 0) { c.type = TEXT; } else { c.type = type0; - xs = lxs; + xs = c.period; } if (xs < step) { loss = 1; @@ -380,13 +395,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, /* printf("%s\n", line); */ if (lin == NULL) break; if (line[0] == '#') { - lxs = getOpt(line, &isdst, &c.exact); - if (lxs >= 0) { - if (lxs == 0) { + c.period = getOpt(line, &isdst, &c.exact); + if (c.period >= 0) { + if (c.period == 0) { c.type = TEXT; } else { c.type = type0; - xs = lxs; + xs = c.period; } if (xs < step) { loss = 1; @@ -413,13 +428,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, if (p) { stp = p+1; *p='\0'; - iret = sscanf(stp, "%ld", &lxs); + iret = sscanf(stp, "%ld", &c.period); if (iret == 1) { - if (lxs == 0) { + if (c.period == 0) { c.type = TEXT; } else { c.type = type0; - xs = lxs; + xs = c.period; } if (xs < step) { loss = 1; @@ -464,8 +479,8 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData, PutValue(&c, lastt, lastval); } } - c.ylast = LOGGER_NAN; /* force output of last value */ - PutValue(&c, 0, ""); /* finish */ + WriteHeader(&c); /* write header, if not already done */ + PutFinish(&c, nowi); if (fil) { fclose(fil); fil = NULL; diff --git a/logsetup.c b/logsetup.c index 3eef2d92..cf7445d6 100644 --- a/logsetup.c +++ b/logsetup.c @@ -73,11 +73,17 @@ static int LogSetup(SConnection *pCon, SicsInterp *pSics, void *pData, } 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); + logger = FindHdbCallbackData(node, HCBUPDATE, LoggerUpdateCallback, NULL); + if (logger != 0) { /* logger exists already, changed only period */ + LoggerSetPeriod(logger, period); + } else { + 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; } diff --git a/obdes.c b/obdes.c index f19ccaa8..127e56bc 100644 --- a/obdes.c +++ b/obdes.c @@ -71,7 +71,6 @@ pRes->parNode = NULL; pRes->SaveStatus = DefaultSave; pRes->GetInterface = DefaultGetInterface; - pRes->creationCommand = NULL; return pRes; } /*---------------------------------------------------------------------------*/ @@ -157,7 +156,7 @@ { if(NULL!=self) { - IFSetOption(self->pKeys,keyName,eltValue); + self->pKeys = IFSetOption(self->pKeys,keyName,eltValue); } } /*--------------------------------------------------------------------------*/ @@ -167,7 +166,7 @@ { return; } - IFSetOption(self->pKeys,"group",group); + self->pKeys = IFSetOption(self->pKeys,"group",group); } /*--------------------------------------------------------------------------*/ void SetDescriptorDescription(pObjectDescriptor self, char *description) @@ -176,7 +175,7 @@ { return; } - IFSetOption(self->pKeys,"description", description); + self->pKeys = IFSetOption(self->pKeys,"description", description); } /*--------------------------------------------------------------------------*/ char * GetDescriptorKey(pObjectDescriptor self, char *keyName) diff --git a/obdes.h b/obdes.h index 4013e9db..f842a2e9 100644 --- a/obdes.h +++ b/obdes.h @@ -31,7 +31,6 @@ void *(*GetInterface)(void *self, int iInterfaceID); IPair *pKeys; pHdb parNode; - char *creationCommand; /* NULL when a static object */ } ObjectDescriptor, *pObjectDescriptor; /*---------------------------------------------------------------------------*/ diff --git a/savehdb.c b/savehdb.c index 647f4587..0785de89 100644 --- a/savehdb.c +++ b/savehdb.c @@ -3,8 +3,6 @@ #include "statusfile.h" #include "sicshipadaba.h" -static pDummy creationCommands = NULL; - static void SaveHdbBranch(pHdb node, FILE *fil) { pHdb child; char prop[16]; diff --git a/scriptcontext.c b/scriptcontext.c index 459b2df9..fe6afc46 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -28,6 +28,7 @@ typedef enum { sct_take_keyword, sct_get_keyword, sct_complete_keyword, + sct_retry_keyword, sct_chain_keyword, sct_next_keyword, sct_steplist_keyword, @@ -44,6 +45,7 @@ static char *sctKeywords[]={ "take", "get", "complete", + "retry", "chain", "next", "steplist", @@ -116,6 +118,7 @@ struct Sct { char *result; char *nextScript; SctChain *runningChain; + int tryCnt; SCStore debugConn; char *debugCommand; int sent; @@ -259,6 +262,7 @@ static int SctReadCallback(void *user, void *conn, pHdb node, hdbValue value) { int SctCallDynamicScript(Sct *sct, char *name, char *script) { SctList *sl; SctChain *sc; + for (sl = sct->scriptLists.head; sl != NULL; sl = sl->next) { for (sc = sl->chains.head; sc != NULL; sc = sc->next) { /* don't touch the list pos */ if (sc->dynamic && strcasecmp(name, sc->dynamic) == 0) { @@ -408,6 +412,25 @@ static int SctExec(SConnection *con, SicsInterp *sics, void *object, int argc, c } goto missingScriptList; + case sct_retry_keyword: + if (argc < 3) { + SCPrintf(con, eInError, "ERROR: should be: %s retry ", argv[0]); + goto quit; + } + if (sct->runningChain == NULL) { + SCPrintf(con, eInError, "ERROR: no running chain (fatal error)", argv[0]); + goto quit; + } + sct->tryCnt++; + if (sct->tryCnt >= atoi(argv[2])) { + SCPrintf(con, eInError, "ERROR: too may retries (%d) after %s", + sct->tryCnt, ConcatArgs(argc-3, argv+3)); + goto quit; + } + sct->nextScript = sct->runningChain->command; + if (sct->result) free(sct->result); + sct->result = NULL; + break; case sct_chain_keyword: if (argc < 4) { SCPrintf(con, eInError, "ERROR: should be: %s chain