From ecd96f9ab0582d8d7ec466b2c87c066c656c6b83 Mon Sep 17 00:00:00 2001 From: koennecke Date: Thu, 19 Apr 2012 10:01:31 +0000 Subject: [PATCH] - Extended confvirtmot to allow for sequences of calls - Extended confvirtmot to have a checkscript - Made sure that targets get updated when calling tasdrive - Fixed some output codes in tasdrive.c - Made tdchm invoke counters event message for Melone - Fixed the ConID inefficiency by caching the host name in asynnet.c - Added a traceActive function to trace SKIPPED: psi/tdchm.c --- asynnet.c | 20 ++++++++------ confvirtmot.i | 1 + confvirtualmot.c | 70 ++++++++++++++++++++++++++++++++++++++++++++---- confvirtualmot.w | 1 + devexec.c | 14 ++++++++-- lld.c | 18 +++++++++++++ motor.c | 9 +++++++ motor.h | 1 + scriptcontext.c | 10 ++++++- sicvar.c | 2 +- tasdrive.c | 35 ++++++++++++++---------- trace.c | 9 +++++++ trace.h | 6 +++++ 13 files changed, 165 insertions(+), 31 deletions(-) diff --git a/asynnet.c b/asynnet.c index 78d022c3..d59c854d 100644 --- a/asynnet.c +++ b/asynnet.c @@ -57,6 +57,7 @@ typedef struct { ANETcallback readCallback; void *userData; ANETkill killUser; + char host[132]; } SocketDescriptor, *pSocketDescriptor; static SocketDescriptor connections[MAXCONNECTIONS]; @@ -480,16 +481,19 @@ int ANETinfo(int handle, char *hostname, int hostnameLen) if (con == NULL) { return ANETDISCONNECTED; } else { - len = sizeof sin; - if (getpeername(con->socket, (struct sockaddr *) &sin, &len) < 0) { - return ANETSOCKERROR; - } - if ((host = gethostbyaddr((char *) &sin.sin_addr, - sizeof(sin.sin_addr), AF_INET)) == NULL) { - return ANETSOCKERROR; + if(strlen(con->host) < 3){ + len = sizeof sin; + if (getpeername(con->socket, (struct sockaddr *) &sin, &len) < 0) { + return ANETSOCKERROR; + } + if ((host = gethostbyaddr((char *) &sin.sin_addr, + sizeof(sin.sin_addr), AF_INET)) == NULL) { + return ANETSOCKERROR; + } + strlcpy(con->host,host->h_name, 132); } memset(hostname, 0, hostnameLen); - strlcpy(hostname, host->h_name, hostnameLen); + strlcpy(hostname, con->host, hostnameLen); } return 1; } diff --git a/confvirtmot.i b/confvirtmot.i index 2ebd6187..f1fc5739 100644 --- a/confvirtmot.i +++ b/confvirtmot.i @@ -12,6 +12,7 @@ typedef struct __CONFVIRTMOT { char *scriptName; char *readScript; char *checkScript; + char *state; int motorList; float targetValue; int targetReached; diff --git a/confvirtualmot.c b/confvirtualmot.c index 8087dfe6..c8216e12 100644 --- a/confvirtualmot.c +++ b/confvirtualmot.c @@ -9,6 +9,22 @@ Mark Koennecke, August 2004 interest added: Ferdi Franceschini, April 2006 + + Additions: + - a checkscript to be run at the end of driving the motor + - a means to call the write script multiple times. This is useful if + you need to drive to the value in multiple steps. An example is the + BOA double crystal monochromator where you first have to pu the baldes to + 0, then drive the translation and then drive the blades to the real theta. + All this to avoid collisions. In order to support this, a state field and + and a readable target field has been added. The mode of operation is such + that the on first run the, writescript set the state to something different + then idle. This causes after the first set of motors finished running the + writescript to be called again. This can figure out by lookin at the + state variable what to do. This can be doen in repetition until the + writescript sets state to idle again. + + Mark Koennecke, April 2012 -------------------------------------------------------------------------*/ #include #include @@ -299,7 +315,7 @@ static void invokeCheckScript(pConfigurableVirtualMotor self, pTcl = InterpGetTcl(pServ->pSics); if(self->checkScript != NULL){ - status = Tcl_Eval(pTcl, self->readScript); + status = Tcl_Eval(pTcl, self->checkScript); if (status != TCL_OK) { snprintf(self->scriptError, 510, "ERROR: Tcl subsystem reported %s", Tcl_GetStringResult(pTcl)); @@ -331,6 +347,10 @@ static int ConfCheckStatus(void *pData, SConnection * pCon) break; case HWFault: case HWPosFault: + if(self->state != NULL){ + free(self->state); + self->state = strdup("idle"); + } return status; break; default: @@ -344,10 +364,20 @@ static int ConfCheckStatus(void *pData, SConnection * pCon) } if (result == HWIdle) { - invokeCheckScript(self,pCon); - event.pName = self->name; - event.fVal = self->pDriv->GetValue(self, pCon); - InvokeCallBack(self->pCall, MOTDRIVE, &event); + /* + * Do we have to do another step? If so run it. + */ + if(strstr(self->state,"idle") == NULL){ + status = ConfSetValue(self,pCon,self->targetValue); + if(status == OKOK){ + result = HWBusy; + } + } else { + invokeCheckScript(self,pCon); + event.pName = self->name; + event.fVal = self->pDriv->GetValue(self, pCon); + InvokeCallBack(self->pCall, MOTDRIVE, &event); + } } else if (result == HWBusy) { self->posCount++; if (self->posCount >= 10 /*ObVal(self->ParArray,MOVECOUNT) */ ) { @@ -468,6 +498,10 @@ static void KillConfigurableVirtualMotor(void *data) free(self->readScript); self->readScript = NULL; } + if(self->state != NULL){ + free(self->state); + self->state = NULL; + } free(self); self = NULL; } @@ -504,6 +538,7 @@ int MakeConfigurableVirtualMotor(SConnection * pCon, SicsInterp * pSics, eError); return 0; } + pNew->state = strdup("idle"); /* assign functions @@ -613,6 +648,31 @@ int ConfigurableVirtualMotorAction(SConnection * pCon, SicsInterp * pSics, return 1; } } + } else if (strcmp(argv[1], "state") == 0) { + if (argc > 2) { + /* set case */ + Arg2Text(argc - 2, &argv[2], pBueffel, 510); + self->state = strdup(pBueffel); + SCSendOK(pCon); + return 1; + } else { + /* inquiry */ + if (self->state == NULL) { + snprintf(pBueffel, 510, "%s.state = UNDEFINED", argv[0]); + SCWrite(pCon, pBueffel, eValue); + return 1; + } else { + snprintf(pBueffel, 510, "%s.state = %s", argv[0], + self->state); + SCWrite(pCon, pBueffel, eValue); + return 1; + } + } + } else if (strcmp(argv[1], "target") == 0) { + /* inquiry */ + snprintf(pBueffel, 510, "%s.target = %f", argv[0], self->targetValue); + SCWrite(pCon, pBueffel, eValue); + return 1; } else if (strcmp(argv[1], "interest") == 0) { pRegInfo = (pRegisteredInfo) malloc(sizeof(RegisteredInfo)); if (!pRegInfo) { diff --git a/confvirtualmot.w b/confvirtualmot.w index 4e475465..169ac0c1 100644 --- a/confvirtualmot.w +++ b/confvirtualmot.w @@ -17,6 +17,7 @@ typedef struct __CONFVIRTMOT { char *scriptName; char *readScript; char *checkScript; + char *state; int motorList; float targetValue; int targetReached; diff --git a/devexec.c b/devexec.c index 187a0427..5aad35f2 100644 --- a/devexec.c +++ b/devexec.c @@ -280,7 +280,7 @@ void ExeInterest(pExeList self, pDevEntry pDev, char *text) } } /*------------------------------------------------------------------------*/ -static void InvokeNewTarget(pExeList self, char *name, float target) +void InvokeNewTarget(pExeList self, char *name, float target) { NewTarget targetEvent; @@ -772,25 +772,35 @@ int CheckExeList(pExeList self) iRet = LLDnodePtr2First(self->iList); return testFinish(self); } +/*-------------------------------------------------------------------------- +Cludge to not move the current pointer for CheckExeList +*/ +void *LLDgetCurrent(int List); +void LLDsetCurrent(int List, void *pointer); + /*---------------------------------------------------------------------------*/ int DevExecLevelRunning(pExeList self, int level) { int iRet; pDevEntry pDev = NULL; - + void *current; + if(self->lTask < 0){ return 0; } + current = LLDgetCurrent(self->iList); iRet = LLDnodePtr2First(self->iList); while (iRet != 0) { LLDnodeDataTo(self->iList, &pDev); if (pDev) { if(pDev->level >= level){ + LLDsetCurrent(self->iList,current); return 1; } } iRet = LLDnodePtr2Next(self->iList); } + LLDsetCurrent(self->iList,current); return 0; } diff --git a/lld.c b/lld.c index 18d2f5ae..c5e7f3dd 100644 --- a/lld.c +++ b/lld.c @@ -22,6 +22,14 @@ - Node deletion via first and/or last node pointers. (as for access functions, then simplify ...) + ** Comment by Mark Koennecke ** + This implementation has problems when being accessed + concurrently in any form. The reason is the single + current pointer in the list data stucture. A improvement + would be to have a function to get an iterator which holds + this crucial value and functions to iterate on the iterator + *************** end of comment ********* + _____ This version is Public Domain. /_|__| A.Reitsma, Delft, The Netherlands. / | \ --------------------------------------------------------------- */ @@ -647,3 +655,13 @@ int LLDnodeDataFrom(int List, void *source) } /* ==== LLD.c end ==================================================== */ +/** + * These two functions help me implement a solution for a race condition + * in devexec.c, especially in DevexecLevelRunning. + */ +void *LLDgetCurrent(int List){ + return ListControl[List].current; +} +void LLDsetCurrent(int List, void *pointer){ + ListControl[List].current = (struct Node*)pointer; +} diff --git a/motor.c b/motor.c index 40770d83..179af765 100644 --- a/motor.c +++ b/motor.c @@ -364,6 +364,7 @@ static void finishDriving(pMotor self, SConnection * pCon) InvokeCallBack(self->pCall, MOTDRIVE, &sCall); /* send also very last position */ InvokeCallBack(self->pCall, MOTEND, &sCall); tracePar(self->name,"%f",sCall.fVal); + self->running = 0; } /*--------------------------------------------------------------------*/ @@ -484,6 +485,10 @@ static int MotorStatus(void *sulf, SConnection * pCon) assert(sulf); self = (pMotor) sulf; + if(self->running != 1){ + return HWIdle; + } + status = evaluateStatus(self, pCon); if (self->pDrivInt->drivableStatus != status) { ((SConnection *) pCon)->conEventType = STATUS; @@ -752,10 +757,12 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew) case MOTREDO: iRet = self->pDriver->RunTo(self->pDriver, fHard); if (iRet == OKOK) { + self->running = 1; return OKOK; } break; case MOTOK: + self->running = 1; return OKOK; break; } @@ -766,6 +773,7 @@ static long MotorRunImpl(void *sulf, SConnection * pCon, float fNew) SCSetInterrupt(pCon, (int) ObVal(self->ParArray, INT)); return HWFault; } + self->running = 1; return OKOK; } @@ -1109,6 +1117,7 @@ void MotorReset(pMotor pM) usUser); ObParInit(pM->ParArray, SZERO, "softzero", ZEROINACTIVE, usUser); ObParInit(pM->ParArray, FIX, "fixed", -1, usUser); + pM->running = 0; } /*------------------------------------------------------------------------*/ diff --git a/motor.h b/motor.h index 145e33ac..027e66ab 100644 --- a/motor.h +++ b/motor.h @@ -38,6 +38,7 @@ typedef struct __Motor { int posFaultCount; int stopped; int errorCount; + int running; ObPar *ParArray; void *pPrivate; void (*KillPrivate) (void *); diff --git a/scriptcontext.c b/scriptcontext.c index 3862fa26..a91732ed 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -472,6 +472,13 @@ static char *SctActionHandler(void *actionData, char *lastReply, SCPrintf(con, eError, "ERROR: action {%s} in {%s} node %s:\nERROR: %s", data->name, origScript, path, result); + if(data != NULL && data->controller != NULL){ + traceIO(data->controller->node->name, "ERROR: action {%s} in {%s} node %s:\nERROR: %s", + data->name, origScript, path, result); + } else { + traceIO("sctunknown", "reply:%s", "ERROR: action {%s} in {%s} node %s:\nERROR: %s", + data->name, origScript, path, result); + } } snprintf(msg, sizeof msg, "{%s} %s", origScript, result); if (strcasecmp(data->name, "read") == 0) { @@ -776,13 +783,14 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData, */ SCDeleteConnection(data->conCtx); } - DeleteDynString(text); data->conCtx = SCCopyConnection(con); data->answered = 0; data->inMacro = SCinMacro(con); + tracePar(node->name,"Queued %s to %s",node->name, GetCharArray(text)); DevQueue(data->controller->devser, data, prio, SctWriteHandler, SctMatch, NULL, SctDataInfo); /* no kill function in DevQueue: data is owned by the node (callback list) */ + DeleteDynString(text); return hdbContinue; } diff --git a/sicvar.c b/sicvar.c index f33111f0..7d2ffc33 100644 --- a/sicvar.c +++ b/sicvar.c @@ -533,7 +533,7 @@ int VarWrapper(SConnection * pCon, SicsInterp * pInterp, void *pData, Undocumented feauture: force a set even while driving etc. Internal privilege required to do this. */ - if (!SCMatchRights(pCon, usInternal)) { + if (!SCMatchRights(pCon, usUser)) { return 0; } pCurrent = pCurrent->pNext; diff --git a/tasdrive.c b/tasdrive.c index 95bf979a..16cf765a 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -43,7 +43,7 @@ static long TASSetValue(void *pData, SConnection * pCon, float value) if (self->code > 5 && self->math->tasMode == ELASTIC) { SCWrite(pCon, "ERROR: cannot drive this motor in elastic mode", - eError); + eLogError); return HWFault; } setTasPar(&self->math->target, self->math->tasMode, self->code, value); @@ -146,7 +146,7 @@ static float TASGetValue(void *pData, SConnection * pCon) &self->math->current); if (status < 0) { SCWrite(pCon, "ERROR: out of memory calculating Q-E variables", - eError); + eLogError); return -999.99; } if (self->math->tasMode == ELASTIC) { @@ -182,7 +182,7 @@ static float TASQMGetValue(void *pData, SConnection * pCon) angles, &self->math->current); if (status < 0) { SCWrite(pCon, "ERROR: out of memory calculating Q-E variables", - eError); + eLogError); return -999.99; } if (self->math->tasMode == ELASTIC) { @@ -250,6 +250,8 @@ static float getMotorValue(pMotor mot, SConnection * pCon) GetDrivablePosition(mot, pCon, &val); return val; } +/*--------------------- In devexec.c --------------------------------------*/ +void InvokeNewTarget(pExeList self, char *name, float target); /*--------------------------------------------------------------------------*/ static int startTASMotor(pMotor mot, SConnection * pCon, char *name, @@ -268,20 +270,25 @@ static int startTASMotor(pMotor mot, SConnection * pCon, char *name, MotorGetPar(mot, "fixed", &fixed); if (ABS(fixed - 1.0) < .1) { snprintf(buffer, 131, "WARNING: %s is FIXED", name); - SCWrite(pCon, buffer, eWarning); + SCWrite(pCon, buffer, eLog); return OKOK; } } mot->stopped = 0; if (ABS(val - target) > MOTPREC) { pDriv = GetDrivableInterface(mot); - SCStartBuffering(pCon); + /* SCStartBuffering(pCon); */ status = pDriv->SetValue(mot, pCon, (float) target); - mes = SCEndBuffering(pCon); + /* + to force updates on targets + */ + InvokeNewTarget(pServ->pExecutor, name, target); + /*mes = SCEndBuffering(pCon); if (status != OKOK) { SCPrintf(pCon,eLogError, GetCharArray(mes)); return status; } + */ } writeMotPos(pCon, silent, name, val, target); return status; @@ -316,7 +323,7 @@ static int startMotors(ptasMot self, tasAngles angles, status = startTASMotor(self->math->motors[MCV], pCon, "mcv", curve, silent); if (status != OKOK) { - SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eWarning); + SCWrite(pCon,"WARNING: monochromator vertical curvature motor failed to start", eLog); SCSetInterrupt(pCon,eContinue); } } @@ -327,7 +334,7 @@ static int startMotors(ptasMot self, tasAngles angles, status = startTASMotor(self->math->motors[MCH], pCon, "mch", curve, silent); if (status != OKOK) { - SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eWarning); + SCWrite(pCon,"WARNING: monochromator horizontal curvature motor failed to start", eLog); SCSetInterrupt(pCon,eContinue); } } @@ -354,7 +361,7 @@ static int startMotors(ptasMot self, tasAngles angles, status = startTASMotor(self->math->motors[ACV], pCon, "acv", curve, silent); if (status != OKOK) { - SCWrite(pCon,"WARNING: analyzer vertical curvature motor failed to start", eWarning); + SCWrite(pCon,"WARNING: analyzer vertical curvature motor failed to start", eLog); SCSetInterrupt(pCon,eContinue); } } @@ -364,7 +371,7 @@ static int startMotors(ptasMot self, tasAngles angles, status = startTASMotor(self->math->motors[ACH], pCon, "ach", curve, silent); if (status != OKOK) { - SCWrite(pCon,"WARNING: analyzer horizontal curvature motor failed to start", eWarning); + SCWrite(pCon,"WARNING: analyzer horizontal curvature motor failed to start", eLog); SCSetInterrupt(pCon,eContinue); } } @@ -422,7 +429,7 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon, if (status != 1) { retVal = 0; snprintf(pBueffel, 256, "ERROR: limit violation an a3: %s", error); - SCWrite(pCon, pBueffel, eError); + SCWrite(pCon, pBueffel, eLogError); } } @@ -434,7 +441,7 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon, if (status != 1) { retVal = 0; snprintf(pBueffel, 256, "ERROR: limit violation an a4: %s", error); - SCWrite(pCon, pBueffel, eError); + SCWrite(pCon, pBueffel, eLogError); } if (driveTilt == 1) { @@ -445,7 +452,7 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon, if (status != 1) { retVal = 0; snprintf(pBueffel, 256, "ERROR: limit violation an SGU: %s", error); - SCWrite(pCon, pBueffel, eError); + SCWrite(pCon, pBueffel, eLogError); } pDrivInt = GetDrivableInterface(self->math->motors[SGL]); @@ -455,7 +462,7 @@ static int checkQMotorLimits(ptasMot self, SConnection * pCon, if (status != 1) { retVal = 0; snprintf(pBueffel, 256, "ERROR: limit violation an SGL: %s", error); - SCWrite(pCon, pBueffel, eError); + SCWrite(pCon, pBueffel, eLogError); } } return retVal; diff --git a/trace.c b/trace.c index 9d249d94..ce135f03 100644 --- a/trace.c +++ b/trace.c @@ -31,6 +31,15 @@ static int hdbInit = 0; static int filterProv = 0; static int debug = 0; /*----------------------------------------------------------------------------------------*/ +int traceActive() +{ + if (log == NULL){ + return 0; + } else { + return 1; + } +} +/*----------------------------------------------------------------------------------------*/ static char *GetTracePath(pHdb node) { pHdb nodeStack[64]; diff --git a/trace.h b/trace.h index 91334d1b..afd6d71b 100644 --- a/trace.h +++ b/trace.h @@ -29,4 +29,10 @@ void traceprint(char *sub, char *id,char *data); * A debugging trace. This has to be switched on separately */ void traceDebug(char *id, char *format, ...); + +/* + * 1 when tracing active, 0 else + */ +int traceActive(); + #endif /* TRACE_H_ */