337 lines
9.0 KiB
C
337 lines
9.0 KiB
C
/*-----------------------------------------------------------------------
|
|
Automatic update of NeXus files a scheduled time intervalls.
|
|
For more information see nxudpate.tex.
|
|
|
|
copyright: see file COPYRIGHT
|
|
|
|
Mark Koennecke, December 2003
|
|
----------------------------------------------------------------------*/
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <errno.h>
|
|
#include <time.h>
|
|
#include "fortify.h"
|
|
#include "sics.h"
|
|
#include "splitter.h"
|
|
#include "nxupdate.h"
|
|
#include "nxupdate.i"
|
|
/*-------------------------------------------------------------------*/
|
|
static int UpdateTask(void *pData)
|
|
{
|
|
pNXupdate self = NULL;
|
|
|
|
self = (pNXupdate) pData;
|
|
if (self == NULL) {
|
|
return 0;
|
|
}
|
|
|
|
if (self->onOff == 0) {
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
update when intervall reached or when end
|
|
*/
|
|
if (time(NULL) >= self->nextUpdate || self->iEnd == 1) {
|
|
if (self->updateScript != NULL && self->pCon != NULL) {
|
|
InterpExecute(pServ->pSics, self->pCon, self->updateScript);
|
|
}
|
|
self->nextUpdate = time(NULL) + self->updateIntervall;
|
|
}
|
|
|
|
if (self->iEnd == 1) {
|
|
self->pCon = NULL;
|
|
return 0;
|
|
} else {
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static int CountCallback(int iEvent, void *pEventData, void *pUser)
|
|
{
|
|
pNXupdate self = NULL;
|
|
SConnection *pCon = NULL;
|
|
|
|
self = (pNXupdate) pUser;
|
|
pCon = (SConnection *) pEventData;
|
|
|
|
if (self->onOff == 0) {
|
|
return 1;
|
|
}
|
|
|
|
if (iEvent == COUNTSTART) {
|
|
assert(pCon);
|
|
assert(self);
|
|
/*
|
|
start file
|
|
*/
|
|
if (self->startScript != NULL) {
|
|
InterpExecute(pServ->pSics, pCon, self->startScript);
|
|
}
|
|
if (self->updateScript != NULL) {
|
|
InterpExecute(pServ->pSics, pCon, self->updateScript);
|
|
}
|
|
if (self->linkScript != NULL) {
|
|
InterpExecute(pServ->pSics, pCon, self->linkScript);
|
|
}
|
|
/*
|
|
register update function
|
|
*/
|
|
self->nextUpdate = time(NULL) + self->updateIntervall;
|
|
self->iEnd = 0;
|
|
self->pCon = pCon;
|
|
TaskRegisterN(pServ->pTasker, "NXupdater", UpdateTask, NULL, NULL, self, TASK_PRIO_HIGH);
|
|
return 1;
|
|
} else if (iEvent == COUNTEND) {
|
|
self->iEnd = 1;
|
|
assert(self);
|
|
return 1;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
void KillUpdate(void *pData)
|
|
{
|
|
pNXupdate self = NULL;
|
|
|
|
self = (pNXupdate) pData;
|
|
if (self == NULL) {
|
|
return;
|
|
}
|
|
|
|
if (self->startScript != NULL) {
|
|
free(self->startScript);
|
|
self->startScript = NULL;
|
|
}
|
|
if (self->updateScript != NULL) {
|
|
free(self->updateScript);
|
|
self->updateScript = NULL;
|
|
}
|
|
if (self->linkScript != NULL) {
|
|
free(self->linkScript);
|
|
self->linkScript = NULL;
|
|
}
|
|
free(self);
|
|
}
|
|
|
|
/*-------------------------------------------------------------------*/
|
|
static void printUpdateList(SConnection * pCon, pNXupdate self, char *name)
|
|
{
|
|
char pBueffel[256];
|
|
|
|
snprintf(pBueffel, 255, "%s.startScript = %s", name, self->startScript);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
snprintf(pBueffel, 255, "%s.updateScript = %s", name,
|
|
self->updateScript);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
snprintf(pBueffel, 255, "%s.linkScript = %s", name, self->linkScript);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
snprintf(pBueffel, 255, "%s.updateIntervall = %d", name,
|
|
self->updateIntervall);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
snprintf(pBueffel, 255, "%s.onOff = %d", name, self->onOff);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
}
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
static int printUpdateParameters(SConnection * pCon, pNXupdate self,
|
|
char *name, char *param)
|
|
{
|
|
char pBueffel[256];
|
|
if (strcmp(param, "list") == 0) {
|
|
printUpdateList(pCon, self, name);
|
|
return 1;
|
|
} else if (strcmp(param, "startscript") == 0) {
|
|
snprintf(pBueffel, 255, "%s.startScript = %s", name,
|
|
self->startScript);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(param, "updatescript") == 0) {
|
|
snprintf(pBueffel, 255, "%s.updateScript = %s", name,
|
|
self->updateScript);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(param, "linkscript") == 0) {
|
|
snprintf(pBueffel, 255, "%s.linkScript = %s", name, self->linkScript);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(param, "updateintervall") == 0) {
|
|
snprintf(pBueffel, 255, "%s.updateIntervall = %d", name,
|
|
self->updateIntervall);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else if (strcmp(param, "onoff") == 0) {
|
|
snprintf(pBueffel, 255, "%s.onoff = %d", name, self->onOff);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 255, "ERROR: parameter %s not known", param);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*---------------------------------------------------------------------*/
|
|
static int configureUpdate(SConnection * pCon, pNXupdate self,
|
|
char *param, char *value)
|
|
{
|
|
char pBueffel[256];
|
|
int newUpdate;
|
|
|
|
if (strcmp(param, "startscript") == 0) {
|
|
if (self->startScript != NULL) {
|
|
free(self->startScript);
|
|
}
|
|
self->startScript = strdup(value);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(param, "updatescript") == 0) {
|
|
if (self->updateScript != NULL) {
|
|
free(self->updateScript);
|
|
}
|
|
self->updateScript = strdup(value);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(param, "linkscript") == 0) {
|
|
if (self->linkScript != NULL) {
|
|
free(self->linkScript);
|
|
}
|
|
self->linkScript = strdup(value);
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(param, "updateintervall") == 0) {
|
|
if (Tcl_GetInt(InterpGetTcl(pServ->pSics), value, &newUpdate) !=
|
|
TCL_OK) {
|
|
snprintf(pBueffel, 255,
|
|
"ERROR: %s not an int, cannot set updateIntervall", value);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
self->updateIntervall = newUpdate;
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else if (strcmp(param, "onoff") == 0) {
|
|
if (Tcl_GetInt(InterpGetTcl(pServ->pSics), value, &newUpdate) !=
|
|
TCL_OK) {
|
|
snprintf(pBueffel, 255, "ERROR: %s not an int, cannot set onoff",
|
|
value);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
if (newUpdate >= 1) {
|
|
self->onOff = 1;
|
|
} else {
|
|
self->onOff = 0;
|
|
}
|
|
SCSendOK(pCon);
|
|
return 1;
|
|
} else {
|
|
snprintf(pBueffel, 255, "ERROR: parameter %s not known", param);
|
|
SCWrite(pCon, pBueffel, eValue);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
int UpdateAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pNXupdate self = NULL;
|
|
char pBueffel[132];
|
|
|
|
self = (pNXupdate) pData;
|
|
assert(self);
|
|
|
|
if (argc < 2) {
|
|
snprintf(pBueffel, 131, "ERROR: need argument to %s", argv[0]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
if (argc < 3) {
|
|
strtolower(argv[1]);
|
|
return printUpdateParameters(pCon, self, argv[0], argv[1]);
|
|
} else {
|
|
Arg2Text(argc - 2, &argv[2], pBueffel, 131);
|
|
return configureUpdate(pCon, self, argv[1], pBueffel);
|
|
}
|
|
|
|
/*
|
|
not reached
|
|
*/
|
|
assert(0);
|
|
return 0;
|
|
}
|
|
|
|
/*----------------------------------------------------------------------*/
|
|
int UpdateFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
|
|
int argc, char *argv[])
|
|
{
|
|
pICountable pCount = NULL;
|
|
pICallBack pCall = NULL;
|
|
void *pPtr = NULL;
|
|
char pBueffel[256];
|
|
pNXupdate self = NULL;
|
|
CommandList *pCom = NULL;
|
|
|
|
if (argc < 3) {
|
|
SCWrite(pCon, "ERROR: insuffcient number of argument to UpdateFactory",
|
|
eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
argv[1] = name
|
|
argv[2] = counter with which to register for automatic notifications
|
|
*/
|
|
pCom = FindCommand(pSics, argv[2]);
|
|
if (pCom) {
|
|
pPtr = pCom->pData;
|
|
}
|
|
if (!pPtr) {
|
|
snprintf(pBueffel, 255, "ERROR: cannot find %s to register to",
|
|
argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
pCount = GetCountableInterface(pPtr);
|
|
pCall = GetCallbackInterface(pPtr);
|
|
if (!pCount || !pCall) {
|
|
snprintf(pBueffel, 255, "ERROR: %s is not a usable counter", argv[2]);
|
|
SCWrite(pCon, pBueffel, eError);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
allocate memory and initialize
|
|
*/
|
|
self = (pNXupdate) malloc(sizeof(NXupdate));
|
|
if (self == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in UpdateFactory", eError);
|
|
return 0;
|
|
}
|
|
memset(self, 0, sizeof(NXupdate));
|
|
self->pDes = CreateDescriptor("AutoUpdate");
|
|
if (self->pDes == NULL) {
|
|
SCWrite(pCon, "ERROR: out of memory in UpdateFactory", eError);
|
|
return 0;
|
|
}
|
|
self->startScript = strdup("UNDEFINED");
|
|
self->updateScript = strdup("UNDEFINED");
|
|
self->linkScript = strdup("UNDEFINED");
|
|
self->updateIntervall = 1200; /* 20 min */
|
|
self->onOff = 1;
|
|
|
|
|
|
/*
|
|
register callbacks
|
|
*/
|
|
RegisterCallback(pCall, COUNTSTART, CountCallback, self, NULL);
|
|
RegisterCallback(pCall, COUNTEND, CountCallback, self, NULL);
|
|
|
|
AddCommand(pSics, argv[1], UpdateAction, KillUpdate, self);
|
|
return 1;
|
|
}
|