From 99d2485d22bf3bcd508c43b28d4c22d6e3dd04e7 Mon Sep 17 00:00:00 2001 From: koennecke Date: Fri, 17 Apr 2009 12:52:01 +0000 Subject: [PATCH] - Connections write timeouts were incorrectly handled in asynnetc. Fixed. - Implemented the desired run/drive behaviour: drive waits for what it started run starts, and success waits for everything to finish. This required changes to a lot of files. - Fixed a bug in remob which supressed required messages --- anticollider.c | 3 +- asynnet.c | 68 +++++++++++++---- conman.c | 5 +- conman.h | 1 + counter.c | 13 +++- counter.h | 5 ++ countersec.c | 33 +++++++-- devexec.c | 58 ++++++++++++--- devexec.h | 189 ++++++++++++++++++++++++----------------------- devexec.tex | 14 +++- devexec.w | 14 +++- drive.c | 10 +-- drive.h | 4 +- evcontroller.c | 2 +- fitcenter.c | 2 +- fomerge.c | 4 + hdbtable.c | 3 + hdbtable.h | 2 +- hipadaba.c | 3 +- histmem.c | 13 +++- hmcontrol.c | 2 +- macro.c | 2 +- maximize.c | 11 +-- motor.c | 6 +- motorsec.c | 20 +++-- motreg.c | 2 +- multicounter.c | 7 +- optimise.c | 2 +- proxy.c | 2 +- remob.c | 2 +- scanvar.c | 3 +- scriptcontext.c | 77 +++++++++++++++++-- selector.c | 8 +- sicshdbadapter.c | 5 ++ sicshipadaba.c | 4 +- sicsobj.c | 1 + stdscan.c | 14 ++-- tasscanub.c | 2 +- velo.c | 6 +- 39 files changed, 422 insertions(+), 200 deletions(-) diff --git a/anticollider.c b/anticollider.c index 2080c3ce..f4f3dd46 100644 --- a/anticollider.c +++ b/anticollider.c @@ -59,7 +59,8 @@ static int ReplacementCheckStatus(void *pData, SConnection * pCon) if (myCollider->isDirty == 1) { myCollider->isDirty = 0; StartDevice(pServ->pExecutor, - "anticollider", myCollider->pDes, myCollider, pCon, 77.77); + "anticollider", myCollider->pDes, myCollider, + pCon,pCon->runLevel, 77.77); return HWIdle; } else { return HWIdle; diff --git a/asynnet.c b/asynnet.c index 33b248da..8367ac4e 100644 --- a/asynnet.c +++ b/asynnet.c @@ -42,7 +42,7 @@ #define DATASOCKET 1 #define MAXCONNECTIONS 1024 #define RBUFFERSIZE 262144 /* 256kb */ -#define WBUFFERSIZE 2*262144 /* 512kb */ +#define WBUFFERSIZE 4*262144 /* 512kb */ /*--------------------------------------------------------------------------*/ typedef struct { int socket; @@ -233,8 +233,8 @@ int ANETconnect(char *name, int iPort) } memset(&addresse, 0, sizeof(struct sockaddr_in)); addresse.sin_family = AF_INET; - addresse.sin_port = iPort; - addresse.sin_addr = addr; + addresse.sin_port = htons((unsigned short)(iPort &0xFFFF)); + addresse.sin_addr.s_addr = addr.s_addr; socke = socket(AF_INET, SOCK_STREAM, 0); status = connect(socke, (struct sockaddr *) &addresse, sizeof(struct sockaddr_in)); @@ -281,12 +281,11 @@ static int anetWrite(SocketDescriptor con) int status, length; void *pPtr; - con.lastOpenForWrite = time(NULL); pPtr = GetRWBufferData(con.writeBuffer, &length); if (length > 0) { status = send(con.socket, pPtr, length, 0); if (status < 0) { - if (errno == EAGAIN) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { return 1; } ANETclose(con.handle); @@ -296,7 +295,39 @@ static int anetWrite(SocketDescriptor con) } return 1; } +/*-------------------------------------------------------------------------- + * I have seen that select did not report the write possibility set, + * though the send buffer was empty. Thus I try to write if data is there + * and leave the lastOpenForWrite flag only when the socket would block + * on write. + *--------------------------------------------------------------------------*/ +static int anetTestWrite(SocketDescriptor con) +{ + int status, length; + void *pPtr; + time_t lastTime; + if(con.type != DATASOCKET){ + return 1; + } + + lastTime = con.lastOpenForWrite; + con.lastOpenForWrite = time(NULL); + pPtr = GetRWBufferData(con.writeBuffer, &length); + if (length > 0) { + status = send(con.socket, pPtr, length, 0); + if (status < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + con.lastOpenForWrite = lastTime; + return 1; + } + ANETclose(con.handle); + return 0; + } + RemoveRWBufferData(con.writeBuffer, status); + } + return 1; +} /*--------------------------------------------------------------------------*/ static int anetRead(SocketDescriptor con) { @@ -354,7 +385,7 @@ static int anetRead(SocketDescriptor con) /*---------------------------------------------------------------------------*/ void ANETprocess(void) { - int i, status, count = 0, socke = 0; + int i, status, count = 0, socke = 0, length; fd_set readMask, writeMask; struct timeval tmo = { 0, 10 }; @@ -378,7 +409,7 @@ void ANETprocess(void) return; } - /** + /** * I always jump out of this loop when a socket is created or closed * because then the order in the connections array is no longer valid. * Try again the next time round. @@ -386,21 +417,30 @@ void ANETprocess(void) for (i = 0; i < noConnections; i++) { socke = connections[i].socket; if (FD_ISSET(socke, &readMask)) { - if (!anetRead(connections[i])) { + if (anetRead(connections[i]) == 0) { return; } } if (FD_ISSET(socke, &writeMask)) { - if (!anetWrite(connections[i])) { + /* + * This has to be here, as I found out tracing a subtle bug: + * If the time is set in writeANET the modification will not + * propagate into the array as C copies the structure for the function call. + */ + connections[i].lastOpenForWrite = time(NULL); + if (anetWrite(connections[i]) == 0) { return; } } else { /* - * if I could not write to the socket for three minutes, - * the socket is considered broken and is closed + * If I could not write to the socket for 5 minutes, + * the socket is considered broken and is closed. */ - if (time(NULL) > connections[i].lastOpenForWrite + 180 && + if (time(NULL) > connections[i].lastOpenForWrite + 300 && connections[i].type == DATASOCKET) { + GetRWBufferData(connections[i].writeBuffer, &length); + anetLog(ANETCON, "Closing socket because of time overrun: %d, delay = %d, bytes to be written = %d, write bit = %d\n", connections[i].socket, + (int)(time(NULL) - connections[i].lastOpenForWrite), length, FD_ISSET(connections[i].socket, &writeMask) ); ANETclose(connections[i].handle); return; } @@ -467,8 +507,8 @@ int ANETwrite(int handle, void *buffer, int count) status = StoreRWBuffer(con->writeBuffer, buffer, count); } if (status != 1) { - anetLog(ANETERROR, "write buffer overrun on handle %d, socket %d", - con->handle, con->socket); + anetLog(ANETERROR, "Write buffer overrun on handle %d, socket %d, trying to write %d bytes", + con->handle, con->socket, count); return ANETWRITEBUFFERFULL; } } diff --git a/conman.c b/conman.c index f0372e6d..d5ba423a 100644 --- a/conman.c +++ b/conman.c @@ -198,7 +198,8 @@ static SConnection *CreateConnection(SicsInterp * pSics) pRes->listening = 0; pRes->conStart = time(NULL); pRes->write = SCNormalWrite; - + pRes->runLevel = RUNDRIVE; + /* initialise context variables */ pRes->iCmdCtr = 0; pRes->conEventType = -1; @@ -425,6 +426,7 @@ SConnection *SCCopyConnection(SConnection * pCon) result->conStart = pCon->conStart; result->contextStack = -1; result->iList = -1; + result->runLevel = pCon->runLevel; return result; } @@ -847,7 +849,6 @@ int SCWriteWithOutcode(SConnection * self, char *buffer, int iOut) free(bufPtr); return 1; } - /*-------------------------------------------------------------------------*/ static int SCBufferWrite(SConnection * self, char *buffer, int iOut) { diff --git a/conman.h b/conman.h index 40c0436e..b0f7b49b 100644 --- a/conman.h +++ b/conman.h @@ -54,6 +54,7 @@ typedef struct __SConnection { int transID; /* transaction ID */ char deviceID[256]; /* transaction device ID */ int iUserRights; /* user rights of the connection */ + int runLevel; /* run level, either RUNRUN for asynchronous or RUNDRIVE for synchronous */ /* master connection object fields */ int iList; /* callback registry, may go? */ diff --git a/counter.c b/counter.c index b58c2ca3..e37447f1 100644 --- a/counter.c +++ b/counter.c @@ -115,7 +115,7 @@ static int StartCount(void *pData, SConnection * pCon) } else { iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); sprintf(pBueffel, "WARNING: %s ", pError); - SCWrite(pCon, pBueffel, eError); + SCWrite(pCon, pBueffel, eLog); iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); if (iRet == COTERM) { SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", @@ -226,7 +226,7 @@ static int CheckCountStatus(void *pData, SConnection * pCon) self->badStatusCount++; iRet = self->pDriv->GetError(self->pDriv, &iErr, pError, 79); sprintf(pBueffel, "WARNING: %s ", pError); - SCWrite(pCon, pBueffel, eError); + SCWrite(pCon, pBueffel, eLog); iRet = self->pDriv->TryAndFixIt(self->pDriv, iErr); if (iRet == COTERM || self->badStatusCount > 3) { SCWrite(pCon, "ERROR: Cannot fix counter problem, aborting", eError); @@ -373,7 +373,7 @@ void DeleteCounter(void *pData) /*-------------------------------------------------------------------------*/ int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock) { - int iRet; + int iRet, level; char pBueffel[132]; Status eOld; @@ -392,8 +392,13 @@ int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock) /* set Preset */ SetCounterPreset(self, fPreset); + if(iBlock){ + level = RUNDRIVE; + } else { + level = RUNRUN; + } iRet = StartDevice(GetExecutor(), self->name, self->pDes, self, pCon, - fPreset); + level, fPreset); if (!iRet) { SetStatus(eOld); SCWrite(pCon, "Counting aborted", eError); diff --git a/counter.h b/counter.h index 46ceb3d5..6c2aee8c 100644 --- a/counter.h +++ b/counter.h @@ -8,6 +8,10 @@ Mark Koennecke, January 1996 copyright: see implementation file. + + Massively reworked to accomodate second generation counter objects. + + Mark Koennecke, January 2009 ----------------------------------------------------------------------------*/ #ifndef SICSCOUNTER #define SICSCOUNTER @@ -25,6 +29,7 @@ typedef struct __Counter{ unsigned long tStart; int iCallbackCounter; int badStatusCount; + int haltFixFlag; /* solely here to prevent multiple calls to the halt function on overrun timers in countersec.c*/ int (*setMode)(struct __Counter *self, CounterMode eMode); CounterMode (*getMode)(struct __Counter *self); int (*getNMonitor)(struct __Counter *self); diff --git a/countersec.c b/countersec.c index 6f5c7630..8967e91b 100644 --- a/countersec.c +++ b/countersec.c @@ -61,6 +61,7 @@ static int SecStartCount(void *pData, SConnection *pCon) } status = SecCtrInvokeFunction(self,pCon, START); + self->haltFixFlag = 0; if(status == 1){ self->isUpToDate = 0; self->badStatusCount = 0; @@ -68,6 +69,13 @@ static int SecStartCount(void *pData, SConnection *pCon) node = GetHipadabaNode(self->pDes->parNode, "status"); UpdateHipadabaPar(node,MakeHdbText("run"), pCon); SetHdbProperty(node,"geterror", NULL); + /* + * set time to 0. Otherwise, if there is a delay, + * the check for overrun counters in SecCtrCheckStatus + * may trigger! + */ + node = GetHipadabaNode(self->pDes->parNode, "time"); + UpdateHipadabaPar(node,MakeHdbFloat(.0), pCon); InvokeCallBack(self->pCall,COUNTSTART, pCon); return 1; } else { @@ -135,13 +143,15 @@ static int SecCtrCheckStatus(void *pData, SConnection *pCon) ReleaseCountLock(self->pCountInt); status = HWFault; } - + ReleaseHdbValue(&v); + /* * check for overrun timers */ if(self->getMode(self) == eTimer && - time(NULL) > self->tStart + self->getPreset(self)){ + time(NULL) > self->tStart + self->getPreset(self) && self->haltFixFlag == 0){ SecCtrHalt(self); + self->haltFixFlag = 1; } node = GetHipadabaNode(self->pDes->parNode,"control"); @@ -182,11 +192,14 @@ static int SecCtrTransferData(void *pData, SConnection *pCon) assert(self != NULL); pHdb node = NULL; hdbValue v; + int status; node = GetHipadabaNode(self->pDes->parNode,"values"); assert(node != NULL); self->isUpToDate = 1; - return GetHipadabaPar(node,&v,pCon); + status = GetHipadabaPar(node,&v,pCon); + ReleaseHdbValue(&v); + return status; } /*------------------------------------------------------------------------*/ static void *SecCtrCounterGetInterface(void *pData, int iID) @@ -225,16 +238,19 @@ static CounterMode SecCtrGetMode(pCounter self) { hdbValue v; pHdb node = NULL; + CounterMode mode; node = GetHipadabaNode(self->pDes->parNode,"mode"); assert(node != NULL); GetHipadabaPar(node,&v,NULL); assert(v.v.text != NULL); if(strcmp(v.v.text,"timer") == 0){ - return eTimer; + mode = eTimer; } else { - return ePreset; + mode = ePreset; } + ReleaseHdbValue(&v); + return mode; } /*--------------------------------------------------------------------------*/ static int SecCtrSetPreset(pCounter self, float val) @@ -287,6 +303,7 @@ static long SecCtrGetMonitor(pCounter self, int iNum, SConnection *pCon) { hdbValue v; pHdb node = NULL; + long val; if (!self->isUpToDate) { self->pCountInt->TransferData(self, pCon); @@ -295,10 +312,12 @@ static long SecCtrGetMonitor(pCounter self, int iNum, SConnection *pCon) assert(node != NULL); GetHipadabaPar(node,&v,pCon); if(iNum >= 0 && iNum < v.arrayLength){ - return (long)v.v.intArray[iNum]; + val = (long)v.v.intArray[iNum]; } else { - return -1L; + val = -1L; } + ReleaseHdbValue(&v); + return val; } /*--------------------------------------------------------------------------*/ static long SecCtrGetCounts(pCounter self, SConnection *pCon) diff --git a/devexec.c b/devexec.c index 6ce19f74..eef71286 100644 --- a/devexec.c +++ b/devexec.c @@ -15,6 +15,9 @@ Reworked to use copied connection objects instead of context pushes. Mark Koennecke, January 2009 + Modified to accomodate run levels + Mark Koennecke, April 2009 + Copyright: Labor fuer Neutronenstreuung @@ -121,6 +124,7 @@ typedef struct _DevEntry { float fVal; char *name; SConnection *pCon; + int level; } DevEntry, *pDevEntry; /*------------------------------------------------------------------------*/ typedef struct { @@ -131,7 +135,7 @@ typedef struct { } checkContext, *pCheckContext; /*-------------------------------------------------------------------------*/ static pDevEntry CreateDevEntry(pObjectDescriptor pDes, SConnection * pCon, - void *pData, float fVal, char *name) + void *pData, float fVal, char *name, int level) { pDevEntry pNew = NULL; @@ -146,6 +150,8 @@ static pDevEntry CreateDevEntry(pObjectDescriptor pDes, SConnection * pCon, pNew->name = strdup(name); pNew->fVal = fVal; pNew->pCon = SCCopyConnection(pCon); + pNew->pCon->runLevel = level; + pNew->level = level; return pNew; } @@ -275,7 +281,7 @@ void ExeInterest(pExeList self, pDevEntry pDev, char *text) /*------------------------------------------------------------------------*/ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, - void *pData, SConnection * pCon, float fNew) + void *pData, SConnection * pCon, int level, float fNew) { pDevEntry pNew = NULL; int iRet; @@ -319,7 +325,7 @@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, /* well create a new entry */ self->iStop = 0; - pNew = CreateDevEntry(pDes, pCon, pData, fNew, name); + pNew = CreateDevEntry(pDes, pCon, pData, fNew, name, level); if (!pNew) { SCWrite(pCon, "ERROR: memory exhausted in Device Executor ", eError); return 0; @@ -380,7 +386,7 @@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, /*--------------------------------------------------------------------------*/ int StartMotor(pExeList self, SicsInterp * pSics, SConnection * pCon, - char *name, float fVal) + char *name, int level, float fVal) { pDummy pMot = NULL; CommandList *pCom = NULL; @@ -415,12 +421,12 @@ int StartMotor(pExeList self, SicsInterp * pSics, SConnection * pCon, return 0; } return StartDevice(self, name, pMot->pDescriptor, (void *) pMot, pCon, - fVal); + level, fVal); } /*---------------------------------------------------------------------------*/ int StartCounter(pExeList self, SicsInterp * pSics, SConnection * pCon, - char *name) + int level, char *name) { pCounter pCter = NULL; CommandList *pCom = NULL; @@ -455,7 +461,7 @@ int StartCounter(pExeList self, SicsInterp * pSics, SConnection * pCon, return 0; } return StartDevice(self, name, pCter->pDes, (void *) pCter, - pCon, pCter->pDriv->fPreset); + pCon, level, pCter->pDriv->fPreset); } /*-------------------------------------------------------------------------*/ @@ -652,6 +658,27 @@ int CheckExeList(pExeList self) iRet = LLDnodePtr2First(self->iList); return testFinish(self); } +/*---------------------------------------------------------------------------*/ +int DevExecLevelRunning(pExeList self, int level) +{ + int iRet; + pDevEntry pDev = NULL; + + if(self->lTask < 0){ + return 0; + } + iRet = LLDnodePtr2First(self->iList); + while (iRet != 0) { + LLDnodeDataTo(self->iList, &pDev); + if (pDev) { + if(pDev->level >= level){ + return 1; + } + } + iRet = LLDnodePtr2Next(self->iList); + } + return 0; +} /*---------------------------------------------------------------------------*/ int Wait4Success(pExeList self) @@ -667,7 +694,10 @@ int Wait4Success(pExeList self) } /* wait for Devexec task to finish */ - TaskWait(self->pTask, self->lTask); + /*TaskWait(self->pTask, self->lTask); */ + while(DevExecLevelRunning(self,RUNDRIVE)){ + TaskYield(self->pTask); + } #ifdef DEBUG printf("Wait4Success finished\n"); #endif @@ -759,7 +789,7 @@ int StopExe(pExeList self, char *name) } iRet = LLDnodePtr2Next(self->iList); } - SCWrite(self->pOwner, "ERROR: Full Stop called!!", eError); + SCWrite(self->pOwner, "ERROR: Full Stop called!!", eLogError); if (SCGetInterrupt(self->pOwner) > eContinue) { self->iStatus = DEVINT; } @@ -826,7 +856,9 @@ int StopByData(pExeList self, void *data) int StopExeWait(pExeList self) { StopExe(self, "all"); - Wait4Success(self); + while(DevExecLevelRunning(self,RUNRUN)){ + TaskYield(self->pTask); + } return 1; } /*--------------------------------------------------------------------------*/ @@ -1044,10 +1076,14 @@ int Success(SConnection * pCon, SicsInterp * pSics, void *pData, { int iRet; Status eOld; + pExeList self = (pExeList)pData; eOld = GetStatus(); SetStatus(eRunning); - iRet = Wait4Success((pExeList) pData); + while(DevExecLevelRunning(self, RUNRUN)){ + TaskYield(self->pTask); + } + iRet = self->iStatus; if (iRet == DEVINT) { if (SCGetInterrupt(pCon) == eAbortOperation) { SCSetInterrupt(pCon, eContinue); diff --git a/devexec.h b/devexec.h index 8ea32768..a0a3d1ba 100644 --- a/devexec.h +++ b/devexec.h @@ -1,5 +1,5 @@ -#line 197 "devexec.w" +#line 202 "devexec.w" /*---------------------------------------------------------------------------- @@ -28,7 +28,7 @@ #include "obdes.h" #include "task.h" -typedef struct __EXELIST *pExeList; + typedef struct __EXELIST *pExeList; /* Returncodes */ @@ -37,140 +37,145 @@ typedef struct __EXELIST *pExeList; #define DEVERROR 2 #define DEVBUSY 3 +/* run level codes */ +#define RUNRUN 0 +#define RUNDRIVE 1 /*------------------------------------------------------------------------ B I R T H & D E A T H */ -pExeList CreateExeList(pTaskMan pTask); -void DeleteExeList(void *self); - + pExeList CreateExeList(pTaskMan pTask); + void DeleteExeList(void *self); + /* ================= Functions to talk to the above ====================== */ #line 43 "devexec.w" -int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, - void *pData, SConnection * pCon, float fNew); -int StartMotor(pExeList self, SicsInterp * pSics, SConnection * pCon, - char *name, float fNew); -int StartCounter(pExeList self, SicsInterp * pSics, SConnection * pCon, - char *name); + int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, + void *pData, SConnection *pCon, int level, float fNew); + int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon, + char *name, int level, float fNew); + int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon, + int level, char *name); -#line 241 "devexec.w" +#line 249 "devexec.w" /*------------------------------------------------------------------------*/ -#line 88 "devexec.w" +#line 89 "devexec.w" -int CheckExeList(pExeList self); + int CheckExeList(pExeList self); /* - checks the entries for success and deletes entries which have finished - operation. If there are none left, the pOwner will be set to NULL. - */ -int Wait4Success(pExeList self); + checks the entries for success and deletes entries which have finished + operation. If there are none left, the pOwner will be set to NULL. + */ + int Wait4Success(pExeList self); -long GetDevexecID(pExeList self); + long GetDevexecID(pExeList self); -int DevExecTask(void *pEL); -void DevExecSignal(void *pEL, int iSignal, void *pSigData); + int DevExecLevelRunning(pExeList self, int level); + + int DevExecTask(void *pEL); + void DevExecSignal(void *pEL, int iSignal, void *pSigData); -#line 243 "devexec.w" +#line 251 "devexec.w" /* - Waits for execution to finish. returns 1 on Success, 0 if problems - ocurred. Than the Interrupt code shall be checked and acted upon - accordingly. - */ + Waits for execution to finish. returns 1 on Success, 0 if problems + ocurred. Than the Interrupt code shall be checked and acted upon + accordingly. + */ /*-------------------------------------------------------------------------*/ -SConnection *GetExeOwner(pExeList self); + SConnection *GetExeOwner(pExeList self); /*-------------------------------------------------------------------------*/ -int isInRunMode(pExeList self); + int isInRunMode(pExeList self); /*--------------------------------------------------------------------------*/ -int ListPending(pExeList self, SConnection * pCon); + int ListPending(pExeList self, SConnection *pCon); /* - lists the Operations still pending on pCon. - */ + lists the Operations still pending on pCon. + */ /*-------------------------------------------------------------------------*/ -#line 137 "devexec.w" +#line 142 "devexec.w" -int StopExe(pExeList self, char *name); -int StopExeWait(pExeList self); + int StopExe(pExeList self, char *name); + int StopExeWait(pExeList self); /* - will stop the entry name and its subentries from executing. - If ALL is specified as name, everything will be stopped and - the Executor cleared. - StopExeWait will stop all running things and wait for the stop - to complete. - */ - -int StopByData(pExeList self, void *data); + will stop the entry name and its subentries from executing. + If ALL is specified as name, everything will be stopped and + the Executor cleared. + StopExeWait will stop all running things and wait for the stop + to complete. + */ + int StopByData(pExeList self, void *data); /* stop the entry with the given data from execution */ /*------------------------------------------------------------------------*/ -void ClearExecutor(pExeList self); + void ClearExecutor(pExeList self); /* - clears the executor without sending commands to the devices. - */ + clears the executor without sending commands to the devices. + */ /*-----------------------------------------------------------------------*/ -int IsCounting(pExeList self); -int PauseExecution(pExeList self); -int ContinueExecution(pExeList self); + int IsCounting(pExeList self); + int PauseExecution(pExeList self); + int ContinueExecution(pExeList self); -#line 261 "devexec.w" +#line 269 "devexec.w" /*-------------------------- Commands ------------------------------------*/ -int DevexecAction(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); -int StopCommand(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); + int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); + int StopCommand(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); /* - implements the stop command - */ - -int ListExe(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); + implements the stop command + */ + + int ListExe(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); /* - lists all currently executing objects - */ -int SicsIdle(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); + lists all currently executing objects + */ + int SicsIdle(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); /* - prints the seconds since the device executor was running the last time - */ + prints the seconds since the device executor was running the last time + */ -int Success(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); + int Success(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); /* - waits until completion of all pending operations. Used in - connection with non blocking operation such as motors started - with run. - */ -int PauseAction(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); + waits until completion of all pending operations. Used in + connection with non blocking operation such as motors started + with run. + */ + int PauseAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); /* - pauses execution - */ -int ContinueAction(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]); + pauses execution + */ + int ContinueAction(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]); /* - continues execution - */ - + continues execution + */ + /*--------------------------- Locking ---------------------------------*/ - -#line 185 "devexec.w" - -void LockDeviceExecutor(pExeList self); -void UnlockDeviceExecutor(pExeList self); - - -#line 301 "devexec.w" - + +#line 190 "devexec.w" + + void LockDeviceExecutor(pExeList self); + void UnlockDeviceExecutor(pExeList self); + + +#line 309 "devexec.w" + /* -------------------------- Executor management -------------------------*/ -pExeList GetExecutor(void); -void SetExecutor(pExeList pExe); + + pExeList GetExecutor(void); + void SetExecutor(pExeList pExe); /*----------------------- Logging -----------------------------------------*/ -void DevexecLog(char *op, char *device); -#endif + void DevexecLog(char *op, char *device); +#endif diff --git a/devexec.tex b/devexec.tex index f129290f..e98167fb 100644 --- a/devexec.tex +++ b/devexec.tex @@ -47,11 +47,11 @@ $\langle$devreg {\footnotesize ?}$\rangle\equiv$ \begin{list}{}{} \item \mbox{}\verb@@\\ \mbox{}\verb@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,@\\ -\mbox{}\verb@ void *pData, SConnection *pCon, float fNew);@\\ +\mbox{}\verb@ void *pData, SConnection *pCon, int level, float fNew);@\\ \mbox{}\verb@ int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon,@\\ -\mbox{}\verb@ char *name, float fNew);@\\ +\mbox{}\verb@ char *name, int level, float fNew);@\\ \mbox{}\verb@ int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon,@\\ -\mbox{}\verb@ char *name); @\\ +\mbox{}\verb@ int level, char *name); @\\ \mbox{}\verb@@$\Diamond$ \end{list} \vspace{-1ex} @@ -67,6 +67,7 @@ The main interface function is {\bf StartDevice}. The parameters are: \item {\bf name}. The name of the object which operates. \item {\bf pDes}. A pointer to the ObjectDescriptor of the object to drive or count. \item {\bf pData}. A pointer to the data structure coming with the object. +\item {\bf level} The start level of the device. \item {\bf pCon}. A pointer to the client connection on whose request the operation was initiated. \item {\bf fNew}. A floating point value which sets the target value for @@ -112,6 +113,8 @@ $\langle$devcheck {\footnotesize ?}$\rangle\equiv$ \mbox{}\verb@@\\ \mbox{}\verb@ long GetDevexecID(pExeList self);@\\ \mbox{}\verb@@\\ +\mbox{}\verb@ int DevExecLevelRunning(pExeList self, int level);@\\ +\mbox{}\verb@@\\ \mbox{}\verb@ int DevExecTask(void *pEL);@\\ \mbox{}\verb@ void DevExecSignal(void *pEL, int iSignal, void *pSigData);@\\ \mbox{}\verb@@\\ @@ -155,6 +158,8 @@ properly finished operation, DEVERROR for an operation which finished with an error code and DEVINT for an aoperation which was interrupted by the user. + {\bf DevExeclevelRunning} tests if the level given as a parameter is still running. + \subsubsection{Influencing Execution} In certain cases it is necessary to interact with running devices directly. This is done via the following interface. @@ -285,6 +290,9 @@ to the global SICS device executor. \mbox{}\verb@#define DEVERROR 2@\\ \mbox{}\verb@#define DEVBUSY 3@\\ \mbox{}\verb@@\\ +\mbox{}\verb@/* run level codes */@\\ +\mbox{}\verb@#define RUNRUN 0@\\ +\mbox{}\verb@#define RUNDRIVE 1@\\ \mbox{}\verb@/*------------------------------------------------------------------------@\\ \mbox{}\verb@ B I R T H & D E A T H@\\ \mbox{}\verb@*/@\\ diff --git a/devexec.w b/devexec.w index ac53a445..8d6f791d 100644 --- a/devexec.w +++ b/devexec.w @@ -42,11 +42,11 @@ functions are provided. @d devreg @{ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, - void *pData, SConnection *pCon, float fNew); + void *pData, SConnection *pCon, int level, float fNew); int StartMotor(pExeList self, SicsInterp *pSics, SConnection *pCon, - char *name, float fNew); + char *name, int level, float fNew); int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon, - char *name); + int level, char *name); @} The main interface function is {\bf StartDevice}. The parameters are: @@ -55,6 +55,7 @@ The main interface function is {\bf StartDevice}. The parameters are: \item {\bf name}. The name of the object which operates. \item {\bf pDes}. A pointer to the ObjectDescriptor of the object to drive or count. \item {\bf pData}. A pointer to the data structure coming with the object. +\item {\bf level} The start level of the device. \item {\bf pCon}. A pointer to the client connection on whose request the operation was initiated. \item {\bf fNew}. A floating point value which sets the target value for @@ -95,6 +96,8 @@ From within the SICS main loops this special function is called: long GetDevexecID(pExeList self); + int DevExecLevelRunning(pExeList self, int level); + int DevExecTask(void *pEL); void DevExecSignal(void *pEL, int iSignal, void *pSigData); @@ -130,6 +133,8 @@ properly finished operation, DEVERROR for an operation which finished with an error code and DEVINT for an aoperation which was interrupted by the user. + {\bf DevExeclevelRunning} tests if the level given as a parameter is still running. + \subsubsection{Influencing Execution} In certain cases it is necessary to interact with running devices directly. This is done via the following interface. @@ -231,6 +236,9 @@ to the global SICS device executor. #define DEVERROR 2 #define DEVBUSY 3 +/* run level codes */ +#define RUNRUN 0 +#define RUNDRIVE 1 /*------------------------------------------------------------------------ B I R T H & D E A T H */ diff --git a/drive.c b/drive.c index 6c0d2c6c..1a76b9ac 100644 --- a/drive.c +++ b/drive.c @@ -107,7 +107,7 @@ int Drive(SConnection * pCon, SicsInterp * pInter, char *name, float fNew) SCSetInterrupt(pCon, eAbortOperation); return 0; } - iRet = StartDevice(GetExecutor(), name, pDes, pDum, pCon, fNew); + iRet = StartDevice(GetExecutor(), name, pDes, pDum, pCon, RUNDRIVE, fNew); if (!iRet) { sprintf(pBueffel, "ERROR: cannot start device %s", name); SCWrite(pCon, pBueffel, eError); @@ -143,7 +143,7 @@ int Drive(SConnection * pCon, SicsInterp * pInter, char *name, float fNew) /*---------------------------------------------------------------------------*/ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name, - float fNew) + int level, float fNew) { CommandList *pObject = NULL; pObjectDescriptor pDes = NULL; @@ -199,7 +199,7 @@ int Start2Run(SConnection * pCon, SicsInterp * pInter, char *name, SCSetInterrupt(pCon, eAbortOperation); return 0; } - iRet = StartDevice(GetExecutor(), name, pDes, pDum, pCon, fNew); + iRet = StartDevice(GetExecutor(), name, pDes, pDum, pCon,level, fNew); if (!iRet) { return 0; } else { @@ -315,7 +315,7 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, SetStatus(eOld); return 0; } - iRet = Start2Run(pCon, pSics, argv[i], dTarget); + iRet = Start2Run(pCon, pSics, argv[i], RUNDRIVE, dTarget); if (!iRet) { sprintf(pBueffel, "ERROR: cannot run %s to %s", argv[i], argv[i + 1]); @@ -407,7 +407,7 @@ int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, SetStatus(eOld); return 0; } - iRet = Start2Run(pCon, pSics, argv[i], dTarget); + iRet = Start2Run(pCon, pSics, argv[i], RUNRUN, dTarget); if (!iRet) { sprintf(pBueffel, "ERROR: cannot run %s to %s", argv[i], argv[i + 1]); diff --git a/drive.h b/drive.h index 46f70287..06c7d10f 100644 --- a/drive.h +++ b/drive.h @@ -12,8 +12,8 @@ int Drive(SConnection * pCon, SicsInterp * pSics, char *name, float fNew); -int Start2Run(SConnection * pCon, SicsInterp * pSics, char *name, float - fNew); +int Start2Run(SConnection * pCon, SicsInterp * pSics, char *name, + int level, float fNew); int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); diff --git a/evcontroller.c b/evcontroller.c index e0a7384f..20244410 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -840,7 +840,7 @@ int EVCDrive(pEVControl self, SConnection * pCon, float fVal) /* start executing */ iRet = StartDevice(GetExecutor(), self->pName, self->pDes, - self, pCon, fVal); + self, pCon, pCon->runLevel, fVal); if (!iRet) { sprintf(pBueffel, "ERROR: Failure to start %s", self->pName); SCWrite(pCon, pBueffel, eError); diff --git a/fitcenter.c b/fitcenter.c index 607685f8..b325f97f 100644 --- a/fitcenter.c +++ b/fitcenter.c @@ -293,7 +293,7 @@ int DriveCenter(pFit self, SConnection * pCon, SicsInterp * pSics) iRet = StartMotor(pServ->pExecutor, pSics, pCon, self->pName, - self->fCenter); + RUNDRIVE, self->fCenter); if (!iRet) { return 0; } diff --git a/fomerge.c b/fomerge.c index 6b1eaa3c..39b88481 100644 --- a/fomerge.c +++ b/fomerge.c @@ -477,6 +477,10 @@ static int *calculateTimeSum(HistInt * data, int iDet, int iTime) int i, j; int *sum = NULL; + if(data == NULL){ + return NULL; + } + sum = (int *) malloc(iTime * sizeof(int)); if (!sum) { return NULL; diff --git a/hdbtable.c b/hdbtable.c index dc90eccb..bd33bfc5 100644 --- a/hdbtable.c +++ b/hdbtable.c @@ -55,6 +55,9 @@ static int ClearTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, node = GetHipadabaNode(self->objectNode,"data"); if(node != NULL){ + if(CountHdbChildren(node) < 1){ + return 1; + } DeleteNodeData(node); RemoveHdbNodeFromParent(node, pCon); } diff --git a/hdbtable.h b/hdbtable.h index 3bf00b80..c1848a0d 100644 --- a/hdbtable.h +++ b/hdbtable.h @@ -12,5 +12,5 @@ pSICSOBJ MakeHdbTable(char *name, char *hdbclass); int ReadTableTemplate(pSICSOBJ self, SConnection *con); - + #endif /*HDBTABLE_H_*/ diff --git a/hipadaba.c b/hipadaba.c index 0f4404f4..20a95ab6 100644 --- a/hipadaba.c +++ b/hipadaba.c @@ -972,9 +972,8 @@ int GetHipadabaPar(pHdb node, hdbValue *v, void *callData) { int status; + memset(v,0,sizeof(hdbValue)); v->dataType = node->value.dataType; - v->doNotFree = 0; - v->v.text = NULL; /* this sets all pointers in the union to NULL */ status = SendDataMessage(node, get, v, callData); copyHdbValue(&node->value, v); diff --git a/histmem.c b/histmem.c index d7e7b8f4..b2a6a628 100644 --- a/histmem.c +++ b/histmem.c @@ -203,6 +203,7 @@ static int HistStartCount(void *pData, SConnection * pCon) } SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); return HWFault; } @@ -237,12 +238,14 @@ static int HistPause(void *pData, SConnection * pCon) SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); return HWFault; } } } SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); return HWFault; } @@ -277,11 +280,13 @@ static int HistContinue(void *pData, SConnection * pCon) SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); SCSetInterrupt(pCon, eAbortBatch); + ReleaseCountLock(self->pCountInt); return HWFault; } } } SCWrite(pCon, "ERROR: failed to fix histogram memory problem", eError); + ReleaseCountLock(self->pCountInt); SCSetInterrupt(pCon, eAbortBatch); return HWFault; } @@ -299,6 +304,7 @@ static int HistCountStatus(void *pData, SConnection * pCon) if (!self->iInit) { SCWrite(pCon, "ERROR: histogram memory not initialised", eError); InvokeCallBack(self->pCall, COUNTEND, NULL); + ReleaseCountLock(self->pCountInt); return COTERM; } @@ -726,7 +732,7 @@ int HistDoCount(pHistMem self, SConnection * pCon) /* start */ return StartDevice(GetExecutor(), "HistogramMemory", self->pDes, self, - pCon, self->pDriv->fCountPreset); + pCon, RUNRUN, self->pDriv->fCountPreset); } /*-----------------------------------------------------------------------*/ @@ -738,7 +744,7 @@ int HistBlockCount(pHistMem self, SConnection * pCon) /* start counting */ iRet = StartDevice(GetExecutor(), "HistogramMemory", self->pDes, self, - pCon, self->pDriv->fCountPreset); + pCon, RUNDRIVE, self->pDriv->fCountPreset); if (!iRet) { /* error has already been reported */ return 0; @@ -1569,7 +1575,8 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData, /* getdelay */ else if(strcmp(argv[1],"getdelay") == 0){ if(self->pDriv->data->nTimeChan > 1) { - SCPrintf(pCon,eValue,"hm.delay = %d", self->pDriv->data->timeBinning[0]); + iVal = (int)self->pDriv->data->timeBinning[0]; + SCPrintf(pCon,eValue,"hm.delay = %d", iVal); return 1; } else { SCPrintf(pCon,eError,"ERROR: no TOF configured"); diff --git a/hmcontrol.c b/hmcontrol.c index f3d01c8a..dc1c5763 100644 --- a/hmcontrol.c +++ b/hmcontrol.c @@ -337,7 +337,7 @@ int HMControlAction(SConnection * pCon, SicsInterp * pSics, */ self->pCount->SetCountParameters(self, (float) dPreset, eMode); status = StartDevice(pServ->pExecutor, "hmcontrol", self->pDes, - self, pCon, 99); + self, pCon, RUNRUN, 99); if (!status) { SCWrite(pCon, "ERROR: failed to start counting", eError); return 0; diff --git a/macro.c b/macro.c index 310abc53..df512bb1 100644 --- a/macro.c +++ b/macro.c @@ -931,7 +931,7 @@ static int TclAction(SConnection * pCon, SicsInterp * pSics, void *pData, sprintf(pBueffel, "ERROR: you are not authorised to invoke %s", argv[0]); SCWrite(pCon, pBueffel, eError); - return 1; + return 0; } /* make a string */ diff --git a/maximize.c b/maximize.c index 67c304da..9c857bb8 100644 --- a/maximize.c +++ b/maximize.c @@ -80,12 +80,12 @@ static int maxDrive(void *pObject, char *pVarName, pDummy pDum; int status; char pBueffel[132]; - long lTask; /* start */ pDum = (pDummy) pObject; status = StartDevice(pServ->pExecutor, - pVarName, pDum->pDescriptor, pObject, pCon, fPos); + pVarName, pDum->pDescriptor, pObject, pCon, + RUNDRIVE, fPos); if (!status) { sprintf(pBueffel, "ERROR: failed to start %s", pVarName); SCWrite(pCon, pBueffel, eError); @@ -93,11 +93,8 @@ static int maxDrive(void *pObject, char *pVarName, } /* wait */ - lTask = GetDevexecID(pServ->pExecutor); - if (lTask > 0) { - TaskWait(pServ->pTasker, lTask); - } else { - return 0; + while(DevExecLevelRunning(pServ->pExecutor,RUNDRIVE)){ + TaskYield(pServ->pTasker); } /* check interrupts */ diff --git a/motor.c b/motor.c index 60cec23c..78899356 100644 --- a/motor.c +++ b/motor.c @@ -311,7 +311,7 @@ static int statusRunTo(pMotor self, SConnection * pCon) if (self->retryCount >= ObVal(self->ParArray, POSCOUNT)) { snprintf(pBueffel, 255, "ERROR: aborting motor %s after %d retries", self->name, self->retryCount); - SCWrite(pCon, pBueffel, eError); + SCWrite(pCon, pBueffel, eLogError); return HWFault; } if (SCGetInterrupt(pCon) != eContinue) { @@ -320,7 +320,7 @@ static int statusRunTo(pMotor self, SConnection * pCon) self->retryCount++; snprintf(pBueffel, 255, "WARNING: restarting %s, %d time", self->name, self->retryCount); - SCWrite(pCon, pBueffel, eWarning); + SCWrite(pCon, pBueffel, eLog); self->pDriver->RunTo(self->pDriver, self->fTarget); return HWBusy; } @@ -345,7 +345,7 @@ static int checkPosition(pMotor self, SConnection * pCon) } snprintf(pBueffel, 131, "WARNING: %s off position by %f", self->name, absf(fHard - self->fTarget)); - SCWrite(pCon, pBueffel, eWarning); + SCWrite(pCon, pBueffel, eLog); status = statusRunTo(self, pCon); return status; } diff --git a/motorsec.c b/motorsec.c index 448d6468..cce60b40 100644 --- a/motorsec.c +++ b/motorsec.c @@ -96,7 +96,14 @@ static long SecMotorRun(void *sulf, SConnection * pCon, float fNew) { pMotor self = (pMotor) sulf; hdbValue v; - + int accesscode; + + assert(SICSHdbGetPar(self, NULL, "accesscode", &v) == 1); + accesscode = (int)v.v.doubleValue; + if(!SCMatchRights(pCon, accesscode)){ + return 0; + } + v = MakeHdbFloat(fNew); return SetHipadabaPar(self->pDescriptor->parNode, v, pCon); } @@ -206,13 +213,13 @@ static int checkPosition(pMotor self, SConnection * pCon) SecMotorGetPar(self, "maxretry", &maxretry); if (ABS(target - hard) > precision) { if (self->retryCount >= (int) maxretry) { - SCPrintf(pCon, eError, + SCPrintf(pCon, eLogError, "ERROR: Aborting %s after %d retries, off position by %f", self->name, (int) maxretry, target - hard); return HWFault; } self->retryCount++; - SCPrintf(pCon, eWarning, "WARNING: %s off position by %f, restarting", + SCPrintf(pCon, eLog, "WARNING: %s off position by %f, restarting", self->name, target - hard); node = GetHipadabaNode(self->pDescriptor->parNode, "status"); assert(node != NULL); @@ -279,6 +286,8 @@ static int SecMotorStatus(void *sulf, SConnection * pCon) v.v.text); status = HWFault; } + ReleaseHdbValue(&v); + /* * when terminating: force an update of the position. */ @@ -608,8 +617,9 @@ pMotor SecMotorInit(char *name) free(pM); return NULL; } - /* TODO: give it a sicsdev here */ node = pM->pDescriptor->parNode; + SetHdbProperty(node,"type","drivable"); + SetHdbProperty(node,"sicsdev", name); pM->objectNode = node; AppendHipadabaCallback(pM->pDescriptor->parNode, MakeHipadabaCallback(SecMotorCallback, pM, NULL)); @@ -674,7 +684,7 @@ pMotor SecMotorInit(char *name) SetHdbProperty(child, "__save", "true"); AddHipadabaChild(node, child, NULL); - child = MakeSICSHdbPar("precision", usMugger, MakeHdbFloat(.1)); + child = MakeSICSHdbPar("precision", usMugger, MakeHdbFloat(.01)); SetHdbProperty(child, "__save", "true"); AddHipadabaChild(node, child, NULL); diff --git a/motreg.c b/motreg.c index 0e5a4c57..bdf22d19 100644 --- a/motreg.c +++ b/motreg.c @@ -118,7 +118,7 @@ int StartRegMot(pMotReg self, SConnection * pCon, float fValue) pDriv->SetValue = self->originalSetValue; ret = StartDevice(pServ->pExecutor, self->motorName, FindDescriptor(self->motorData), - self->motorData, pCon, fValue); + self->motorData, pCon, pCon->runLevel, fValue); /* sprintf(pBueffel,"anticollision started %s to %f",self->motorName, fValue); diff --git a/multicounter.c b/multicounter.c index f68463de..35ffd86e 100644 --- a/multicounter.c +++ b/multicounter.c @@ -92,13 +92,14 @@ static int MMCCStart(void *pData, SConnection * pCon) } for (i = 0; i < self->nSlaves; i++) { - self->slaves[i]->SetCountParameters(self->slaveData[i], + ReleaseCountLock(self->slaves[i]); + self->slaves[i]->SetCountParameters(self->slaveData[i], pCount->pDriv->fPreset, pCount->pDriv->eMode); - ReleaseCountLock(self->slaves[i]); status = self->slaves[i]->StartCount(self->slaveData[i], pCon); if (status != OKOK) { MMCCHalt(pData); + ReleaseCountLock(pCount->pCountInt); return status; } } @@ -124,6 +125,7 @@ static int MMCCStatus(void *pData, SConnection * pCon) if (self->nSlaves == 0) { pCount->pDriv->iErrorCode = NOCOUNTERS; + ReleaseCountLock(pCount->pCountInt); return HWFault; } @@ -142,6 +144,7 @@ static int MMCCStatus(void *pData, SConnection * pCon) if (strcmp(pDum->pDescriptor->name, "HistMem") == 0) { HistDirty((pHistMem) self->slaveData[i]); } + ReleaseCountLock(self->slaves[i]); } } return status; diff --git a/optimise.c b/optimise.c index 6666543a..d17f55ba 100644 --- a/optimise.c +++ b/optimise.c @@ -445,7 +445,7 @@ static int ClimbDrive(SConnection * pCon, char *name, float value) { int status; - status = Start2Run(pCon, pServ->pSics, name, value); + status = Start2Run(pCon, pServ->pSics, name, RUNDRIVE, value); if (status != 1) { return DRIVEERROR; } diff --git a/proxy.c b/proxy.c index b7065485..4e495ae2 100644 --- a/proxy.c +++ b/proxy.c @@ -294,7 +294,7 @@ static hdbCallbackReturn ProxyCallback(pHdb node, void *userData, GetHdbProperty(node, "proxy", proxyDev, 80); status = StartDevice(pServ->pExecutor, proxyDev, self->pDes, self, pCon, - (float) set->v->v.doubleValue); + pCon->runLevel, (float) set->v->v.doubleValue); if (status == 1) { return hdbContinue; } else { diff --git a/remob.c b/remob.c index 1e05602e..8e5d3b35 100644 --- a/remob.c +++ b/remob.c @@ -169,7 +169,7 @@ static int RemHandle(RemServer * remserver) static void RemCopy(RemChannel * rc, SConnection * pCon) { if (pCon != NULL && rc->line[0] != '\0') { - SCPrintf(pCon, eWarning, " %s", rc->line); + SCPrintf(pCon, eValue, " %s", rc->line); } } diff --git a/scanvar.c b/scanvar.c index 5bc0720c..a9b48416 100644 --- a/scanvar.c +++ b/scanvar.c @@ -184,7 +184,8 @@ int StartScanVar(pVarEntry pVar, SConnection * pCon, int i) fVal = pVar->fStart + i * pVar->fStep; status = StartDevice(pServ->pExecutor, pVar->Name, - pDum->pDescriptor, pVar->pObject, pCon, fVal); + pDum->pDescriptor, pVar->pObject, pCon, + RUNDRIVE, fVal); if (!status) { snprintf(pBueffel, 511, "ERROR: Failed to start %s", pVar->Name); SCWrite(pCon, pBueffel, eError); diff --git a/scriptcontext.c b/scriptcontext.c index 58c963ae..bee87d6e 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -304,7 +304,9 @@ static int SctMatch(void *data1, void *data2) return a->node == b->node && strcasecmp(a->name, b->name) == 0; } - +/* + * This routine is running the script chain + */ static char *SctActionHandler(void *actionData, char *lastReply, int commError) { @@ -335,18 +337,41 @@ static char *SctActionHandler(void *actionData, char *lastReply, } else { con = controller->conn; } + /* + * If this is a followup call, the I/O system will have set the + * property result to the data from the device. Read this now and + * print it if diagnostics is required. + */ SetProp(node, controller->node, "result", lastReply); script = NULL; if (!commError && controller->verbose && lastReply != NULL && *lastReply != '\0') { SCPrintf(con, eLog, "reply : %s", lastReply); } + + /* + * When this is a followup, we use the content of the + * state field as the property storing the next script to + * run. If this is the start of a chain this is set to the + * data->name which is either read or write + */ state = GetProp(node, controller->node, "state"); if (state == NULL || strcasecmp(state, "idle") == 0) { state = data->name; SetProp(node, controller->node, "state", state); } + + /* + * Sometimes one wishes to call multiple scripts in succession + * before returning into I/O. Such scripts then do not set the + * send property. The loop is taking care of this. Not more + * then 10 scripts can be changed in this way. + */ for (i = 0; i < 10; i++) { + /* + * read the script to invoke from the property living + * in state + */ script = GetProp(node, controller->node, state); if (script == NULL) script = state; @@ -357,12 +382,18 @@ static char *SctActionHandler(void *actionData, char *lastReply, script = errorScript; commError = 0; } + /* + * Set the context and invoke the script + */ script = strdup(script); sct->sendNode = node; sct->sendCalled = 0; ret = SctCallInContext(con, script, node, controller, &result); sct->sendNode = NULL; if (ret == 0) { + /* + * an error occurred in the script: complain bitterly + */ snprintf(eprop, sizeof eprop, "error_during_%s", data->name); emsg = GetHdbProp(node, eprop); if (emsg == NULL || con != controller->conn) { @@ -392,13 +423,24 @@ static char *SctActionHandler(void *actionData, char *lastReply, free(script); goto finish; } + /* + * The script executed OK. + * The next state is the result + */ state = result; + /* + * if the new state is idle, clean everything up + * and terminate the script chain + */ if (strcasecmp(state, "idle") == 0 || strcasecmp(state, "unpoll") == 0) { + /* + * send an O.k. if there was no othe rreply on write's + */ if (queueData == data && !data->answered) { if (queueData->inMacro == 0) { iMacro = SCinMacro(con); con->iMacro = 0; - SCWrite(con, "o.k.", eWarning); + SCWrite(con, "o.k.", eValue); SCsetMacro(con, iMacro); } } @@ -418,9 +460,16 @@ static char *SctActionHandler(void *actionData, char *lastReply, free(script); goto finish; } + /* + * set the state property to the next state for + * the next invocation of this routine + */ SetProp(node, controller->node, "state", state); free(script); script = NULL; + /* + * If there is data to send, check it and do so + */ if (sct->sendCalled) { send = GetProp(node, controller->node, "send"); if (send == NULL) @@ -470,6 +519,10 @@ static int SctMatchNode(void *vNode, void *vData) return node == d->node; } +/* + * This is the read callback for nodes particpating in the + * scriptcontext system + */ static hdbCallbackReturn SctMainCallback(Hdb * node, void *userData, hdbMessage * msg) { @@ -530,7 +583,10 @@ static hdbCallbackReturn SctMainCallback(Hdb * node, void *userData, return hdbContinue; } - +/* + * This is the callback registered for nodes which + * are written too. + */ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData, hdbMessage * msg) { @@ -602,6 +658,9 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData, prio = WritePRIO; } + /* + * check for duplicate sets on a node. + */ if (data->conCtx != NULL) { if (data->inMacro == 0) { GetHdbPath(node, path, sizeof path); @@ -610,6 +669,11 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData, "%s target changed to %s before completion", path, GetCharArray(text)); } + /* + * the node has already been queued for execution. But as we never + * know if the script chain is already running, the only clean + * solution is to requeue the node. + */ SCDeleteConnection(data->conCtx); } DeleteDynString(text); @@ -624,11 +688,11 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData, mm = GetHdbUpdateMessage(msg); if (mm != NULL) { - if (queueData != NULL && queueData->conCtx != NULL && !data->answered) { + if (queueData != NULL && queueData->conCtx != NULL && queueData->answered != 1) { /* update called from a write action */ text = formatValue(*(mm->v), node); if (queueData->inMacro == 0 && queueData->node == node) { - data->answered = 1; + queueData->answered = 1; iMacro = SCinMacro(queueData->conCtx); SCsetMacro(queueData->conCtx, 0); sicsCommand = GetHdbProp(node, "sicscommand"); @@ -915,7 +979,8 @@ void SctQueueNode(SctController * controller, Hdb * node, data->node = node; data->name = strdup(action); data->conCtx = NULL; - + data->answered = 1; + if (!DevQueue(data->controller->devser, data, prio, SctWriteHandler, SctMatch, SctKillData)) { if (data->name != NULL) { diff --git a/selector.c b/selector.c index 45b4294b..49d2263e 100644 --- a/selector.c +++ b/selector.c @@ -614,13 +614,13 @@ int MonoRun(pSicsSelector self, SConnection * pCon, float fWaveLength) /* start each motor in turn */ iRet = StartDevice(GetExecutor(), self->pTheta->name, self->pTheta->pDescriptor, - self->pTheta, pCon, sNeu.fTheta); + self->pTheta, pCon, pCon->runLevel, sNeu.fTheta); if (!iRet) { return 0; } iRet = StartDevice(GetExecutor(), self->pTwoTheta->name, self->pTwoTheta->pDescriptor, - self->pTwoTheta, pCon, sNeu.fTwoTheta); + self->pTwoTheta, pCon, pCon->runLevel, sNeu.fTwoTheta); if (!iRet) { return 0; } @@ -630,7 +630,7 @@ int MonoRun(pSicsSelector self, SConnection * pCon, float fWaveLength) if (self->pBend1) { iRet = StartDevice(GetExecutor(), self->pBend1->name, self->pBend1->pDescriptor, - self->pBend1, pCon, sNeu.fVert); + self->pBend1, pCon, pCon->runLevel, sNeu.fVert); if (!iRet) { return 0; } @@ -639,7 +639,7 @@ int MonoRun(pSicsSelector self, SConnection * pCon, float fWaveLength) if (self->pBend2) { iRet = StartDevice(GetExecutor(), self->pBend2->name, self->pBend2->pDescriptor, - self->pBend2, pCon, sNeu.fHor); + self->pBend2, pCon, pCon->runLevel, sNeu.fHor); if (!iRet) { return 0; } diff --git a/sicshdbadapter.c b/sicshdbadapter.c index 0ac612e7..c7207343 100644 --- a/sicshdbadapter.c +++ b/sicshdbadapter.c @@ -687,6 +687,11 @@ int SICSHdbAdapter(SConnection * pCon, SicsInterp * pSics, void *pData, */ pMot = (pMotor) FindCommandData(pSics, argv[2], "Motor"); if (pMot != NULL) { + if(pMot->ParArray == NULL){ + SCWrite(pCon,"ERROR: secong generation motors need to be linked rather then adapted", + eError); + return 0; + } node = CreateMotorAdapter(argv[3], pMot); if (node == NULL) { SCWrite(pCon, "ERROR: out of memory creating motor node", eError); diff --git a/sicshipadaba.c b/sicshipadaba.c index cb7661e7..b87429b2 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -258,10 +258,10 @@ static hdbCallbackReturn SICSDriveCallback(pHdb node, void *userData, assert(pCon != NULL && dum != NULL); if (GetHdbProperty(node, "sicsdev", pSicsdev, 79)) { status = StartDevice(pServ->pExecutor, pSicsdev, dum->pDescriptor, - userData, pCon, (float) v.v.doubleValue); + userData, pCon, RUNDRIVE, (float) v.v.doubleValue); } else { status = StartDevice(pServ->pExecutor, node->name, dum->pDescriptor, - userData, pCon, (float) v.v.doubleValue); + userData, pCon, pCon->runLevel, (float) v.v.doubleValue); } if (status == 1) { return hdbContinue; diff --git a/sicsobj.c b/sicsobj.c index 8e0addf0..5f5db105 100644 --- a/sicsobj.c +++ b/sicsobj.c @@ -52,6 +52,7 @@ static void saveSICSNode(pHdb node, char *prefix, FILE * fd) fprintf(fd, "%s %s\n", prefix, GetCharArray(data)); DeleteDynString(data); } + ReleaseHdbValue(&v); child = node->child; while (child != NULL) { snprintf(newprefix, 1024, "%s/%s", prefix, child->name); diff --git a/stdscan.c b/stdscan.c index 12c0c910..4c9f8d1d 100644 --- a/stdscan.c +++ b/stdscan.c @@ -846,9 +846,8 @@ int ScanDrive(pScanData self, int iPoint) status = 1; } /* wait for finish */ - lTask = GetDevexecID(pServ->pExecutor); - if (lTask > 0) { - TaskWait(pServ->pTasker, lTask); + while(DevExecLevelRunning(pServ->pExecutor, RUNDRIVE)){ + TaskYield(pServ->pTasker); } return status; } @@ -890,17 +889,16 @@ int ScanCount(pScanData self, int iPoint) iRet = StartDevice(pServ->pExecutor, "ScanCounter", pDum->pDescriptor, - self->pCounterData, self->pCon, self->fPreset); + self->pCounterData, self->pCon, RUNDRIVE, + self->fPreset); if (!iRet) { SCWrite(self->pCon, "ERROR: Cannot Count, Scan aborted", eLogError); return 0; } SetStatus(eCounting); /* wait for finish */ - lTask = GetDevexecID(pServ->pExecutor); - if (lTask > 0); - { - TaskWait(pServ->pTasker, lTask); + while(DevExecLevelRunning(pServ->pExecutor, RUNDRIVE)){ + TaskYield(pServ->pTasker); } return 1; } diff --git a/tasscanub.c b/tasscanub.c index df7eaa4b..e204c643 100644 --- a/tasscanub.c +++ b/tasscanub.c @@ -646,7 +646,7 @@ static int TASUBScanDrive(pScanData self, int iPoint) pVar = (pVarEntry) pPtr; if (pVar) { StartMotor(pServ->pExecutor, self->pSics, self->pCon, pVar->Name, - pVar->fStart + iPoint * pVar->fStep); + RUNDRIVE, pVar->fStart + iPoint * pVar->fStep); /* Ignore errors. TAS scans continues when a motor runs into a limit. diff --git a/velo.c b/velo.c index 9b12f3dd..9b92ae2f 100644 --- a/velo.c +++ b/velo.c @@ -516,7 +516,7 @@ int VSSetTiltRot(pVelSel self, SConnection * pCon, float fNewRot, if (fDelta > ObVal(self->pPar, TILTPREC)) { /* yes */ /* first stop the Rotation of the selector */ iRet = StartDevice(GetExecutor(), "Velocity Selector Rot", - self->pDes, self, pCon, -10.); + self->pDes, self, pCon, RUNDRIVE, -10.); if (!iRet) { return 0; } @@ -539,7 +539,7 @@ int VSSetTiltRot(pVelSel self, SConnection * pCon, float fNewRot, SCSetRights(pCon, usInternal); iRet = StartDevice(GetExecutor(), "Velocity Selector Tilt", self->pTilt->pDescriptor, self->pTilt, - pCon, fNewTilt); + pCon, RUNDRIVE, fNewTilt); /* wait for this to finish */ SCWrite(pCon, "Driving tilt-angle", eWarning); @@ -559,7 +559,7 @@ int VSSetTiltRot(pVelSel self, SConnection * pCon, float fNewRot, /* drive rotation */ iRet = StartDevice(GetExecutor(), "Velocity Selector Rot", - self->pDes, self, pCon, fNewRot); + self->pDes, self, pCon, RUNDRIVE, fNewRot); if (!iRet) { return 0; }