diff --git a/SCinter.c b/SCinter.c index 326803d2..1d5cd1a4 100644 --- a/SCinter.c +++ b/SCinter.c @@ -543,6 +543,7 @@ void DeleteInterp(SicsInterp * self) call KillSicsUnknown instead to clean up all memory properly. M.Z., Apr 05 */ + Tcl_DeleteInterp(pTcl); KillSicsUnknown(); } diff --git a/SCinter.h b/SCinter.h index 33147ac8..255e8db6 100644 --- a/SCinter.h +++ b/SCinter.h @@ -155,7 +155,7 @@ void *FindCommandData(SicsInterp * pSics, char *name, char *comclass); */ pObjectDescriptor FindCommandDescriptor(SicsInterp * pSics, char *name); -/*------------------------------------------------------------------------ +/*--------------------------------------------------------------------- FindDrivable tries to find Drivable object by the name given. Returns a pointer to the drivable interface in the case of success, NULL in case of failure. In order to save me fixing header files the pointer must diff --git a/arrayutil.c b/arrayutil.c index 9d9c458a..4c352212 100644 --- a/arrayutil.c +++ b/arrayutil.c @@ -36,11 +36,18 @@ long sumWindow(int *data, int xstart, int xend, int xlength, } - for(j = ystart; j < yend; j++){ - row = data + j*xlength; - for(i = xstart; i < xend; i++){ - result += row[i]; + /* for(j = ystart; j < yend; j++){ */ + /* row = data + j*xlength; */ + /* for(i = xstart; i < xend; i++){ */ + /* result += row[i]; */ + /* } */ + /* } */ + for(i = xstart; i < xend; i++){ + row = data + i*ylength; + for(j = ystart; j < yend; j++){ + result += row[j]; } } + return result; } diff --git a/asynnet.c b/asynnet.c index 7f92eb46..a4f39d33 100644 --- a/asynnet.c +++ b/asynnet.c @@ -45,7 +45,8 @@ #define MAXCONNECTIONS 1024 #define RBUFFERSIZE 262144 /* 256kb */ #define WBUFFERSIZE 20*262144 -/* #define WBUFFERSIZE 100*262144 /* +/* #define WBUFFERSIZE 100*262144 */ +#define MAXWBUFFERSIZE 128*1000*1024 /*--------------------------------------------------------------------------*/ typedef struct { int socket; @@ -204,7 +205,7 @@ int ANETregisterSocket(int socket) flags =1; setsockopt(socket,IPPROTO_TCP,TCP_NODELAY,(char *) &flags, sizeof(int)); socke.readBuffer = MakeRWPuffer(RBUFFERSIZE); - socke.writeBuffer = MakeRWPuffer(WBUFFERSIZE); + socke.writeBuffer = MakeBigRWPuffer(WBUFFERSIZE, MAXWBUFFERSIZE); if (socke.readBuffer == NULL || socke.writeBuffer == NULL) { return ANETMEM; } @@ -247,6 +248,7 @@ int ANETconnect(char *name, int iPort) status = connect(socke, (struct sockaddr *) &addresse, sizeof(struct sockaddr_in)); if (status < 0) { + close(socke); anetLog(ANETERROR, "Failed to open socket to %s:%d", name, iPort); return ANETOPENFAIL; } @@ -497,7 +499,20 @@ int ANETinfo(int handle, char *hostname, int hostnameLen) } return 1; } +/*---------------------------------------------------------------------------*/ +int ANETcanWrite(int handle, void *buffer, int count) +{ + pSocketDescriptor con = NULL; + int status; + con = findSocketDescriptor(handle); + if (con == NULL) { + return ANETDISCONNECTED; + } else { + ANETprocess(); + return CanStoreRWBuffer(con->writeBuffer, buffer, count); + } +} /*---------------------------------------------------------------------------*/ int ANETwrite(int handle, void *buffer, int count) { diff --git a/asynnet.h b/asynnet.h index 9912b70f..ae2f114d 100644 --- a/asynnet.h +++ b/asynnet.h @@ -145,6 +145,14 @@ int ANETinfo(int handle, char *hostname, int hostNameLen); * \return 1 on success, 0 on failure */ int ANETwrite(int handle, void *buffer, int count); +/** + * \brief Test if the buffer can be written to the network + * \param handle The handle for the connection + * \param buffer A pointer to the data to write + * \param count The number of bytes to write. + * \return 1 when possible, 0 when buffer overrun + */ +int ANETcanWrite(int handle, void *buffer, int count); /** * \brief copy at max bufferLength bytes into buffer. The data is not deleted from * the read buffer yet. diff --git a/commandlog.h b/commandlog.h index d02d1da3..82293f79 100644 --- a/commandlog.h +++ b/commandlog.h @@ -9,7 +9,7 @@ --------------------------------------------------------------------------*/ #ifndef COMMANDLOG #define COMMANDLOG -void WriteToCommandLog(char *prompt, char *pText); +void WriteToCommandLog(const char *prompt, const char *pText); void WriteToCommandLogId(char *prompt, int id, char *text); void WriteToCommandLogCmd(int id, char *text); int CompactCommandLog(void); diff --git a/cone.c b/cone.c index b90279ca..9ac2e252 100644 --- a/cone.c +++ b/cone.c @@ -171,7 +171,6 @@ static long ConeSetValue(void *pData, SConnection * pCon, float fVal) */ SICSHdbGetPar(obj, pCon, "target", &v); target.h = v.v.floatArray[0]; - target.k = v.v.floatArray[1]; target.l = v.v.floatArray[2]; SICSHdbGetPar(obj, pCon, "qscale", &v); /* @@ -198,7 +197,7 @@ static long ConeSetValue(void *pData, SConnection * pCon, float fVal) mat_free(csToPsi); if (status != 1) { SCWrite(pCon, "ERROR: cannot get cone vector into scattering position", - eError); + eLogError); SCSetInterrupt(pCon, eAbortOperation); return 0; } diff --git a/conman.c b/conman.c index ee8ff769..88b2ad1f 100644 --- a/conman.c +++ b/conman.c @@ -1016,7 +1016,6 @@ int SCPureSockWrite(SConnection * self, char *buffer, int iOut) return 1; } - /*-------------------------------------------------------------------------- special for ClientLog. Do not use elsewhere without check ----------------------------------------------------------------------------*/ @@ -1044,6 +1043,18 @@ int SCLogWrite(SConnection * self, char *buffer, int iOut) if(pPtr != pBueffel){ free(pPtr); } + } else if(self->iProtocolID == 2) { + if (strlen(buffer) + 30 > 1024) { + pPtr = (char *) malloc((strlen(buffer) + 30) * sizeof(char)); + memset(pPtr, 0, strlen(buffer) + 20); + } else { + pPtr = pBueffel; + } + sprintf(pPtr,"%s@@%s",buffer,pCode[iOut]); + testAndWriteSocket(self, pPtr, iOut); + if(pPtr != pBueffel){ + free(pPtr); + } } else { testAndWriteSocket(self, buffer, iOut); } @@ -1178,6 +1189,8 @@ int SCWriteZipped(SConnection * self, char *pName, void *pData, SCWrite(self, "ERROR: no data to write in SCWriteZiped", eError); return 0; } + + pBuf = malloc(iDataLen*sizeof(char)); memset(pBuf,0,iDataLen*sizeof(char)); @@ -1204,6 +1217,19 @@ int SCWriteZipped(SConnection * self, char *pName, void *pData, } compressedLength = compStream.total_out; + /* + If data is large, test if we can do it + */ + if(compressedLength > 2*1000*1024) { + if(!ANETcanWrite(self->sockHandle,pData,compressedLength)){ + SCWrite(self,"WARNING: skipping excessive data in SCWriteZipped",eLogError); + deflateEnd(&compStream); + free(pBuf); + return 0; + } + } + + /* write header line */ memset(outBuf, 0, 65536); @@ -1270,6 +1296,16 @@ int SCWriteBinary(SConnection * self, char *pName, void *pData, return 0; } + /* + If data is large, test if we can do it + */ + if(iDataLen > 2*1000*1024) { + if(!ANETcanWrite(self->sockHandle,pData,iDataLen)){ + SCWrite(self,"WARNING: skipping excessive data in SCWriteBinary",eLogError); + return 0; + } + } + /* write header line */ memset(outBuf, 0, 65536); @@ -1521,8 +1557,6 @@ int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen) SCWrite(pCon, pPrompt, eWarning); master = SCfindMaster(pCon); - eOld = GetStatus(); - SetStatus(eInput); CostaUnlock(master->pStack); while (1) { /* @@ -1542,14 +1576,12 @@ int SCPrompt(SConnection * pCon, char *pPrompt, char *pResult, int iLen) /* do we have data ? */ iRet = CostaPop(master->pStack, &pPtr); if (iRet == 1) { - SetStatus(eOld); CostaLock(master->pStack); strlcpy(pResult, pPtr, iLen); WriteToCommandLogId(" prompted>", pCon->sockHandle, pPtr); return 1; } } - SetStatus(eOld); CostaLock(master->pStack); return 0; } @@ -1570,8 +1602,6 @@ int SCPromptTMO(SConnection * pCon, char *pPrompt, char *pResult, int iLen, int SCWrite(pCon, pPrompt, eWarning); master = SCfindMaster(pCon); - eOld = GetStatus(); - SetStatus(eInput); CostaUnlock(master->pStack); for(i = 0; i < timeout; i++) { /* @@ -1591,14 +1621,12 @@ int SCPromptTMO(SConnection * pCon, char *pPrompt, char *pResult, int iLen, int /* do we have data ? */ iRet = CostaPop(master->pStack, &pPtr); if (iRet == 1) { - SetStatus(eOld); CostaLock(master->pStack); strlcpy(pResult, pPtr, iLen); WriteToCommandLogId(" prompted>", pCon->sockHandle, pPtr); return 1; } } - SetStatus(eOld); CostaLock(master->pStack); return 0; } @@ -1724,10 +1752,8 @@ int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand) return 0; } strlcpy(pCopy->deviceID, pBueffel, SCDEVIDLEN); - /* SCAdvanceContext(self,pBueffel); */ traceCommand(ConID(self),"in:%s", pCommand); iRet = InterpExecute(pInter, pCopy, pCommand); - /* SCPopContext(self); */ SCDeleteConnection(pCopy); StatusFileTask(NULL); /* save changed parameters */ diff --git a/counter.c b/counter.c index 53b4ac80..7b75da54 100644 --- a/counter.c +++ b/counter.c @@ -265,7 +265,7 @@ static int CheckCountStatus(void *pData, SConnection * pCon) int eCt; char pError[80], pBueffel[132]; int iErr; - float fControl, rate; + float fControl = .0, rate; MonEvent sMon; self = (pCounter) pData; @@ -409,8 +409,6 @@ int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock) return 0; } - eOld = GetStatus(); - SetStatus(eCounting); /* set Preset */ SetCounterPreset(self, fPreset); @@ -423,7 +421,6 @@ int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock) iRet = StartDevice(GetExecutor(), self->name, self->pDes, self, pCon, level, fPreset); if (!iRet) { - SetStatus(eOld); SCWrite(pCon, "Counting aborted", eError); return 0; } @@ -444,7 +441,6 @@ int DoCount(pCounter self, float fPreset, SConnection * pCon, int iBlock) SCWrite(pCon, "Counting finished", eValue); iRet = 1; } - SetStatus(eOld); return iRet; } /*-------------------------------------------------------------------------*/ @@ -835,7 +831,8 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData, {"getpar", 2, {FUPATEXT, FUPAOPT}}, {"getnmon", 0, {0, 0}}, {"state", 0, {0, 0}}, - {"error", 0, {0, 0}} + {"error", 0, {0, 0}}, + {"countstatus", 0, {0, 0}} }; char *pMode[] = { "timer", @@ -852,7 +849,7 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData, argtolower(argc, argv); argx = &argv[1]; iRet = - EvaluateFuPa((pFuncTemplate) & ActionTemplate, 25, argc - 1, argx, + EvaluateFuPa((pFuncTemplate) & ActionTemplate, 26, argc - 1, argx, &PaRes); if (iRet < 0) { snprintf(pBueffel, 255,"%s", PaRes.pError); @@ -961,6 +958,7 @@ int CountAction(SConnection * pCon, SicsInterp * pSics, void *pData, SCSendOK(pCon); return 1; case 11: /* status */ + case 25: self->pCountInt->TransferData(self, pCon); if (GetCounterMode(self) == ePreset) { lVal = GetCounterPreset(self); diff --git a/countersec.c b/countersec.c index 9cad865a..5eb78ad5 100644 --- a/countersec.c +++ b/countersec.c @@ -9,6 +9,7 @@ * * Mark Koennecke, February 2009 */ +#include #include #include #include @@ -507,6 +508,41 @@ static int InterestCmd(pSICSOBJ ccmd, SConnection * con, } /*--------------------------------------------------------------------------*/ +static int CountStatusCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + float preset, done; + int exponent; + pHdb node, data; + + node = GetHipadabaNode(ccmd->objectNode,"preset"); + assert(node != NULL); + preset = node->value.v.doubleValue; + + node = GetHipadabaNode(ccmd->objectNode,"mode"); + assert(node != NULL); + strtolower(node->value.v.text); + if(strcmp(node->value.v.text,"timer") == 0) { + data = GetHipadabaNode(ccmd->objectNode,"time"); + assert(data != NULL); + done = data->value.v.doubleValue; + } else { + data = GetHipadabaNode(ccmd->objectNode,"values"); + assert(data != NULL); + done = data->value.v.intArray[0]; + data = GetHipadabaNode(ccmd->objectNode,"exponent"); + assert(data != NULL); + exponent = data->value.v.intValue; + if(exponent != 0){ + done /= pow(10,exponent); + } + } + SCPrintf(con,eValue,"%s.CountStatus = %f %f", + ccmd->objectNode->name, preset, done); + + return 1; +} +/*--------------------------------------------------------------------------*/ pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length) { pCounter pRes = NULL; @@ -634,6 +670,7 @@ pCounter CreateSecCounter(SConnection *pCon, char *type, char *name, int length) child = AddSICSHdbPar(node,"pause", usUser, MakeSICSFunc(PauseCmd)); child = AddSICSHdbPar(node,"continue", usUser, MakeSICSFunc(ContinueCmd)); child = AddSICSHdbPar(node,"interest", usUser, MakeSICSFunc(InterestCmd)); + child = AddSICSHdbPar(node,"countstatus", usUser, MakeSICSFunc(CountStatusCmd)); return pRes; } diff --git a/devexec.c b/devexec.c index 063e5ab0..52d51632 100644 --- a/devexec.c +++ b/devexec.c @@ -182,12 +182,13 @@ pExeList CreateExeList(pTaskMan pTask) pRes->waitID = -1; pRes->runID = -1; pRes->iLock = 0; - pRes->drivePrint = 0; + pRes->drivePrint = 0; pRes->paused = 0; pRes->taskRunning = 0; pRes->pCall = CreateCallBackInterface(); pRes->lastRun = time(NULL); pRes->pDes->GetInterface = DevexecInterface; + pRes->instStatus = eEager; return pRes; } @@ -295,7 +296,6 @@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, taskID = StartDriveTask(pData, pCon, name, fNew); if(taskID > 0 && self->instStatus != eCounting){ self->instStatus = eDriving; - SetStatus(eDriving); } if(taskID > 0 && self->drivePrint == 1){ oldVal = pDrivInt->GetValue(pData, pCon); @@ -307,7 +307,6 @@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes, taskID = StartCountTask(pData,pCon,name); if(taskID > 0){ self->instStatus = eCounting; - SetStatus(eCounting); } } else { SCPrintf(pCon,eLogError, "ERROR: type unkonw, cannot start %s", name); @@ -530,7 +529,6 @@ int PauseExecution(pExeList self) if(IsCounting(self)){ TaskSignalGroup(self->pTask, IPAUSE, &interrupt, self->waitID); TaskSignalGroup(self->pTask, IPAUSE, &interrupt, self->runID); - SetStatus(ePaused); } return 1; @@ -559,7 +557,6 @@ int ContinueExecution(pExeList self) if(GetStatus() == ePaused){ TaskSignalGroup(self->pTask, CONTINUE, &interrupt, self->waitID); TaskSignalGroup(self->pTask, CONTINUE, &interrupt, self->runID); - SetStatus(eCounting); } return 1; } @@ -716,7 +713,6 @@ int Success(SConnection * pCon, SicsInterp * pSics, void *pData, pExeList self = (pExeList)pData; eOld = GetStatus(); - SetStatus(eRunning); if(argc > 1){ if(strcmp(argv[1],"RUNDRIVE") == 0){ @@ -758,7 +754,6 @@ int Success(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, "Level done", eValue); iRet = 1; } - SetStatus(eEager); return iRet; } /*-------------------------------------------------------------------------*/ @@ -894,7 +889,6 @@ int DevExecTask(void *pData) self->lTask = -1; self->iRun = 0; self->instStatus = eEager; - SetStatus(eEager); /* This is sort of unclean. Setting DEVERROR has to be done in the device task function as it is the only one that knows about this. @@ -965,3 +959,12 @@ void SetDevexecStatus(pExeList pExe, int code) pExe->iStatus = code; } } +/*------------------------------------------------------------------------*/ +int GetDevExecInstStatus(pExeList self) +{ + if(self->lTask < 0){ + return eEager; + } else { + return self->instStatus; + } +} diff --git a/devexec.h b/devexec.h index f35bfe7d..c9290e2c 100644 --- a/devexec.h +++ b/devexec.h @@ -1,5 +1,5 @@ -#line 202 "devexec.w" +#line 204 "devexec.w" /*---------------------------------------------------------------------------- @@ -57,7 +57,7 @@ int StartCounter(pExeList self, SicsInterp *pSics, SConnection *pCon, int level, char *name); -#line 249 "devexec.w" +#line 251 "devexec.w" /*------------------------------------------------------------------------*/ @@ -77,8 +77,10 @@ int DevExecTask(void *pEL); void DevExecSignal(void *pEL, int iSignal, void *pSigData); + int GetDevExecInstStatus(pExeList self); -#line 251 "devexec.w" + +#line 253 "devexec.w" /* @@ -98,7 +100,7 @@ */ /*-------------------------------------------------------------------------*/ -#line 142 "devexec.w" +#line 144 "devexec.w" int StopExe(pExeList self, char *name); int StopExeWait(pExeList self); @@ -122,7 +124,7 @@ int ContinueExecution(pExeList self); -#line 269 "devexec.w" +#line 271 "devexec.w" /*-------------------------- Commands ------------------------------------*/ int DevexecAction(SConnection *pCon, SicsInterp *pSics, void *pData, @@ -164,13 +166,13 @@ /*--------------------------- Locking ---------------------------------*/ -#line 190 "devexec.w" +#line 192 "devexec.w" void LockDeviceExecutor(pExeList self); void UnlockDeviceExecutor(pExeList self); -#line 309 "devexec.w" +#line 311 "devexec.w" /* -------------------------- Executor management -------------------------*/ diff --git a/devexec.w b/devexec.w index dafc2a21..403e60eb 100644 --- a/devexec.w +++ b/devexec.w @@ -101,6 +101,8 @@ From within the SICS main loops this special function is called: int DevExecTask(void *pEL); void DevExecSignal(void *pEL, int iSignal, void *pSigData); + int GetDevExecInstStatus(pExeList self); + @} CheckExeList then scan through its list of executing objects and request a status from each of them. The next action depend on the status returned from diff --git a/devser.c b/devser.c index 0525188d..fc1f90b2 100644 --- a/devser.c +++ b/devser.c @@ -333,7 +333,8 @@ static void DevReset(DevSer * devser) devser->current->kill(devser->current->data); } devser->killCurrent = 0; - /* free(devser->current); */ + free(devser->current); + devser->current = NULL; } } diff --git a/drive.c b/drive.c index 03a16bab..43e0d44f 100644 --- a/drive.c +++ b/drive.c @@ -302,19 +302,16 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, } /* interprete arguments as pairs name value and try to start */ - SetStatus(eDriving); for (i = 1; i < argc; i += 2) { if (argv[i + 1] == NULL) { snprintf(pBueffel, 511, "ERROR: no value found for driving %s", argv[i]); SCWrite(pCon, pBueffel, eError); - SetStatus(eOld); return 0; } iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget); if (iRet == TCL_ERROR) { SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); StopExe(GetExecutor(), "ALL"); - SetStatus(eOld); return 0; } iRet = Start2Run(pCon, pSics, argv[i], RUNDRIVE, dTarget); @@ -328,7 +325,6 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, } SCWrite(pCon, pBueffel, eError); StopExe(GetExecutor(), "ALL"); - SetStatus(eOld); return 0; } } @@ -351,17 +347,14 @@ int DriveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, sprintf(pBueffel, "Driving finished with problem"); SCWrite(pCon, pBueffel, eError); ClearExecutor(GetExecutor()); - SetStatus(eOld); return 0; } else if (iRet == DEVINT) { sprintf(pBueffel, "ERROR: Driving Interrupted!"); SCWrite(pCon, pBueffel, eError); ClearExecutor(GetExecutor()); - SetStatus(eOld); return 0; } SCWrite(pCon, "Driving finished sucessfully", eValue); - SetStatus(eOld); return 1; } @@ -399,19 +392,16 @@ int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, } /* interprete arguments as pairs name value and try to start */ - SetStatus(eDriving); for (i = 1; i < argc; i += 2) { if (argv[i + 1] == NULL) { snprintf(pBueffel,511, "ERROR: no value found for driving %s", argv[i]); SCWrite(pCon, pBueffel, eError); - SetStatus(eOld); return 0; } iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget); if (iRet == TCL_ERROR) { SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); StopExe(GetExecutor(), "ALL"); - SetStatus(eOld); return 0; } iRet = Start2Run(pCon, pSics, argv[i], RUNRUN, dTarget); @@ -420,7 +410,6 @@ int RunWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, argv[i + 1]); SCWrite(pCon, pBueffel, eError); StopExe(GetExecutor(), "ALL"); - SetStatus(eOld); return 0; } } @@ -466,14 +455,12 @@ int MoveWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, if (argv[i + 1] == NULL) { snprintf(pBueffel,511, "ERROR: no value found for driving %s", argv[i]); SCWrite(pCon, pBueffel, eError); - SetStatus(eOld); return 0; } iRet = Tcl_GetDouble(tcl_interp, argv[i + 1], &dTarget); if (iRet == TCL_ERROR) { SCWrite(pCon, Tcl_GetStringResult(tcl_interp), eError); StopExe(GetExecutor(), "ALL"); - SetStatus(eOld); return 0; } obj = FindCommandData(pSics,argv[i],NULL); diff --git a/evcontroller.c b/evcontroller.c index 33fb9abc..f1120b5c 100644 --- a/evcontroller.c +++ b/evcontroller.c @@ -80,12 +80,9 @@ static long EVIDrive(void *pData, SConnection * pCon, float fVal) assert(pCon); if (self->runScript != NULL) { - savedStatus = GetStatus(); - SetStatus(eBatch); pTcl = InterpGetTcl(pServ->pSics); snprintf(pBueffel, sizeof(pBueffel), "%s %f", self->runScript, fVal); iRet = Tcl_Eval(pTcl, pBueffel); - SetStatus(savedStatus); if (iRet != TCL_OK) { SCPrintf(pCon, eError, "ERROR: %s while processing runscript for %s", @@ -423,7 +420,6 @@ static int ErrPause(void *pData) } /* OK now, continue */ - SetStatus(eEager); self->iWarned = 0; ContinueExecution(pExe); return 1; diff --git a/exebuf.c b/exebuf.c index 0ec9d5ce..69e2fbf9 100644 --- a/exebuf.c +++ b/exebuf.c @@ -323,7 +323,6 @@ int exeBufProcess(pExeBuf self, SicsInterp * pSics, DeleteDynString(command); if (SCGetInterrupt(pCon) >= eAbortBatch) { SCWrite(pCon, "ERROR: batch processing interrupted", eError); - SetStatus(eEager); if (pCall != NULL) { InvokeCallBack(pCall, BATCHEND, self->name); } @@ -375,7 +374,6 @@ int exeBufProcessErrList(pExeBuf self, SicsInterp * pSics, DeleteDynString(command); if (SCGetInterrupt(pCon) >= eAbortBatch) { SCWrite(pCon, "ERROR: batch processing interrupted", eError); - SetStatus(eEager); return 0; } else { SCSetInterrupt(pCon, eContinue); diff --git a/exeman.c b/exeman.c index 40301635..55ae402a 100644 --- a/exeman.c +++ b/exeman.c @@ -224,7 +224,16 @@ pDynString findBatchFile(SicsInterp * pSics, char *name) } return locateBatchBuffer(self, name); } - +/*--------------------------------------------------------------------*/ +int isBatchRunning() +{ + pExeMan self = (pExeMan) FindCommandData(pServ->pSics, "exe", "ExeManager"); + if(self != NULL && self->exeStackPtr > 0){ + return 1; + } else { + return 0; + } +} /*--------------------------------------------------------------------*/ static int runBatchBuffer(pExeMan self, SConnection * pCon, SicsInterp * pSics, char *name) diff --git a/exeman.h b/exeman.h index fc110a6e..0718c67f 100644 --- a/exeman.h +++ b/exeman.h @@ -19,4 +19,6 @@ pDynString findBatchFile(SicsInterp * pSics, char *name); int exeHdbBuffer(SConnection * pCon, SicsInterp * pSics, char *name); int exeHdbNode(pHdb exeNode, SConnection * pCon); +int isBatchRunning(); + #endif diff --git a/fourmess.c b/fourmess.c index 8e2cbf6e..27393a2d 100644 --- a/fourmess.c +++ b/fourmess.c @@ -753,11 +753,11 @@ static int GenInconsumerate(pSICSOBJ self, SConnection * pCon, { double hkl[3], qvec[3]; pFourMess priv = self->pPrivate; - int i, j; + int i, j, iGen = 0, startCount; if (nPar < 3) { SCWrite(pCon, - "ERROR: need q displacement vector with three compononts", + "ERROR: need q displacement vector with three components", eError); return 0; } @@ -765,31 +765,32 @@ static int GenInconsumerate(pSICSOBJ self, SConnection * pCon, qvec[1] = par[1]->value.v.doubleValue; qvec[2] = par[2]->value.v.doubleValue; - for (i = 0; i < priv->masterCount; i++) { + startCount = priv->masterCount; + for (i = 0; i < startCount; i++) { GetRefIndex(priv->messList, i, hkl); - if(ABS(hkl[0])+ABS(hkl[1])+ABS(hkl[2]) < .3){ - /* - * Stop generation for 0,0,0, - */ - continue; - } for (j = 0; j < 3; j++) { hkl[j] += qvec[j]; } AddRefIdx(priv->messList, hkl); + iGen++; GetRefIndex(priv->messList, i, hkl); for (j = 0; j < 3; j++) { hkl[j] -= qvec[j]; } - AddRefIdx(priv->messList, hkl); + if(FindHKL(priv->messList, hkl[0], hkl[1], hkl[2]) == NULL){ + AddRefIdx(priv->messList, hkl); + iGen++; + } if(SCGetInterrupt(pCon) != eContinue){ SCWrite(pCon,"ERROR: generating incommensurate reflections aborted", eError); return 0; } + if( (i % 50) == 0 ){ + SCPrintf(pCon,eLog, "%d of %d input reflections processed", i, startCount); + } } SCPrintf(pCon, eValue, - "%d additional inconsumerate reflections generated", - priv->masterCount*2); + "%d additional inconsumerate reflections generated", iGen); return 1; } diff --git a/hipadaba.c b/hipadaba.c index 806cdf4f..1514374c 100644 --- a/hipadaba.c +++ b/hipadaba.c @@ -22,6 +22,7 @@ static char update[] = { "update" }; static char treeChange[] = { "treeChange" }; static char dataSearch[] = { "dataSearch" }; static char killNode[] = { "killNode" }; +static char propertyChange[] = { "propertyChange" }; /*------------------------------------------------------------------------*/ pHdbDataMessage GetHdbSetMessage(pHdbMessage toTest) @@ -77,6 +78,15 @@ pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest) return NULL; } +/*-------------------------------------------------------------------------*/ +pHdbPropertyChange GetPropertyChangeMessage(pHdbMessage toTest) +{ + if (toTest->type == propertyChange) { + return (pHdbPropertyChange)toTest; + } + return NULL; +} + /*================== internal functions ===================================*/ void DeleteCallbackChain(pHdb node) { @@ -1140,6 +1150,8 @@ static int calcDataLength(pHdb node, int testLength) /*============================= Property Functions ==========================*/ void SetHdbProperty(pHdb node, char *key, char *value) { + hdbPropertyChange propMes; + if (node != NULL && key != NULL && node->properties != NULL) { if (value == NULL) { StringDictDelete(node->properties, key); @@ -1148,6 +1160,10 @@ void SetHdbProperty(pHdb node, char *key, char *value) } else { StringDictAddPair(node->properties, key, value); } + propMes.type = propertyChange; + propMes.key = key; + propMes.value = value; + InvokeCallbackChain(node,(pHdbMessage)&propMes); } } diff --git a/hipadaba.h b/hipadaba.h index 09e49336..f4f86328 100644 --- a/hipadaba.h +++ b/hipadaba.h @@ -26,6 +26,8 @@ * Added support for properties, Mark Koennecke, January 2007 * * Refactored callback handling, Markus Zolliker, Mark Koennecke, March 2008 + * + * Added property chnage events. Mark Koennecke, February 2015 */ #ifndef HIPADABA #define HIPADABA @@ -71,11 +73,12 @@ typedef struct __hipadaba { struct __hdbcallback *callBackChain; char *name; hdbValue value; - int protected; + int iprotected; pStringDict properties; } Hdb, *pHdb; /*-------------- return values for callback functions -------------------------*/ -typedef enum { hdbContinue, +typedef enum { + hdbContinue, hdbAbort, hdbKill } hdbCallbackReturn; @@ -101,6 +104,12 @@ typedef struct { void *result; } hdbDataSearch, *pHdbDataSearch; /*-------------------------------------------------------------------------------*/ +typedef struct { + char *type; + char *key; + char *value; +} hdbPropertyChange, *pHdbPropertyChange; +/*-------------------------------------------------------------------------------*/ typedef hdbCallbackReturn(*hdbCallbackFunction) (pHdb currentNode, void *userData, pHdbMessage message); @@ -156,6 +165,14 @@ pHdbDataSearch GetHdbDataSearchMessage(pHdbMessage toTest); * pointer if it is. */ pHdbMessage GetHdbKillNodeMessage(pHdbMessage toTest); +/** + * Test a message if it is a property change message + * @param toTest The message to test. + * @return NULL if the message is no property chnage message or a message + * pointer if it is. + */ +pHdbPropertyChange GetPropertyChangeMessage(pHdbMessage toTest); + /*======================== Function protoypes: hdbData ========================*/ /** * make a hdbValue with the given datatype and length diff --git a/histmemsec.c b/histmemsec.c index 259466ef..248b57c2 100644 --- a/histmemsec.c +++ b/histmemsec.c @@ -44,7 +44,7 @@ static int initArray(pCounter self, int value) assert(datalength != NULL); length = dim->value.v.intArray[0]; - for(i = 1; i < rank->value.v.intValue; i++){ + for(i = 1; i < dim->value.arrayLength; i++){ length *= dim->value.v.intArray[i]; } /* printf("initArray called with length %d\n", length);*/ @@ -262,6 +262,22 @@ static int SumCmd(pSICSOBJ ccmd, SConnection * pCon, } return 1; } +/*-------------------------------------------------------------------------*/ +static int TotalCmd(pSICSOBJ ccmd, SConnection * pCon, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + pHdb dataNode = NULL; + long lSum = 0; + int i; + + dataNode = GetHipadabaNode(ccmd->objectNode,"data"); + assert(dataNode != NULL); + for(i = 0, lSum = 0; i < dataNode->value.arrayLength; i++){ + lSum += dataNode->value.v.intArray[i]; + } + SCPrintf(pCon,eValue,"%s.total = %ld", ccmd->objectNode->name, lSum); + return 1; +} /*--------------------------------------------------------------------------*/ static int InitCmd(pSICSOBJ ccmd, SConnection * con, Hdb * cmdNode, Hdb * par[], int nPar) @@ -382,6 +398,8 @@ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData, AddSICSHdbPar(child, "ystart", usSpy, MakeHdbInt(0)); AddSICSHdbPar(child, "yend", usSpy, MakeHdbInt(0)); + child = AddSICSHdbPar(node,"total", usSpy, MakeSICSFunc(TotalCmd)); + /* * test TOF option */ diff --git a/histsim.c b/histsim.c index 1813b584..3fa3e114 100644 --- a/histsim.c +++ b/histsim.c @@ -77,6 +77,7 @@ static int SimConfig(pHistDriver self, SConnection * pCon, self->pPriv = NewSIMCounter("HistoSim", fFail); } + /* configured test value */ diff --git a/hmcontrol.c b/hmcontrol.c index aed00d55..dd0e22fe 100644 --- a/hmcontrol.c +++ b/hmcontrol.c @@ -126,6 +126,9 @@ static int HMCStatus(void *pData, SConnection * pCon) assert(self); if(self->checkSlaves == 0) { + /* + check master + */ status = self->slaves[0]->CheckCountStatus(self->slaveData[0], pCon); /* Warning: this assumes that slaves 1 - MAXSLAVE are histogram memories. @@ -194,7 +197,7 @@ static int HMCBoaStatus(void *pData, SConnection * pCon) HMCHalt(self); ReleaseCountLock(self->pCount); self->checkSlaves = 0; - for(j = 0; j < 100; j++){ + for(j = 0; j < 200; j++){ SicsWait(1); status = self->slaves[i]->CheckCountStatus(self->slaveData[i], pCon); if(status == HWIdle || status == HWFault) { diff --git a/interface.c b/interface.c index c8b9bc4e..d661b2c3 100644 --- a/interface.c +++ b/interface.c @@ -176,6 +176,7 @@ int GetDrivablePosition(void *pObject, SConnection * pCon, float *fPos) } /*--------------------------------------------------------------------------*/ typedef struct { + int id; void *obj; pIDrivable pDriv; SConnection *pCon; @@ -195,6 +196,7 @@ static void KillDriveTaskData(void *data) if(taskData->pCon != NULL){ SCDeleteConnection(taskData->pCon); } + free(taskData); } /*-------------------------------------------------------------------------*/ static void DriveTaskSignal(void *data, int iSignal, void *pSigData) @@ -235,9 +237,11 @@ static int DriveTaskFunc(void *data) DevexecLog("STOP",taskData->name); if(status == HWIdle || status == OKOK){ ExeInterest(pServ->pExecutor,taskData->name, "finished"); + } else { ExeInterest(pServ->pExecutor,taskData->name, "finished with problem"); } + traceSys("drive","DriveTask %s finished with state %d", taskData->name,status); return 0; } /*--------------------------------------------------------------------------*/ @@ -250,7 +254,7 @@ long StartDriveTask(void *obj, SConnection *pCon, char *name, float fTarget) pDriv = GetDrivableInterface(obj); if(pDriv == NULL){ SCPrintf(pCon,eError,"ERROR: %s is not drivable", name); - return 1; + return -1; } if(pDriv->CheckLimits(obj,fTarget,error,sizeof(error)) != OKOK){ SCPrintf(pCon,eError,"ERROR: %s cannot reach %f, reason %s", name, @@ -269,6 +273,7 @@ long StartDriveTask(void *obj, SConnection *pCon, char *name, float fTarget) DevexecLog("START",name); InvokeNewTarget(pServ->pExecutor,name,fTarget); + taskData->id = DRIVEID; taskData->obj = obj; taskData->pDriv = pDriv; taskData->pCon = SCCopyConnection(pCon); @@ -315,6 +320,7 @@ int isRunning(pICountable self) } /*--------------------------------------------------------------------------*/ typedef struct { + int id; void *obj; pICountable pCount; SConnection *pCon; @@ -334,6 +340,7 @@ static void KillCountTaskData(void *data) if(taskData->pCon != NULL){ SCDeleteConnection(taskData->pCon); } + free(taskData); } /*-------------------------------------------------------------------------*/ static void CountTaskSignal(void *data, int iSignal, void *pSigData) @@ -366,13 +373,10 @@ static int CountTaskFunc(void *data) status = taskData->pCount->CheckCountStatus(taskData->obj,taskData->pCon); if(status == HWBusy) { - SetStatus(eCounting); return 1; } else if(status == HWNoBeam){ - SetStatus(eOutOfBeam); return 1; } else if(status == HWPause){ - SetStatus(ePaused); return 1; } @@ -388,6 +392,7 @@ static int CountTaskFunc(void *data) } else { ExeInterest(pServ->pExecutor,taskData->name, "finished with problem"); } + traceSys("count","CountTask %s finished with state %d", taskData->name,status); return 0; } /*--------------------------------------------------------------------------*/ @@ -414,6 +419,7 @@ long StartCountTask(void *obj, SConnection *pCon, char *name) ExeInterest(pServ->pExecutor,name,"started"); DevexecLog("START",name); + taskData->id = COUNTID; taskData->obj = obj; taskData->pCount = pCount; taskData->pCon = SCCopyConnection(pCon); diff --git a/linux_def b/linux_def index e312d828..fe008112 100644 --- a/linux_def +++ b/linux_def @@ -10,4 +10,5 @@ MFLAGS=-f makefile_linux$(DUMMY) HDFROOT=/usr/local -TCLINC=/usr/include/tcl \ No newline at end of file +TCLINC=/usr/include/tcl +EPICS=/usr/local/epics \ No newline at end of file diff --git a/macosx_def b/macosx_def index f7d12721..60789d3c 100644 --- a/macosx_def +++ b/macosx_def @@ -11,5 +11,6 @@ MFLAGS=-f makefile_macosx HDFROOT=/usr/pkg - +EPICS=/usr/local/epics +EPICSLIBS=-L$(EPICS)/lib/darwin-x86 -lca -lCom diff --git a/macro.c b/macro.c index 76f3d914..4e5ac5e1 100644 --- a/macro.c +++ b/macro.c @@ -474,8 +474,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, } /* handle status first */ - eOld = GetStatus(); - SetStatus(eBatch); SICSLogWrite("Evaluating in MacroFileEval", eValue); SICSLogWrite(argv[1], eValue); @@ -500,7 +498,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, Tcl_DStringAppend(&command, pBueffel, -1); pCom = Tcl_DStringValue(&command); if (Tcl_CommandComplete(pCom)) { - SetStatus(eEager); FirstWord(pCom, pBueffel); if (FindCommand(pInter, pBueffel) != NULL) { snprintf(pBueffel,sizeof(pBueffel)-1, "%s:%d>> %s", pFile, iLine, pCom); @@ -512,7 +509,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, iLine++; } iRet = Tcl_Eval(pTcl, pCom); - SetStatus(eBatch); if (iRet != TCL_OK) { /* write TCL error and check for total interrupt */ if (Tcl_GetVar(pTcl, SICSERROR, TCL_GLOBAL_ONLY) == NULL) { /* Tcl error */ @@ -537,7 +533,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, fclose(fp); Tcl_DStringFree(&command); SCWrite(pCon, "ERROR: batch processing interrupted", eError); - SetStatus(eEager); return 0; } else { SCSetInterrupt(pCon, eContinue); @@ -555,7 +550,6 @@ int MacroFileEval(SConnection * pCon, SicsInterp * pInter, void *pData, /* clean up */ fclose(fp); Tcl_DStringFree(&command); - SetStatus(eOld); SCSendOK(pCon); return 1; } diff --git a/make_gen b/make_gen index 8f0e4581..55ee30b8 100644 --- a/make_gen +++ b/make_gen @@ -46,7 +46,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ rwpuffer.o asynnet.o background.o countersec.o hdbtable.o velosec.o \ histmemsec.o sansbc.o sicsutil.o strlutil.o genbinprot.o trace.o\ singlebinb.o taskobj.o sctcomtask.o tasmono.o multicountersec.o \ - messagepipe.o sicsget.o + messagepipe.o sicsget.o remoteobject.o MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o @@ -63,7 +63,7 @@ OBJ = $(SOBJ) $(MOTOROBJ) $(COUNTEROBJ) $(VELOOBJ) $(DIFIL) $(EXTRA) $(EPICSOBJ) #--- This .SECONDARY. target is necessary to preserve generated .c files for debugging .SECONDARY.: sicspoll.c polldriv.c -all: libmat libhlib libtecsl libpsi SICServer +all: libmat libhlib libpsi SICServer # use this target when some of the libraries SUBLIBS might be incomplete full: purge all @@ -81,12 +81,7 @@ $(SICSROOT)/sicspsi/hardsup/libhlib.a: libhlib libhlib: cd $(SICSROOT)/sicspsi/hardsup; make $(MFLAGS) libhlib.a -$(SICSROOT)/sicspsi/tecs/libtecsl.a: libtecsl - -libtecsl: - cd $(SICSROOT)/sicspsi/tecs; make $(MFLAGS) libtecsl.a - -$SICSROOT)/sicspsi/libpsi.a: libpsi +$(SICSROOT)/sicspsi/libpsi.a: libpsi libpsi: cd $(SICSROOT)/sicspsi; make $(MFLAGS) libpsi.a @@ -98,7 +93,6 @@ clean: rm -f *.o *.d SICServer cd $(SICSROOT)/sicspsi/hardsup; make $(MFLAGS) clean cd matrix; make $(MFLAGS) clean - cd $(SICSROOT)/sicspsi/tecs; make $(MFLAGS) clean cd $(SICSROOT)/sicspsi; make $(MFLAGS) clean Dbg.o: Dbg.c diff --git a/makefile b/makefile index adc02ada..34301d05 100644 --- a/makefile +++ b/makefile @@ -1,22 +1,4 @@ -# M. Zolliker 03.2005 +# when SICS_MAKE_VERSION is defined: use this makefile version +# if not: show usage (see makefile_) -%: usage - @echo - -%.o: usage - @echo - -default: usage - -usage: - @ echo "" - @ echo "Usage:" - @ echo "" - @ echo " make -f makefile_xxx [target]" - @ echo "" - @ echo ' where makefile_xxx is one of' - @ echo "" - @ ls -1 makefile_* | pr -t -o 4 - - -# DO NOT DELETE +include makefile_$(SICS_MAKE_VERSION) diff --git a/makefile_ b/makefile_ new file mode 100644 index 00000000..2c993731 --- /dev/null +++ b/makefile_ @@ -0,0 +1,25 @@ +# M. Zolliker 03.2005 +# this file shows the correct usage of make in the sics source directory + +%: usage + @echo + +%.o: usage + @echo + +default: usage + +usage: + @ echo "" + @ echo "Usage:" + @ echo "" + @ echo " make -f makefile_xxx [target]" + @ echo "" + @ echo ' where makefile_xxx is one of' + @ echo "" + @ ls -1 makefile_?* | pr -t -o 4 + @ echo "" + @ echo " or use make without args:" + @ echo "" + @ echo " setenv SICS_MAKE_VERSION slinux" + @ echo " make [target]" diff --git a/makefile_alpha b/makefile_alpha index d85e5e0a..832ab6cb 100644 --- a/makefile_alpha +++ b/makefile_alpha @@ -19,8 +19,7 @@ CFLAGS = -I$(HDFROOT)/include $(DFORTIFY) -DHDF4 -DHDF5 \ -g -std1 -warnprotos BINTARGET = bin EXTRA= -SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \ - psi/tecs/libtecsl.a +SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a LIBS = -L$(HDFROOT)/lib $(SUBLIBS) \ -ltcl -lfor $(HDFROOT)/lib/libhdf5.a \ $(HDFROOT)/lib/libmfhdf.a $(HDFROOT)/lib/libdf.a \ diff --git a/makefile_linux b/makefile_linux index ace6d454..92978e55 100644 --- a/makefile_linux +++ b/makefile_linux @@ -22,8 +22,7 @@ CFLAGS = -I$(HDFROOT)/include -I/usr/include/hdf -I$(TCLINC) -DHDF4 -DHDF5 \ BINTARGET = bin EXTRA=nintf.o -SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a \ - psi/tecs/libtecsl.a +SUBLIBS = psi/libpsi.a psi/hardsup/libhlib.a matrix/libmatrix.a LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB)\ -ltcl -lNeXus -lhdf5 -lmfhdf -ldf \ -lmxml -lghttp -ljpeg -ljson -ldl -lz -lm -lc diff --git a/makefile_macosx b/makefile_macosx index 91e265f9..e2d81ad4 100644 --- a/makefile_macosx +++ b/makefile_macosx @@ -26,8 +26,8 @@ BINTARGET = bin EXTRA=nintf.o SUBLIBS = $(SICSROOT)/sicspsi/libpsi.a $(SICSROOT)/sicspsi/hardsup/libhlib.a matrix/libmatrix.a \ $(SICSROOT)/sicspsi/tecs/libtecsl.a -LIBS = -L$(HDFROOT)/lib -L/usr/local/lib $(SUBLIBS) $(NILIB)\ - -ltcl -lhdf5 -lNeXus -ljson -lghttp -ldl -lz -lmxml -lm -lc +LIBS = -L$(HDFROOT)/lib -L/usr/local/lib $(SUBLIBS) $(NILIB) -L$(EPICS)/lib/darwin-x86 \ + -ltcl -lhdf5 -lNeXus -ljson -lghttp $(EPICSLIBS) -ldl -lz -lmxml -lm -lc include make_gen diff --git a/makefile_slinux b/makefile_slinux index 09e3af71..6be471f6 100644 --- a/makefile_slinux +++ b/makefile_slinux @@ -12,11 +12,14 @@ NI= -DHAVENI NIOBJ= nigpib.o NILIB=$(SINQDIR)/sl6/lib/cib.o -EPICSLIBS=-L$(SINQDIR)/sl6/lib/linux-x86 -lezca -lca -lCom +EPICSDIR=$(SINQDIR)/sl6/lib/linux-x86 +EPICSLIBS=$(EPICSDIR)/libezca.a $(EPICSDIR)/libca.a $(EPICSDIR)/libCom.a -lreadline -lhistory +#EPICSLIBS=-L$(EPICSDIR) -lezca -lca -lCom include sllinux_def CC = gcc + CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \ -I$(SICSROOT)/sicspsi/hardsup -I$(SICSROOT) -I. -MMD \ -Werror -DCYGNUS -DNONINTF $(DBG) $(DFORTIFY) \ @@ -25,7 +28,7 @@ CFLAGS = -I$(HDFROOT)/include -DNXXML -DHDF5 $(NI) \ BINTARGET = bin EXTRA=nintf.o SUBLIBS = $(SICSROOT)/sicspsi/libpsi.a $(SICSROOT)/sicspsi/hardsup/libhlib.a \ - matrix/libmatrix.a $(SICSROOT)/sicspsi/tecs/libtecsl.a + matrix/libmatrix.a LIBS = -L$(HDFROOT)/lib $(SUBLIBS) $(NILIB) $(EPICSLIBS) \ -ltcl -lNeXus $(HDFROOT)/lib/libhdf5.a \ $(HDFROOT)/lib/libsz.a \ diff --git a/matrix/makefile b/matrix/makefile index 03dfa3af..2902297e 100644 --- a/matrix/makefile +++ b/matrix/makefile @@ -1,21 +1,34 @@ -# M. Zolliker 03.2005 +#--------------------------------------------------------------------------- +# Makefile for the Matrix library +# +# Mark Koennecke, November 1996 +#-------------------------------------------------------------------------- +OBJ= matadd.o matcreat.o matdet.o matdump.o matdurbn.o materr.o \ + matinv.o matmul.o matsolve.o matsub.o matsubx.o mattoepz.o \ + mattran.o -%: usage - @echo +#---------- for Redhat linux +#CC= gcc +#CFLAGS= -I/usr/local/include -I. -I../ -DLINUX -g -c -%.o: usage - @echo +#------------ for DigitalUnix +CC=cc +CFLAGS= -I/data/koenneck/include -I. -I../ -std1 -g -c +#------------ for DigitalUnix with Fortify +#CFLAGS= -I/data/koenneck/include -DFORTIFY -I. -I../ -std1 -g -c -default: usage +#------------ for CYGNUS toolchain on Win32 +#CC=gcc +#CFLAGS= -I. -I../ -DCYGNUS -g -c -usage: - @ echo "" - @ echo "Usage:" - @ echo "" - @ echo " make -f makefile_xxx [target]" - @ echo "" - @ echo ' where makefile_xxx is one of' - @ echo "" - @ ls -1 makefile_* | pr -t -o 4 +.c.o: + $(CC) $(CFLAGS) $*.c +matrix: $(OBJ) + - rm -f libmatrix.a + ar cr libmatrix.a $(OBJ) + ranlib libmatrix.a +clean: + rm -f *.o + rm -f *.a diff --git a/motor.c b/motor.c index a0be2715..6347bdf6 100644 --- a/motor.c +++ b/motor.c @@ -1066,19 +1066,6 @@ int MotorCreate(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, pBueffel, eLogError); return 0; } - /* - } else if (strcmp(argv[2], "epics") == 0) { - if(argc > 3){ - pDriver = epicsMakeMotorDriver(argv[3]); - if (!pDriver) { - return 0; - } - - } else { - SCWrite(pCon,"ERROR: missing basename argument to create EPICS motor",eError); - return 0; - } - */ } else { site = getSite(); if (site != NULL) { diff --git a/motorsec.c b/motorsec.c index 3f6710b5..6f0ed33a 100644 --- a/motorsec.c +++ b/motorsec.c @@ -47,6 +47,7 @@ #define ABS(x) (x < 0 ? -(x) : (x)) + /*-------------------------------------------------------------------------*/ static void SecMotorSetError(pMotor self, char *text) { @@ -268,9 +269,6 @@ static int checkPosition(pMotor self, SConnection * pCon) node = GetHipadabaNode(self->pDescriptor->parNode, "hardposition"); assert(node != NULL); SetHipadabaPar(node, MakeHdbFloat(target), pCon); - node = GetHipadabaNode(self->pDescriptor->parNode, "targetposition"); - assert(node != NULL); - SetHipadabaPar(node, MakeHdbFloat(target), pCon); return HWBusy; } return HWIdle; @@ -377,7 +375,7 @@ static float SecMotorGetValue(void *pData, SConnection * pCon) assert(pData); status = GetHdbProperty(self->pDescriptor->parNode,"geterror", error,sizeof(error)); if(status == 1 && strcmp(error,"none") != 0) { - SCPrintf(pCon,eValue,"ERROR: Failed to read %s with %s", self->name, error); + SCPrintf(pCon,eError,"ERROR: Failed to read %s with %s", self->name, error); return -9999999.99; } status = GetHipadabaPar(self->pDescriptor->parNode, &v, pCon); @@ -467,7 +465,7 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData, pHdb child = NULL; pMotor self = NULL; float fHard, fVal, sign, zero; - char pBueffel[512], pError[132]; + char pBueffel[512], pError[132], *pPtr = NULL; int status; self = (pMotor) userData; @@ -511,6 +509,7 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData, self->name); SCWrite(pCon, pBueffel, eWarning); self->errorCount = 0; + self->pDrivInt->iErrorCount = 0; } /* @@ -527,6 +526,8 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData, ServerWriteGlobal(pBueffel, eError); SCSetInterrupt(pCon, eAbortBatch); self->pDrivInt->iErrorCount = 0; + child = GetHipadabaNode(self->pDescriptor->parNode, "status"); + UpdateHipadabaPar(child, MakeHdbText("run"), pCon); return hdbAbort; } @@ -548,6 +549,12 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData, if (mm != NULL) { pCon = (SConnection *) mm->callData; SecMotorGetPar(self, "hardposition", &fVal); + child = GetHipadabaNode(self->pDescriptor->parNode, "hardposition"); + if((pPtr = GetHdbProp(child,"geterror")) != NULL){ + SetHdbProperty(node,"geterror",pPtr); + } else { + SetHdbProperty(node,"geterror",NULL); + } fVal = hardToSoftPosition(self, fVal); node->value.v.doubleValue = fVal; mm->v->v.doubleValue = fVal; @@ -562,6 +569,7 @@ static hdbCallbackReturn HardUpdateCallback(pHdb node, void *userData, pHdbMessage message) { pHdbDataMessage mm = NULL; + pHdbPropertyChange pm = NULL; pMotor self = (pMotor) userData; float fVal; hdbValue v; @@ -576,6 +584,18 @@ static hdbCallbackReturn HardUpdateCallback(pHdb node, void *userData, UpdateHipadabaPar(self->pDescriptor->parNode, v, mm->callData); return hdbContinue; } + + /* + forward geterror + */ + pm = GetPropertyChangeMessage(message); + if(pm != NULL){ + if(strstr(pm->key,"geterror") != NULL){ + SetHdbProperty(self->pDescriptor->parNode,pm->key, pm->value); + } + } + + return hdbContinue; } @@ -655,6 +675,80 @@ static hdbCallbackReturn SecMotorZeroCallback(pHdb node, void *userData, return hdbContinue; } +/*--------------------------------------------------------------------------*/ +typedef struct { + char *pName; + SConnection *pCon; + float lastValue; +} MotInfo, *pMotInfo; +/*--------------------------------------------------------------------------*/ +static void KillInfo(void *pData) +{ + pMotInfo self = NULL; + + assert(pData); + self = (pMotInfo) pData; + if (self->pName) { + free(self->pName); + } + if (self->pCon != NULL) { + SCDeleteConnection(self->pCon); + } + free(self); +} +/*-------------------------------------------------------------------------*/ +static hdbCallbackReturn InterestCallback(pHdb node, void *userData, + pHdbMessage message) +{ + pHdbDataMessage mm = NULL; + pMotor self = (pMotor) userData; + float fVal; + hdbValue v; + pMotInfo priv = (pMotInfo)userData; + + + assert(self != NULL); + + mm = GetHdbUpdateMessage(message); + if (mm != NULL) { + v = *mm->v; + if(!SCisConnected(priv->pCon)){ + return hdbKill; + } + if(ABS(v.v.doubleValue - priv->lastValue) > .1) { + SCPrintf(priv->pCon,eValue,"%s.position = %f", + priv->pName, v.v.doubleValue); + priv->lastValue = v.v.doubleValue; + } + return hdbContinue; + } + return hdbContinue; +} +/*---------------------------------------------------------------------------*/ +static int InterestCmd(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + pMotInfo priv = NULL; + + priv = malloc(sizeof(MotInfo)); + if(priv == NULL){ + SCWrite(con,"ERROR: out of memory registering interest",eError); + return 0; + } + + if(nPar >= 1 && (strcmp(par[0]->value.v.text,"UNKNOWN") != 0)) { + priv->pName = strdup(par[0]->value.v.text); + } else { + priv->pName = strdup(ccmd->objectNode->name); + } + priv->lastValue = .0; + priv->pCon = SCCopyConnection(con); + AppendHipadabaCallback(ccmd->objectNode, + MakeHipadabaCallback(InterestCallback,priv,KillInfo)); + SCSendOK(con); + return 1; + +} /*---------------------------------------------------------------------------*/ pMotor SecMotorInit(char *name) { @@ -793,6 +887,10 @@ pMotor SecMotorInit(char *name) child = MakeHipadabaNode("error", HIPTEXT, 1); AddHipadabaChild(node, child, NULL); + child = AddSICSHdbPar(node,"interest", usUser, MakeSICSFunc(InterestCmd)); + AddSICSHdbPar(child, "name", usUser, MakeHdbText("UNKNOWN")); + + pM->endScriptID = 0; /* initialise Drivable interface */ diff --git a/multicountersec.c b/multicountersec.c index 659b6486..c94b2c0f 100644 --- a/multicountersec.c +++ b/multicountersec.c @@ -15,7 +15,14 @@ #include #include #include +#include #include "sicshipadaba.h" +/*---------------------------------------------------------------------------*/ +typedef struct { + float fPreset; + float fCurrent; + char *pName; +} MonEvent, *pMonEvent; /*-------------------------------------------------------------------------*/ static void SecCounterSetError(pCounter self, char *text) { @@ -134,6 +141,7 @@ static void startMultiCounting(pHdb self, SConnection *pCon) assert(sID != NULL); assert(mID != NULL); + strtolower(mode->value.v.text); if(strcmp(mode->value.v.text,"timer") == 0) { eMode = eTimer; } else { @@ -231,129 +239,177 @@ static hdbCallbackReturn MultiSecControllCallback(pHdb node, return hdbContinue; } -/*-------------------------------------------------------------------------------------*/ -static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) +/*-------------------------------------------------------------------------2-*/ +static int MultiSecTransfer(void *pData, SConnection * pCon) { - pHdb mID, master, myStatus, control, ccd, stopTime; - hdbValue v; - long mlID; - void *data; - pICountable pCount; - float controlVal; + int i, retVal = OKOK, tclStatus; + char pBueffel[132]; + pCounter pCount = NULL; + pHdb transfer; + SConnection *myCon; - mID = GetHipadabaNode(self->objectNode,"masterID"); - master = GetHipadabaNode(self->objectNode,"master"); - myStatus = GetHipadabaNode(self->objectNode,"status"); - control = GetHipadabaNode(self->objectNode,"control"); - ccd = GetHipadabaNode(self->objectNode,"ccd"); - stopTime = GetHipadabaNode(self->objectNode,"stopTime"); - assert(mID != NULL); - assert(master != NULL); - assert(myStatus != NULL); - assert(control != NULL); - assert(ccd != NULL); - assert(stopTime != NULL); - + pCount = (pCounter) pData; - mlID = mID->value.v.intValue; - if(mlID == 0) { - return 0; - } - - data = FindCommandData(pServ->pSics,master->value.v.text,NULL); - assert(data != NULL); - pCount = GetCountableInterface(data); - assert(pCount != NULL); - - if(isTaskIDRunning(pServ->pTasker,mlID)) { - *status = pCount->CheckCountStatus(data,pCon); - controlVal = GetControlValue((pCounter)data); - UpdateHipadabaPar(control,MakeHdbFloat(controlVal),pCon); - SecCounterSetError(self,"None"); - switch(*status){ - case HWFault: - UpdateHipadabaPar(myStatus,MakeHdbText("error"),pCon); - UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); - SecCounterSetError(self,"Master counter errror"); - *status = HWBusy; - break; - case HWPause: - UpdateHipadabaPar(myStatus,MakeHdbText("paused"),pCon); - break; - case HWNoBeam: - UpdateHipadabaPar(myStatus,MakeHdbText("nobeam"),pCon); - break; - default: - *status = HWBusy; - UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); - break; - } - } else { - /* - we recently stopped. Mark it so and stop slaves. - */ - mID->value.v.intValue = 0; - *status = HWBusy; - UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); - UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); - if(ccd->value.v.intValue != 1) { - doCountCommand(self->objectNode,pCon,1011); + transfer = GetHipadabaNode(pCount->objectNode,"transfer"); + if(transfer != NULL){ + myCon = SCCopyConnection(pCon); + SCsetMacro(myCon,1); + MacroPush(myCon); + tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), transfer->value.v.text); + if (tclStatus != TCL_OK) { + snprintf(pBueffel, 131, "ERROR: TransferScript returned: %s", + Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); + SCWrite(pCon, pBueffel, eError); + MacroPop(); + SCDeleteConnection(myCon); + return HWFault; } + MacroPop(); + SCDeleteConnection(myCon); } - return 1; + return retVal; } /*-------------------------------------------------------------------------------------*/ -static int areSlavesRunning(pCounter self, SConnection *pCon, int *status) -{ - pHdb slaveID, myStatus, stopTime, ccd; - int i; + static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) + { + pHdb mID, master, myStatus, control, ccd, stopTime, timeNode; + hdbValue v; + long mlID; + void *data; + pICountable pCount; + float controlVal, tVal; + MonEvent sMon; - slaveID = GetHipadabaNode(self->objectNode,"slaveID"); - myStatus = GetHipadabaNode(self->objectNode,"status"); - stopTime = GetHipadabaNode(self->objectNode,"stopTime"); - ccd = GetHipadabaNode(self->objectNode,"ccd"); - assert(slaveID != NULL); - assert(myStatus != NULL); - assert(stopTime != NULL); - assert(ccd != NULL); + mID = GetHipadabaNode(self->objectNode,"masterID"); + master = GetHipadabaNode(self->objectNode,"master"); + myStatus = GetHipadabaNode(self->objectNode,"status"); + control = GetHipadabaNode(self->objectNode,"control"); + ccd = GetHipadabaNode(self->objectNode,"ccd"); + stopTime = GetHipadabaNode(self->objectNode,"stopTime"); + timeNode = GetHipadabaNode(self->objectNode,"time"); + assert(mID != NULL); + assert(master != NULL); + assert(myStatus != NULL); + assert(control != NULL); + assert(ccd != NULL); + assert(stopTime != NULL); + assert(timeNode != NULL); + - if(isTaskGroupRunning(pServ->pTasker,slaveID->value.v.intValue)){ - if(ccd->value.v.intValue == 1 && time(NULL) > stopTime->value.v.intValue + 100) { - SCWrite(pCon,"WARNING: CCD overrun, restarting counting...", eLogError); - self->pCountInt->Halt(self); - ReleaseCountLock(self->pCountInt); - for(i = 0; i < 100; i++){ - SicsWait(1); - if(!isTaskGroupRunning(pServ->pTasker,slaveID->value.v.intValue)){ - self->pCountInt->StartCount(self,pCon); - UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); - UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); - *status = HWBusy; - return 1; - } + mlID = mID->value.v.intValue; + if(mlID == 0) { + return 0; } - SCWrite(pCon,"ERROR: failed to stop overrun CCD",eLogError); - *status = HWFault; - return 0; - } else { + + data = FindCommandData(pServ->pSics,master->value.v.text,NULL); + assert(data != NULL); + pCount = GetCountableInterface(data); + assert(pCount != NULL); + + if(isTaskIDRunning(pServ->pTasker,mlID)) { + *status = pCount->CheckCountStatus(data,pCon); + controlVal = GetControlValue((pCounter)data); + UpdateHipadabaPar(control,MakeHdbFloat(controlVal),pCon); + tVal = GetCountTime((pCounter)data,pCon); + UpdateHipadabaPar(timeNode,MakeHdbFloat(tVal),pCon); + SecCounterSetError(self,"None"); + switch(*status){ + case HWFault: + UpdateHipadabaPar(myStatus,MakeHdbText("error"),pCon); + UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); + SecCounterSetError(self,"Master counter errror"); + *status = HWBusy; + break; + case HWPause: + UpdateHipadabaPar(myStatus,MakeHdbText("paused"),pCon); + *status = HWPause; + break; + case HWNoBeam: + UpdateHipadabaPar(myStatus,MakeHdbText("nobeam"),pCon); + *status = HWNoBeam; + break; + default: + *status = HWBusy; + UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); + if (self->iCallbackCounter > 20) { + MultiSecTransfer(self,pCon); + sMon.fCurrent = controlVal; + sMon.fPreset = GetCounterPreset(self); + sMon.pName = self->name; + InvokeCallBack(self->pCall, MONITOR, &sMon); + self->iCallbackCounter = 0; + } else { + self->iCallbackCounter++; + } + break; + } + } else { + /* + we recently stopped. Mark it so and stop slaves. + */ + mID->value.v.intValue = 0; + *status = HWBusy; + UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); + UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); + tVal = GetCountTime((pCounter)data,pCon); + UpdateHipadabaPar(timeNode,MakeHdbFloat(tVal),pCon); + if(ccd->value.v.intValue != 1) { + doCountCommand(self->objectNode,pCon,1011); + } + } + return 1; + } + /*-------------------------------------------------------------------------------------*/ + static int areSlavesRunning(pCounter self, SConnection *pCon, int *status) + { + pHdb slaveID, myStatus, stopTime, ccd; + int i; + + slaveID = GetHipadabaNode(self->objectNode,"slaveID"); + myStatus = GetHipadabaNode(self->objectNode,"status"); + stopTime = GetHipadabaNode(self->objectNode,"stopTime"); + ccd = GetHipadabaNode(self->objectNode,"ccd"); + assert(slaveID != NULL); + assert(myStatus != NULL); + assert(stopTime != NULL); + assert(ccd != NULL); + + if(isTaskGroupRunning(pServ->pTasker,slaveID->value.v.intValue)){ + if(ccd->value.v.intValue == 1 && time(NULL) > stopTime->value.v.intValue + 100) { + SCWrite(pCon,"WARNING: CCD overrun, restarting counting...", eLogError); + self->pCountInt->Halt(self); + ReleaseCountLock(self->pCountInt); + for(i = 0; i < 100; i++){ + SicsWait(1); + if(!isTaskGroupRunning(pServ->pTasker,slaveID->value.v.intValue)){ + self->pCountInt->StartCount(self,pCon); + UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); + UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); + *status = HWBusy; + return 1; + } + } + SCWrite(pCon,"ERROR: failed to stop overrun CCD",eLogError); + *status = HWFault; + } else { *status = HWBusy; UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); return 1; - } - } else { + } + } else { *status = HWIdle; - UpdateHipadabaPar(myStatus,MakeHdbText("idle"),pCon); - return 0; - } - return 1; -} + UpdateHipadabaPar(myStatus,MakeHdbText("idle"),pCon); + return 0; + } + return 1; + } /*------------------------------------------------------------------------------------*/ static void multiEndCounting(pCounter self, SConnection *pCon) { InvokeCallBack(self->pCall, COUNTEND, NULL); ReleaseCountLock(self->pCountInt); - + MultiSecTransfer(self,pCon); } /*-------------------------------------------------------------------------------------*/ @@ -375,35 +431,9 @@ static int MultiSecStatus(void *pData, SConnection * pCon) } multiEndCounting(self,pCon); - + return HWIdle; } -/*--------------------------------------------------------------------------*/ -static int MultiSecTransfer(void *pData, SConnection * pCon) -{ - int i, retVal = OKOK, tclStatus; - char pBueffel[132]; - pCounter pCount = NULL; - pHdb transfer; - - pCount = (pCounter) pData; - - transfer = GetHipadabaNode(pCount->objectNode,"transfer"); - if(transfer != NULL){ - MacroPush(pCon); - tclStatus = Tcl_Eval(InterpGetTcl(pServ->pSics), transfer->value.v.text); - if (tclStatus != TCL_OK) { - snprintf(pBueffel, 131, "ERROR: TransferScript returned: %s", - Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); - SCWrite(pCon, pBueffel, eError); - MacroPop(); - return HWFault; - } - MacroPop(); - } - return retVal; -} - /*--------------------------------------------------------------------------- Forward unknown commands to the master counter -----------------------------------------------------------------------------*/ diff --git a/network.c b/network.c index a9801b19..f6b7d709 100644 --- a/network.c +++ b/network.c @@ -67,7 +67,7 @@ struct timeval lastclose = { -1, 0 }; /*----------------------------------------------------------------------- Redefine this function if another means of error reporting is necessary. */ -static void NetError(char *pText) +static void NetError(const char pText[]) { /* SICSLogWrite(pText,eError); @@ -287,8 +287,9 @@ mkChannel *NETConnectWithFlags(char *name, int port, int flags) iRet = connect(pRes->sockid, (struct sockaddr *) &(pRes->adresse), sizeof(struct sockaddr_in)); - if (iRet < 0) { + if (iRet < 0 && errno ) { if (errno != EINPROGRESS) { + close(pRes->sockid); free(pRes); return NULL; } @@ -607,7 +608,7 @@ int NETReadTillTerm(mkChannel * self, long timeout, gettimeofday(&start, NULL); if (pTerm == NULL) - pTerm = ""; + pTerm = strdup(""); length = strlen(pTerm); memset(pBuffer, 0, iBufLen); @@ -842,8 +843,9 @@ mkChannel *UDPOpen(int iPort) i = 1; setsockopt(pRes->sockid, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(int)); + /* assert(pRes->sockid < (sizeof(long) * 8)); - /* if this fails the masks for select will be to + if this fails the masks for select will be to short. */ diff --git a/nserver.c b/nserver.c index 6356a6e8..5f5fb02a 100644 --- a/nserver.c +++ b/nserver.c @@ -221,7 +221,6 @@ int InitServer(char *file, pServer * pServ) printf("Cannot find InterruptPort number in options file %s\n", "This value is required!"); DeleteInterp(self->pSics); - IFDeleteOptions(pSICSOptions); return 0; } iRet = sscanf(pText, "%d", &iPort); @@ -234,6 +233,8 @@ int InitServer(char *file, pServer * pServ) } /* install a secret fully priviledged entry point for ME */ AddUser("Achterbahn", "Kiel", usInternal); + /* install a secret entry point for remote objects */ + AddUser("RemoteMaster","3ed4c656a15f0aa45e02fd5ec429225bb93b762e7eb06cc81a0b4f6c35c76184",usInternal); /* install environment monitor */ self->pMonitor = GetEnvMon(self->pSics); @@ -263,6 +264,9 @@ int InitServer(char *file, pServer * pServ) INIT(StatusFileInit); + /* install status task */ + InitStatus(); + /* exit handlers need to be installed here */ atexit(StopExit); (void)Fortify_CheckAllMemory(); @@ -455,14 +459,10 @@ int UserWait(SConnection * pCon, SicsInterp * pSics, void *pData, return 1; } - eOld = GetStatus(); - SetStatus(eUserWait); sWait.dFinish = DoubleTime() + (double)fVal; sWait.iEnd = 0; lID = TaskRegisterN(pTask,"wait", WaitTask, WaitSignal, NULL, &sWait, 1); - TaskWait(pTask, lID); - SetStatus(eOld); - if (SCGetInterrupt(pCon) != eContinue) { + TaskWait(pTask, lID); if (SCGetInterrupt(pCon) != eContinue) { return 0; } else { return 1; diff --git a/nxscript.c b/nxscript.c index fb93a260..ef31f14f 100644 --- a/nxscript.c +++ b/nxscript.c @@ -235,6 +235,7 @@ static int handleFileOperations(SConnection * pCon, pNXScript self, SCWrite(pCon, buffer, eError); return -1; } + traceIO("datafile", "Opening %s", argv[2]); SCSendOK(pCon); return 1; } @@ -1491,6 +1492,38 @@ static int SPutAddType(void *message, void *userData) } return MPCONTINUE; } +/*----------------------------------------------------------------------- +Writing should not fail due to some error in padding. Thus this routine +protects against errors but does not fail + ------------------------------------------------------------------------*/ +static int SPutPadding(void *message, void *userData) +{ + pPutMessage self = (pPutMessage)message; + char *pPtr = NULL, *pEnd = NULL; + unsigned int len = 0, i; + + if(self->v.dataType == HIPTEXT && strstr(self->v.v.text,"@len") != NULL){ + pPtr = strchr(self->v.v.text,'='); + pPtr++; + pEnd = strchr(pPtr,'@'); + if(pPtr != NULL && pEnd != NULL){ + *pEnd = '\0'; + len = atoi(pPtr); + } + pPtr = malloc((len+7)*sizeof(char)); + if(pPtr != NULL){ + memset(pPtr,0,len*sizeof(char)); + strncpy(pPtr,pEnd+1,len); + for(i = strlen(pPtr); i < len-2; i++){ + pPtr[i] = ' '; + } + pPtr[len-1] = '!'; + free(self->v.v.text); + self->v.v.text = pPtr; + } + } + return MPCONTINUE; +} /*------------------------------------------------------------------------*/ static int SPutDim(void *message, void *userData) { @@ -1518,7 +1551,11 @@ static int SPutDim(void *message, void *userData) self->dim[0] = self->v.arrayLength; break; case HIPTEXT: - self->dim[0] = strlen(self->v.v.text)+1; + if(self->v.v.text != NULL){ + self->dim[0] = strlen(self->v.v.text)+1; + } else { + self->dim[0] = 1; + } break; default: snprintf(self->error, sizeof(self->error),"invalid data type %d", @@ -1604,6 +1641,7 @@ static void configurePutPipe() AppendMPFilter(putPipe,SGetData, NULL,NULL); AppendMPFilter(putPipe,GetDefString, NULL,NULL); AppendMPFilter(putPipe,SPutAddType, NULL,NULL); + AppendMPFilter(putPipe,SPutPadding, NULL,NULL); AppendMPFilter(putPipe,SPutDim, NULL,NULL); AppendMPFilter(putPipe,SPutWrite, NULL,NULL); } @@ -2123,3 +2161,20 @@ int MakeNXScript(SConnection * pCon, SicsInterp * pSics, void *pData, } return 1; } +static pNXScript sysScript= NULL; +/*-----------------------------------------------------------------------------------*/ +int isNXScriptWriting(void) +{ + + if(sysScript == NULL){ + sysScript = FindCommandData(pServ->pSics,"nxscript","NXScript"); + } + + + if(sysScript != NULL && sysScript->fileHandle != NULL){ + return 1; + } else { + return 0; + } + +} diff --git a/nxscript.h b/nxscript.h index 08b8290a..28f43cef 100644 --- a/nxscript.h +++ b/nxscript.h @@ -21,6 +21,7 @@ int NXScriptAction(SConnection * pCon, SicsInterp * pSics, void *pData, char *makeFilename(SicsInterp * pSics, SConnection * pCon); void changeExtension(char *filename, char *newExtension); +int isNXScriptWriting(void); /*============== a personal data structure ============================*/ typedef struct { pObjectDescriptor pDes; diff --git a/ofac.c b/ofac.c index 095482f9..88867250 100644 --- a/ofac.c +++ b/ofac.c @@ -48,6 +48,7 @@ static void InitGeneral(void) INIT(AddSyncedProt); INIT(MakeTrace); INIT(InitTaskOBJ); + INIT(RemoteObjectInit); INIT(SiteInit); /* site specific initializations */ } diff --git a/outcode.c b/outcode.c index eb38384f..7b7f8f77 100644 --- a/outcode.c +++ b/outcode.c @@ -26,5 +26,5 @@ static char *pCode[] = { "logerror", NULL }; -static int iNoCodes = 13; +static int iNoCodes = 15; #endif diff --git a/protocol.c b/protocol.c index a6226c17..73ddbc71 100644 --- a/protocol.c +++ b/protocol.c @@ -290,7 +290,7 @@ static int ProtocolSet(SConnection * pCon, Protocol * pPro, char *pProName) SCSetWriteFunc(pCon, SCWriteJSON_String); SCSetWriteFunc(pMaster, SCWriteJSON_String); break; - case 5: + case 5: /* ACT */ SCSetWriteFunc(pMaster, SCACTWrite); SCSetWriteFunc(pCon, SCACTWrite); break; diff --git a/reflist.c b/reflist.c index 0f0833e1..0a8c1645 100644 --- a/reflist.c +++ b/reflist.c @@ -25,6 +25,8 @@ static char undef[] = "Undefined"; #define IDXFMT " %8.4f" #define ANGFMT " %8.2f" +#define ABS(x) (x < 0 ? -(x) : (x)) + int CountTblCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode, pHdb par[], int nPar); /* from hdbtable.c */ @@ -369,6 +371,32 @@ static int ShowCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, return 1; } /*-----------------------------------------------------------------------*/ +const char *FindHKL(pSICSOBJ self, double h, double k, double l) +{ + pHdb node, idx; + + node = GetHipadabaNode(self->objectNode, "data"); + node = node->child; + while(node != NULL){ + idx = node->child; + if(ABS(idx->value.v.doubleValue-h) > .1){ + node = node->next; + continue; + } + idx = idx->next; + if(ABS(idx->value.v.doubleValue-k) > .1){ + node = node->next; + continue; + } + idx = idx->next; + if(ABS(idx->value.v.doubleValue-l) < .1){ + return node->name; + } + node = node->next; + } + return NULL; +} +/*-----------------------------------------------------------------------*/ static int NamesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { @@ -394,6 +422,28 @@ static int NamesCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, return 1; } /*----------------------------------------------------------------------*/ +static int RelabelCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, + pHdb par[], int nPar) +{ + char buffer[10]; + pHdb node = NULL; + int count = 0; + + node = GetHipadabaNode(self->objectNode, "data"); + node = node->child; + while (node != NULL) { + snprintf(buffer,sizeof(buffer),"%4.4d", count); + if(node->name != NULL){ + free(node->name); + node->name = strdup(buffer); + } + count++; + node = node->next; + } + + return 1; +} +/*----------------------------------------------------------------------*/ static int SetIndexCmd(pSICSOBJ self, SConnection * pCon, pHdb commandNode, pHdb par[], int nPar) { @@ -557,6 +607,11 @@ pSICSOBJ CreateReflectionList(SConnection * pCon, SicsInterp * pSics, cmd = AddSICSHdbPar(pNew->objectNode, "count", usUser, MakeSICSFunc(CountTblCmd)); + cmd = AddSICSHdbPar(pNew->objectNode, "relabel", usUser, + MakeSICSFunc(RelabelCmd)); + + + AddCommand(pSics, name, InterInvokeSICSOBJ, KillSICSOBJ, pNew); return pNew; } @@ -687,10 +742,10 @@ int GetRefIndexID(pSICSOBJ refl, char *id, double hkl[]) snprintf(path, 132, "data/%s", id); node = GetHipadabaNode(refl->objectNode, path); if (node != NULL) { - child = node->child; - for(i = 0; i < 3; i++, child = child->next){ - hkl[i] = child->value.v.doubleValue; - } + child = node->child; + for(i = 0; i < 3; i++, child = child->next){ + hkl[i] = child->value.v.doubleValue; + } return 1; } else { return 0; diff --git a/reflist.h b/reflist.h index ea591e7c..f96bbadf 100644 --- a/reflist.h +++ b/reflist.h @@ -57,4 +57,6 @@ int GetRefFlag(pSICSOBJ refl, int idx); char *GetRefName(pSICSOBJ refl, int idx); +const char *FindHKL(pSICSOBJ self, double h, double k, double l); + #endif /*REFLIST_H_ */ diff --git a/remoteobject.c b/remoteobject.c new file mode 100644 index 00000000..5cad0a91 --- /dev/null +++ b/remoteobject.c @@ -0,0 +1,1008 @@ +/** + * Remote objects in sicsobj. This means accessing remote objects in a different + * SICS server from a master SICS server. + * + * Reading is implementd according to this scheme: + * + * * When a read connection is made between a local node and a remote node in slave, then a + * callback is installed on remote node in slave. + * * The callback on remote in slave sends commands to update the local node when either the + * value or the geterror property changes on the remote node. The commands sent are + * enclosed in special delimiters + * * A special ANET callback evaluates the data coming from slave and acts accordingly, thus + * updating the local node. This is driven by the general network driving code of SICS + * + * * in order to detect availability and re-availability of slave a Heartbeat Task sends a + * heartbeat message to slave. Thereby testing the connection regularly, trying to reconnect etc. + * + * COPRYRIGHT: see file COPYRIGHT + * + * Mark Koennecke, February 2015 +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define OOM -5001 /* out of memory */ +#define TO -5002 /* timeout */ + +static char *login = {"RemoteMaster 3ed4c656a15f0aa45e02fd5ec429225bb93b762e7eb06cc81a0b4f6c35c76184\r\n"}; +extern char *trim(char *txt); +/*---------------------- our very private data structure -------------------*/ +typedef struct { + char *host; + int port; + int readHandle; + int writeHandle; + int writeInUse; + int readList; + unsigned int connected; + time_t nextHeartbeat; +} RemoteOBJ, *pRemoteOBJ; +/*----------------------------------------------------------------------------*/ +typedef struct { + char localNode[1024]; + char remoteNode[1024]; +} ReadData, *pReadData; +/*---------------------------------------------------------------------------*/ +typedef struct { + SConnection *sendCon; + char *remotePath; +} UpdateCallback, *pUpdateCallback; +/*----------------------------------------------------------------------------*/ +void KillRemoteOBJ(void *data) +{ + char roTaskName[132]; + + pRemoteOBJ self = (pRemoteOBJ) data; + if(data != NULL){ + snprintf(roTaskName,sizeof(roTaskName),"ro-%s-%d", self->host, self->port); + StopTask(pServ->pTasker,roTaskName); + free(self->host); + ANETclose(self->readHandle); + ANETclose(self->writeHandle); + LLDdeleteBlob(self->readList); + } +} +/*========================= reading related code ================================*/ +static int RemoteReadCallback(int handle, void *userData) +{ + int length; + char *pPtr, *pStart, *pEnd; + + pPtr = ANETreadPtr(handle,&length); + + /* + * deal with command results + */ + pStart = strstr(pPtr, "TRANSACTIONSTART"); + pEnd = strstr(pPtr,"TRANSACTIONEND"); + if(pStart != NULL && pEnd != NULL){ + pStart = pStart + strlen("TRANSACTIONSTART"); + *pEnd = '\0'; + traceIO("RO","Received command - reply: %s", pStart); + pEnd += strlen("TRANSACTIONEND"); + ANETreadConsume(handle,pEnd - pPtr); + } + + /* + * deal with update messages + */ + pStart = strstr(pPtr, "SROC:"); + pEnd = strstr(pPtr,":EROC\r\n"); + if(pStart != NULL && pEnd != NULL){ + pStart += strlen("SROC:"); + *pEnd = '\0'; + InterpExecute(pServ->pSics, pServ->dummyCon,pStart); + traceIO("RO", "Received %s from remote", pStart); + pEnd += strlen("EROC\r\n"); + ANETreadConsume(handle,pEnd - pPtr); + } + + /* + * deal with heartbeats + */ + if((pStart = strstr(pPtr,"Poch")) != NULL){ + ANETreadConsume(handle,(pStart+4) - pPtr); + } + + /* + If there is more stuff to process: recurse + */ + pPtr = ANETreadPtr(handle,&length); + if(length > 0 && + ( strstr(pPtr,":EROC\r\n") != NULL || + strstr(pPtr,"TRANSACTIONEND") != NULL + || strstr(pPtr,"Poch") != NULL ) ) { + RemoteReadCallback(handle,userData); + } + + return 1; +} +/*-----------------------------------------------------------------------------*/ +static int transactCommand(int handle, char *command, char *reply, int replyLen) +{ + char *toSend = NULL; + char *prefix = {"transact "}; + int status, length, type; + time_t start; + char *pPtr; + + /* + * read possible dirt of the line + */ + pPtr = ANETreadPtr(handle,&length); + ANETreadConsume(handle,length); + + + toSend = malloc(strlen(command) + strlen(prefix) + 1); + if(toSend == NULL){ + return OOM; + } + strcpy(toSend, prefix); + strcat(toSend, command); + status = ANETwrite(handle,toSend,strlen(toSend)); + free(toSend); + if(status != 1){ + return status; + } + + /* + * wait for a reply for max 2 seconds + */ + start = time(NULL); + while(time(NULL) < start + 2.0){ + ANETprocess(); + pPtr = ANETreadPtr(handle,&length); + if(length > 0 && strstr(pPtr,"TRANSACTIONFINISHED") != NULL){ + strncpy(reply,pPtr,replyLen); + ANETreadConsume(handle,length); + return 1; + } + usleep(100); + } + + /* + * here we have run into a timeout + */ + ANETreadConsume(handle,length); + return TO; + +} +/*----------------------------------------------------------------------------*/ +static void ConnectRemoteObject(pRemoteOBJ self) +{ + char *pPtr, command[1024]; + int length, status; + ReadData rd; + pHdb node; + + + if(self->connected){ + return; + } + + self->readHandle = ANETconnect(self->host, self->port); + self->writeHandle = ANETconnect(self->host, self->port); + if(self->readHandle < 0 || self->writeHandle < 0){ + self->connected = 0; + traceIO("RO","Failed to connect to remote objects at %s, port %d", + self->host, self->port); + return; + } + traceIO("RO","Connected to %s, port %d for remote objects", + self->host, self->port); + + /* + Default login with hard coded manager login. Defined in + nserver.c + */ + ANETwrite(self->readHandle,login,strlen(login)); + ANETwrite(self->writeHandle,login,strlen(login)); + usleep(500); + ANETprocess(); + /* + eat the login responses + */ + pPtr = ANETreadPtr(self->readHandle, &length); + ANETreadConsume(self->readHandle,length); + pPtr = ANETreadPtr(self->writeHandle, &length); + ANETreadConsume(self->writeHandle,length); + + + /* + * install the read callback + */ + ANETsetReadCallback(self->readHandle,RemoteReadCallback, NULL, NULL); + + /* + * Remove geterror on read nodes and reinstall callbacks for reconnects + */ + status = LLDnodePtr2First(self->readList); + while(status != 0) { + LLDblobData(self->readList,&rd); + node = FindHdbNode(NULL,rd.localNode,NULL); + if(node != NULL){ + SetHdbProperty(node,"geterror",NULL); + snprintf(command,sizeof(command),"fulltransact addremotecb %s %s \r\n", + rd.remoteNode, rd.localNode); + ANETwrite(self->readHandle,command,strlen(command)); + } + status = LLDnodePtr2Next(self->readList); + } + + transactCommand(self->writeHandle,"protocol set withcode\r\n", command,sizeof(command)); + + self->connected = 1; + self->writeInUse = 0; +} +/*-----------------------------------------------------------------------------*/ +static void MarkDisconnected(pRemoteOBJ self) +{ + int status; + ReadData rd; + pHdb node; + + status = LLDnodePtr2First(self->readList); + while(status != 0) { + LLDblobData(self->readList,&rd); + node = FindHdbNode(NULL,rd.localNode,NULL); + if(node != NULL){ + SetHdbProperty(node,"geterror","Disconnected from remote server"); + } + status = LLDnodePtr2Next(self->readList); + } + self->connected = 0; + } +/*-----------------------------------------------------------------------------*/ +static hdbCallbackReturn ROUpdateCallback(pHdb currentNode, void *userData, + pHdbMessage mes) +{ + pUpdateCallback uppi = (pUpdateCallback)userData; + hdbDataMessage *mm = NULL; + pDynString text; + char *prefix = {"SROC:hupdate "}; + char *postfix= {":EROC\r\n"}; + char *txt = NULL; + int length; + pHdbPropertyChange propChange = NULL; + + mm = GetHdbUpdateMessage(mes); + if(mm != NULL){ + /* + * remove myself when the connection is dead... + */ + if(!SCisConnected(uppi->sendCon)){ + return hdbKill; + } + /* + * format and send the update command to master + */ + text = formatValue(*(mm->v), currentNode); + length = GetDynStringLength(text) + + strlen(prefix) + strlen(postfix) + strlen(uppi->remotePath) +5; + txt = malloc(length*sizeof(char)); + if(txt == NULL){ + return hdbContinue; + } + snprintf(txt,length,"%s %s %s %s", prefix, uppi->remotePath, + GetCharArray(text), postfix); + SCWrite(uppi->sendCon,txt,eValue); + free(txt); + DeleteDynString(text); + } + + propChange = GetPropertyChangeMessage(mes); + if(propChange != NULL){ + /* + * remove myself when the connection is dead... + */ + if(!SCisConnected(uppi->sendCon)){ + return hdbKill; + } + length = strlen("SROC:hdelprop ") + strlen(uppi->remotePath) + + strlen(propChange->key) + 10; + if(propChange->value != NULL){ + length += strlen(propChange->value); + } + txt = malloc(length*sizeof(char)); + if(txt == NULL){ + return hdbContinue; + } + if(propChange->value == NULL){ + snprintf(txt,length,"SROC:hdelprop %s %s %s", uppi->remotePath, + propChange->key,postfix); + } else { + snprintf(txt,length,"SROC:hsetprop %s %s %s %s", uppi->remotePath, + propChange->key,propChange->value, postfix); + } + SCWrite(uppi->sendCon,txt,eValue); + free(txt); + } + + return hdbContinue; +} +/*-----------------------------------------------------------------------------*/ +static hdbCallbackReturn GetErrorCallback(pHdb currentNode, void *userData, + pHdbMessage mes) +{ + hdbDataMessage *mm= NULL; + char *geterror, error[512]; + SConnection *con = NULL; + + + mm = GetHdbGetMessage(mes); + if (mm != NULL) { + con = mm->callData; + geterror = GetHdbProp(currentNode, "geterror"); + if (geterror != NULL) { + snprintf(error,sizeof(error),"ERROR: %s", geterror); + SCWrite(con, error, eError); + if (mm->v->dataType == HIPTEXT) { + if (mm->v->v.text != NULL) { + free(mm->v->v.text); + } + mm->v->v.text = strdup(error); + } + return hdbAbort; + } + } + return hdbContinue; +} +/*-----------------------------------------------------------------------------*/ +static void KillUpdateStruct(void *data) +{ + pUpdateCallback self = (pUpdateCallback)data; + if(data != NULL){ + SCDeleteConnection(self->sendCon); + free(self->remotePath); + free(self); + } +} +/*-----------------------------------------------------------------------------*/ +static int ConnectRead(pRemoteOBJ self, SConnection * pCon, ReadData rd) +{ + char command[1024], reply[1024], *pPtr; + int status, type; + pHdb localNode = NULL; + + /* + * Initialize.... + */ + localNode = FindHdbNode(NULL,rd.localNode, pCon); + if(localNode == NULL){ + SCPrintf(pCon,eError,"ERROR: local node %s not found", rd.localNode); + return 0; + } + + /** + * Refuse duplicate connections + */ + pPtr = GetHdbProp(localNode,"remoteread"); + if(pPtr != NULL){ + SCPrintf(pCon,eError,"ERROR: %s is already connected to %s", rd.localNode, pPtr); + return 0; + } + + /* + * Get information about the remote node and check compatability + */ + snprintf(command,sizeof(command),"hinfo %s\r\n", rd.remoteNode); + status = transactCommand(self->writeHandle,command,reply,sizeof(reply)); + if(status != 1){ + /* + * try a reconnect, + * when fails: + * Warning + * add blob + */ + self->connected = 0; + ConnectRemoteObject(self); + status = transactCommand(self->writeHandle,command,reply,sizeof(reply)); + if(status != 1){ + SCPrintf(pCon,eWarning,"WARNING: cannot yet reach slave %s, but continuing...", + self->host); + MarkDisconnected(self); + LLDblobAdd(self->readList,&rd,sizeof(rd)); + AppendHipadabaCallback(localNode, MakeHipadabaCallback(GetErrorCallback, + NULL,NULL)); + SetHdbProperty(localNode,"remoteread",rd.remoteNode); + return 1; + } + } + if(strstr(reply, "ERROR") != NULL){ + SCPrintf(pCon,eError,"%s while trying to contact remote node %s", + reply, rd.remoteNode); + return 0; + } + /* only interested in type: answer is of style: type,nochildren,length */ + pPtr = strchr(reply,','); + *pPtr= '\0'; + type = convertHdbType(reply); + if(type != localNode->value.dataType){ + SCPrintf(pCon,eError, + "ERROR: data type mismatch between local %s and remote %s, local type %d, remote type %d", + rd.localNode, rd.remoteNode, localNode->value.dataType, type); + return 0; + } + + /* + * Make an entry in the read list + */ + LLDblobAdd(self->readList,&rd,sizeof(rd)); + AppendHipadabaCallback(localNode, MakeHipadabaCallback(GetErrorCallback, + NULL,NULL)); + + SetHdbProperty(localNode,"remoteread",rd.remoteNode); + + /* + * Install a callback on the remote node to update the master. The remote should + * then immediatly send an update which will be processed by the read callback. + */ + snprintf(command,sizeof(command),"fulltransact addremotecb %s %s \r\n", + rd.remoteNode, rd.localNode); + ANETwrite(self->readHandle,command,strlen(command)); + + return 1; +} + +/*-----------------------------------------------------------------------------*/ +static int ConnectreadCmd(pSICSOBJ ccmd, SConnection * pCon, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + ReadData rd; + pHdb localNode = NULL; + char command[1024], reply[1024], *pPtr; + int status, type; + pRemoteOBJ self; + + + if(nPar < 2) { + SCWrite(pCon,"ERROR: need path to local node and remote node for connectread", + eError); + return 0; + } + + /* + * Initialize.... + */ + strncpy(rd.localNode ,par[0]->value.v.text, sizeof(rd.localNode)); + strncpy(rd.remoteNode ,par[1]->value.v.text, sizeof(rd.remoteNode)); + self = (pRemoteOBJ)ccmd->pPrivate; + + status = ConnectRead(self,pCon,rd); + + if(status == 1){ + SCSendOK(pCon); + } + + return status; +} +/*-----------------------------------------------------------------------------*/ +static int HeartbeatTask(void *pData) +{ + pRemoteOBJ self = (pRemoteOBJ)pData; + int status; + char command[] = {"Poch\r\n"}; + + if (time(NULL) > self->nextHeartbeat){ + status = ANETwrite(self->readHandle,command, strlen(command)); + if(status != 1){ + traceIO("RO","Trying a reconnect to %s, %d", self->host, self->port); + self->connected = 0; + ConnectRemoteObject(self); + if(!self->connected){ + MarkDisconnected(self); + } + } + self->nextHeartbeat = time(NULL) + 10; + } + return 1; +} +/*============================= writing related code =========================== + The logic here is to use the standard writeHandle when available. I expect most + communication to be short and to happen through the writeHandle. If that one is + in use, a new connection will be built. + --------------------------------------------------------------------------------- + suppress all superfluous OK from the slave + -----------------------------------------------------------------------------------*/ +#include +static OutCode findOutCode(char *txt) +{ + int i; + + for(i = 0; i < iNoCodes; i++){ + if(strstr(txt,pCode[i]) != NULL){ + return i; + } + } + return eValue; +} +/*--------------------------------------------------------------------------------*/ +static void printSICS(char *answer, SConnection *pCon) +{ + char line[1024], *pPtr, *pCode; + OutCode eCode; + + pPtr = answer; + while(pPtr != NULL){ + memset(line,0,sizeof(line)); + pPtr = stptok(pPtr,line,sizeof(line),"\n"); + if(strstr(line,"OK") == NULL){ + pCode = strstr(line,"@@"); + if(pCode != NULL){ + *pCode = '\0'; + pCode += 2; + eCode = findOutCode(trim(pCode)); + + } else { + eCode = eValue; + } + SCWrite(pCon,line,eCode); + } + } +} +/*---------------------------------------------------------------------------------*/ +static int PrepareWriteHandle(pRemoteOBJ self, SConnection *pCon, int *newHandle) +{ + int handle, length; + char *answer = NULL; + char command[80]; + + if(self->writeInUse) { + handle = ANETconnect(self->host,self->port); + if(handle < 0){ + traceIO("RO","Failed to connect to %s at %d", self->host, self->port); + if(pCon != NULL){ + SCPrintf(pCon,eError,"ERROR: Failed to connect to %s %d", self->host, self->port); + } + return handle; + } + ANETwrite(handle,login,strlen(login)); + usleep(500); + ANETprocess(); + /* + eat the login responses + */ + answer = ANETreadPtr(handle, &length); + ANETreadConsume(handle,length); + *newHandle = 1; + + transactCommand(handle,"protocol set withcode\r\n", command,sizeof(command)); + + } else { + self->writeInUse = 1; + handle = self->writeHandle; + /* + eat dirt from the line + */ + answer = ANETreadPtr(handle, &length); + ANETreadConsume(handle,length); + } + return handle; +} +/*---------------------------------------------------------------------------------*/ +static void ProcessWriteResponse(pRemoteOBJ self, int handle, SConnection *pCon) +{ + char *answer = NULL, *pEnd, *command = NULL; + int length; + + while(1){ + TaskYield(pServ->pTasker); + if(!ANETvalidHandle(handle)){ + SCPrintf(pCon,eError,"ERROR: Disconnected from %s", self->host); + break; + } + answer = ANETreadPtr(handle,&length); + if(length > 0 && (pEnd = strstr(answer,"TRANSACTIONFINISHED")) != NULL){ + if(pCon != NULL){ + *pEnd = '\0'; + printSICS(answer,pCon); + } + traceIO("RO","%s:%d: Received %s", self->host, self->port,answer); + ANETreadConsume(handle,length); + break; + } + } + +} +/*---------------------------------------------------------------------------------*/ +static hdbCallbackReturn ROWriteCallback(pHdb currentNode, void *userData, + pHdbMessage mes) +{ + pHdbDataMessage mm = NULL; + int handle, status, length, newHandle = 0; + pRemoteOBJ self = (pRemoteOBJ)userData; + SConnection *pCon = NULL; + pDynString data; + char *remoteNode; + char *command, *answer, *pEnd; + + + if((mm = GetHdbSetMessage(mes)) != NULL){ + pCon = (SConnection *)mm->callData; + handle = PrepareWriteHandle(self,pCon,&newHandle); + if(handle < 0){ + return hdbAbort; + } + + /* + build the command to send + */ + data = formatValue(*(mm->v),currentNode); + remoteNode = GetHdbProp(currentNode,"remotewrite"); + length = 40 + strlen(remoteNode) + GetDynStringLength(data); + command = malloc(length*sizeof(char)); + if(command == NULL){ + if(pCon != NULL){ + SCWrite(pCon,"ERROR: out of memory writing remote node",eError); + } + return hdbAbort; + } + snprintf(command,length,"transact hset %s %s\r\n",remoteNode, GetCharArray(data)); + + /* + write + */ + traceIO("RO","%s:%d: Sending %s ", self->host, self->port, command); + status = ANETwrite(handle,command,strlen(command)); + free(command); + DeleteDynString(data); + if(status < 0){ + if(pCon != NULL){ + SCPrintf(pCon,eError,"ERROR: remote %s on %s disconnected", remoteNode, self->host); + } + return hdbAbort; + } + + /* + wait for a response: TRANSACTIONFINISHED + */ + ProcessWriteResponse(self,handle,pCon); + + /* + Is there a termination script? + */ + command = GetHdbProp(currentNode,"termscript"); + if(command != NULL){ + while(1) { + TaskYield(pServ->pTasker); + Tcl_Eval(InterpGetTcl(pServ->pSics),command); + answer = (char *)Tcl_GetStringResult(InterpGetTcl(pServ->pSics)); + if(strstr(answer,"idle") != NULL){ + answer = ANETreadPtr(handle,&length); + printSICS(answer,pCon); + traceIO("RO","%s:%d:Received %s", self->host,self->port,answer); + ANETreadConsume(handle,length); + break; + } + } + } + + + if(newHandle){ + ANETclose(handle); + } else { + self->writeInUse = 0; + } + + } + + return hdbContinue; +} +/*------------------------------------------------------------------------------*/ +static int ConnectWrite(pRemoteOBJ self, SConnection *pCon, ReadData rd) +{ + pHdb localNode = NULL; + char command[1024], reply[1024], *pPtr; + int status, type; + + localNode = FindHdbNode(NULL,rd.localNode, pCon); + if(localNode == NULL){ + SCPrintf(pCon,eError,"ERROR: local node %s not found", rd.localNode); + return 0; + } + + pPtr = GetHdbProp(localNode,"remotewrite"); + if(pPtr != NULL){ + SCPrintf(pCon,eError,"ERROR: %s alread connected to %s", rd.localNode, + rd.remoteNode); + return 0; + } + + SetHdbProperty(localNode,"remotewrite",rd.remoteNode); + AppendHipadabaCallback(localNode, MakeHipadabaCallback(ROWriteCallback, + self,NULL)); + + /* + * Get information about the remote node and check compatability + */ + snprintf(command,sizeof(command),"hinfo %s\r\n", rd.remoteNode); + status = transactCommand(self->writeHandle,command,reply,sizeof(reply)); + if(status != 1){ + SCPrintf(pCon,eWarning,"WARNING: cannot yet reach slave %s, but continuing...", + self->host); + MarkDisconnected(self); + return 0; + } + if(strstr(reply, "ERROR") != NULL){ + SCPrintf(pCon,eError,"%s while trying to contact remote node %s", + reply, rd.remoteNode); + return 0; + } + /* only interested in type: answer is of style: type,nochildren,length */ + pPtr = strchr(reply,','); + *pPtr= '\0'; + type = convertHdbType(reply); + if(type != localNode->value.dataType){ + SCPrintf(pCon,eError, + "ERROR: data type mismatch between local %s and remote %s, local type %d, remote type %d", + rd.localNode, rd.remoteNode, localNode->value.dataType, type); + return 0; + } + + return 1; +} +/*---------------------------------------------------------------------------------*/ +static int ConnectwriteCmd(pSICSOBJ ccmd, SConnection * pCon, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + ReadData rd; + int status; + pRemoteOBJ self; + + + if(nPar < 2) { + SCWrite(pCon,"ERROR: need path to local node and remote node for connectwrite", + eError); + return 0; + } + + /* + * Initialize.... + */ + strncpy(rd.localNode ,par[0]->value.v.text, sizeof(rd.localNode)); + strncpy(rd.remoteNode ,par[1]->value.v.text, sizeof(rd.remoteNode)); + self = (pRemoteOBJ)ccmd->pPrivate; + + status = ConnectWrite(self,pCon,rd); + + if(status == 1){ + SCSendOK(pCon); + } + return status; +} +/*============================ remote execute =================================*/ +static int RemoteExecute(pRemoteOBJ self, SConnection *pCon, char *command) +{ + int status, handle, newHandle = 0, length; + char *answer, *pEnd; + + handle = PrepareWriteHandle(self,pCon,&newHandle); + if(handle < 0){ + return 0; + } + + /* + write, thereby taking care to prefix with transact and for proper termination + */ + if(strstr(command,"transact") == NULL){ + ANETwrite(handle,"transact ", sizeof("transact ")); + } + status = ANETwrite(handle,command,strlen(command)); + if(strstr(command,"\n") == NULL){ + ANETwrite(handle,"\r\n",2); + } + if(status < 0){ + traceIO("RO","Disconnect from %s while executing %s", self->host, command); + if(pCon != NULL){ + SCPrintf(pCon,eError,"ERROR: Disconnected from %s %d", self->host, self->port); + } + return 0; + } + + /* + wait for response + */ + while(1){ + TaskYield(pServ->pTasker); + if(!ANETvalidHandle(handle)){ + if(pCon != NULL){ + SCPrintf(pCon,eError,"ERROR: Disconnected from %s %d", self->host, self->port); + } + break; + } + answer = ANETreadPtr(handle,&length); + if(length > 0 && (pEnd = strstr(answer,"TRANSACTIONFINISHED")) != NULL){ + if(pCon != NULL){ + *pEnd = '\0'; + SCPrintf(pCon,eValue,answer); + } + ANETreadConsume(handle,length); + break; + } + } + + if(newHandle){ + ANETclose(handle); + } else { + self->writeInUse = 0; + } + + return 1; +} +/*------------------------------------------------------------------------------*/ +static int RemoteExecuteCmd(pSICSOBJ ccmd, SConnection * pCon, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + int status, i; + char *pPtr; + Tcl_DString com; + pDynString val; + pRemoteOBJ self; + + self = (pRemoteOBJ)ccmd->pPrivate; + + Tcl_DStringInit(&com); + for (i = 0; i < nPar; i++) { + val = formatValue(par[i]->value, par[i]); + if (val != NULL) { + Tcl_DStringAppend(&com, " ", 1); + pPtr = GetCharArray(val); + Tcl_DStringAppend(&com, pPtr, strlen(pPtr)); + DeleteDynString(val); + } + } + + status = RemoteExecute(self,pCon,Tcl_DStringValue(&com)); + Tcl_DStringFree(&com); + + return status; + +} +/*============================= connect command ================================*/ +static int ConnectCmd(pSICSOBJ ccmd, SConnection * pCon, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + pRemoteOBJ self; + + self = (pRemoteOBJ)ccmd->pPrivate; + ConnectRemoteObject(self); + + if(self->connected){ + SCSendOK(pCon); + } else { + SCPrintf(pCon,eError,"ERROR: failed to connect to %s %d", self->host, self->port); + return 0; + } + + return 1; +} +/*============================ object initialisation etc =======================*/ +static int MakeRemoteObject(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) +{ + pSICSOBJ pNew = NULL; + pRemoteOBJ self = NULL; + int status; + pHdb cmd; + char roTaskName[256]; + + if(argc < 4) { + SCWrite(pCon,"ERROR: need name and remote host name and port in order to create remote object", + eError); + return 0; + } + + strtolower(argv[1]); + if(FindCommand(pSics,argv[1]) != NULL){ + SCPrintf(pCon,eError, "ERROR: command %s already exists!", argv[1]); + return 0; + } + + pNew = MakeSICSOBJ(argv[1],"RemoteOBJ"); + self = calloc(1, sizeof(RemoteOBJ)); + if(pNew == NULL || self == NULL){ + SCWrite(pCon,"ERROR: out of memory creating remote object", eError); + return 0; + } + pNew->pPrivate = self; + pNew->KillPrivate = KillRemoteOBJ; + self->host = strdup(argv[2]); + self->port = atoi(argv[3]); + self->readList = LLDblobCreate(); + ConnectRemoteObject(self); + + cmd = AddSICSHdbPar(pNew->objectNode, + "connectread", usMugger, MakeSICSFunc(ConnectreadCmd)); + AddSICSHdbPar(cmd, "localnode", usMugger, MakeHdbText("")); + AddSICSHdbPar(cmd, "remotenode", usMugger, MakeHdbText("")); + + + cmd = AddSICSHdbPar(pNew->objectNode, + "connectwrite", usMugger, MakeSICSFunc(ConnectwriteCmd)); + AddSICSHdbPar(cmd, "localnode", usMugger, MakeHdbText("")); + AddSICSHdbPar(cmd, "remotenode", usMugger, MakeHdbText("")); + + + cmd = AddSICSHdbPar(pNew->objectNode, + "exe", usMugger, MakeSICSFunc(RemoteExecuteCmd)); + AddSICSHdbPar(cmd, "args", usMugger, MakeHdbText("")); + + cmd = AddSICSHdbPar(pNew->objectNode, + "connect", usMugger, MakeSICSFunc(ConnectCmd)); + + + status = AddCommand(pSics, + argv[1], + InterInvokeSICSOBJ, + KillSICSOBJ, pNew); + + snprintf(roTaskName,sizeof(roTaskName),"ro-%s-%d", self->host, self->port); + TaskRegisterN(pServ->pTasker, roTaskName, HeartbeatTask, NULL,NULL,self,1); + + return status; +} +/*----------------------------------------------------------------------------------------*/ +static int AddRemoteCallback(SConnection *pCon, SicsInterp *pSics, void *pData, + int argc, char *argv[]) +{ + pHdb localNode = NULL; + pUpdateCallback up = NULL; + + if(argc < 3) { + SCWrite(pCon,"ERROR: need path to local node and remote node for updatecb", + eError); + return 0; + } + + localNode = FindHdbNode(NULL,argv[1], pCon); + if(localNode == NULL){ + SCPrintf(pCon,eError,"ERROR: local node %s not found", argv[1]); + return 0; + } + + up = malloc(sizeof(UpdateCallback)); + if(up == NULL){ + SCWrite(pCon,"ERROR: out of memory installing update callback",eError); + return 0; + } + up->sendCon = SCCopyConnection(pCon); + up->remotePath = strdup(argv[2]); + AppendHipadabaCallback(localNode, MakeHipadabaCallback(ROUpdateCallback, + up,KillUpdateStruct)); + /** + * This is meant to send an update immediatly such that the remote node + * is updated right away, + */ + NotifyHipadabaPar(localNode, NULL); + + SCSendOK(pCon); + return 1; + +} +/*----------------------------------------------------------------------------------------*/ +void RemoteObjectInit(void) +{ + + AddCommand(pServ->pSics, + "makeremo", + MakeRemoteObject, + NULL,NULL); + + AddCommand(pServ->pSics, + "addremotecb", + AddRemoteCallback, + NULL,NULL); + + +} diff --git a/rwpuffer.c b/rwpuffer.c index a678e700..68acf5e0 100644 --- a/rwpuffer.c +++ b/rwpuffer.c @@ -4,6 +4,11 @@ * copyright: see file COPYRIGHT * * Mark Koennecke, January 2009 + * + * added resizing option and MakeBigRWPuffer in order to support transfer + * of large amounts of image data on few connections + * + * Mark Koennecke, August 2014 */ #include #include @@ -15,6 +20,7 @@ typedef struct __RWBuffer { int length; int startPtr; int endPtr; + int maxSize; } RWBuffer; /*----------------------------------------------------------------------*/ prwBuffer MakeRWPuffer(int size) @@ -32,9 +38,18 @@ prwBuffer MakeRWPuffer(int size) self->length = size; self->startPtr = 0; self->endPtr = 0; + self->maxSize = size; return self; } - +/*------------------------------------------------------------------------*/ +prwBuffer MakeBigRWPuffer(int size, int maxSize) +{ + prwBuffer result = MakeRWPuffer(size); + if(result != NULL){ + result->maxSize = maxSize; + } + return result; +} /*------------------------------------------------------------------------*/ void KillRWBuffer(prwBuffer self) { @@ -46,16 +61,51 @@ void KillRWBuffer(prwBuffer self) } free(self); } +/*------------------------------------------------------------------------*/ +int CanStoreRWBuffer(prwBuffer self, void *data, int count) +{ + int length; + char *ptr; + length = self->endPtr - self->startPtr; + if (count + length >= self->length ) { + if(self->length < self->maxSize){ + ptr = calloc(self->maxSize,sizeof(char)); + if(ptr == NULL) { + return 0; + } + memcpy(ptr,self->data, length*sizeof(char)); + free(self->data); + self->data = ptr; + self->length = self->maxSize; + } else { + return 0; + } + } + return 1; +} /*------------------------------------------------------------------------*/ int StoreRWBuffer(prwBuffer self, void *data, int count) { int length; + char *ptr; length = self->endPtr - self->startPtr; if (count + length >= self->length ) { + if(self->length < self->maxSize){ + ptr = calloc(self->maxSize,sizeof(char)); + if(ptr == NULL) { printf("HELP: RWBuffer overrun!!!!\n"); - return 0; + return 0; + } + memcpy(ptr,self->data, length*sizeof(char)); + free(self->data); + self->data = ptr; + self->length = self->maxSize; + } else { + printf("HELP: RWBuffer overrun!!!!\n"); + return 0; + } } if (count + self->endPtr > self->length) { memmove(self->data, self->data + self->startPtr, length); @@ -81,5 +131,6 @@ void RemoveRWBufferData(prwBuffer self, int count) if (self->startPtr >= self->endPtr) { self->startPtr = 0; self->endPtr = 0; + memset(self->data,0,self->length*sizeof(char)); } } diff --git a/rwpuffer.h b/rwpuffer.h index e69795b4..59ec439e 100644 --- a/rwpuffer.h +++ b/rwpuffer.h @@ -16,6 +16,13 @@ typedef struct __RWBuffer *prwBuffer; * \return NULL on success, else a pointer to t a new rwPuffer */ prwBuffer MakeRWPuffer(int size); +/** + * \brief create a RW buffer which can grow. + * \param size The size of the buffer. + * \param maxSize The maximum size of the buffer. + * \return NULL on success, else a pointer to t a new rwPuffer + */ +prwBuffer MakeBigRWPuffer(int size, int maxSize); /** * \brief delete a rw buffer. * \param self The rwPuffer to delete. @@ -29,6 +36,14 @@ void KillRWBuffer(prwBuffer self); * \return 1 on success, 0 on failure */ int StoreRWBuffer(prwBuffer self, void *data, int count); +/** + * \brief Test if the data can be stored in the rwBuffer + * \param self The rw buffer to store the data in + * \param data pointer to the data to store + * \param count The number of bytes to store + * \return 1 when OK, 0 when buffer full + */ +int CanStoreRWBuffer(prwBuffer self, void *data, int count); /** * \brief Get a pointer to the current buffer data * \param self the buffer to get the data from diff --git a/scan.c b/scan.c index 21bd521c..87449183 100644 --- a/scan.c +++ b/scan.c @@ -999,7 +999,11 @@ int GetScanVarName(pScanData self, int iWhich, char *pName, int iLength) return 0; } } - +/*---------------------------------------------------------------------*/ +int isScanRunning(pScanData self) +{ + return self->iActive; +} /*---------------------------------------------------------------------*/ int GetScanVarStep(pScanData self, int iWhich, float *fStep) { @@ -1720,6 +1724,12 @@ int ScanWrapper(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, pBueffel, eValue); return 1; } +/*-------- isactive */ + else if (strcmp(argv[1], "isactive") == 0) { + snprintf(pBueffel,sizeof(pBueffel)-1, "%s.active = %d", argv[0], self->iActive); + SCWrite(pCon, pBueffel, eValue); + return 1; + } /*--------- getvardata */ else if (strcmp(argv[1], "getvardata") == 0) { /* we need an integer parameter saying which */ diff --git a/scan.h b/scan.h index f9e2ca2e..37e13960 100644 --- a/scan.h +++ b/scan.h @@ -40,6 +40,7 @@ int GetScanVarStep(pScanData self, int iWhich, float *fStep); int GetScanMonitor(pScanData self, int iWhich, long *lData, int iDataLen); int GetScanNP(pScanData self); float GetScanPreset(pScanData self); +int isScanRunning(pScanData self); int ScanIntegrate(pScanData self, float *fSum, float *fVariance); diff --git a/script.c b/script.c index 5568e3cf..73a5303a 100644 --- a/script.c +++ b/script.c @@ -143,11 +143,17 @@ int SetSICSInterrupt(SConnection * pCon, SicsInterp * pSics, void *pData, return 1; } -/*-------------------------------------------------------------------------*/ +/*------------------------------------------------------------------------- +This method does nothing anymore. Status is now calculated from the state +of SICS and no longer explicitly set. I left the code in because I am to +lazy to find all use cases and eliminate them + +M.K. 07/2014 +--------------------------------------------------------------------------*/ int SetSICSStatus(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]) { - int iInt; + int iInt = 0; char pBueffel[132]; assert(pCon); @@ -166,6 +172,13 @@ int SetSICSStatus(SConnection * pCon, SicsInterp * pSics, void *pData, return 0; } + SCWrite(pCon,"Status is calculated, cannot be set manually any longer", eValue); + return 1; + + /* + The code below is defunct and just here for documentary reasons + */ + /* is there a value ? */ if (argc < 2) { SCWrite(pCon, "ERROR: missing parameter for SetStatus", eError); @@ -174,7 +187,7 @@ int SetSICSStatus(SConnection * pCon, SicsInterp * pSics, void *pData, /* actually do a job */ strtolower(argv[1]); - iInt = SetStatusFromText(argv[1]); + /* iInt = SetStatusFromText(argv[1]); */ if (iInt) { SCSendOK(pCon); return 1; @@ -193,7 +206,7 @@ static int isNum(char *pText) for (i = 0; i < strlen(pText); i++) { if (!isdigit(pText[i])) { - if (!((pText[i] == '+') || (pText[i] == '-') || (pText[i] == '.'))) { + if (!((pText[i] == '+') || (pText[i] == '-') || (pText[i] == '.') || (tolower(pText[i]) == 'e' ))) { iRet = 0; break; } diff --git a/scriptcontext.c b/scriptcontext.c index 3653b23c..faa347c4 100644 --- a/scriptcontext.c +++ b/scriptcontext.c @@ -1552,6 +1552,7 @@ static int SctProcessCmd(pSICSOBJ ccmd, SConnection * con, { SctData *data = NULL; SctController *c; + time_t startTime; c = (SctController *) ccmd->pPrivate; @@ -1581,9 +1582,10 @@ static int SctProcessCmd(pSICSOBJ ccmd, SConnection * con, data->busy = 1; data->inMacro = SCinMacro(con); + startTime = time(NULL); DevQueue(c->devser, data, WritePRIO, - SctWriteHandler, SctMatch, NULL, SctDataInfo); - while (data->busy == 1) { + SctWriteHandler, SctTransactMatch, NULL, SctDataInfo); + while (data->busy == 1 && time(NULL) < startTime + 20) { TaskYield(pServ->pTasker); } SctKillData(data); diff --git a/sctdriveadapter.c b/sctdriveadapter.c index 98cf6739..c3f7e3d5 100644 --- a/sctdriveadapter.c +++ b/sctdriveadapter.c @@ -174,11 +174,11 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon) SCPrintf(pCon, eError, " script %s returned %s", script, result); } } - if (strstr(result, "busy") != NULL) { + if (strstr(result, "run") != NULL) { return HWBusy; } else if (strstr(result, "posfault") != NULL) { return HWPosFault; - } else if (strstr(result, "fault") != NULL) { + } else if (strstr(result, "error") != NULL) { return HWFault; } else if (strstr(result, "idle") != NULL) { return HWIdle; diff --git a/sctdriveobj.c b/sctdriveobj.c index aae56d47..c47ef8a7 100644 --- a/sctdriveobj.c +++ b/sctdriveobj.c @@ -212,11 +212,11 @@ static int SCTDRIVCheckStatus(void *data, SConnection * pCon) SCPrintf(pCon, eError, " script %s returned %s", script, result); } } - if (strstr(result, "busy") != NULL) { + if (strstr(result, "run") != NULL) { return HWBusy; } else if (strstr(result, "posfault") != NULL) { return HWPosFault; - } else if (strstr(result, "fault") != NULL) { + } else if (strstr(result, "error") != NULL) { return HWFault; } else if (strstr(result, "idle") != NULL) { return HWIdle; diff --git a/sicsdata.c b/sicsdata.c index f00784e7..8ccd7d63 100644 --- a/sicsdata.c +++ b/sicsdata.c @@ -954,7 +954,7 @@ static int copyToNode(pSICSData self, int argc, char *argv[], } node->value.arrayLength = length; } - memcpy(node->value.v.intArray, self->data, length*sizeof(int)); + memcpy(node->value.v.intArray, self->data + start, length*sizeof(int)); break; case HIPFLOATAR: case HIPFLOATVARAR: diff --git a/sicsget.c b/sicsget.c index c4ecc55c..2924a2a6 100644 --- a/sicsget.c +++ b/sicsget.c @@ -81,7 +81,7 @@ static int SICSGetCommand(SConnection * pCon, SicsInterp * pSics, void *pData, if(status){ data = formatValue(v,NULL); if(data != NULL){ - SCPrintf(pCon,eValue,"%s",trim(GetCharArray(data))); + SCWrite(pCon,trim(GetCharArray(data)),eValue); DeleteDynString(data); } else { SCPrintf(pCon,eError,"ERROR: formatting value for %s failed", argv[1]); @@ -89,7 +89,11 @@ static int SICSGetCommand(SConnection * pCon, SicsInterp * pSics, void *pData, return 0; } } else { - SCPrintf(pCon,eError,"ERROR: value for %s not found", argv[1]); + if(v.dataType == HIPTEXT && strstr(v.v.text,"ERROR") != NULL){ + SCPrintf(pCon,eError,v.v.text); + } else { + SCPrintf(pCon,eError,"ERROR: value for %s not found", argv[1]); + } return 0; } ReleaseHdbValue(&v); @@ -137,16 +141,22 @@ static int SICSPutCommand(SConnection * pCon, SicsInterp * pSics, void *pData, static int InvokeSICSFunc(void *ms, void *userData) { pParseMessage self = (pParseMessage)ms; + SConnection *pCon = NULL; int status; - SCsetMacro(pServ->dummyCon,1); - status = InterpExecute(pServ->pSics, pServ->dummyCon, self->command); - SCsetMacro(pServ->dummyCon,0); + pCon = SCCreateDummyConnection(pServ->pSics); + if(pCon == NULL){ + return MPSTOP; + } + SCsetMacro(pCon,1); + status = InterpExecute(pServ->pSics, pCon, self->command); + SCsetMacro(pCon,0); if(!status){ self->success = 0; return MPSTOP; } self->response = strdup(Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); + SCDeleteConnection(pCon); return MPCONTINUE; } /*----------------------------------------------------------------------------*/ @@ -174,12 +184,26 @@ static int SplitOffEqual(void *ms, void *userData) return MPCONTINUE; } /*---------------------------------------------------------------------------*/ +static int isExtra(char c) +{ + char extra[] = {"{}"}; + int i; + + for(i = 0; i < strlen(extra); i++){ + if(extra[i] == c ){ + return 1; + } + } + + return 0; +} +/*---------------------------------------------------------------------------*/ static int isNumber(char *txt) { if(*txt == '\0' || *txt == ' '){ return 1; } - if(isalpha(*txt)){ + if(isalpha(*txt) || isExtra(*txt)){ return 0; } else { return isNumber(txt+1); @@ -192,7 +216,7 @@ static int countWords(char *txt) int count = 0; char *pPtr = txt; - while(pPtr != NULL){ + while(pPtr != NULL && strlen(pPtr) > 0){ count++; pPtr = stptok(pPtr,number,sizeof(number)," "); } @@ -280,8 +304,12 @@ static void configureSICSPipe() static int FindTclVar(void *ms, void *userData) { pParseMessage self = (pParseMessage)ms; + char *pPtr = NULL; - self->response = Tcl_GetVar(InterpGetTcl(pServ->pSics),self->command, TCL_GLOBAL_ONLY); + pPtr = Tcl_GetVar(InterpGetTcl(pServ->pSics),self->command, TCL_GLOBAL_ONLY); + if(pPtr != NULL){ + self->response = strdup(pPtr); + } if(self->response == NULL){ return MPSTOP; } @@ -302,10 +330,20 @@ static int GetHdbFunc(void *ms, void *userData) { pSSGMessage self = (pSSGMessage)ms; pHdb node = NULL; + char *geterror = NULL, error[512]; + hdbValue ve; node = FindHdbNode(NULL,self->name,NULL); if(node != NULL){ - cloneHdbValue(&node->value, self->v); + geterror = GetHdbProp(node,"geterror"); + if(geterror != NULL){ + snprintf(error,sizeof(error),"ERROR: %s",geterror); + ve = MakeHdbText(strdup(error)); + cloneHdbValue(&ve, self->v); + ReleaseHdbValue(&ve); + } else { + cloneHdbValue(&node->value, self->v); + } self->success = 1; return MPSTOP; } else { @@ -357,14 +395,28 @@ static int GetDrivableFunc(void *ms, void *userData) pIDrivable pDriv = NULL; float fVal; hdbValue v; + int oldMacro; data = FindCommandData(pServ->pSics, self->name,NULL); if(data != NULL){ pDriv = GetDrivableInterface(data); if(pDriv != NULL){ + /* + All this macro flag handling is there to get hold of a + error message stored in the Tcl interpreter if there is + one. + */ + oldMacro = SCinMacro(pServ->dummyCon); + SCsetMacro(pServ->dummyCon,1); fVal = pDriv->GetValue(data,pServ->dummyCon); - v = MakeHdbFloat(fVal); - self->success = 1; + SCsetMacro(pServ->dummyCon,oldMacro); + if(fVal < -900000) { + v = MakeHdbText(Tcl_GetStringResult(InterpGetTcl(pServ->pSics))); + self->success = 0; + } else { + v = MakeHdbFloat(fVal); + self->success = 1; + } cloneHdbValue(&v,self->v); return MPSTOP; } @@ -419,7 +471,7 @@ static int PutHdbFunc(void *ms, void *userData) node = FindHdbNode(NULL,self->name,NULL); if(node != NULL){ - status = UpdateHipadabaPar(node,*(self->v),NULL); + status = SetHipadabaPar(node,*(self->v),NULL); self->success = status; if(status == 1){ return MPSTOP; diff --git a/sicshdbadapter.c b/sicshdbadapter.c index c7357f9a..31e6d9aa 100644 --- a/sicshdbadapter.c +++ b/sicshdbadapter.c @@ -315,7 +315,7 @@ static pHdb CreateMotorAdapter(char *name, pMotor pMot) DeleteHipadabaNode(result, NULL); return NULL; } - result->protected = 1; + result->iprotected = 1; return result; } @@ -499,7 +499,7 @@ static pHdb MakeSicsVarNode(pSicsVariable pVar, char *name) snprintf(command, 1023, "%s ", pVar->name); SetHdbProperty(node, "sicscommand", command); - node->protected = 1; + node->iprotected = 1; return node; } diff --git a/sicshdbfactory.c b/sicshdbfactory.c index 82599f2f..e6db0511 100644 --- a/sicshdbfactory.c +++ b/sicshdbfactory.c @@ -339,6 +339,7 @@ static int MakeCommandNode(pHdb parent, char *name, SConnection * pCon, node->value.v.text = strdup(argv[3]); node->value.arrayLength = strlen(argv[3]); SetHdbProperty(node, "sicscommand", argv[3]); + SetHdbProperty(node, "scriptcommand", "yes"); kalle = MakeHipadabaCallback(CommandSetCallback, NULL, NULL); if (kalle == NULL) { diff --git a/sicshipadaba.c b/sicshipadaba.c index c11fcf75..dd6fc203 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -289,9 +289,8 @@ hdbCallbackReturn SICSValueCheckCallback(pHdb node, void *userData, } return hdbAbort; + } - - /*-------------------------------------------------------------------------------------*/ static hdbCallbackReturn SICSDriveCallback(pHdb node, void *userData, pHdbMessage message) @@ -693,7 +692,7 @@ static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData, SCPureSockWrite(cbInfo->pCon, GetCharArray(result), outCode); DeleteDynString(printedData); } else { - formatNameValue(protocol, pPath, "!!datachange!!", result, HIPTEXT); + formatNameValue(protocol, updatePath, "!!datachange!!", result, HIPTEXT); SCWrite(cbInfo->pCon, GetCharArray(result), outCode); } DeleteDynString(result); @@ -2342,7 +2341,7 @@ static int isNodeProtected(pHdb node) { pHdb current = NULL; - if (node->protected == 1) { + if (node->iprotected == 1) { return 1; } current = node->child; @@ -2524,7 +2523,7 @@ static int UpdateHdbNode(SConnection * pCon, SicsInterp * pSics, } status = UpdateHipadabaPar(targetNode, newValue, pCon); ReleaseHdbValue(&newValue); - if (status == 1) { + if (status == 1 && SCinMacro(pCon) == 0) { SCSendOK(pCon); } return status; @@ -2708,10 +2707,10 @@ static int GetHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData, return 0; } /* - * if transfer = zip, redirect to zip + * if transfer = zip or bin, redirect to zip */ if (GetHdbProperty(targetNode, "transfer", value, 80) == 1) { - if (strstr(value, "zip") != NULL) { + if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) { return ZipGetHdbNode(pCon, pSics, pData, argc, argv); } } @@ -3131,6 +3130,7 @@ static int RemoveHdbCallback(SConnection * pCon, SicsInterp * pSics, { int id; hdbIDMessage m; + pObjectDescriptor pObj = NULL; if (argc < 2) { SCWrite(pCon, "ERROR: need callback id to remove", eError); @@ -3139,7 +3139,14 @@ static int RemoveHdbCallback(SConnection * pCon, SicsInterp * pSics, id = atoi(argv[1]); m.type = killID; m.ID = id; - RecurseCallbackChains(root, (pHdbMessage) & m); + if(argc < 3){ + RecurseCallbackChains(root, (pHdbMessage) & m); + } else { + pObj = FindCommandDescriptor(pSics,argv[2]); + if(pObj != NULL && pObj->parNode != NULL){ + RecurseCallbackChains(pObj->parNode,(pHdbMessage)&m); + } + } SCSendOK(pCon); return 1; } diff --git a/sicsobj.c b/sicsobj.c index abe477f6..330e5933 100644 --- a/sicsobj.c +++ b/sicsobj.c @@ -459,7 +459,7 @@ static int ListObj(pSICSOBJ self, SConnection * pCon, int argc, /*---------------------------------------------------------------------------*/ int InvokeSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData, - int argc, char *argv[]) + int argc, char *argv[]) { pSICSOBJ self = NULL; int status; @@ -476,50 +476,50 @@ int InvokeSICSOBJ(SConnection * pCon, SicsInterp * pSics, void *pData, if (parNode != NULL && isNodePrintable(parNode)) { status = GetHdbProperty(parNode,"geterror",buffer,sizeof(buffer)); if (status == 1 && strstr(buffer,"none") == NULL){ - SCPrintf(pCon,eValue,"ERROR: %s on last read of %s", buffer, argv[0]); - SCPrintf(pCon,eValue,"%s = -99999", argv[0]); - return 0; - } - status = GetHipadabaPar(parNode, &data, pCon); - if (status != 1) { - return 0; - } - parData = formatValue(data, parNode); - if (parData == NULL) { - SCWrite(pCon, "ERROR: failed to format data", eError); - return 0; - } - SCPrintf(pCon, eValue, "%s = %s", argv[0], GetCharArray(parData)); - DeleteDynString(parData); - return 1; - } else { - SCWrite(pCon, "ERROR: nothing to print", eError); + SCPrintf(pCon,eValue,"ERROR: %s on last read of %s", buffer, argv[0]); + SCPrintf(pCon,eValue,"%s = -99999", argv[0]); + return 0; + } + status = GetHipadabaPar(parNode, &data, pCon); + if (status != 1) { return 0; } - } else { - parNode = GetHipadabaNode(self->objectNode, argv[1]); - if(parNode == NULL){ - strtolower(argv[1]); - parNode = GetHipadabaNode(self->objectNode,argv[1]); + parData = formatValue(data, parNode); + if (parData == NULL) { + SCWrite(pCon, "ERROR: failed to format data", eError); + return 0; } - } - if (parNode != NULL && parNode->value.dataType == HIPFUNC) { - status = invokeOBJFunction(self, parNode, pCon, argc - 2, &argv[2]); + SCPrintf(pCon, eValue, "%s = %s", argv[0], GetCharArray(parData)); + DeleteDynString(parData); + return 1; } else { - snprintf(buffer, sizeof buffer, "%s ", argv[0]); - status = ProcessSICSHdbPar(self->objectNode, pCon, buffer, - argc - 1, &argv[1]); + SCWrite(pCon, "ERROR: nothing to print", eError); + return 0; + } +} else { + parNode = GetHipadabaNode(self->objectNode, argv[1]); + if(parNode == NULL){ + strtolower(argv[1]); + parNode = GetHipadabaNode(self->objectNode,argv[1]); + } +} +if (parNode != NULL && parNode->value.dataType == HIPFUNC) { + status = invokeOBJFunction(self, parNode, pCon, argc - 2, &argv[2]); +} else { + snprintf(buffer, sizeof buffer, "%s ", argv[0]); + status = ProcessSICSHdbPar(self->objectNode, pCon, buffer, + argc - 1, &argv[1]); +} +if (status == -1) { + if (strcmp(argv[1], "makescriptfunc") == 0) { + return MakeScriptFunc(self, pCon, argc, argv); + } else if (strcmp(argv[1], "list") == 0) { + return ListObj(self, pCon, argc, argv); } - if (status == -1) { - if (strcmp(argv[1], "makescriptfunc") == 0) { - return MakeScriptFunc(self, pCon, argc, argv); - } else if (strcmp(argv[1], "list") == 0) { - return ListObj(self, pCon, argc, argv); - } /* error message written by the caller */ - } +} - return status; +return status; } /*---------------------------------------------------------------------------*/ diff --git a/sllinux_def b/sllinux_def index 0e22a767..ee2f5005 100644 --- a/sllinux_def +++ b/sllinux_def @@ -12,4 +12,5 @@ MFLAGS=-f makefile_linux$(DUMMY) HDFROOT=/afs/psi.ch/project/sinq/sl6 TCLINC=. -DBG= -g +#DBG= -g -fstack-protector-all +DBG= -g \ No newline at end of file diff --git a/statemon.c b/statemon.c index 8a7a5364..63167f05 100644 --- a/statemon.c +++ b/statemon.c @@ -124,7 +124,7 @@ static int StateInterest(int iEvent, void *pEvent, void *pUser) /*--------------------------------------------------------------------------*/ static pHdb recurseInterestNode(pHdb current, char *pDevice) { - char pSicsdev[131], pAlias[132]; + char pSicsdev[132], pAlias[132]; pHdb result = NULL; char *alias = NULL, *pPtr = NULL; diff --git a/status.c b/status.c index 34a0bbad..c850e698 100644 --- a/status.c +++ b/status.c @@ -13,6 +13,10 @@ Reworked restore to keep parameters from uninitialized devices Mark Koennecke, November 2007 + Reworked to determine the status from the state of the machine rather then + from explicit sets on a global variable. Which caused trouble, trouble and more + trouble. Mark Koennecke, July 2015 + Copyright: Labor fuer Neutronenstreuung @@ -52,6 +56,10 @@ #include "status.h" #include "interrupt.h" #include "sicshipadaba.h" +#include "messagepipe.h" +#include "scan.h" +#include "exeman.h" +#include "nxscript.h" #undef VALUECHANGE #define VALUECHANGE 2 @@ -97,6 +105,8 @@ static char *iText[] = { static pICallBack pCall = NULL; static int fixed = 0; static Status eCode = eEager; +static int userWait = 0; +static double lastStatus = .0; /*-------------------------------------------------------------------------*/ void KillStatus(void *pData) { @@ -108,24 +118,35 @@ void KillStatus(void *pData) /*--------------------------------------------------------------------------*/ void SetStatus(Status eNew) { - if (!fixed) { +/* if (!fixed) { if (eCode == eNew) { return; } eCode = eNew; InvokeCallBack(pCall, VALUECHANGE, NULL); } +*/ + /* + This now only manages the userWait status + */ + if(eNew == eUserWait){ + userWait = 1; + } else { + if(userWait == 1){ + userWait = 0; + } + } } /*----------------------------------------------------------------------*/ void SetStatusFixed(Status eNew) { - if (eCode == eNew) { - return; - } - eCode = eNew; - InvokeCallBack(pCall, VALUECHANGE, NULL); - fixed = 1; + // if (eCode == eNew) { + // return; + // } + // eCode = eNew; + // InvokeCallBack(pCall, VALUECHANGE, NULL); + // fixed = 1; } /*----------------------------------------------------------------------*/ @@ -279,7 +300,9 @@ int ResetStatus(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, "Insufficient authorisation to reset server", eError); return 0; } - SetStatus(eEager); + // SetStatus(eEager); + eCode = eEager; + InvokeCallBack(pCall, VALUECHANGE, NULL); SetInterrupt(eContinue); ClearExecutor(GetExecutor()); SCsetMacro(pCon, 0); @@ -337,3 +360,149 @@ int RedirectControl(SConnection * pCon, SicsInterp * pSics, void *pData, pOwner->sockHandle = pCon->sockHandle; return 1; } +/*---------------------------------------------------------------------------- +Message pipe based new status calculation code +------------------------------------------------------------------------------*/ + +static int DevexecStatusFunc(void *message, void *userData) +{ + + int *status = (int *)message; + + *status = GetDevExecInstStatus(pServ->pExecutor); + return MPCONTINUE; +} +/*----------------------------------------------------------------------------- +This must be identical to the definition in interface.c As this structure is only +required in interface.c and here, I choose not to put it into an header file. +-------------------------------------------------------------------------------*/ +typedef struct { + int id; + void *obj; + pICountable pCount; + SConnection *pCon; + char *name; +}CountTaskData; +/*-----------------------------------------------------------------------------*/ +static int CheckCountStatus(void *message, void *userData) +{ + int *status = (int *)message; + int testStatus; + pTaskHead it; + CountTaskData *countTask = NULL; + + if(*status == eCounting){ + for(it = TaskIteratorStart(pServ->pTasker); it != NULL; it = TaskIteratorNext(it)){ + countTask = (CountTaskData *)GetTaskData(it); + if(countTask != NULL && countTask->id == COUNTID){ + testStatus = countTask->pCount->CheckCountStatus(countTask->obj,pServ->dummyCon); + if(testStatus == HWNoBeam){ + *status = eOutOfBeam; + } + if(testStatus == HWPause){ + *status = ePaused; + } + } + } + return MPSTOP; + } + return MPCONTINUE; +} +/*---------------------------------------------------------------------------*/ +static pScanData scan = NULL; +static int CheckScan(void *message, void *userData) +{ + char *scannames[] = {"xxxscan","iscan", NULL}; + unsigned int count = 0; + int *status = (int *)message; + + if(*status == eEager){ + if(scan == NULL){ + while(scannames[count] != NULL){ + scan = FindCommandData(pServ->pSics, scannames[count],NULL); + if(scan != NULL){ + break; + } + count++; + } + } + + if(scan != NULL){ + if(isScanRunning(scan)){ + *status = eScanning; + return MPCONTINUE; + } + } +} +return MPCONTINUE; +} +/*----------------------------------------------------------------------------*/ + +static int CheckExe(void *message, void *userData) +{ + int *status = (int *)message; + + if(*status == eEager){ + if(isBatchRunning()){ + *status = eBatch; + } + } + return MPCONTINUE; +} +/*------------------------------------------------------------------------------*/ +static int CheckUserWait(void *message, void *userData) +{ + int *status = (int *)message; + + if(*status == eEager){ + if(isTaskRunning(pServ->pTasker,"wait")){ + *status = eUserWait; + } + } + return MPCONTINUE; +} +/*--------------------------------------------------------------------------------*/ +static int CheckNXScript(void *message, void *userData) +{ + int *status = (int *)message; + + if(*status == eEager){ + if(isNXScriptWriting()){ + *status = eWriting; + } + } + return MPCONTINUE; +} +/*--------------------------------------------------------------------------------*/ +static pMP statusPipe = NULL; + +static void BuildStatusChain(void) +{ + statusPipe = MakeMP(); + AppendMPFilter(statusPipe,DevexecStatusFunc,NULL,NULL); + AppendMPFilter(statusPipe,CheckCountStatus,NULL,NULL); + AppendMPFilter(statusPipe,CheckScan,NULL,NULL); + AppendMPFilter(statusPipe,CheckExe,NULL,NULL); + AppendMPFilter(statusPipe,CheckUserWait,NULL,NULL); + AppendMPFilter(statusPipe,CheckNXScript,NULL,NULL); +} +/*-------------------------------------------------------------------------------*/ +static int StatusTask(void *data) +{ + int status = eEager; + + MPprocess(statusPipe,&status); + if(status != eCode && DoubleTime() > lastStatus + .1){ + eCode = status; + lastStatus = DoubleTime(); + InvokeCallBack(pCall, VALUECHANGE, NULL); + } + + return 1; +} +/*---------------------------------------------------------------------------------*/ +void InitStatus(void) +{ + BuildStatusChain(); + TaskRegisterN(pServ->pTasker,"statustask",StatusTask, NULL, NULL, NULL,1); +} diff --git a/status.h b/status.h index 468e0354..457c6fe8 100644 --- a/status.h +++ b/status.h @@ -27,19 +27,7 @@ typedef enum { } Status; /* for status display */ -void SetStatus(Status eNew); -int SetStatusFromText(char *text); void KillStatus(void *pData); -/** - * set a status and disallow any further changes to the status. This serves - * in order to prevent massive message flows to the client from status - * changes while processing synchronisation files - */ -void SetStatusFixed(Status eNew); -/** - * clear a fixed status again, status will be updated again. - */ -void ClearFixedStatus(Status eNew); Status GetStatus(void); void GetStatusText(char *buf, int iBufLen); @@ -49,5 +37,6 @@ int UserStatus(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); int ResetStatus(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); +void InitStatus(void); #endif diff --git a/stdscan.c b/stdscan.c index c0df18ff..d1cc0234 100644 --- a/stdscan.c +++ b/stdscan.c @@ -903,7 +903,6 @@ int ScanCount(pScanData self, int iPoint) SCWrite(self->pCon, "ERROR: Cannot Count, Scan aborted", eLogError); return 0; } - SetStatus(eCounting); /* wait for finish */ while(DevExecLevelRunning(pServ->pExecutor, RUNDRIVE)){ TaskYield(pServ->pTasker); diff --git a/syncedprot.c b/syncedprot.c index 7d6a87b2..5d5b5aa1 100644 --- a/syncedprot.c +++ b/syncedprot.c @@ -163,10 +163,10 @@ long SyncedBegin(long syncid) return SYNCED_NO_MEMORY; } } - sp++; if (sp >= NSTACK) { return SYNCED_STACK_OVERFLOW; } + sp++; sync->count++; actualSync = sync; return sync->id; @@ -181,13 +181,13 @@ long SyncedEnd(long syncid) if (sp <= 0) { return SYNCED_STACK_UNDERFLOW; } - sync = actualSync; sp--; + sync = actualSync; actualSync = stack[sp]; - sync->count--; - if (sync->count < 0) { + if (sync->count <= 0) { return SYNCED_COUNT_UNDERFLOW; } + sync->count--; if (syncid != 0 && syncid != sync->id) { return SYNCED_ID_MISMATCH; } diff --git a/synchronize.c b/synchronize.c index b8212a48..2f532467 100644 --- a/synchronize.c +++ b/synchronize.c @@ -175,7 +175,6 @@ tryagain: /* first tell the remote server to backup */ - SetStatusFixed(eBatch); strcpy(pBueffel, "transact syncbackup"); if (syncFile != NULL) { strcat(pBueffel, " "); @@ -187,7 +186,6 @@ tryagain: NETClosePort(connection); free(connection); connection = NULL; - ClearFixedStatus(eEager); if (try > 0) goto tryagain; SCWrite(pCon, "ERROR: Failed to contact main SICS server", eError); @@ -207,7 +205,6 @@ tryagain: NETClosePort(connection); free(connection); connection = NULL; - ClearFixedStatus(eEager); pServ->simMode = 1; if (try > 0) goto tryagain; @@ -247,7 +244,6 @@ tryagain: internalCon = SCCreateDummyConnection(pSics); if (internalCon == NULL) { SCWrite(pCon, "ERROR: out of memory in sync", eError); - ClearFixedStatus(eEager); return 0; } @@ -258,7 +254,6 @@ tryagain: } test = InterpExecute(pSics, internalCon, pBueffel); SCDeleteConnection(internalCon); - ClearFixedStatus(eEager); if (test != 1) { SCWrite(pCon, "ERROR: Failed to read sync information", eError); return 0; diff --git a/tasdrive.c b/tasdrive.c index 852dc1e0..4808f7ca 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -352,6 +352,7 @@ static int startMotors(ptasMot self, tasAngles angles, { double curve; int status, silent, stopFixed; + long monoID; silent = self->math->silent; stopFixed = self->math->stopFixed; @@ -363,12 +364,25 @@ static int startMotors(ptasMot self, tasAngles angles, monochromator */ status = self->math->mono->SetValue(self->math->monoData, - pCon,angles.monochromator_two_theta); + pCon,angles.monochromator_two_theta); + /* + The call to CheckStatus is necessary because the eiger monochromator may not + start until then. Deferred until all parameters are known. + */ + self->math->mono->CheckStatus(self->math->monoData,pCon); if(status != OKOK){ return status; } else { AddTaskToGroup(pServ->pTasker, self->math->monoTaskID, self->math->groupID); } + /* monoID = StartDriveTask(self->math->monoData, pCon,"mono", */ + /* angles.monochromator_two_theta); */ + /* self->math->mono->CheckStatus(self->math->monoData,pCon); */ + /* if(monoID < 0){ */ + /* SCWrite(pCon,"ERROR: failed to start monochromator",eLogError); */ + /* } else { */ + /* AddTaskToGroup(pServ->pTasker,monoID, self->math->groupID); */ + /* } */ /* analyzer @@ -583,7 +597,8 @@ static int checkMotors(ptasMot self, SConnection * pCon) { self->math->mustRecalculate = 1; - if(isTaskGroupRunning(pServ->pTasker,self->math->groupID)){ + if(isTaskGroupRunning(pServ->pTasker,self->math->groupID) || + isTaskGroupRunning(pServ->pTasker,self->math->monoTaskID)){ return HWBusy; } else { return HWIdle; diff --git a/task.c b/task.c index ad93c6d9..a511357f 100644 --- a/task.c +++ b/task.c @@ -24,8 +24,12 @@ #define READY 1 #define WAITING 2 #define YIELDING 3 + +#define IDUNDEFINED 0L +#define TASKMAGIC 777111999 /*--------------------------------------------------------------------------*/ typedef struct __TaskHead { + long magic; long lID; long groupID; int iStatus; @@ -46,8 +50,12 @@ typedef struct __TaskMan { pTaskHead pCurrent; /* Think trice before you interfere with this! */ pTaskHead pHead; } TaskMan; -/*---------------------------------------------------------------------------*/ -static long lIDMama = 0L; +/*--------------------------------------------------------------------------- +The 7 below solves a subtle bug which occurs when a groupID in user code +has been initialized to 0 and starting fails. Then it seems as if this +group keeps running. As there will always be some task running at 0. + ----------------------------------------------------------------------------*/ +static long lIDMama = 7L; #define TASKERID 123399 /*---------------------------------------------------------------------------*/ @@ -62,6 +70,7 @@ static pTaskHead MakeTaskHead(char *name, TaskFunc pTask, SignalFunc pSignal, } memset(pNew, 0, sizeof(TaskHead)); + pNew->magic = TASKMAGIC; pNew->name = strdup(name); pNew->start_time = time(NULL); pNew->pRun = pTask; @@ -71,9 +80,10 @@ static pTaskHead MakeTaskHead(char *name, TaskFunc pTask, SignalFunc pSignal, lIDMama++; pNew->lID = lIDMama; pNew->iStatus = READY; + pNew->groupID = IDUNDEFINED; if(lIDMama < 0){ - lIDMama = 0; + lIDMama = 7; } return pNew; @@ -99,6 +109,7 @@ static void DeleteTaskHead(pTaskHead self) if (self->pNext != NULL) { self->pNext->pPrevious = self->pPrevious; } + memset(self,0,sizeof(TaskHead)); free(self); } @@ -485,7 +496,7 @@ pTaskHead TaskIteratorStart(pTaskMan self) /*-----------------------------------------------------------------------------*/ pTaskHead TaskIteratorNext(pTaskHead it) { - if(it != NULL){ + if(it != NULL && it->magic == TASKMAGIC){ return it->pNext; } return NULL; @@ -529,7 +540,7 @@ long GetTaskID(pTaskHead it) /*------------------------------------------------------------------------------*/ long GetGroupID(pTaskHead it) { - return it-> groupID; + return it->groupID; } /*------------------------------------------------------------------------------*/ const char * GetTaskName(pTaskHead it) @@ -537,6 +548,15 @@ const char * GetTaskName(pTaskHead it) return (const char*)it->name; } /*------------------------------------------------------------------------------*/ +const void *GetTaskData(pTaskHead it) +{ + if(it->magic == TASKMAGIC){ + return (const void*)it->pData; + } else { + return NULL; + } +} +/*------------------------------------------------------------------------------*/ long GetTaskGroupID(pTaskMan self) { lIDMama++; @@ -569,13 +589,15 @@ int isTaskGroupRunning(pTaskMan self, long groupID) pTaskHead pCurrent, pNext; if (self == NULL) return 0; + if (groupID == IDUNDEFINED) return 0; + assert(self->iID == TASKERID); pNext = self->pHead->pNext; /* skip dummy task */ while (pNext != NULL) { pCurrent = pNext; pNext = pCurrent->pNext; - if (pCurrent->groupID == groupID) { + if (pCurrent->groupID != IDUNDEFINED && pCurrent->groupID == groupID) { return 1; } } diff --git a/task.h b/task.h index 4cd0c729..03d6636c 100644 --- a/task.h +++ b/task.h @@ -197,7 +197,10 @@ const char *GetTaskName(pTaskHead it); /* get the name of the current task. Do not delete the returned pointer. */ - +const void *GetTaskData(pTaskHead it); +/* + Get the user data for the current task. Do not free the returned pointer! +*/ /*============================================================================= Task Groups. The implementation has the limit that any given task can only be member of one task group diff --git a/taskobj.c b/taskobj.c index 99a8ad8f..3a3757b8 100644 --- a/taskobj.c +++ b/taskobj.c @@ -89,8 +89,10 @@ static int TclTaskFunction(void *pData) MacroPush(self->con); status = Tcl_Eval(pTcl, self->scriptName); MacroPop(); + /* traceSys("task","Executed %s with results %d and %s",self->scriptName, status, Tcl_GetStringResult(pTcl)); + */ if(status == 0){ retVal = atoi(Tcl_GetStringResult(pTcl)); } else { diff --git a/tasmono.c b/tasmono.c index f538d989..0129d6ae 100644 --- a/tasmono.c +++ b/tasmono.c @@ -8,6 +8,13 @@ * copyright: see file COPYRIGHT * * Mark Koennecke, February 2013 + * + * TODO: this may need a refactoring towards a monochromator object with its + * own parameters and such. Eiger would have benefitted from this. This here + * just implements a drivable interface on top of the tasub parameters. As EIGER + * is now working; this has gone low priority. + * + * Mark Koennecke, September 2014 */ #include #include "tasmono.h" diff --git a/tasscanub.c b/tasscanub.c index 0fb62607..a1ce7343 100644 --- a/tasscanub.c +++ b/tasscanub.c @@ -771,7 +771,6 @@ static int TASUBScanCount(pScanData self, int iPoint) } else { status = 1; } - SetStatus(eOld); return status; } diff --git a/tasscanub.h b/tasscanub.h index faf0bb89..868af18c 100644 --- a/tasscanub.h +++ b/tasscanub.h @@ -5,7 +5,7 @@ Mark Koennecke, May 2005, using code from an earlier TASAMAD emulation core. ------------------------------------------------------------------------*/ -#ifndef SICUBSTAS +#ifndef SICSUBTAS #define SICSUBTAS #include #include "tasub.h" diff --git a/tasub.c b/tasub.c index 3694c347..e76e248c 100644 --- a/tasub.c +++ b/tasub.c @@ -15,6 +15,7 @@ Mark Koennecke, September 2011 ----------------------------------------------------------------------*/ #include + #include #include "sics.h" #include "lld.h" #include "SCinter.h" @@ -971,7 +972,7 @@ static void listDiagnostik(ptasUB self, SConnection * pCon) static int addAuxReflection(ptasUB self, SConnection * pCon, SicsInterp * pSics, int argc, char *argv[]) { - int status; + int status, ss; tasReflection r1, r2; float value = -999.99; char pBueffel[256]; @@ -1027,7 +1028,8 @@ static int addAuxReflection(ptasUB self, SConnection * pCon, r2.qe.kf = self->current.kf; r2.qe.ki = self->current.ki; GetDrivablePosition(self->motors[A3], pCon, &value); - r2.angles.a3 = value + 180.; + ss = self->machine.ss_sample; + r2.angles.a3 = fmod(value + ss*180.,360.) - ss*180.; r2.angles.sgu = .0; r2.angles.sgl = .0; calcTwoTheta(B, r2.qe, self->machine.ss_sample, diff --git a/tasublib.c b/tasublib.c index 5e2a28ce..a8ea3907 100644 --- a/tasublib.c +++ b/tasublib.c @@ -184,7 +184,7 @@ double tasAngleBetweenReflections(MATRIX B, tasReflection r1, chi1 = mat_mul(B, h1); chi2 = mat_mul(B, h2); if (chi1 != NULL && chi2 != NULL) { - angle = angleBetween(chi1, chi2); + angle = tasAngleBetween(chi1, chi2); killVector(chi1); killVector(chi2); } @@ -271,8 +271,9 @@ int makeAuxReflection(MATRIX B, tasReflection r1, tasReflection * r2, r2->qe.ki = r1.qe.ki; r2->qe.kf = r1.qe.kf; - theta = calcTheta(r1.qe.ki, r1.qe.kf, r1.angles.sample_two_theta); - om = r1.angles.a3 - theta; + theta = calcTheta(r1.qe.ki, r1.qe.kf, + ss*r1.angles.sample_two_theta); + om = r1.angles.a3 - ss*theta; om += tasAngleBetweenReflections(B, r1, *r2); QC = tasReflectionToHC(r2->qe, B); @@ -289,12 +290,17 @@ int makeAuxReflection(MATRIX B, tasReflection r1, tasReflection * r2, return TRIANGLENOTCLOSED; } r2->angles.sample_two_theta = ss * Acosd(cos2t); - theta = calcTheta(r1.qe.ki, r1.qe.kf, r2->angles.sample_two_theta); - r2->angles.a3 = om + theta; + theta = calcTheta(r1.qe.ki, r1.qe.kf, ss*r2->angles.sample_two_theta); + r2->angles.a3 = om + ss*theta; + + r2->angles.a3 = fmod(r2->angles.a3 + ss*180.,360.) - ss*180.; + + /* r2->angles.a3 -= 180.; if (r2->angles.a3 < -180.) { r2->angles.a3 += 360.; } + */ mat_free(QC); return 1; @@ -415,22 +421,16 @@ MATRIX calcPlaneNormalQ(MATRIX UB, tasReflection r1, tasReflection r2) return planeNormal; } -/*--------------------------------------------------------------------*/ -MATRIX calcTestUB(lattice cell, double om, double sgu, double sgl) +/*-------------------------------------------------------------------- + This is shot. The resulting UB is invalid. This needs more throught. + +*/ +MATRIX calcUBFromAngles(MATRIX B, double om, double sgu, double sgl) { - MATRIX B, M, N, OM, UB; + + MATRIX M, N, OM, UB; int status; - /* - * create matrices - */ - B = mat_creat(3, 3, ZERO_MATRIX); - - status = calculateBMatrix(cell, B); - if (status < 0) { - return NULL; - } - M = mat_creat(3, 3, ZERO_MATRIX); N = mat_creat(3, 3, ZERO_MATRIX); OM = mat_creat(3, 3, ZERO_MATRIX); @@ -468,11 +468,30 @@ MATRIX calcTestUB(lattice cell, double om, double sgu, double sgl) mat_free(OM); mat_free(N); mat_free(M); - mat_free(B); return UB; } /*--------------------------------------------------------------------*/ +MATRIX calcTestUB(lattice cell, double om, double sgu, double sgl) +{ + MATRIX B, UB; + int status; + + /* + * create matrices + */ + B = mat_creat(3, 3, ZERO_MATRIX); + + status = calculateBMatrix(cell, B); + if (status < 0) { + return NULL; + } + UB = calcUBFromAngles(B,om,sgu,sgl); + + mat_free(B); + return UB; +} +/*--------------------------------------------------------------------*/ MATRIX calcTestNormal(double sgu, double sgl) { MATRIX M, N, Z, NORM; diff --git a/tasublib.h b/tasublib.h index 15ef992f..3bccc5c3 100644 --- a/tasublib.h +++ b/tasublib.h @@ -186,21 +186,33 @@ MATRIX calcTasUBFromTwoReflections(lattice cell, tasReflection r1, */ MATRIX calcTestNormal(double sgu, double sgl); /** - * calculate a test UB - * @param cell The lattice constant of the crystal + * calculate a test UB from angles + * @param cell The B lattice constants * @param om A theoretical om for the crystal * @param sgu A theoretical plane tilt on upper * @param sgl A theoretical plane tilt on lower - * @return a UB matix on sucess, or NULL on failure. This can only happen + * @return a UB matrix on sucess, or NULL on failure. This can only happen * when out of memory or with a bad cell */ MATRIX calcTestUB(lattice cell, double om, double sgu, double sgl); +/** + * calculate a test UB + * @param B The B matrix as calculated from the cell constants + * @param om A theoretical om for the crystal + * @param sgu A theoretical plane tilt on upper + * @param sgl A theoretical plane tilt on lower + * @return a UB matrix on sucess, or NULL on failure. This can only happen + * when out of memory or with a bad cell + */ +MATRIX calcUBFromAngles(MATRIX B, double om, double sgu, double sgl); + /** * calcluate the normal to the plane describe by the two reflections r1, r2 * @param r1 first reflection * @param r2 second reflection * @return a plane normal on success, NULL else */ + MATRIX calcPlaneNormal(tasReflection r1, tasReflection r2); /** * calcluate the normal to the plane describe by the two reflections r1, r2 diff --git a/trace.c b/trace.c index 96364900..db2dade1 100644 --- a/trace.c +++ b/trace.c @@ -37,6 +37,7 @@ static int hdbInit = 0; static int filterProv = 0; static int debug = 0; static int lastTen = -10; +static long traceStamperID = -1; /*----------------------------------------------------------------------------------------*/ int traceActive() { @@ -468,12 +469,56 @@ static int TraceLog(pSICSOBJ ccmd, SConnection * con, TraceObjects(); hdbInit = 1; } - TaskRegisterN(pServ->pTasker,"tracestamper", - TraceLogTask, NULL, NULL, NULL, 1); + if(traceStamperID < 0){ + traceStamperID = TaskRegisterN(pServ->pTasker,"tracestamper", + TraceLogTask, NULL, NULL, NULL, 1); + } } } return 1; } +/*----------------------------------------------------------------*/ +static int TraceAppend(pSICSOBJ ccmd, SConnection * con, + Hdb * cmdNode, Hdb * par[], int nPar) +{ + char *filename = NULL; + + if(nPar < 1) { + if(logFD != NULL){ + SCPrintf(con,eValue,"Tracing to %s", logfile); + } else { + SCWrite(con,"Tracing is off", eValue); + } + return 1; + } + + filename = par[0]->value.v.text; + /* + This is good even if appending to the same file: + it flushes all buffers + */ + if(logFD != NULL){ + fclose(logFD); + free(logfile); + } + logFD = fopen(filename,"a+"); + if(logFD == NULL){ + SCPrintf(con,eError,"ERROR: failed to open %s for logging", filename); + return 0; + } else { + logfile = strdup(filename); + saveInitialParameters(); + SCPrintf(con,eValue,"Logging to %s", filename); + if(hdbInit == 0){ + TraceObjects(); + hdbInit = 1; + } + TaskRegisterN(pServ->pTasker,"tracestamper", + TraceLogTask, NULL, NULL, NULL, 1); + } + return 1; +} + /*-----------------------------------------------------------------------------*/ static int TraceDebug(pSICSOBJ ccmd, SConnection * con, Hdb * cmdNode, Hdb * par[], int nPar) @@ -520,6 +565,11 @@ void MakeTrace(void) "log", usMugger, MakeSICSFunc(TraceLog)); AddSICSHdbPar(cmd, "filename", usMugger, MakeHdbText("")); + cmd = AddSICSHdbPar(ccmd->objectNode, + "append", usMugger, MakeSICSFunc(TraceAppend)); + AddSICSHdbPar(cmd, "filename", usMugger, MakeHdbText("")); + + cmd = AddSICSHdbPar(ccmd->objectNode, "filter", usMugger, MakeSICSFunc(TraceFilter)); AddSICSHdbPar(cmd, "selection", usMugger, MakeHdbInt(0)); diff --git a/vector.c b/vector.c index a508ff9e..bbf42d38 100644 --- a/vector.c +++ b/vector.c @@ -189,6 +189,37 @@ double angleBetween(MATRIX v1, MATRIX v2) } return angle; } +/*----------------------------------------------------------------------- + angleBetween gives only angles between 0 - 180. This is also the + only thing there is; the direction of the rotation depends on the + viewpoint and thus is ill defined. This version determines the + sign of the rotation from v3[2]. I made a special version in order not + to trouble other uses of angleBetween. + -----------------------------------------------------------------------*/ + +double tasAngleBetween(MATRIX v1, MATRIX v2) +{ + double angle, angles, sum; + MATRIX v3 = NULL; + int i; + + angle = vectorDotProduct(v1, v2) / (vectorLength(v1) * vectorLength(v2)); + v3 = vectorCrossProduct(v1, v2); + if (v3 != NULL) { + angles = vectorLength(v3) / (vectorLength(v1) * vectorLength(v2)); + angle = Atan2d(angles, angle); + for(i = 0, sum = .0; i < 3; i++){ + sum += v3[i][0]; + } + if(sum < 0){ + angle *= -1.; + } + } else { + angle = Acosd(angle); + } + return angle; +} + /*----------------------------------------------------------------------*/ void scaleVector(MATRIX v, double scale) diff --git a/vector.h b/vector.h index c2c9b5ea..7fcef878 100644 --- a/vector.h +++ b/vector.h @@ -91,12 +91,20 @@ MATRIX vectorCrossProduct(MATRIX v1, MATRIX v2); */ MATRIX matFromTwoVectors(MATRIX v1, MATRIX v2); /** - * calculate the nagle between two vectors + * calculate the angle between two vectors * @param v1 first vector * @param v2 second vector * @return angle in degree */ double angleBetween(MATRIX v1, MATRIX v2); +/** + * calculate the angle between two vectors. Try to determine the + * sign of the rotation + * @param v1 first vector + * @param v2 second vector + * @return angle in degree + */ +double tasAngleBetween(MATRIX v1, MATRIX v2); /** * scale the vector v with scale diff --git a/velo.c b/velo.c index 797bcc23..500d60e2 100644 --- a/velo.c +++ b/velo.c @@ -588,10 +588,7 @@ int VSGetLossCurrent(pVelSel self, SConnection * pCon, float *fLoss) assert(self); assert(pCon); - eOld = GetStatus(); - SetStatus(eRunning); iRet = self->pDriv->GetLossCurrent(self->pDriv, fLoss); - SetStatus(eOld); if (!iRet) { self->pDriv->GetError(self->pDriv, &iCode, pError, 131); snprintf(pBueffel,sizeof(pBueffel)-1, "ERROR: %s while trying to measure loss current", @@ -1161,9 +1158,7 @@ int VelSelAction(SConnection * pCon, SicsInterp * pSics, void *pData, eError); return 0; } - SetStatus(eDriving); iRet = VSSetTiltRot(self, pCon, fRot, fTilt); - SetStatus(eEager); if (iRet) { SCSendOK(pCon); return 1;