/*----------------------------------------------------------------------- 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, commandContext cc){ 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; TaskRegister(pServ->pTasker,UpdateTask,NULL,NULL,self,1); 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; commandContext comCon; 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 */ comCon.transID = 0; strncpy(comCon.deviceID,"internal",SCDEVIDLEN); RegisterCallback(pCall,comCon,COUNTSTART,CountCallback, self,NULL); RegisterCallback(pCall,comCon,COUNTEND,CountCallback, self,NULL); AddCommand(pSics,argv[1],UpdateAction,KillUpdate,self); return 1; }