- added FindCommandDescriptor to SCinter.*

- modified support for dynamic objects
- improved logger system
- various fixes
This commit is contained in:
zolliker
2008-03-03 14:49:15 +00:00
parent 33c0b7dcaa
commit a529bda307
13 changed files with 337 additions and 285 deletions

View File

@ -976,6 +976,11 @@ static void printType(SicsInterp *pSics, SConnection *pCon, char *typeName)
if(!pCom->pData) if(!pCom->pData)
return NULL; return NULL;
if (cclass == NULL)
{
return pCom->pData;
}
pDum = (pDummy)pCom->pData; pDum = (pDummy)pCom->pData;
if(strcmp(pDum->pDescriptor->name,cclass) == 0) if(strcmp(pDum->pDescriptor->name,cclass) == 0)
{ {
@ -983,6 +988,19 @@ static void printType(SicsInterp *pSics, SConnection *pCon, char *typeName)
} }
return NULL; 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){ void *FindDrivable(SicsInterp *pSics, char *name){
pIDrivable pDriv; pIDrivable pDriv;

View File

@ -143,10 +143,16 @@ typedef struct __SINTER
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
FindCommandData finds a command with the name given. It tests the name in the 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 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); 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 FindDrivable tries to find Drivable object by the name given. Returns a
pointer to the drivable interface in the case of success, NULL in pointer to the drivable interface in the case of success, NULL in

View File

@ -121,29 +121,31 @@ static int DriverList(SConnection *con, SicsInterp *sics,
static int RemoveObject(SConnection *con, SicsInterp *sics, static int RemoveObject(SConnection *con, SicsInterp *sics,
void *data, int argc, char *argv[]) { void *data, int argc, char *argv[]) {
CmdInitializer cmdin; CmdInitializer cmdin;
CommandList *command; ObjectDescriptor *desc;
char *className; char *className;
char shortClassName[32]; char shortClassName[32];
char *p; char *p;
int removeAllowed; int removeAllowed;
char *creationCommand;
if (argc != 2) { if (argc != 2) {
SCPrintf(con, eError, "ERROR: should be: %s <object>", argv[0]); SCPrintf(con, eError, "ERROR: should be: %s <object>", argv[0]);
return 0; return 0;
} }
command = FindCommand(sics, argv[1]); desc = FindCommandDescriptor(sics, argv[1]);
if (!command) { if (!desc) {
SCPrintf(con, eError, "ERROR: %s not found", argv[1]); SCPrintf(con, eError, "ERROR: %s not found", argv[1]);
return 0; 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 */ /* if there is a creationCommand, we are allowed to remove */
removeAllowed = 1; removeAllowed = 1;
} else { } else {
/* if we have an initializer: we are also allowed to remove */ /* 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); cmdin = (CmdInitializer)GetInitializer("Object", className);
if (cmdin == 0) { if (cmdin == 0) {
/* allow also a longer descriptor starting with the initializer name and a blank */ /* 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) { typedef struct {
CommandList *p; int printHeader;
ObjectDescriptor *desc; FILE *fil;
int printHeader = 0; } SaveData;
for (p = pServ->pSics->pCList; p != NULL; p = p->pNext) { static int SaveCreationCommand(char *name, pDummy object, void *userData) {
desc = ((pDummy)p->pData)->pDescriptor; SaveData *saveData = userData;
if (desc->creationCommand && strcmp(desc->creationCommand, "0") != 0) { char *creationCommand;
if (printHeader == 0) {
printHeader = 1; creationCommand = GetDescriptorKey(object->pDescriptor, "creationCommand");
fprintf(fil, "\n#--- BEGIN creation commands\n"); if (creationCommand && strcmp(creationCommand, "0") != 0) {
} if (saveData->printHeader == 0) {
fprintf(fil, "%s\n", desc->creationCommand); 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"); fprintf(fil, "#--- END creation commands\n\n");
} }
return 1; return 1;
@ -193,37 +206,43 @@ static int SaveCreationCommands(void *object, char *name, FILE *fil) {
static int CreationCommand(SConnection *con, SicsInterp *sics, static int CreationCommand(SConnection *con, SicsInterp *sics,
void *data, int argc, char *argv[]) { void *data, int argc, char *argv[]) {
CmdInitializer cmdin; CmdInitializer cmdin;
CommandList *command;
char *className; char *className;
char shortClassName[32]; char shortClassName[32];
char *p; char *p;
int removeAllowed; int removeAllowed;
ObjectDescriptor *desc; ObjectDescriptor *desc;
char *creationCommand;
char buf[256];
if (argc < 2) { if (argc < 2) {
SCPrintf(con, eError, "ERROR: should be: %s <object> [<creation command>]", argv[0]); SCPrintf(con, eError, "ERROR: should be: %s <object> [<creation command>]", argv[0]);
return 0; return 0;
} }
command = FindCommand(sics, argv[1]); desc = FindCommandDescriptor(sics, argv[1]);
if (!command) { if (!desc) {
SCPrintf(con, eError, "ERROR: %s not found", argv[1]); SCPrintf(con, eError, "ERROR: %s not found", argv[1]);
return 0; return 0;
} }
desc = ((pDummy)command->pData)->pDescriptor; creationCommand = GetDescriptorKey(desc, "creationCommand");
if (argc < 3) { if (argc < 3) {
if (desc->creationCommand != NULL) { if (creationCommand != NULL) {
SCPrintf(con, eValue, "%s", desc->creationCommand); SCPrintf(con, eValue, "%s", creationCommand);
} else { } else {
SCPrintf(con, eValue, "<static object>"); SCPrintf(con, eValue, "<static object>");
} }
} else { } else {
if (! desc->creationCommand) { if (!creationCommand) {
SCPrintf(con, eValue, "ERROR: %s is a static object", argv[1]); SCPrintf(con, eValue, "ERROR: %s is a static object", argv[1]);
return 0; return 0;
} }
free(desc->creationCommand); creationCommand = Arg2Tcl(argc - 2, argv + 2, buf, sizeof buf);
desc->creationCommand = Arg2Tcl(argc - 2, argv + 2, NULL, -1); if (creationCommand) {
SetDescriptorKey(desc, "creationCommand", creationCommand);
if (creationCommand != buf) free(creationCommand);
} else {
SetDescriptorKey(desc, "creationCommand", "0");
}
} }
return 1; return 1;
} }

192
logger.c
View File

@ -20,21 +20,16 @@ struct Logger {
char *old; char *old;
int oldsize; int oldsize;
int period; int period;
time_t last; time_t last, lastWrite;
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 numeric;
int exact; int exact;
double oldFloat, newFloat;
time_t newTime;
Logger *next; Logger *next;
}; };
static char *dir = NULL; static char *dir = NULL;
static Logger *list; static Logger *list;
static time_t lastLife = 0; static time_t lastLife = 0;
static time_t lastWritten = 0;
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
char *LoggerName(Logger *log) { char *LoggerName(Logger *log) {
return log->name; return log->name;
@ -60,45 +55,55 @@ Logger *LoggerFind(const char *name) {
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
#define LASTLOGTXT "#last logging entry at:\n" #define LASTLOGTXT "#last logging entry at:\n"
void LoggerSetDir(char *dirarg) { time_t LoggerGetLastLife(char *dirarg) {
char path[256], line[32]; char path[256], line[32];
FILE *fil; FILE *fil;
time_t t = 0;
dir = dirarg; if (dirarg == NULL) {
snprintf(path, sizeof path, "%s/lastlife.dat", dir); return lastWritten;
}
snprintf(path, sizeof path, "%s/lastlife.dat", dirarg);
fil = fopen(path, "r"); fil = fopen(path, "r");
if (fil) { if (fil) {
fgets(line, sizeof line, fil); fgets(line, sizeof line, fil);
if (strcmp(line, LASTLOGTXT) == 0) { if (strcmp(line, LASTLOGTXT) == 0) {
fgets(line, sizeof line, fil); fgets(line, sizeof line, fil);
lastLife = atol(line); t = atol(line);
if (lastLife < 1000000000) { if (t < 1000000000) {
printf("bad lastLife %ld\n", (long)lastLife); printf("bad lastLife %ld\n", (long)t);
} }
} }
fclose(fil); fclose(fil);
} else { } else {
printf("can not read %s\n", path); 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 *LoggerGetDir(void) {
char path[256]; char path[256];
FILE *fil; FILE *fil;
time_t now;
static time_t last; static time_t last;
now = time(NULL); lastWritten = time(NULL);
if (now != last) { if (lastWritten != last) { /* do not write more than once per second */
snprintf(path, sizeof path, "%s/lastlife.dat", dir); snprintf(path, sizeof path, "%s/lastlife.dat", dir);
fil = fopen(path, "w"); fil = fopen(path, "w");
if (fil) { if (fil) {
fprintf(fil, "%s%ld\n", LASTLOGTXT, (long)now); fprintf(fil, "%s%ld\n", LASTLOGTXT, (long)lastWritten);
fclose(fil); fclose(fil);
} else { } else {
printf("can not write %s\n", path); printf("can not write %s\n", path);
} }
last = now; last = lastWritten;
} }
return dir; 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) { int LoggerWrite0(Logger *log, time_t now, int period, char *value) {
char path[256], stim[32], buf[32], chr; char path[256], stim[32], buf[32];
struct tm *tm; struct tm tm, lasttm;
int yday; int l, ext, writeInfo;
int isdst;
int l, ext, skip, changed;
FILE *fil; FILE *fil;
long endPos, pos1, p; time_t beforenow;
char info[80];
LoggerGetDir(); LoggerGetDir();
if (dir == NULL) return 0; if (dir == NULL) return 0;
if (now == 0) { if (now == 0) {
printf("now==0\n"); printf("now==0\n");
} }
tm = localtime(&log->last); lasttm = *localtime(&log->last);
isdst = tm->tm_isdst; /* last isdst */ tm = *localtime(&now);
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); l = LoggerVarPath(dir, path, sizeof path, log->name);
strftime(path + l, sizeof path - l, "%m-%d.log", tm); strftime(path + l, sizeof path - l, "%m-%d.log", &tm);
strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S", tm); strftime(stim, sizeof stim, "#%Y-%m-%d %H:%M:%S", &tm);
fil = fopen(path, "r+");
skip = 0;
if (period <= 0) period = 1; if (period <= 0) period = 1;
if (fil == NULL) { /* create new file */ writeInfo = (tm.tm_isdst != lasttm.tm_isdst ||
fil = fopen(path, "w+"); tm.tm_yday != lasttm.tm_yday ||
if (fil == NULL) return 0; (period != log->period && log->numeric));
fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm->tm_isdst, period, log->exact); if (strcmp(value, log->old) != 0 || writeInfo) {
log->period = period;
isdst = tm->tm_isdst; fil = fopen(path, "r+");
endPos = ftell(fil); if (fil == NULL) { /* create new file */
fseek(fil, -1, SEEK_CUR); /* position to newline */ fil = fopen(path, "w+");
} 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; if (fil == NULL) return 0;
fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm->tm_isdst, period, log->exact); fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm.tm_isdst, period, log->exact);
log->period = period; } else { /* check if file is from today */
isdst = tm->tm_isdst; fgets(buf, sizeof buf, fil);
endPos = ftell(fil); if (0 != strncmp(buf, stim, 11)) {
fseek(fil, -1, SEEK_CUR); /* position to newline */ fclose(fil); /* it was file from an earlier year */
} else { fil=fopen(path, "w+"); /* overwrite old logfile */
fseek(fil, -log->lastLn, SEEK_END); /* set position to last line */ if (fil == NULL) return 0;
endPos = ftell(fil) + log->lastLn; fprintf(fil, "%s isdst %d period %d exact %d\n", stim, tm.tm_isdst, period, log->exact);
if (endPos > 0 && log->lastLn == 0) { } else {
/* find last newline in newly opened file */ fseek(fil, 0, SEEK_END); /* set position to end */
fseek(fil, -1, SEEK_CUR); if (writeInfo) {
chr = fgetc(fil); fprintf(fil, "#isdst %d period %d exact %d\n", tm.tm_isdst, period, log->exact);
while (chr != '\n' && ftell(fil) >= 2) { }
fseek(fil, -2, SEEK_CUR); if (log->lastWrite != 0 && now >= log->lastWrite + 2 * period) {
chr = fgetc(fil); /* 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);
changed = (0 != strcmp(value, log->old)); fprintf(fil, "%s\t%s\n", stim, value);
info[0]='\0'; log->lastWrite = now;
if (period != log->period) { fclose(fil);
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);
} }
log->period = period;
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); 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; ext = ((l - log->oldsize)/16 + 1) * 16;
if (ext < log->oldsize / 4) ext += (log->oldsize / 64) * 16; if (ext < log->oldsize / 4) ext += (log->oldsize / 64) * 16;
log->oldsize += ext; log->oldsize += ext;
free(log->old); free(log->old);
log->old = calloc(1, log->oldsize); log->old = calloc(1, log->oldsize);
assert(log->old);
assert(l < log->oldsize);
} }
assert(log->old);
assert(l < log->oldsize);
strcpy(log->old, value); strcpy(log->old, value);
log->old[l] = '\0'; assert(log->old[l] == '\0');
log->last = now; log->last = now;
return 1; return 1;
} }
@ -263,6 +225,7 @@ int LoggerWrite(Logger *log, time_t now, int period, char *value) {
yday = tm->tm_yday; yday = tm->tm_yday;
/* -- debug logging if dir/debug exists */
l = LoggerVarPath(dir, path, sizeof path, "debug"); l = LoggerVarPath(dir, path, sizeof path, "debug");
strftime(path + l, sizeof path - l, "%m-%d.log", tm); strftime(path + l, sizeof path - l, "%m-%d.log", tm);
fil=fopen(path, "a"); 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) */ /* log old values (forced midnight log) */
p = list; p = list;
while (p != NULL) { while (p != NULL) {
if (fil) {
if (fil) { /* debug logging */
strftime(tim, sizeof tim, "last %m-%d %H:%M:%S, ", localtime(&p->last)); strftime(tim, sizeof tim, "last %m-%d %H:%M:%S, ", localtime(&p->last));
fputs(tim, fil); fputs(tim, fil);
fprintf(fil, "period %d, name %s, old %s\n", p->period, p->name, p->old); fprintf(fil, "period %d, name %s, old %s\n", p->period, p->name, p->old);
} }
if (p->last < h0 && p->last != 0 && if (p->last < h0 && p->last != 0 &&
p->period >= 0 && p->old[0] != '\0') { p->period >= 0 && p->old[0] != '\0') {
LoggerWrite0(p, h0, p->period, p->old); LoggerWrite0(p, h0, p->period, p->old);
p->overwrite = 0;
} }
p = p->next; p = p->next;
} }
@ -302,6 +266,10 @@ int LoggerPeriod(Logger *log) {
return log->period; return log->period;
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
void LoggerSetPeriod(Logger *log, int period) {
LoggerWrite0(log, time(NULL), period, log->old);
}
/*--------------------------------------------------------------------------*/
void LoggerKill(Logger *log) { void LoggerKill(Logger *log) {
/* we do not really free the logger, it might be reused /* we do not really free the logger, it might be reused
for the same variable later. We set the value to undefined */ 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->old = calloc(1,12);
log->oldsize = 12; log->oldsize = 12;
log->last = 0; log->last = 0;
log->lastLn = 0; log->lastWrite = 0;
log->numeric = 1; log->numeric = 1;
log->next = list; log->next = list;
list = log; list = log;

View File

@ -17,10 +17,12 @@ void LoggerKill(Logger *log);
int LoggerWrite(Logger *log, time_t now, int period, char *value); int LoggerWrite(Logger *log, time_t now, int period, char *value);
char *LoggerName(Logger *log); char *LoggerName(Logger *log);
void LoggerSetNumeric(Logger *log, int numeric); 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); void LoggerWriteOld(Logger *log, time_t now);
time_t LoggerLastTime(Logger *log); time_t LoggerLastTime(Logger *log);
int LoggerPeriod(Logger *log); int LoggerPeriod(Logger *log);
void LoggerSetPeriod(Logger *log, int period);
int LoggerVarPath(char *dir, char *path, int pathLen, char *name); int LoggerVarPath(char *dir, char *path, int pathLen, char *name);
void LoggerFreeAll(void); void LoggerFreeAll(void);

View File

@ -4,6 +4,7 @@
#include <fortify.h> #include <fortify.h>
#include <errno.h> #include <errno.h>
#include <dirent.h> #include <dirent.h>
#include <math.h>
#include "logger.h" #include "logger.h"
#include "sics.h" #include "sics.h"
@ -13,19 +14,26 @@
typedef enum { NUMERIC, TEXT } CompType; typedef enum { NUMERIC, TEXT } CompType;
typedef struct {
time_t t;
float y;
} Point;
typedef struct { typedef struct {
SConnection *pCon; SConnection *pCon;
char var[1024];
int exact; int exact;
CompType type; CompType type;
time_t step; time_t step;
time_t tlim; time_t tlim; /* 0: initial state */
time_t tmin, tmax, tlast, told; Point best; /* best point, to be written if tlim > 0 */
float ymin, ymax, ylast, yold; Point written; /* last written point */
char slast[LLEN]; Point last; /* last point */
/* char set[LLEN]; */ char buf[LLEN];
int np; int np;
char *none; char *none;
char *header;
time_t period;
int omitEqual;
} Compressor; } Compressor;
static char *dir = NULL; static char *dir = NULL;
@ -34,112 +42,103 @@ static char *dir2 = NULL;
static void InitCompressor(Compressor *c, SConnection *pCon, time_t step) { static void InitCompressor(Compressor *c, SConnection *pCon, time_t step) {
c->pCon = pCon; c->pCon = pCon;
c->step = step; c->step = step;
c->tmin = -2;
c->tmax = 0;
c->tlast = 0;
c->tlim = 0; c->tlim = 0;
c->told = 0; c->last.y = LOGGER_NAN;
c->slast[0]='\0'; c->last.t = 0;
c->ylast = LOGGER_NAN; 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) { static void OutFloat(Compressor *c, Point p) {
char line[LLEN]; char *value;
/* printf("out %ld %g\n", t, y); */ if (p.y == LOGGER_NAN) {
if (0 != strcmp(str, c->slast)) { if (c->omitEqual && c->written.y == LOGGER_NAN) return;
snprintf(line, sizeof line, "%ld %s\n", (long)(t - c->tlast), str); if (c->none) {
c->tlast = t; value = c->none;
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 { } else {
snprintf(line, sizeof line, "%ld %g\n", (long)(t - c->tlast), y); value = "";
} }
/* printf("-%s\n", line); */ } else {
c->tlast = t; if (c->omitEqual && c->written.y == p.y) return;
SCWrite(c->pCon, line, eWarning); snprintf(c->buf, sizeof(c->buf), "%g", p.y);
c->np--; 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) { static void PutValue(Compressor *c, time_t t, char *value) {
char *p; char *p;
double y; Point new;
if (c->var[0]) { WriteHeader(c);
SCPrintf(c->pCon, eWarning, "*%s exact %d\n", c->var, c->exact);
c->var[0] = 0;
}
if (c->type == NUMERIC) { if (c->type == NUMERIC) {
if (t == 0) { /* finish */ new.y = strtod(value, &p);
t = c->tlim + 3 * c->step; if (p == value) {
y = 0; new.y = LOGGER_NAN;
} else { } else {
y = strtod(value, &p); if (new.y == LOGGER_NAN) new.y *= 1.0000002;
if (p == value) {
y = LOGGER_NAN;
} else {
if (y == LOGGER_NAN) y *= 1.0000002;
}
} }
/* printf("put %ld %g\n", t, y); */ new.t = t;
if (c->tlim == 0) goto first; if (t >= c->tlim) { /* a new interval starts */
if (t >= c->tlim) { 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; c->tlim += c->step;
if (c->tmin > c->tmax) { if (t > c->tlim) {
OutFloat(c, c->tmax, c->ymax); if (c->last.y != c->written.y) {
c->ymax = c->ymin; OutFloat(c, c->last);
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; 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->last = new;
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) { } 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) 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, 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. blanks.
After the header line for every data point a line follows with After the header line for every data point a line follows with
a time relative to the last point and the value. a time relative to the last point and the value.
@ -207,13 +206,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
<overflow> is 1, when overflow occured, 0 else. Overflow may happen only <overflow> is 1, when overflow occured, 0 else. Overflow may happen only
when np is given and a text variable was demanded. when np is given and a text variable was demanded.
*actually only one option exists (you might ignore it): *actually only one info exists: period <value>. This is the update rate in seconds.
exact <value> As equal values are not transmitted, two points (t1,y1) and (t2,y2) with a distance
<value> is 1 when the value is exact, i.e. an integer. (t2 - t1) > period should not be connected directly. The plot software should generate
<value> is 0 else. an intermediate point at (t2-period,y1).
*/ */
time_t from, to, step, xs, lastt, now; time_t from, to, step, xs, lastt;
long lxs;
char *p, *varp; char *p, *varp;
int i, j, iarg, l, iret, loss, np; int i, j, iarg, l, iret, loss, np;
int inRange; int inRange;
@ -230,6 +229,8 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
char *opt; char *opt;
int isdst; int isdst;
int overflow; int overflow;
time_t now, now1, now2, nowi;
char var[256];
/* argtolower(argc, argv); */ /* argtolower(argc, argv); */
if (argc < 4) goto illarg; 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); SCWrite(pCon, "ERROR: LoggerDir not found", eError);
return 0; return 0;
} }
LoggerSetDir(dir);
} }
if (dir2 == NULL) { if (dir2 == NULL) {
dir2 = IFindOption(pSICSOptions, "LoggerDir2"); dir2 = IFindOption(pSICSOptions, "LoggerDir2");
if (dir2 == NULL) dir2=""; if (dir2 == NULL) {
dir2="";
}
} }
now1 = LoggerGetLastLife(NULL);
if (now1 == 0) now1 = now;
now2 = 0;
loss = 0; loss = 0;
overflow = 0; overflow = 0;
@ -312,23 +317,32 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
/* convert slashes to dots */ /* convert slashes to dots */
varp = argv[i]; varp = argv[i];
if (*varp == '/') varp++; 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 == '/') { if (*varp == '/') {
c.var[j] = '.'; var[j] = '.';
} else { } else {
c.var[j] = *varp; var[j] = *varp;
} }
} }
c.header = argv[i];
c.period = 0;
var[j] = '\0';
c.type = type0; c.type = type0;
c.np = np; c.np = np;
l = LoggerVarPath(dir, path, sizeof path, c.var); l = LoggerVarPath(dir, path, sizeof path, var);
dr = opendir(path); dr = opendir(path);
if (dr) { if (dr) {
nowi = now1;
closedir(dr); closedir(dr);
} else { } 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); dr = opendir(path);
if (dr) { if (dr) {
closedir(dr); closedir(dr);
@ -337,7 +351,7 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
isdst = -1; isdst = -1;
fil = NULL; fil = NULL;
while (startim <= to && c.tlast <= to) { while (startim <= to && c.last.t <= to) {
tm = *localtime(&startim); tm = *localtime(&startim);
if (tm.tm_yday != yday) { if (tm.tm_yday != yday) {
if (fil != NULL) { /* close file if day changed */ if (fil != NULL) { /* close file if day changed */
@ -356,13 +370,14 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
fclose(fil); fclose(fil);
fil = NULL; fil = NULL;
} else { } else {
lxs = getOpt(line, &isdst, &c.exact); c.period = getOpt(line, &isdst, &c.exact);
if (lxs >= 0) { /* if (c.exact) c.period = 0; */
if (lxs == 0) { if (c.period >= 0) {
if (c.period == 0) {
c.type = TEXT; c.type = TEXT;
} else { } else {
c.type = type0; c.type = type0;
xs = lxs; xs = c.period;
} }
if (xs < step) { if (xs < step) {
loss = 1; loss = 1;
@ -380,13 +395,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
/* printf("%s\n", line); */ /* printf("%s\n", line); */
if (lin == NULL) break; if (lin == NULL) break;
if (line[0] == '#') { if (line[0] == '#') {
lxs = getOpt(line, &isdst, &c.exact); c.period = getOpt(line, &isdst, &c.exact);
if (lxs >= 0) { if (c.period >= 0) {
if (lxs == 0) { if (c.period == 0) {
c.type = TEXT; c.type = TEXT;
} else { } else {
c.type = type0; c.type = type0;
xs = lxs; xs = c.period;
} }
if (xs < step) { if (xs < step) {
loss = 1; loss = 1;
@ -413,13 +428,13 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
if (p) { if (p) {
stp = p+1; stp = p+1;
*p='\0'; *p='\0';
iret = sscanf(stp, "%ld", &lxs); iret = sscanf(stp, "%ld", &c.period);
if (iret == 1) { if (iret == 1) {
if (lxs == 0) { if (c.period == 0) {
c.type = TEXT; c.type = TEXT;
} else { } else {
c.type = type0; c.type = type0;
xs = lxs; xs = c.period;
} }
if (xs < step) { if (xs < step) {
loss = 1; loss = 1;
@ -464,8 +479,8 @@ static int LogReader(SConnection *pCon, SicsInterp *pSics, void *pData,
PutValue(&c, lastt, lastval); PutValue(&c, lastt, lastval);
} }
} }
c.ylast = LOGGER_NAN; /* force output of last value */ WriteHeader(&c); /* write header, if not already done */
PutValue(&c, 0, ""); /* finish */ PutFinish(&c, nowi);
if (fil) { if (fil) {
fclose(fil); fclose(fil);
fil = NULL; fil = NULL;

View File

@ -73,11 +73,17 @@ static int LogSetup(SConnection *pCon, SicsInterp *pSics, void *pData,
} else { } else {
numeric = 0; numeric = 0;
} }
logger = LoggerMake(name, period, !numeric); logger = FindHdbCallbackData(node, HCBUPDATE, LoggerUpdateCallback, NULL);
LoggerSetNumeric(logger, numeric); if (logger != 0) { /* logger exists already, changed only period */
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger, (void (*)(void *))LoggerKill, -1, NULL); LoggerSetPeriod(logger, period);
assert(cb); } else {
AppendHipadabaCallback(node, HCBUPDATE, cb); 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; return 1;
} }

View File

@ -71,7 +71,6 @@
pRes->parNode = NULL; pRes->parNode = NULL;
pRes->SaveStatus = DefaultSave; pRes->SaveStatus = DefaultSave;
pRes->GetInterface = DefaultGetInterface; pRes->GetInterface = DefaultGetInterface;
pRes->creationCommand = NULL;
return pRes; return pRes;
} }
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/
@ -157,7 +156,7 @@
{ {
if(NULL!=self) if(NULL!=self)
{ {
IFSetOption(self->pKeys,keyName,eltValue); self->pKeys = IFSetOption(self->pKeys,keyName,eltValue);
} }
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
@ -167,7 +166,7 @@
{ {
return; return;
} }
IFSetOption(self->pKeys,"group",group); self->pKeys = IFSetOption(self->pKeys,"group",group);
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
void SetDescriptorDescription(pObjectDescriptor self, char *description) void SetDescriptorDescription(pObjectDescriptor self, char *description)
@ -176,7 +175,7 @@
{ {
return; return;
} }
IFSetOption(self->pKeys,"description", description); self->pKeys = IFSetOption(self->pKeys,"description", description);
} }
/*--------------------------------------------------------------------------*/ /*--------------------------------------------------------------------------*/
char * GetDescriptorKey(pObjectDescriptor self, char *keyName) char * GetDescriptorKey(pObjectDescriptor self, char *keyName)

View File

@ -31,7 +31,6 @@
void *(*GetInterface)(void *self, int iInterfaceID); void *(*GetInterface)(void *self, int iInterfaceID);
IPair *pKeys; IPair *pKeys;
pHdb parNode; pHdb parNode;
char *creationCommand; /* NULL when a static object */
} ObjectDescriptor, *pObjectDescriptor; } ObjectDescriptor, *pObjectDescriptor;
/*---------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------*/

View File

@ -3,8 +3,6 @@
#include "statusfile.h" #include "statusfile.h"
#include "sicshipadaba.h" #include "sicshipadaba.h"
static pDummy creationCommands = NULL;
static void SaveHdbBranch(pHdb node, FILE *fil) { static void SaveHdbBranch(pHdb node, FILE *fil) {
pHdb child; pHdb child;
char prop[16]; char prop[16];

View File

@ -28,6 +28,7 @@ typedef enum {
sct_take_keyword, sct_take_keyword,
sct_get_keyword, sct_get_keyword,
sct_complete_keyword, sct_complete_keyword,
sct_retry_keyword,
sct_chain_keyword, sct_chain_keyword,
sct_next_keyword, sct_next_keyword,
sct_steplist_keyword, sct_steplist_keyword,
@ -44,6 +45,7 @@ static char *sctKeywords[]={
"take", "take",
"get", "get",
"complete", "complete",
"retry",
"chain", "chain",
"next", "next",
"steplist", "steplist",
@ -116,6 +118,7 @@ struct Sct {
char *result; char *result;
char *nextScript; char *nextScript;
SctChain *runningChain; SctChain *runningChain;
int tryCnt;
SCStore debugConn; SCStore debugConn;
char *debugCommand; char *debugCommand;
int sent; 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) { int SctCallDynamicScript(Sct *sct, char *name, char *script) {
SctList *sl; SctList *sl;
SctChain *sc; SctChain *sc;
for (sl = sct->scriptLists.head; sl != NULL; sl = sl->next) { 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 */ for (sc = sl->chains.head; sc != NULL; sc = sc->next) { /* don't touch the list pos */
if (sc->dynamic && strcasecmp(name, sc->dynamic) == 0) { 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; goto missingScriptList;
case sct_retry_keyword:
if (argc < 3) {
SCPrintf(con, eInError, "ERROR: should be: %s retry <max try> <message>", 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: case sct_chain_keyword:
if (argc < 4) { if (argc < 4) {
SCPrintf(con, eInError, "ERROR: should be: %s chain <name> <script>", argv[0]); SCPrintf(con, eInError, "ERROR: should be: %s chain <name> <script>", argv[0]);
@ -496,6 +519,7 @@ static char *SctCallChain(SctChain *sc) {
return NULL; /* empty script: do nothing */ return NULL; /* empty script: do nothing */
} }
sct->runningChain = sc; sct->runningChain = sc;
sct->tryCnt = 0;
sct->relatedPath = sc->relatedPath; sct->relatedPath = sc->relatedPath;
sc->msg = NULL; sc->msg = NULL;
return SctCall(sc->command); return SctCall(sc->command);
@ -759,14 +783,14 @@ int SctAddNode2Script(Sct *sct, SctChain *sc, pHdb node, SConnection *con) {
if (child == NULL) { if (child == NULL) {
child = MakeSICSHdbPar("error", usInternal, MakeHdbText("")); child = MakeSICSHdbPar("error", usInternal, MakeHdbText(""));
AddHipadabaChild(node, child, NULL); AddHipadabaChild(node, child, NULL);
SetHdbProperty(child, "hidden", "whenempty"); SetHdbProperty(child, "visible", "false");
} }
if (sc->scriptList->type == set_type) { if (sc->scriptList->type == set_type) {
child = GetHipadabaNode(node, "target"); child = GetHipadabaNode(node, "target");
if (child == NULL) { if (child == NULL) {
child = MakeSICSHdbPar("target", usInternal, node->value); child = MakeSICSHdbPar("target", usInternal, node->value);
AddHipadabaChild(node, child, NULL); AddHipadabaChild(node, child, NULL);
SetHdbProperty(child, "hidden","target"); SetHdbProperty(child, "visible","false");
} }
data->setChain = sc; data->setChain = sc;
} else { } else {

View File

@ -282,8 +282,8 @@ pSICSOBJ SetupSICSOBJ(SConnection *pCon,SicsInterp *pSics, void *pData,
return NULL; return NULL;
} }
if (strcasecmp(argv[0],"DynSicsObj") == 0) { if (strcasecmp(argv[0],"DynSicsObj") == 0) {
/* save creation command */ /* make object dynamic by defining a descriptor command */
pNew->pDes->creationCommand = Arg2Tcl(argc, argv, NULL, -1); SetDescriptorKey(pNew->pDes, "creationCommand", "0");
} }
status = AddCommand(pSics, status = AddCommand(pSics,

View File

@ -222,7 +222,6 @@ static int listRestoreErr(pRestoreObj self, SConnection *pCon){
assert(pSics); assert(pSics);
assert(pCon); assert(pCon);
assert(self != NULL); assert(self != NULL);
StatusFileTask(NULL); /* do a save now, see also parameterChange = 0 at the end */
if(argc < 2) if(argc < 2)
{ {
@ -272,8 +271,7 @@ static int listRestoreErr(pRestoreObj self, SConnection *pCon){
/* /*
if we do not override parameterChange here, the backup file if we do not override parameterChange here, the backup file
would be overwritten after each restore... Not the right thing would be overwritten after each restore... Not the right thing
to do! As we have called StatusFileTask before, we are sure not to do!
to loose a change
*/ */
parameterChange = 0; parameterChange = 0;
SCSendOK(pCon); SCSendOK(pCon);