/*----------------------------------------------------------------------- Automatic update of NeXus files a scheduled time intervalls. For more information see nxudpate.tex. copyright: see file COPYRIGHT Mark Koennecke, December 2003 ----------------------------------------------------------------------*/ #include #include #include #include #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; }