/** * This is a state monitor. It collects all the start and stop messages * from the device executor and from scan and batch commands. Clients can * listen to this in order to figure out what is actually going on in a * given SICS installation. This might in the end supersede the status code * managment in status.c * * copyright: see file COPYRIGHT * * Mark Koennecke, January 2007 */ #include #include "exeman.h" #include "scan.h" #include "scan.i" #include "stptok.h" #include "statemon.h" #include "sicshipadaba.h" /*==========================================================================*/ typedef struct __STATEMON { pObjectDescriptor pDes; pICallBack pCall; }StateMon; /*============================ Callbacks =================================*/ static int DevexecCallback(int iEvent, void *text, void *pData, commandContext cc){ char pDevice[132]; int eventCode; pStateMon self = (pStateMon)pData; memset(pDevice,0,132); if(iEvent == DRIVSTAT){ stptok(text,pDevice,131," "); if(strstr(text,"started") != NULL){ eventCode = STSTART; } else if(strstr(text,"finished") != NULL) { eventCode = STEND; } else { printf("Unrecognized event text from devexec in statemon.c: %s\n", (char *)text); return 0; } if(self != NULL){ InvokeCallBack(self->pCall,eventCode,pDevice); } } return 1; } /*---------------------------------------------------------------------------*/ static int StateMonScanInterest(int iEvent, void *pEventData, void *pUser, commandContext cc){ pScanData pScan = NULL; pStateMon self = (pStateMon)pUser; pScan = (pScanData)pEventData; if(pScan == NULL || self == NULL){ printf("Bad StateMonScanInterst in statemon\n"); return 0; } if(iEvent == SCANSTART){ InvokeCallBack(self->pCall,STSTART,pScan->objectName); return 1; }else if(iEvent == SCANEND){ InvokeCallBack(self->pCall,STEND,pScan->objectName); return 1; } return 1; } /*--------------------------------------------------------------------------*/ static int ExeCallback(int iEvent, void *pEvent, void *pUser, commandContext cc){ pStateMon self = (pStateMon)pUser; char *name = (char *)pEvent; char pBueffel[131]; if(self == NULL || name == NULL){ printf("Bad ExeCallback in statemon\n"); return 0; } if(iEvent == BATCHSTART){ snprintf(pBueffel,131,"exe %s",name); InvokeCallBack(self->pCall,STSTART,pBueffel); return 1; } if(iEvent == BATCHEND){ snprintf(pBueffel,131,"exe %s",name); InvokeCallBack(self->pCall,STEND,pBueffel); return 1; } return 0; } /*=============== user callbacks ============================================*/ static int StateInterest(int iEvent, void *pEvent, void *pUser, commandContext cc){ SConnection *pCon = (SConnection *)pUser; char *device = (char *)pEvent; char buffer[256]; if(pCon == NULL || device == NULL){ printf("Bad StateInterest in statemon\n"); return 0; } if(iEvent == STSTART){ snprintf(buffer,255,"STARTED = %s", device); SCWriteInContext(pCon,buffer,eWarning,cc); } if(iEvent == STEND){ snprintf(buffer,255,"FINISH = %s", device); SCWriteInContext(pCon,buffer,eWarning,cc); } return 1; } /*--------------------------------------------------------------------------*/ static pHdb recurseInterestNode(pHdb current, char *pDevice){ char pSicsdev[131], pAlias[132]; pHdb result = NULL; char *alias = NULL, *pPtr = NULL; memset(pSicsdev,0,132); memset(pAlias,0,132); if(current != NULL){ if(GetHdbProperty(current,"sicsdev",pSicsdev,131) != 0){ strtolower(pSicsdev); if(strcmp(pSicsdev,pDevice) == 0){ return current; } /* * try to look for aliases, too */ alias = FindAliases(pServ->pSics,pSicsdev); pPtr = alias; if(pPtr != NULL){ while((pPtr = stptok(pPtr,pAlias,131,",")) != NULL){ if(strcmp(pAlias,pDevice) == 0){ return current; } } if(alias != NULL){ free(alias); } } } current = current->child; while(current != NULL){ result = recurseInterestNode(current, pDevice); if(result != NULL){ return result; } current = current->next; } } return NULL; } /*--------------------------------------------------------------------------*/ static pHdb locateInterestNode(char *device){ char pDevice[132], pSicsdev[132]; pHdb current = NULL, result = NULL; memset(pDevice,0,132); memset(pSicsdev,0,132); /* * this is to strip off exes batch file name */ stptok(device,pDevice,131," "); strtolower(pDevice); current = GetHipadabaRoot(); return recurseInterestNode(current,pDevice); } /*--------------------------------------------------------------------------*/ static int StateHdbInterest(int iEvent, void *pEvent, void *pUser, commandContext cc){ SConnection *pCon = (SConnection *)pUser; char *device = (char *)pEvent, *path = NULL; char buffer[1024]; pHdb node = NULL; if(pCon == NULL || device == NULL){ printf("Bad StateHdbInterest in statemon\n"); return 0; } node = locateInterestNode(device); if(node != NULL){ path = GetHipadabaPath(node); if(iEvent == STSTART){ snprintf(buffer,1024,"%s STARTED", path); SCWriteInContext(pCon,buffer,eWarning,cc); } if(iEvent == STEND){ snprintf(buffer,1024,"%s FINISH", path); SCWriteInContext(pCon,buffer,eWarning,cc); } if(path != NULL){ free(path); } } return 1; } /*====================== interpreter interface ==============================*/ static void killStateMon(void *pData){ pStateMon self = NULL; self = (pStateMon)pData; if(self != NULL){ if(self->pDes != NULL){ DeleteDescriptor(self->pDes); } if(self->pCall != NULL){ DeleteCallBackInterface(self->pCall); } free(self); } } /*---------------------------------------------------------------------------*/ int StateMonFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pStateMon pNew = NULL; commandContext cc; pICallBack target = NULL; void *pPtr = NULL, *exe = NULL, *pDevexec = NULL; exe = FindCommandData(pSics,"exe", "ExeManager"); pDevexec = FindCommandData(pSics,"stopexe","DeviceExecutor"); if(exe == NULL || pDevexec == NULL){ SCWrite(pCon, "ERROR: both the device executor and the batch file module must be installed before initialising statemon", eError); return 0; } /* * generate data structures */ strcpy(cc.deviceID,"statemon"); cc.transID = -120; pNew = (pStateMon)malloc(sizeof(StateMon)); if(pNew == NULL){ SCWrite(pCon,"ERROR: out of memory creating StateMon",eError); return 0; } memset(pNew,0,sizeof(StateMon)); pNew->pDes = CreateDescriptor("statemon"); pNew->pCall = CreateCallBackInterface(); if(pNew->pDes == NULL || pNew->pCall == NULL){ SCWrite(pCon,"ERROR: out of memory creating StateMon",eError); return 0; } /* * register callbacks */ target = GetCallbackInterface(pDevexec); assert(target != NULL); RegisterCallback(target,cc,DRIVSTAT,DevexecCallback,pNew,NULL); target = GetCallbackInterface(exe); assert(target != NULL); RegisterCallback(target,cc,BATCHSTART,ExeCallback,pNew,NULL); RegisterCallback(target,cc,BATCHEND,ExeCallback,pNew,NULL); if(argc > 1) { pPtr = FindCommandData(pSics,argv[1],"ScanObject"); if(pPtr == NULL){ SCWrite(pCon,"ERROR: failked to locate scan object",eError); } else { target = GetCallbackInterface(pPtr); assert(target != NULL); RegisterCallback(target,cc,SCANSTART,StateMonScanInterest,pNew,NULL); RegisterCallback(target,cc,SCANEND,StateMonScanInterest,pNew,NULL); } } /* * TODO: add kill functions */ AddCommand(pSics,"statemon",StateMonAction,killStateMon,pNew); return 1; } /*---------------------------------------------------------------------------*/ int StateMonAction(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ long lID; int i; pStateMon self = NULL; self = (pStateMon)pData; assert(self != NULL); if(argc < 2){ SCWrite(pCon,"ERROR: not enough arguments to statemon",eError); return 0; } strtolower(argv[1]); if(strcmp(argv[1],"interest") == 0){ lID = RegisterCallback(self->pCall, SCGetContext(pCon),STSTART, StateInterest, pCon, NULL); SCRegister(pCon,pSics, self->pCall,lID); lID = RegisterCallback(self->pCall, SCGetContext(pCon),STEND, StateInterest, pCon, NULL); SCRegister(pCon,pSics, self->pCall,lID); SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"uninterest") == 0) { for(i = 0; i < 2; i++){ lID = SCgetCallbackID(pCon,self->pCall); if(lID >= 0){ RemoveCallback(self->pCall,lID); SCUnregisterID(pCon,lID); } } SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"hdbinterest") == 0){ lID = RegisterCallback(self->pCall, SCGetContext(pCon),STSTART, StateHdbInterest, pCon, NULL); SCRegister(pCon,pSics, self->pCall,lID); lID = RegisterCallback(self->pCall, SCGetContext(pCon),STEND, StateHdbInterest, pCon, NULL); SCRegister(pCon,pSics, self->pCall,lID); SCSendOK(pCon); return 1; } else if(strcmp(argv[1],"start") == 0) { if(argc > 2){ InvokeCallBack(self->pCall,STSTART,argv[2]); SCSendOK(pCon); return 1; } return 0; } else if(strcmp(argv[1],"stop") == 0) { if(argc > 2){ InvokeCallBack(self->pCall,STEND,argv[2]); SCSendOK(pCon); return 1; } return 0; } SCWrite(pCon,"ERROR: keyword not recognized",eError); return 0; }