- 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
This commit is contained in:
koennecke
2009-04-17 12:52:01 +00:00
parent 50b0a5c4a7
commit 99d2485d22
39 changed files with 422 additions and 200 deletions

View File

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

View File

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

View File

@ -198,6 +198,7 @@ static SConnection *CreateConnection(SicsInterp * pSics)
pRes->listening = 0;
pRes->conStart = time(NULL);
pRes->write = SCNormalWrite;
pRes->runLevel = RUNDRIVE;
/* initialise context variables */
pRes->iCmdCtr = 0;
@ -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)
{

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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,43 +37,48 @@ 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);
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"
/*
@ -83,20 +88,20 @@ void DevExecSignal(void *pEL, int iSignal, void *pSigData);
*/
/*-------------------------------------------------------------------------*/
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.
*/
/*-------------------------------------------------------------------------*/
#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
@ -104,55 +109,54 @@ int StopExeWait(pExeList self);
StopExeWait will stop all running things and wait for the stop
to complete.
*/
int StopByData(pExeList self, void *data);
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.
*/
/*-----------------------------------------------------------------------*/
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 DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
int StopCommand(SConnection * pCon, SicsInterp * pSics, void *pData,
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 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 SicsIdle(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
/*
prints the seconds since the device executor was running the last time
*/
int Success(SConnection * pCon, SicsInterp * pSics, void *pData,
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 PauseAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
/*
pauses execution
*/
int ContinueAction(SConnection * pCon, SicsInterp * pSics, void *pData,
int ContinueAction(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
/*
continues execution
@ -160,17 +164,18 @@ int ContinueAction(SConnection * pCon, SicsInterp * pSics, void *pData,
/*--------------------------- Locking ---------------------------------*/
#line 185 "devexec.w"
#line 190 "devexec.w"
void LockDeviceExecutor(pExeList self);
void UnlockDeviceExecutor(pExeList self);
void LockDeviceExecutor(pExeList self);
void UnlockDeviceExecutor(pExeList self);
#line 301 "devexec.w"
#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);
void DevexecLog(char *op, char *device);
#endif

View File

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

View File

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

10
drive.c
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -96,6 +96,13 @@ 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);

View File

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

View File

@ -92,13 +92,14 @@ static int MMCCStart(void *pData, SConnection * pCon)
}
for (i = 0; i < self->nSlaves; 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;

View File

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

View File

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

View File

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

View File

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

View File

@ -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,6 +979,7 @@ 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)) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

6
velo.c
View File

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