/*-------------------------------------------------------------------------- * A module which reads the broadcast messages from the PSI Accelerator group * and allows to use the information in them in SICS. This facility runs * as a SICS task which tries to read incoming messages and stores the * messages of interest in an internal data structure. Some code is provided * to make the content of these messages available within SICS. This code * follows very closely the DoesItComeMC program from Demir Anici * * The module also holds a circular backlog of the last MAXLOG measurements. * This is used in order to calulcate an average. * * copyright: see file COPYRIGHT * * Mark Koennecke, July 2005 */ #include #include #include #include #include #include #include #include #include #include "dgrambroadcast.h" #include "sinq.h" #ifdef SEND_PORT #define RECEIVE_PORT SEND_PORT #else #define RECEIVE_PORT 0xABCC #endif #define MAX_BLEN 2048 /*====================== life and death =====================================*/ static int SinqTask(void *data){ pSinq self = (pSinq)data; char buff[MAX_BLEN]; int status, sinq; if(self == NULL){ return 0; } status = selectReceiveSocket(self->receiveSocket, 0); if(status <= 0){ /* * no pending message */ return 1; } memset(buff,0,MAX_BLEN); status = read(self->receiveSocket, buff, MAX_BLEN); if(status < 0) { ServerWriteGlobal("WARNING: failed to read Sinq Status",eWarning); return 1; } if(memcmp(buff,"D110",4) == 0){ strcpy(self->d110,buff); sinq = getSinqBeam(self,SINQBEAM); self->lastSinq[self->lastCount] = sinq; self->lastCount++; if(self->lastCount >= MAXLOG){ self->lastCount = 0; } } if(memcmp(buff,"A110",4) == 0){ strcpy(self->a110,buff); } /* * ignore any other message */ return 1; } /*------------------------------------------------------------------------*/ static void KillSinq(void *data){ pSinq self = (pSinq)data; if(self == NULL){ return; } if(self->pDes != NULL){ DeleteDescriptor(self->pDes); } free(self); } /*-------------------------------------------------------------------------*/ int SinqFactory(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSinq pNew = NULL; int i; pNew = (pSinq)malloc(sizeof(Sinq)); if(pNew == NULL){ SCWrite(pCon,"ERROR: out of memory allocating Sinq",eError); return 0; } memset(pNew,0,sizeof(Sinq)); pNew->pDes = CreateDescriptor("Sinq"); if(pNew->pDes == NULL){ SCWrite(pCon,"ERROR: out of memory allocating Sinq",eError); free(pNew); return 0; } pNew->receiveSocket = openReceiveSocket(RECEIVE_PORT); if(pNew->receiveSocket < 0){ SCWrite(pCon,"ERROR: failed to open Sinq Status Broadcast port", eError); KillSinq(pNew); return 0; } for(i = 0; i < MAXLOG; i++){ pNew->lastSinq[i] = -200; } TaskRegister(pServ->pTasker,SinqTask, NULL, NULL, pNew, 1); return AddCommand(pSics,"sinq",SinqWrapper, KillSinq, pNew); } /*===================== actual Action ====================================*/ extern char *trim(char *txt); /*-----------------------------------------------------------------------*/ int getSinqBeam(pSinq self, int code){ int result, i; char *pPtr; if(self == NULL) { return -900; } switch(code){ case SINQBEAM: pPtr = strstr(&self->d110[4],"MHC6"); break; case RINGBEAM: pPtr = strstr(&self->d110[4],"MHC3"); break; default: return -900; } if(pPtr == NULL){ printf("Invalid Sinq message: %s\n",&self->d110[4]); return -900; } pPtr = strstr(pPtr,":"); if(pPtr == NULL){ return -900; } pPtr++; /* * zero out units */ for(i = strlen(pPtr); i > 0; i--){ if(isdigit(pPtr[i])){ break; } else { pPtr[i] = '\0'; } } return atoi(trim(pPtr)); } /*-------------------------------------------------------------------------*/ int SinqWrapper(SConnection *pCon, SicsInterp *pSics, void *pData, int argc, char *argv[]){ pSinq self = (pSinq)pData; char pBueffel[132]; int sum, count, i, avg; assert(self != NULL); if(argc < 2) { SCWrite(pCon,&self->a110[4],eValue); return 1; } strtolower(argv[1]); if(strcmp(argv[1],"beam") == 0){ snprintf(pBueffel,131,"sinq.beam = %d", getSinqBeam(self,SINQBEAM)); } else if(strcmp(argv[1],"ring") == 0){ snprintf(pBueffel,131,"sinq.ring = %d", getSinqBeam(self,RINGBEAM)); } else if(strcmp(argv[1],"beamavg") == 0){ for(i = 0, count = 0, sum = 0; i < MAXLOG; i++){ if(self->lastSinq[i] > -50) { count++; sum += self->lastSinq[i]; } } if(count > 0){ avg = sum/count; } else { avg = 0; } snprintf(pBueffel,131,"sinq.beamavg = %d", avg); } else{ SCWrite(pCon,"ERROR: invalid key, I understand: beam, ring",eError); return 0; } SCWrite(pCon,pBueffel,eValue); return 1; }