- added FindCommandDescriptor to SCinter.*
- modified support for dynamic objects - improved logger system - various fixes
This commit is contained in:
18
SCinter.c
18
SCinter.c
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
saveData->printHeader = 1;
|
||||||
|
fprintf(saveData->fil, "\n#--- BEGIN creation commands\n");
|
||||||
}
|
}
|
||||||
fprintf(fil, "%s\n", desc->creationCommand);
|
fprintf(saveData->fil, "%s\n", creationCommand);
|
||||||
}
|
}
|
||||||
}
|
return 1;
|
||||||
if (printHeader == 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;
|
||||||
}
|
}
|
||||||
|
174
logger.c
174
logger.c
@ -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);
|
||||||
|
|
||||||
|
if (period <= 0) period = 1;
|
||||||
|
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+");
|
fil = fopen(path, "r+");
|
||||||
skip = 0;
|
|
||||||
if (period <= 0) period = 1;
|
|
||||||
if (fil == NULL) { /* create new file */
|
if (fil == NULL) { /* create new file */
|
||||||
fil = fopen(path, "w+");
|
fil = fopen(path, "w+");
|
||||||
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;
|
|
||||||
isdst = tm->tm_isdst;
|
|
||||||
endPos = ftell(fil);
|
|
||||||
fseek(fil, -1, SEEK_CUR); /* position to newline */
|
|
||||||
} else { /* check if file is from today */
|
} else { /* check if file is from today */
|
||||||
fgets(buf, sizeof buf, fil);
|
fgets(buf, sizeof buf, fil);
|
||||||
if (0 != strncmp(buf, stim, 11)) {
|
if (0 != strncmp(buf, stim, 11)) {
|
||||||
fclose(fil);
|
fclose(fil); /* it was file from an earlier year */
|
||||||
fil=fopen(path, "w+"); /* overwrite old logfile */
|
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;
|
|
||||||
isdst = tm->tm_isdst;
|
|
||||||
endPos = ftell(fil);
|
|
||||||
fseek(fil, -1, SEEK_CUR); /* position to newline */
|
|
||||||
} else {
|
} else {
|
||||||
fseek(fil, -log->lastLn, SEEK_END); /* set position to last line */
|
fseek(fil, 0, SEEK_END); /* set position to end */
|
||||||
endPos = ftell(fil) + log->lastLn;
|
if (writeInfo) {
|
||||||
if (endPos > 0 && log->lastLn == 0) {
|
fprintf(fil, "#isdst %d period %d exact %d\n", tm.tm_isdst, period, log->exact);
|
||||||
/* 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 */
|
if (log->lastWrite != 0 && now >= log->lastWrite + 2 * period) {
|
||||||
} else if (now != log->last) {
|
/* this is only useful for direct access of the log files */
|
||||||
skip = 1;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
changed = (0 != strcmp(value, log->old));
|
strftime(stim, sizeof stim,"%H:%M:%S", &tm);
|
||||||
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);
|
fprintf(fil, "%s\t%s\n", stim, value);
|
||||||
for (p = ftell(fil); p < endPos; p++) { /* overwrite dirt after last line */
|
log->lastWrite = now;
|
||||||
fprintf(fil, " ");
|
|
||||||
}
|
|
||||||
endPos = ftell(fil);
|
|
||||||
fclose(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);
|
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(log->old);
|
||||||
assert(l < log->oldsize);
|
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;
|
||||||
|
4
logger.h
4
logger.h
@ -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);
|
||||||
|
|
||||||
|
251
logreader.c
251
logreader.c
@ -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);
|
|
||||||
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) {
|
if (c->none) {
|
||||||
snprintf(line, sizeof line, "%ld %s\n", (long)(t - c->tlast), c->none);
|
value = c->none;
|
||||||
} else {
|
} else {
|
||||||
snprintf(line, sizeof line, "%ld\n", (long)(t - c->tlast));
|
value = "";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
snprintf(line, sizeof line, "%ld %g\n", (long)(t - c->tlast), y);
|
if (c->omitEqual && c->written.y == p.y) return;
|
||||||
|
snprintf(c->buf, sizeof(c->buf), "%g", p.y);
|
||||||
|
value = c->buf;
|
||||||
}
|
}
|
||||||
/* printf("-%s\n", line); */
|
SCPrintf(c->pCon, eWarning, "%ld %s", (long)(p.t - c->written.t), value);
|
||||||
c->tlast = t;
|
c->written = p;
|
||||||
SCWrite(c->pCon, line, eWarning);
|
|
||||||
c->np--;
|
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;
|
|
||||||
y = 0;
|
|
||||||
} else {
|
|
||||||
y = strtod(value, &p);
|
|
||||||
if (p == value) {
|
if (p == value) {
|
||||||
y = LOGGER_NAN;
|
new.y = LOGGER_NAN;
|
||||||
} else {
|
} else {
|
||||||
if (y == LOGGER_NAN) y *= 1.0000002;
|
if (new.y == LOGGER_NAN) new.y *= 1.0000002;
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
/* printf("put %ld %g\n", t, y); */
|
c->best = new;
|
||||||
if (c->tlim == 0) goto first;
|
|
||||||
if (t >= c->tlim) {
|
|
||||||
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) {
|
c->tlim = t + c->step;
|
||||||
OutFloat(c, c->tmin, c->ymin);
|
|
||||||
if (t >= c->tlim + c->step) {
|
|
||||||
OutFloat(c, c->told, c->yold);
|
|
||||||
}
|
}
|
||||||
goto first;
|
} 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++;
|
|
||||||
for (j = 0; j < sizeof(c.var) && *varp != 0; j++, varp++) {
|
|
||||||
if (*varp == '/') {
|
|
||||||
c.var[j] = '.';
|
|
||||||
} else {
|
|
||||||
c.var[j] = *varp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (*varp == '/') varp++;
|
||||||
|
for (j = 0; j < sizeof(var)-1 && *varp != 0; j++, varp++) {
|
||||||
|
if (*varp == '/') {
|
||||||
|
var[j] = '.';
|
||||||
|
} else {
|
||||||
|
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;
|
||||||
|
@ -73,11 +73,17 @@ static int LogSetup(SConnection *pCon, SicsInterp *pSics, void *pData,
|
|||||||
} else {
|
} else {
|
||||||
numeric = 0;
|
numeric = 0;
|
||||||
}
|
}
|
||||||
|
logger = FindHdbCallbackData(node, HCBUPDATE, LoggerUpdateCallback, NULL);
|
||||||
|
if (logger != 0) { /* logger exists already, changed only period */
|
||||||
|
LoggerSetPeriod(logger, period);
|
||||||
|
} else {
|
||||||
logger = LoggerMake(name, period, !numeric);
|
logger = LoggerMake(name, period, !numeric);
|
||||||
LoggerSetNumeric(logger, numeric);
|
LoggerSetNumeric(logger, numeric);
|
||||||
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger, (void (*)(void *))LoggerKill, -1, NULL);
|
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger, (void (*)(void *))LoggerKill, -1, NULL);
|
||||||
assert(cb);
|
assert(cb);
|
||||||
AppendHipadabaCallback(node, HCBUPDATE, cb);
|
AppendHipadabaCallback(node, HCBUPDATE, cb);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
7
obdes.c
7
obdes.c
@ -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)
|
||||||
|
1
obdes.h
1
obdes.h
@ -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;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------*/
|
||||||
|
@ -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];
|
||||||
|
@ -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 {
|
||||||
|
@ -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,
|
||||||
|
@ -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);
|
||||||
|
Reference in New Issue
Block a user