various improvements
- use dig for resolving host names - ascon.c: fix terminator parsing - property callback: change property before callback - logger.c:default for logger period must be the old value instead of 1 - add frappy type history writing - increase max. logreader line length - HIPNONE returns "null" with json protocol - encode strings properly in formatNameValue - fix memory leak in json2tcl - scriptcontext: do not show debug messages when script starts with underscore or when the "send" property is empty - scriptcontext: remove args for action timestamp - scriptcontext: "que" function will replace an already queued action, e.g. for 'halt - introduced updatestatus script
This commit is contained in:
320
logsetup.c
320
logsetup.c
@ -1,8 +1,161 @@
|
||||
#include "logger.h"
|
||||
#include "logsetup.h"
|
||||
#include "sics.h"
|
||||
#include "sicshipadaba.h"
|
||||
|
||||
static char *loggerID = "loggerID";
|
||||
static char *histDir = NULL;
|
||||
/* static char basepath[1024] = "/"; */
|
||||
|
||||
typedef struct _HistWriter {
|
||||
char *name;
|
||||
int old_hour;
|
||||
FILE *fd;
|
||||
time_t timestamp;
|
||||
} HistWriter;
|
||||
|
||||
HistWriter mainWriter={""};
|
||||
|
||||
int FlushTask(void *data) {
|
||||
HistWriter *wr = data;
|
||||
|
||||
if (wr->fd) fflush(wr->fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int HistPath(char *dir, char *path, int pathLen, struct tm *t)
|
||||
{
|
||||
int l;
|
||||
|
||||
l = strlen(dir);
|
||||
if (l + 17 >= pathLen) {
|
||||
path[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
strcpy(path, dir);
|
||||
strftime(path + l, pathLen - l, "/%Y/%Y-%m-%d/", t);
|
||||
l += 17;
|
||||
path[l] = '\0';
|
||||
return l;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void HistWriteType(Logger *logger)
|
||||
{
|
||||
HistWriter *wr = logger->histWriter;
|
||||
if (logger->numeric) {
|
||||
fprintf(wr->fd, "#NUM %s %s\n", logger->secop_id, logger->name);
|
||||
} else {
|
||||
fprintf(wr->fd, "#STR %s %s\n", logger->secop_id, logger->name);
|
||||
}
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static void HistWrite(Logger *logger, pHdb node, time_t t, char *value)
|
||||
{
|
||||
HistWriter *wr = logger->histWriter;
|
||||
char path[1024];
|
||||
time_t now;
|
||||
int l;
|
||||
struct tm tm, tm0;
|
||||
FILE *fd;
|
||||
Logger *lg;
|
||||
char *secop_id;
|
||||
time_t current_hour;
|
||||
int hour_of_day;
|
||||
int reopen = 0;
|
||||
|
||||
secop_id = GetHdbProp(node, "secop_id");
|
||||
if (!secop_id || !secop_id[0]) {
|
||||
if (logger->secop_old) {
|
||||
free(logger->secop_old);
|
||||
logger->secop_old = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!logger->secop_id) logger->secop_id = strdup("");
|
||||
if (strcmp(secop_id, logger->secop_id) != 0) {
|
||||
free(logger->secop_id);
|
||||
logger->secop_id = strdup(secop_id);
|
||||
}
|
||||
time(&now);
|
||||
tm = *localtime(&now);
|
||||
current_hour = now / 3600;
|
||||
if (current_hour != wr->old_hour) {
|
||||
if (wr->fd) {
|
||||
fprintf(wr->fd, "# %ld\n#END\n", (wr->timestamp / 3600 + 1) * 3600);
|
||||
fclose(wr->fd);
|
||||
wr->fd = NULL;
|
||||
}
|
||||
reopen = 1;
|
||||
}
|
||||
if (!wr->fd) {
|
||||
if (histDir == NULL || reopen) {
|
||||
histDir = IFindOption(pSICSOptions, "HistoryDir");
|
||||
if (histDir == NULL) goto failed;
|
||||
HistPath(histDir, path, sizeof path, &tm);
|
||||
if (LoggerMakeDir(path) == 0) goto failed;
|
||||
} else if (!*histDir) {
|
||||
/* history writing not configured, or failed for current hour */
|
||||
return;
|
||||
}
|
||||
/* last midnight: */
|
||||
tm.tm_hour = 0;
|
||||
tm.tm_min = 0;
|
||||
tm.tm_sec = 0;
|
||||
tm.tm_isdst = -1;
|
||||
hour_of_day = (now - mktime(&tm)) / 3600;
|
||||
l = HistPath(histDir, path, sizeof path, &tm);
|
||||
strftime(path + l, sizeof path - l, "%Y-%m-%d", &tm);
|
||||
l += 10;
|
||||
if (l + 12 >= sizeof path) goto failed;
|
||||
snprintf(path + l, sizeof path - l, "_%02d_hist.txt", hour_of_day);
|
||||
fd = fopen(path, "r");
|
||||
if (!fd) {
|
||||
wr->fd = fopen(path, "w");
|
||||
if (!wr->fd) goto failed; /* can not create file */
|
||||
} else {
|
||||
fclose(fd);
|
||||
wr->fd = fopen(path, "a");
|
||||
if (!wr->fd) goto failed; /* no write access to file */
|
||||
}
|
||||
fprintf(wr->fd, "#FRAPPY_HISTORY\n");
|
||||
if (!wr->old_hour) {
|
||||
TaskRegisterP(pServ->pTasker, "flush", FlushTask, 0, 0, wr, 0, 0.1, 0.1);
|
||||
}
|
||||
wr->old_hour = current_hour;
|
||||
fprintf(wr->fd, "# %ld\n", t);
|
||||
wr->timestamp = t;
|
||||
for (lg = LoggerList(); lg != NULL; lg = lg->next) {
|
||||
if (lg->secop_old) {
|
||||
HistWriteType(lg);
|
||||
fprintf(wr->fd, "%s %s\n", lg->secop_id, lg->secop_old);
|
||||
}
|
||||
}
|
||||
if (logger->secop_old) free(logger->secop_old);
|
||||
logger->secop_old = NULL;
|
||||
}
|
||||
if (logger->secop_old == NULL) {
|
||||
if (value[0] == '\0') {
|
||||
return;
|
||||
}
|
||||
HistWriteType(logger);
|
||||
logger->secop_old = strdup("");
|
||||
}
|
||||
if (strcmp(logger->secop_old, value) != 0) {
|
||||
if (t != wr->timestamp) {
|
||||
fprintf(wr->fd, "# %ld\n", t);
|
||||
wr->timestamp = t;
|
||||
}
|
||||
fprintf(wr->fd, "%s %s\n", secop_id, value);
|
||||
free(logger->secop_old);
|
||||
logger->secop_old = strdup(value);
|
||||
}
|
||||
return;
|
||||
failed:
|
||||
histDir = "";
|
||||
}
|
||||
|
||||
|
||||
static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||
void *userData,
|
||||
@ -14,7 +167,9 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||
hdbValue value;
|
||||
pHdbDataMessage mm = NULL;
|
||||
pHdbDataSearch dsm = NULL;
|
||||
pHdbMessage killmsg = NULL;
|
||||
time_t now;
|
||||
char *strvalue;
|
||||
|
||||
if ((dsm = GetHdbDataSearchMessage(message)) != NULL) {
|
||||
if (dsm->testPtr == loggerID) {
|
||||
@ -24,6 +179,18 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
if ((killmsg = GetHdbKillNodeMessage(message)) != NULL) {
|
||||
if (logger->histWriter) {
|
||||
time(&now);
|
||||
HistWrite(logger, node, now, "");
|
||||
if (logger->secop_old) {
|
||||
free(logger->secop_old);
|
||||
logger->secop_old = NULL;
|
||||
}
|
||||
}
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
if ((mm = GetHdbUpdateMessage(message)) == NULL) {
|
||||
return hdbContinue;
|
||||
}
|
||||
@ -31,66 +198,43 @@ static hdbCallbackReturn LoggerUpdateCallback(pHdb node,
|
||||
value = *(mm->v);
|
||||
|
||||
time(&now);
|
||||
|
||||
if (GetHdbProp(node, "geterror") == NULL) {
|
||||
str = formatValue(value, node);
|
||||
strvalue = GetCharArray(str);
|
||||
} else {
|
||||
str = NULL;
|
||||
strvalue = "";
|
||||
}
|
||||
/* testwise >= */
|
||||
if (now >= LoggerLastTime(logger)) { /* never write more than once per second */
|
||||
if (GetHdbProp(node, "geterror") == NULL) {
|
||||
str = formatValue(value, node);
|
||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), GetCharArray(str));
|
||||
DeleteDynString(str);
|
||||
} else {
|
||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), "");
|
||||
}
|
||||
LoggerWrite(logger, now, LoggerPeriod(logger), strvalue);
|
||||
}
|
||||
if (logger->histWriter) {
|
||||
HistWrite(logger, node, now, strvalue);
|
||||
}
|
||||
if (str) {
|
||||
DeleteDynString(str);
|
||||
}
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pHdb node;
|
||||
pHdbCallback cb;
|
||||
static char basepath[1024] = "/";
|
||||
int LogMakeInternal(pHdb node, char *path, int period) {
|
||||
char buf[1024];
|
||||
char *p, *name;
|
||||
static char *loggerDir = NULL;
|
||||
int numeric, period;
|
||||
char secop_id[1024];
|
||||
char secop_par[1024];
|
||||
char *module;
|
||||
int pos, l;
|
||||
pHdb nd;
|
||||
int numeric;
|
||||
Logger *logger;
|
||||
char *p, *name;
|
||||
pHdbCallback cb;
|
||||
|
||||
if (argc < 2) {
|
||||
SCPrintf(pCon, eError,
|
||||
"ERROR: should be: logsetup <node> [<period> [<filename>]]");
|
||||
/* or logsetup <node> clear */
|
||||
return 0;
|
||||
}
|
||||
if (strcasecmp(argv[1], "basepath") == 0) {
|
||||
if (argc > 2) {
|
||||
snprintf(basepath, sizeof basepath, "%s", argv[2]);
|
||||
}
|
||||
SCPrintf(pCon, eValue, "%s", basepath);
|
||||
return 1;
|
||||
}
|
||||
if (loggerDir == NULL) {
|
||||
loggerDir = IFindOption(pSICSOptions, "LoggerDir");
|
||||
if (loggerDir == NULL)
|
||||
loggerDir = "./";
|
||||
LoggerSetDir(loggerDir);
|
||||
}
|
||||
if (strcasecmp(argv[1], "directory") == 0) {
|
||||
if (argc > 2) {
|
||||
loggerDir = strdup(argv[2]);
|
||||
}
|
||||
SCPrintf(pCon, eValue, "%s", loggerDir);
|
||||
return 1;
|
||||
}
|
||||
node = FindHdbNode(basepath, argv[1], pCon);
|
||||
if (node == NULL) {
|
||||
SCPrintf(pCon, eError, "ERROR: %s not found", argv[1]);
|
||||
return 0;
|
||||
}
|
||||
if (argc > 3) {
|
||||
snprintf(buf, sizeof buf, "%s", argv[3]);
|
||||
if (strncmp(path, "/sics/", 6) == 0) {
|
||||
snprintf(buf, sizeof buf, "%s", path+5);
|
||||
} else {
|
||||
snprintf(buf, sizeof buf, "%s", argv[1]);
|
||||
snprintf(buf, sizeof buf, "%s", path);
|
||||
}
|
||||
for (p = buf; *p != '\0'; p++) {
|
||||
if (*p == '/')
|
||||
@ -101,29 +245,22 @@ static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
} else {
|
||||
name = buf;
|
||||
}
|
||||
if (node->value.dataType == HIPFLOAT) {
|
||||
if (node->value.dataType == HIPFLOAT || node->value.dataType == HIPINT) {
|
||||
numeric = 1;
|
||||
} else {
|
||||
numeric = 0;
|
||||
}
|
||||
logger = FindHdbCallbackData(node, loggerID);
|
||||
period = 0;
|
||||
if (argc > 2) {
|
||||
if (logger != NULL && strcasecmp(argv[2], "clear") == 0) {
|
||||
LoggerWrite(logger, time(NULL), LoggerPeriod(logger), "");
|
||||
return 1;
|
||||
}
|
||||
period = atoi(argv[2]);
|
||||
}
|
||||
if (logger != 0) { /* logger exists already */
|
||||
LoggerChange(logger, period, name);
|
||||
} else {
|
||||
logger = LoggerMake(name, period, !numeric);
|
||||
/* If that failed, we cannot continue - it crashes in the callback */
|
||||
if (logger == NULL) {
|
||||
SCPrintf(pCon, eError, "ERROR: logger %s not created", argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
logger->histWriter = &mainWriter;
|
||||
LoggerSetNumeric(logger, numeric);
|
||||
SetHdbProperty(node, "logger_name", name);
|
||||
cb = MakeHipadabaCallback(LoggerUpdateCallback, logger,
|
||||
@ -131,7 +268,70 @@ static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
assert(cb);
|
||||
AppendHipadabaCallback(node, cb);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int LogSetup(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pHdb node;
|
||||
static char *loggerDir = NULL;
|
||||
int period;
|
||||
Logger *logger;
|
||||
char *p;
|
||||
pDynString result;
|
||||
time_t now;
|
||||
|
||||
if (argc < 2 || argc > 3) {
|
||||
SCPrintf(pCon, eError,
|
||||
"ERROR: should be: logsetup <node> [<period>]");
|
||||
/* or logsetup <node> clear */
|
||||
return 0;
|
||||
}
|
||||
/* seems not used
|
||||
if (strcasecmp(argv[1], "basepath") == 0) {
|
||||
if (argc > 2) {
|
||||
snprintf(basepath, sizeof basepath, "%s", argv[2]);
|
||||
}
|
||||
SCPrintf(pCon, eValue, "%s", basepath);
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
if (loggerDir == NULL) {
|
||||
loggerDir = IFindOption(pSICSOptions, "LoggerDir");
|
||||
if (loggerDir == NULL)
|
||||
loggerDir = "./";
|
||||
LoggerSetDir(loggerDir);
|
||||
}
|
||||
if (strcasecmp(argv[1], "directory") == 0) {
|
||||
/* not used ? M.Z. 10.2020 */
|
||||
if (argc > 2) {
|
||||
loggerDir = strdup(argv[2]);
|
||||
}
|
||||
SCPrintf(pCon, eValue, "%s", loggerDir);
|
||||
return 1;
|
||||
}
|
||||
node = FindHdbIntern(argv[1]);
|
||||
if (node == NULL) {
|
||||
SCPrintf(pCon, eError, "ERROR: %s not found", argv[1]);
|
||||
return 0;
|
||||
}
|
||||
period = 0; /* default period */
|
||||
if (argc > 2 && argv[2][0]) {
|
||||
if (strcasecmp(argv[2], "clear") == 0) {
|
||||
logger = FindHdbCallbackData(node, loggerID);
|
||||
time(&now);
|
||||
if (logger) { /* silently ignore clear on a missing logger */
|
||||
LoggerWrite(logger, now, LoggerPeriod(logger), "");
|
||||
HistWrite(logger, node, now, "");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
period = atoi(argv[2]);
|
||||
}
|
||||
if (!LogMakeInternal(node, argv[1], period)) {
|
||||
SCPrintf(pCon, eError, "ERROR: logger %s not created", argv[1]);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user