- 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
This commit is contained in:
koennecke
2012-04-19 10:01:31 +00:00
parent 12b755de76
commit ecd96f9ab0
13 changed files with 165 additions and 31 deletions

View File

@ -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;
}

View File

@ -12,6 +12,7 @@ typedef struct __CONFVIRTMOT {
char *scriptName;
char *readScript;
char *checkScript;
char *state;
int motorList;
float targetValue;
int targetReached;

View File

@ -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 <stdlib.h>
#include <assert.h>
@ -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) {

View File

@ -17,6 +17,7 @@ typedef struct __CONFVIRTMOT {
char *scriptName;
char *readScript;
char *checkScript;
char *state;
int motorList;
float targetValue;
int targetReached;

View File

@ -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;
}

18
lld.c
View File

@ -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;
}

View File

@ -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;
}
/*------------------------------------------------------------------------*/

View File

@ -38,6 +38,7 @@ typedef struct __Motor {
int posFaultCount;
int stopped;
int errorCount;
int running;
ObPar *ParArray;
void *pPrivate;
void (*KillPrivate) (void *);

View File

@ -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;
}

View File

@ -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;

View File

@ -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;

View File

@ -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];

View File

@ -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_ */