From fc8798d0121076cea6b26e680c592b3a2c5896e4 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Wed, 26 Feb 2014 17:17:08 +0100 Subject: [PATCH 01/34] Reenabled EPICS motor support in order to make the attoCube controller work --- make_gen | 4 ++-- motor.c | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/make_gen b/make_gen index 8f0e4581..d8154fb1 100644 --- a/make_gen +++ b/make_gen @@ -5,8 +5,8 @@ # Markus Zolliker March 2003 #--------------------------------------------------------------------------- -#EPICSOBJ=epicsmotor.o -EPICSOBJ= +EPICSOBJ=epicsmotor.o +#EPICSOBJ= COBJ = Sclient.o network.o ifile.o intcli.o $(FORTIFYOBJ) SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \ diff --git a/motor.c b/motor.c index a0be2715..c07cb051 100644 --- a/motor.c +++ b/motor.c @@ -1066,19 +1066,22 @@ 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; } - + pNew = MotorInit("epics", argv[1], pDriver); + if (!pNew) { + snprintf(pBueffel,sizeof(pBueffel)-1, "Failure to create motor %s", argv[1]); + SCWrite(pCon, pBueffel, eLogError); + return 0; + } } else { SCWrite(pCon,"ERROR: missing basename argument to create EPICS motor",eError); return 0; } - */ } else { site = getSite(); if (site != NULL) { From 722fab935e97bd15e5eb94eb8265a96bfc2d8a7d Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Mon, 7 Apr 2014 14:02:07 +0200 Subject: [PATCH 02/34] Fixed a task and a tasdrive issue There is a rare condition when SICS has frehsly stared up and on the first call to a coordinated driving, like in TAS, something fails. Then the group has ID 0, the default and that one is always active. This has been fixed by starting valid groups at 7, defining 0 ans IDUNDEFINED and checking in isTaskGroupRunning for IDUNDEFINED Then there is an issue in tasdrive. I added a call to CheckStatus when starting the mono. This is necessary for the eiger monochromator as with that one starting is deferred to the CheckSttaus function. The reason is that in other use cases, the looser might want to drive a2 and a2w at the same time. This can only correctly be accomodated by deferring the caclulations to the CheckStatus phase. --- interface.c | 2 +- tasdrive.c | 5 +++++ task.c | 19 ++++++++++++++----- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/interface.c b/interface.c index c8b9bc4e..1fe00113 100644 --- a/interface.c +++ b/interface.c @@ -250,7 +250,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, diff --git a/tasdrive.c b/tasdrive.c index 852dc1e0..4ba2144f 100644 --- a/tasdrive.c +++ b/tasdrive.c @@ -364,6 +364,11 @@ static int startMotors(ptasMot self, tasAngles angles, */ status = self->math->mono->SetValue(self->math->monoData, 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 { diff --git a/task.c b/task.c index ad93c6d9..be911cdc 100644 --- a/task.c +++ b/task.c @@ -24,6 +24,8 @@ #define READY 1 #define WAITING 2 #define YIELDING 3 + +#define IDUNDEFINED 0L /*--------------------------------------------------------------------------*/ typedef struct __TaskHead { long lID; @@ -46,8 +48,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 /*---------------------------------------------------------------------------*/ @@ -71,9 +77,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; @@ -529,7 +536,7 @@ long GetTaskID(pTaskHead it) /*------------------------------------------------------------------------------*/ long GetGroupID(pTaskHead it) { - return it-> groupID; + return it->groupID; } /*------------------------------------------------------------------------------*/ const char * GetTaskName(pTaskHead it) @@ -569,13 +576,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; } } From 8e1ac545ce5b1312af37ee4e955326710c40f484 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Thu, 10 Apr 2014 10:53:18 +0200 Subject: [PATCH 03/34] Linked epics statically --- commandlog.h | 2 +- hipadaba.h | 2 +- make_gen | 2 +- makefile_slinux | 5 ++++- network.c | 7 ++++--- sicshdbadapter.c | 4 ++-- sicshipadaba.c | 2 +- sllinux_def | 2 +- 8 files changed, 15 insertions(+), 11 deletions(-) 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/hipadaba.h b/hipadaba.h index 09e49336..be087396 100644 --- a/hipadaba.h +++ b/hipadaba.h @@ -71,7 +71,7 @@ typedef struct __hipadaba { struct __hdbcallback *callBackChain; char *name; hdbValue value; - int protected; + int iprotected; pStringDict properties; } Hdb, *pHdb; /*-------------- return values for callback functions -------------------------*/ diff --git a/make_gen b/make_gen index d8154fb1..64962730 100644 --- a/make_gen +++ b/make_gen @@ -69,7 +69,7 @@ all: libmat libhlib libtecsl libpsi SICServer full: purge all SICServer: $(OBJ) $(SUBLIBS) - $(CC) $(DBG) -o SICServer $(OBJ) $(LIBS) + g++ $(DBG) -o SICServer $(OBJ) $(LIBS) matrix/libmatrix.a: libmat diff --git a/makefile_slinux b/makefile_slinux index 09e3af71..a384635c 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) \ diff --git a/network.c b/network.c index be90cf31..4e2d2031 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); @@ -607,7 +607,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 +842,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/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/sicshipadaba.c b/sicshipadaba.c index 82da1b6f..2e7ec442 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -2342,7 +2342,7 @@ static int isNodeProtected(pHdb node) { pHdb current = NULL; - if (node->protected == 1) { + if (node->iprotected == 1) { return 1; } current = node->child; diff --git a/sllinux_def b/sllinux_def index 0e22a767..bdd73884 100644 --- a/sllinux_def +++ b/sllinux_def @@ -12,4 +12,4 @@ MFLAGS=-f makefile_linux$(DUMMY) HDFROOT=/afs/psi.ch/project/sinq/sl6 TCLINC=. -DBG= -g +DBG= -g From b466a2d4272bab476e81f1c1cb119963f8c5e285 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Thu, 10 Apr 2014 14:24:38 +0200 Subject: [PATCH 04/34] Fixed another bug with sget mot softzero --- sicsget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sicsget.c b/sicsget.c index c4ecc55c..69e6dbd0 100644 --- a/sicsget.c +++ b/sicsget.c @@ -192,7 +192,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)," "); } From 72f9e59150eeb35ed797081338812a9a022949ac Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Mon, 5 May 2014 13:52:00 +0200 Subject: [PATCH 05/34] Multiple bug fixes - Arrayutil was not summing correctly - Added interest to motorsec in order to support old status clients - core dump because of bad free in devser - fixed transferring of count time in multicounter - added stack debugging to sllinux_def - Modifications to tasdrive to wait for finish of monochromator properly --- arrayutil.c | 15 ++++++--- counter.c | 6 ++-- countersec.c | 37 ++++++++++++++++++++++ devser.c | 3 +- motorsec.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++ multicountersec.c | 11 +++++-- sllinux_def | 2 +- tasdrive.c | 16 ++++++++-- 8 files changed, 156 insertions(+), 13 deletions(-) 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/counter.c b/counter.c index 53b4ac80..38593a4e 100644 --- a/counter.c +++ b/counter.c @@ -835,7 +835,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 +853,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 +962,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/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/motorsec.c b/motorsec.c index 3f6710b5..af3cf59e 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) { @@ -655,6 +656,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 +868,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..3dc133f6 100644 --- a/multicountersec.c +++ b/multicountersec.c @@ -134,6 +134,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 { @@ -234,12 +235,12 @@ static hdbCallbackReturn MultiSecControllCallback(pHdb node, /*-------------------------------------------------------------------------------------*/ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) { - pHdb mID, master, myStatus, control, ccd, stopTime; + pHdb mID, master, myStatus, control, ccd, stopTime, timeNode; hdbValue v; long mlID; void *data; pICountable pCount; - float controlVal; + float controlVal, tVal; mID = GetHipadabaNode(self->objectNode,"masterID"); master = GetHipadabaNode(self->objectNode,"master"); @@ -247,12 +248,14 @@ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *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); mlID = mID->value.v.intValue; @@ -269,6 +272,8 @@ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) *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: @@ -296,6 +301,8 @@ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) *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); } diff --git a/sllinux_def b/sllinux_def index bdd73884..0ebae7a9 100644 --- a/sllinux_def +++ b/sllinux_def @@ -12,4 +12,4 @@ MFLAGS=-f makefile_linux$(DUMMY) HDFROOT=/afs/psi.ch/project/sinq/sl6 TCLINC=. -DBG= -g +DBG= -g -fstack-protector-all diff --git a/tasdrive.c b/tasdrive.c index 4ba2144f..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,9 +364,9 @@ 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 + 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); @@ -374,6 +375,14 @@ static int startMotors(ptasMot self, tasAngles angles, } 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 @@ -588,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; From e89b640088fe64cb2afcb2c88ed0ad9e2bbc0ed5 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Wed, 7 May 2014 14:24:44 +0200 Subject: [PATCH 06/34] Bug fixes - transfer of monitor values in mutlicountersec - Permission denied mesage when restarting a second generation motor fixed --- motorsec.c | 2 +- multicountersec.c | 70 +++++++++++++++++++++++++++++------------------ 2 files changed, 44 insertions(+), 28 deletions(-) diff --git a/motorsec.c b/motorsec.c index af3cf59e..e0f01a06 100644 --- a/motorsec.c +++ b/motorsec.c @@ -271,7 +271,7 @@ static int checkPosition(pMotor self, SConnection * pCon) SetHipadabaPar(node, MakeHdbFloat(target), pCon); node = GetHipadabaNode(self->pDescriptor->parNode, "targetposition"); assert(node != NULL); - SetHipadabaPar(node, MakeHdbFloat(target), pCon); + UpdateHipadabaPar(node, MakeHdbFloat(target), pCon); return HWBusy; } return HWIdle; diff --git a/multicountersec.c b/multicountersec.c index 3dc133f6..00dda9d8 100644 --- a/multicountersec.c +++ b/multicountersec.c @@ -16,6 +16,12 @@ #include #include #include "sicshipadaba.h" +/*---------------------------------------------------------------------------*/ +typedef struct { + float fPreset; + float fCurrent; + char *pName; +} MonEvent, *pMonEvent; /*-------------------------------------------------------------------------*/ static void SecCounterSetError(pCounter self, char *text) { @@ -232,6 +238,31 @@ static hdbCallbackReturn MultiSecControllCallback(pHdb node, return hdbContinue; } +/*--------------------------------------------------------------------------*/ +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; +} /*-------------------------------------------------------------------------------------*/ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) { @@ -241,6 +272,7 @@ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) void *data; pICountable pCount; float controlVal, tVal; + MonEvent sMon; mID = GetHipadabaNode(self->objectNode,"masterID"); master = GetHipadabaNode(self->objectNode,"master"); @@ -291,6 +323,16 @@ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) 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 { @@ -360,7 +402,7 @@ static void multiEndCounting(pCounter self, SConnection *pCon) InvokeCallBack(self->pCall, COUNTEND, NULL); ReleaseCountLock(self->pCountInt); - + MultiSecTransfer(self,pCon); } /*-------------------------------------------------------------------------------------*/ @@ -385,32 +427,6 @@ static int MultiSecStatus(void *pData, SConnection * 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 -----------------------------------------------------------------------------*/ From 325fc6f313685fa524557a9338649cbe6192011e Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Fri, 9 May 2014 16:48:23 +0200 Subject: [PATCH 07/34] Fixed a bug with restarting after mipositioning in motorsec.c --- motorsec.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/motorsec.c b/motorsec.c index e0f01a06..28e77685 100644 --- a/motorsec.c +++ b/motorsec.c @@ -269,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); - UpdateHipadabaPar(node, MakeHdbFloat(target), pCon); return HWBusy; } return HWIdle; From 4f5bcaeb5e457ab28b469767bee79cfddf962363 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Wed, 21 May 2014 09:58:23 +0200 Subject: [PATCH 08/34] Assorted bug fixes - In network.c and asynnet.c code was added to close the socket when a connect failed. Otherwise the socket would leak and the process runs out of file descriptors. - Multicountserc now forcefully handles the counting status. Before I had the status flickering between counting and nobeam because the HM has no way to diagnose nobeam - In motorsec.c the pDrivInt->iErrorCount was not reset to 0 properly. Leading to death. - Removed the stack smashing test flag for the time being. --- asynnet.c | 1 + interface.c | 2 ++ motorsec.c | 1 + multicountersec.c | 11 ++++++++++- network.c | 1 + sllinux_def | 2 +- 6 files changed, 16 insertions(+), 2 deletions(-) diff --git a/asynnet.c b/asynnet.c index 8aa349b1..b9e688d5 100644 --- a/asynnet.c +++ b/asynnet.c @@ -247,6 +247,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; } diff --git a/interface.c b/interface.c index 1fe00113..c10fe697 100644 --- a/interface.c +++ b/interface.c @@ -235,9 +235,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"); } + SetStatus(eEager); return 0; } /*--------------------------------------------------------------------------*/ diff --git a/motorsec.c b/motorsec.c index 28e77685..51853b70 100644 --- a/motorsec.c +++ b/motorsec.c @@ -509,6 +509,7 @@ static hdbCallbackReturn SecMotorCallback(pHdb node, void *userData, self->name); SCWrite(pCon, pBueffel, eWarning); self->errorCount = 0; + self->pDrivInt->iErrorCount = 0; } /* diff --git a/multicountersec.c b/multicountersec.c index 00dda9d8..2b4bbc1e 100644 --- a/multicountersec.c +++ b/multicountersec.c @@ -15,6 +15,7 @@ #include #include #include +#include #include "sicshipadaba.h" /*---------------------------------------------------------------------------*/ typedef struct { @@ -313,14 +314,20 @@ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); SecCounterSetError(self,"Master counter errror"); *status = HWBusy; + ClearFixedStatus(eCounting); break; case HWPause: UpdateHipadabaPar(myStatus,MakeHdbText("paused"),pCon); + *status = HWPause; + SetStatusFixed(ePaused); break; case HWNoBeam: UpdateHipadabaPar(myStatus,MakeHdbText("nobeam"),pCon); + *status = HWNoBeam; + SetStatusFixed(eOutOfBeam); break; default: + SetStatusFixed(eCounting); *status = HWBusy; UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); if (self->iCallbackCounter > 20) { @@ -403,6 +410,7 @@ static void multiEndCounting(pCounter self, SConnection *pCon) InvokeCallBack(self->pCall, COUNTEND, NULL); ReleaseCountLock(self->pCountInt); MultiSecTransfer(self,pCon); + ClearFixedStatus(eEager); } /*-------------------------------------------------------------------------------------*/ @@ -420,11 +428,12 @@ static int MultiSecStatus(void *pData, SConnection * pCon) } if(areSlavesRunning(self,pCon, &status)){ + SetStatusFixed(eCounting); return status; } multiEndCounting(self,pCon); - + return HWIdle; } /*--------------------------------------------------------------------------- diff --git a/network.c b/network.c index 4e2d2031..3fcc6a66 100644 --- a/network.c +++ b/network.c @@ -288,6 +288,7 @@ mkChannel *NETConnectWithFlags(char *name, int port, int flags) iRet = connect(pRes->sockid, (struct sockaddr *) &(pRes->adresse), sizeof(struct sockaddr_in)); if (iRet < 0) { + close(pRes->sockid); if (errno != EINPROGRESS) { free(pRes); return NULL; diff --git a/sllinux_def b/sllinux_def index 0ebae7a9..0e22a767 100644 --- a/sllinux_def +++ b/sllinux_def @@ -12,4 +12,4 @@ MFLAGS=-f makefile_linux$(DUMMY) HDFROOT=/afs/psi.ch/project/sinq/sl6 TCLINC=. -DBG= -g -fstack-protector-all +DBG= -g From d1060a3368a0e3c34f5ba6d56b1b6074566c1219 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Thu, 22 May 2014 09:02:33 +0200 Subject: [PATCH 09/34] - Added and commented out padding handling in nxscript puts. Now HDF5 shortens my strings.... --- nxscript.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/nxscript.c b/nxscript.c index fb93a260..810417cf 100644 --- a/nxscript.c +++ b/nxscript.c @@ -1491,6 +1491,37 @@ 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, 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*sizeof(char)); + if(pPtr != NULL){ + memset(pPtr,0,len*sizeof(char)); + strncpy(pPtr,pEnd+1,len); + for(i = strlen(pPtr); i < len-1; i++){ + pPtr[i] = ' '; + } + free(self->v.v.text); + self->v.v.text = pPtr; + } + } + return MPCONTINUE; +} /*------------------------------------------------------------------------*/ static int SPutDim(void *message, void *userData) { @@ -1604,6 +1635,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); } From 9172b70462a0dc9ec920916f49bb7fa96ba2dc24 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Thu, 22 May 2014 10:47:39 +0200 Subject: [PATCH 10/34] - Fixed a stack smashing bug in statemon.c. String was 1 short... --- sllinux_def | 2 +- statemon.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sllinux_def b/sllinux_def index 0e22a767..0ebae7a9 100644 --- a/sllinux_def +++ b/sllinux_def @@ -12,4 +12,4 @@ MFLAGS=-f makefile_linux$(DUMMY) HDFROOT=/afs/psi.ch/project/sinq/sl6 TCLINC=. -DBG= -g +DBG= -g -fstack-protector-all 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; From 005df1c2009b5d9ca3d679e3515a4621101485b1 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Thu, 22 May 2014 11:47:35 +0200 Subject: [PATCH 11/34] - Made comment padding work --- nxscript.c | 3 ++- sllinux_def | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/nxscript.c b/nxscript.c index 810417cf..b8c41ef3 100644 --- a/nxscript.c +++ b/nxscript.c @@ -1516,6 +1516,7 @@ static int SPutPadding(void *message, void *userData) for(i = strlen(pPtr); i < len-1; i++){ pPtr[i] = ' '; } + pPtr[len-1] = '!'; free(self->v.v.text); self->v.v.text = pPtr; } @@ -1635,7 +1636,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,SPutPadding, NULL,NULL); AppendMPFilter(putPipe,SPutDim, NULL,NULL); AppendMPFilter(putPipe,SPutWrite, NULL,NULL); } diff --git a/sllinux_def b/sllinux_def index 0ebae7a9..5916803b 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 -fstack-protector-all +#DBG= -g -fstack-protector-all +DBG= -g From dc3a3c39c0815eaa5f58a7e433b869fe0a038d23 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Fri, 23 May 2014 09:53:34 +0200 Subject: [PATCH 12/34] Added append to trace in support of the autotrace facility --- trace.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/trace.c b/trace.c index 96364900..7ae47edd 100644 --- a/trace.c +++ b/trace.c @@ -474,6 +474,48 @@ static int TraceLog(pSICSOBJ ccmd, SConnection * con, } 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 +562,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)); From f1e3ae7c0b9d71eaf3898e9954c241ff2730c1b8 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Tue, 3 Jun 2014 12:01:52 +0200 Subject: [PATCH 13/34] Fixed a bug in sicshipadaba which would not cause bin transfer mode properly honoured on hget Added a total feature to histmemsec --- histmemsec.c | 18 ++++++++++++++++++ sicshipadaba.c | 6 +++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/histmemsec.c b/histmemsec.c index 259466ef..ed06e956 100644 --- a/histmemsec.c +++ b/histmemsec.c @@ -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/sicshipadaba.c b/sicshipadaba.c index 2e7ec442..365bddae 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -693,7 +693,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); @@ -2708,10 +2708,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); } } From a27f0d9b94b1fa2a1bc91c969483cc007de1be5f Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Fri, 6 Jun 2014 16:38:14 +0200 Subject: [PATCH 14/34] - Cosmetic changes to sicsget and counter - Fixed a bug when NETconnect would come back with errno EINPROGRESS which is no error really --- counter.c | 2 +- network.c | 4 ++-- sicsget.c | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/counter.c b/counter.c index 38593a4e..977f2239 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; diff --git a/network.c b/network.c index 3fcc6a66..52edc8fa 100644 --- a/network.c +++ b/network.c @@ -287,9 +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) { - close(pRes->sockid); + if (iRet < 0 && errno ) { if (errno != EINPROGRESS) { + close(pRes->sockid); free(pRes); return NULL; } diff --git a/sicsget.c b/sicsget.c index 69e6dbd0..bcb20a37 100644 --- a/sicsget.c +++ b/sicsget.c @@ -280,8 +280,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; } From d6faaa593ab05bb35fea77820f5b117de1b342cb Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Wed, 25 Jun 2014 08:46:54 +0200 Subject: [PATCH 15/34] - Removed trim in sicsget: caused line breaks in text to disappear which was not desired --- sicsget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sicsget.c b/sicsget.c index bcb20a37..931cabbf 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,GetCharArray(data),eValue); DeleteDynString(data); } else { SCPrintf(pCon,eError,"ERROR: formatting value for %s failed", argv[1]); From 4fb94efe9a3f3f5e7402f689c5b523a7cf18f011 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Fri, 27 Jun 2014 11:05:27 +0200 Subject: [PATCH 16/34] This is the first version of the newly refactored status code handling. Status codes are now determined by a special task which inspects SICS for what is going on. Before this was a global variable which caused conflicts when multiple instances in the code tried to set it. --- SCinter.h | 2 +- devexec.c | 9 +++ devexec.w | 2 + exeman.c | 11 +++- exeman.h | 2 + interface.c | 4 ++ nserver.c | 3 + scan.c | 6 +- scan.h | 1 + status.c | 167 +++++++++++++++++++++++++++++++++++++++++++++++++--- status.h | 1 + task.c | 5 ++ task.h | 5 +- 13 files changed, 206 insertions(+), 12 deletions(-) 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/devexec.c b/devexec.c index 7979d9eb..964ce5b6 100644 --- a/devexec.c +++ b/devexec.c @@ -965,3 +965,12 @@ void SetDevexecStatus(pExeList pExe, int code) pExe->iStatus = code; } } +/*------------------------------------------------------------------------*/ +int GetDevExecInstStatus(pExeList self) +{ + if(self->lTask < 0){ + return eEager; + } else { + return self->instStatus; + } +} \ No newline at end of file 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/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/interface.c b/interface.c index c10fe697..9ab9c52a 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; @@ -271,6 +272,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); @@ -317,6 +319,7 @@ int isRunning(pICountable self) } /*--------------------------------------------------------------------------*/ typedef struct { + int id; void *obj; pICountable pCount; SConnection *pCon; @@ -416,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/nserver.c b/nserver.c index 6356a6e8..e87287fb 100644 --- a/nserver.c +++ b/nserver.c @@ -263,6 +263,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(); diff --git a/scan.c b/scan.c index 42f74e01..3d9823dd 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) { 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/status.c b/status.c index 34a0bbad..0d7ba93d 100644 --- a/status.c +++ b/status.c @@ -52,6 +52,9 @@ #include "status.h" #include "interrupt.h" #include "sicshipadaba.h" +#include "messagepipe.h" +#include "scan.h" +#include "exeman.h" #undef VALUECHANGE #define VALUECHANGE 2 @@ -97,6 +100,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 +113,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 +295,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 +355,136 @@ 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 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); +} +/*-------------------------------------------------------------------------------*/ +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..5d38f2b4 100644 --- a/status.h +++ b/status.h @@ -49,5 +49,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/task.c b/task.c index be911cdc..8e338657 100644 --- a/task.c +++ b/task.c @@ -544,6 +544,11 @@ const char * GetTaskName(pTaskHead it) return (const char*)it->name; } /*------------------------------------------------------------------------------*/ +const void *GetTaskData(pTaskHead it) +{ + return (const void*)it->pData; +} +/*------------------------------------------------------------------------------*/ long GetTaskGroupID(pTaskMan self) { lIDMama++; 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 From 709118c286585d2e2ca0cdcb27c95e62885a3d26 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Tue, 8 Jul 2014 08:47:28 +0200 Subject: [PATCH 17/34] - Added isactive command to scan. Such that collect can test for another scan running before starting --- scan.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scan.c b/scan.c index 3d9823dd..97ca1140 100644 --- a/scan.c +++ b/scan.c @@ -1724,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 */ From db6167bfa157b0624171eecf079a84302cf66319 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Tue, 15 Jul 2014 16:43:09 +0200 Subject: [PATCH 18/34] - Removed old stuff in conman - Fixed a bug in processnode which hangs SICS when processnode is called from multiple clients on the same node - Fixed a bug in multicountsersec which caused thrashing of the Tcl results which caused ugly error messages when calling the transfer script. Now a copy of the connection is made before calling the transfer script --- conman.c | 2 -- devexec.h | 16 +++++++------ histsim.c | 1 + multicountersec.c | 58 +++++++++++++++++++++++++---------------------- scriptcontext.c | 6 +++-- 5 files changed, 45 insertions(+), 38 deletions(-) diff --git a/conman.c b/conman.c index ee8ff769..43fa851f 100644 --- a/conman.c +++ b/conman.c @@ -1724,10 +1724,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/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/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/multicountersec.c b/multicountersec.c index 2b4bbc1e..08fbe915 100644 --- a/multicountersec.c +++ b/multicountersec.c @@ -246,21 +246,25 @@ static int MultiSecTransfer(void *pData, SConnection * pCon) char pBueffel[132]; pCounter pCount = NULL; pHdb transfer; + SConnection *myCon; pCount = (pCounter) pData; transfer = GetHipadabaNode(pCount->objectNode,"transfer"); if(transfer != NULL){ - MacroPush(pCon); + myCon = SCCopyConnection(pCon); + 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 retVal; } @@ -374,34 +378,34 @@ static int areSlavesRunning(pCounter self, SConnection *pCon, int *status) 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; - return 0; - } else { - *status = HWBusy; + 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; - } - } else { - *status = HWIdle; - UpdateHipadabaPar(myStatus,MakeHdbText("idle"),pCon); - return 0; - } - return 1; + } + } + SCWrite(pCon,"ERROR: failed to stop overrun CCD",eLogError); + *status = HWFault; + return 0; + } else { + *status = HWBusy; + UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); + return 1; + } +} else { + *status = HWIdle; + UpdateHipadabaPar(myStatus,MakeHdbText("idle"),pCon); + return 0; +} +return 1; } /*------------------------------------------------------------------------------------*/ static void multiEndCounting(pCounter self, SConnection *pCon) diff --git a/scriptcontext.c b/scriptcontext.c index 21aeb6d9..63fb2706 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); From f5e797dd6a1895fbc1222430a16343ea554fa157 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Fri, 18 Jul 2014 14:02:57 +0200 Subject: [PATCH 19/34] - Cleaned all old dtatus setting code --- conman.c | 8 -------- counter.c | 4 ---- devexec.c | 7 ------- drive.c | 13 ------------- evcontroller.c | 4 ---- exebuf.c | 2 -- interface.c | 11 ----------- macro.c | 6 ------ multicountersec.c | 6 ------ nserver.c | 6 +----- script.c | 12 +++++++++--- status.c | 4 ++++ status.h | 12 ------------ stdscan.c | 1 - synchronize.c | 5 ----- tasscanub.c | 1 - velo.c | 5 ----- 17 files changed, 14 insertions(+), 93 deletions(-) diff --git a/conman.c b/conman.c index 43fa851f..a053e2c4 100644 --- a/conman.c +++ b/conman.c @@ -1521,8 +1521,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 +1540,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 +1566,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 +1585,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; } diff --git a/counter.c b/counter.c index 977f2239..7b75da54 100644 --- a/counter.c +++ b/counter.c @@ -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; } /*-------------------------------------------------------------------------*/ diff --git a/devexec.c b/devexec.c index 964ce5b6..86e0f12f 100644 --- a/devexec.c +++ b/devexec.c @@ -295,7 +295,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 +306,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 +528,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 +556,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 +712,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 +753,6 @@ int Success(SConnection * pCon, SicsInterp * pSics, void *pData, SCWrite(pCon, "Level done", eValue); iRet = 1; } - SetStatus(eEager); return iRet; } /*-------------------------------------------------------------------------*/ @@ -894,7 +888,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. 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/interface.c b/interface.c index 9ab9c52a..0e412b5b 100644 --- a/interface.c +++ b/interface.c @@ -240,7 +240,6 @@ static int DriveTaskFunc(void *data) } else { ExeInterest(pServ->pExecutor,taskData->name, "finished with problem"); } - SetStatus(eEager); return 0; } /*--------------------------------------------------------------------------*/ @@ -370,16 +369,6 @@ static int CountTaskFunc(void *data) assert(taskData != NULL); 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; - } taskData->pCount->TransferData(taskData->obj, taskData->pCon); 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/multicountersec.c b/multicountersec.c index 08fbe915..71687a9b 100644 --- a/multicountersec.c +++ b/multicountersec.c @@ -318,20 +318,16 @@ static int isMultiMasterRunning(pCounter self, SConnection *pCon, int *status) UpdateHipadabaPar(stopTime,MakeHdbInt(time(NULL)),pCon); SecCounterSetError(self,"Master counter errror"); *status = HWBusy; - ClearFixedStatus(eCounting); break; case HWPause: UpdateHipadabaPar(myStatus,MakeHdbText("paused"),pCon); *status = HWPause; - SetStatusFixed(ePaused); break; case HWNoBeam: UpdateHipadabaPar(myStatus,MakeHdbText("nobeam"),pCon); *status = HWNoBeam; - SetStatusFixed(eOutOfBeam); break; default: - SetStatusFixed(eCounting); *status = HWBusy; UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); if (self->iCallbackCounter > 20) { @@ -414,7 +410,6 @@ static void multiEndCounting(pCounter self, SConnection *pCon) InvokeCallBack(self->pCall, COUNTEND, NULL); ReleaseCountLock(self->pCountInt); MultiSecTransfer(self,pCon); - ClearFixedStatus(eEager); } /*-------------------------------------------------------------------------------------*/ @@ -432,7 +427,6 @@ static int MultiSecStatus(void *pData, SConnection * pCon) } if(areSlavesRunning(self,pCon, &status)){ - SetStatusFixed(eCounting); return status; } diff --git a/nserver.c b/nserver.c index e87287fb..6462eca5 100644 --- a/nserver.c +++ b/nserver.c @@ -458,14 +458,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/script.c b/script.c index 5568e3cf..4b667d3c 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); @@ -174,7 +180,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; diff --git a/status.c b/status.c index 0d7ba93d..e30db3c1 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 diff --git a/status.h b/status.h index 5d38f2b4..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); 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/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/tasscanub.c b/tasscanub.c index 5e6cb5de..92d060c1 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/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; From 1d1f102b08acea96caa410c666c58d3f7048e68b Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Fri, 18 Jul 2014 15:50:04 +0200 Subject: [PATCH 20/34] - Fixed a serious bug in interface.c introduced while cleaning SetStatus --- interface.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/interface.c b/interface.c index 0e412b5b..ee597677 100644 --- a/interface.c +++ b/interface.c @@ -369,6 +369,13 @@ static int CountTaskFunc(void *data) assert(taskData != NULL); status = taskData->pCount->CheckCountStatus(taskData->obj,taskData->pCon); + if(status == HWBusy) { + return 1; + } else if(status == HWNoBeam){ + return 1; + } else if(status == HWPause){ + return 1; + } taskData->pCount->TransferData(taskData->obj, taskData->pCon); From 9e898d147681bfb64ea96b7b8e9a3b029d4540ce Mon Sep 17 00:00:00 2001 From: boa Date: Fri, 15 Aug 2014 13:36:36 +0200 Subject: [PATCH 21/34] Fixed addauxref for the triple axis code Added a writing state to status --- nxscript.c | 19 +++++++++++++++++- nxscript.h | 1 + sllinux_def | 2 +- status.c | 16 ++++++++++++++- task.c | 12 +++++++++-- tasub.c | 6 ++++-- tasublib.c | 57 +++++++++++++++++++++++++++++++++++------------------ tasublib.h | 18 ++++++++++++++--- vector.c | 31 +++++++++++++++++++++++++++++ vector.h | 10 +++++++++- 10 files changed, 142 insertions(+), 30 deletions(-) diff --git a/nxscript.c b/nxscript.c index b8c41ef3..298d0dbb 100644 --- a/nxscript.c +++ b/nxscript.c @@ -1509,7 +1509,7 @@ static int SPutPadding(void *message, void *userData) *pEnd = '\0'; len = atoi(pPtr); } - pPtr = malloc(len*sizeof(char)); + pPtr = malloc((len+5)*sizeof(char)); if(pPtr != NULL){ memset(pPtr,0,len*sizeof(char)); strncpy(pPtr,pEnd+1,len); @@ -2156,3 +2156,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/sllinux_def b/sllinux_def index 5916803b..ee2f5005 100644 --- a/sllinux_def +++ b/sllinux_def @@ -13,4 +13,4 @@ HDFROOT=/afs/psi.ch/project/sinq/sl6 TCLINC=. #DBG= -g -fstack-protector-all -DBG= -g +DBG= -g \ No newline at end of file diff --git a/status.c b/status.c index e30db3c1..c850e698 100644 --- a/status.c +++ b/status.c @@ -58,7 +58,8 @@ #include "sicshipadaba.h" #include "messagepipe.h" #include "scan.h" -#include "exeman.h" +#include "exeman.h" +#include "nxscript.h" #undef VALUECHANGE #define VALUECHANGE 2 @@ -461,6 +462,18 @@ static int CheckUserWait(void *message, void *userData) 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) @@ -471,6 +484,7 @@ static void BuildStatusChain(void) 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) diff --git a/task.c b/task.c index 8e338657..a511357f 100644 --- a/task.c +++ b/task.c @@ -26,8 +26,10 @@ #define YIELDING 3 #define IDUNDEFINED 0L +#define TASKMAGIC 777111999 /*--------------------------------------------------------------------------*/ typedef struct __TaskHead { + long magic; long lID; long groupID; int iStatus; @@ -68,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; @@ -106,6 +109,7 @@ static void DeleteTaskHead(pTaskHead self) if (self->pNext != NULL) { self->pNext->pPrevious = self->pPrevious; } + memset(self,0,sizeof(TaskHead)); free(self); } @@ -492,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; @@ -546,7 +550,11 @@ const char * GetTaskName(pTaskHead it) /*------------------------------------------------------------------------------*/ const void *GetTaskData(pTaskHead it) { - return (const void*)it->pData; + if(it->magic == TASKMAGIC){ + return (const void*)it->pData; + } else { + return NULL; + } } /*------------------------------------------------------------------------------*/ long GetTaskGroupID(pTaskMan self) 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 1ef9efa1..768d0086 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/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 From 8f704ebab9425f626ca92aef1587c0211d9268f5 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Wed, 27 Aug 2014 16:24:39 +0200 Subject: [PATCH 22/34] Improvements for BOA - Allowed write buffers to become very large in asynnet. Thus in order to allow for the transfer of large images. tested ub to 2kx2k, 16MB - Handle lack of space in the write buffer more gracefully: just skip the image --- asynnet.c | 18 ++++++++++++++++-- asynnet.h | 8 ++++++++ conman.c | 25 +++++++++++++++++++++++++ rwpuffer.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- rwpuffer.h | 15 +++++++++++++++ 5 files changed, 116 insertions(+), 4 deletions(-) diff --git a/asynnet.c b/asynnet.c index b9e688d5..d10c8c5b 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; } @@ -498,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/conman.c b/conman.c index a053e2c4..70c1b25c 100644 --- a/conman.c +++ b/conman.c @@ -1178,6 +1178,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 +1206,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 +1285,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); diff --git a/rwpuffer.c b/rwpuffer.c index a678e700..500a8595 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); 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 From c3fe7555db890c10c76f41580fd17b3555cd9e37 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Wed, 27 Aug 2014 16:26:44 +0200 Subject: [PATCH 23/34] Fixed an incommensurate problem No duplicate reflections are created with propagation vectors containing .5 --- fourmess.c | 25 +++++++++++++------------ reflist.c | 36 ++++++++++++++++++++++++++++++++---- reflist.h | 2 ++ 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/fourmess.c b/fourmess.c index b6cb77b5..c497e21e 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/reflist.c b/reflist.c index 0f0833e1..968614e3 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) { @@ -687,10 +715,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_ */ From 9500b59f04754efe6f8f010723e57939fc6e8eae Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Thu, 28 Aug 2014 09:03:41 +0200 Subject: [PATCH 24/34] Fixed SICSType to recognize exponential numbers --- script.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script.c b/script.c index 4b667d3c..20497fe8 100644 --- a/script.c +++ b/script.c @@ -199,7 +199,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; } From 8ea20b87f4086f27ceead62cf85156617a0a447d Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Mon, 1 Sep 2014 11:17:18 +0200 Subject: [PATCH 25/34] Added reflist relabel This relabels all reflections in numeric order again. This is necessary for travelsort --- reflist.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/reflist.c b/reflist.c index 968614e3..0a8c1645 100644 --- a/reflist.c +++ b/reflist.c @@ -422,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) { @@ -585,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; } From b3194615311d5fdbcabcbb7b1fd5cfc88d6861e8 Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Mon, 13 Oct 2014 13:36:37 +0200 Subject: [PATCH 26/34] Fixed a minor memory leak in count and drive task handling Reformatted multicountser to become clearer Minor fixes Added more tracing output to sort the SANSLI problem --- SCinter.c | 1 + cone.c | 3 +- devexec.c | 3 +- hmcontrol.c | 5 +- interface.c | 4 + multicountersec.c | 254 +++++++++++++++++++++++----------------------- nxscript.c | 13 ++- tasmono.c | 7 ++ 8 files changed, 155 insertions(+), 135 deletions(-) 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/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/devexec.c b/devexec.c index 86e0f12f..3ca44665 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; } 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 ee597677..d661b2c3 100644 --- a/interface.c +++ b/interface.c @@ -196,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) @@ -240,6 +241,7 @@ static int DriveTaskFunc(void *data) } else { ExeInterest(pServ->pExecutor,taskData->name, "finished with problem"); } + traceSys("drive","DriveTask %s finished with state %d", taskData->name,status); return 0; } /*--------------------------------------------------------------------------*/ @@ -338,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) @@ -389,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; } /*--------------------------------------------------------------------------*/ diff --git a/multicountersec.c b/multicountersec.c index 71687a9b..c94b2c0f 100644 --- a/multicountersec.c +++ b/multicountersec.c @@ -239,7 +239,7 @@ static hdbCallbackReturn MultiSecControllCallback(pHdb node, return hdbContinue; } -/*--------------------------------------------------------------------------*/ +/*-------------------------------------------------------------------------2-*/ static int MultiSecTransfer(void *pData, SConnection * pCon) { int i, retVal = OKOK, tclStatus; @@ -253,6 +253,7 @@ static int MultiSecTransfer(void *pData, SConnection * pCon) 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) { @@ -269,140 +270,139 @@ static int MultiSecTransfer(void *pData, SConnection * pCon) return retVal; } /*-------------------------------------------------------------------------------------*/ -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; + 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; - 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); - + 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); + - 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); - 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++; + mlID = mID->value.v.intValue; + if(mlID == 0) { + return 0; } - 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); + data = FindCommandData(pServ->pSics,master->value.v.text,NULL); + assert(data != NULL); + pCount = GetCountableInterface(data); + assert(pCount != 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); + 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; } - } - SCWrite(pCon,"ERROR: failed to stop overrun CCD",eLogError); - *status = HWFault; - return 0; - } else { - *status = HWBusy; - UpdateHipadabaPar(myStatus,MakeHdbText("run"),pCon); - return 1; - } -} else { - *status = HWIdle; - UpdateHipadabaPar(myStatus,MakeHdbText("idle"),pCon); - return 0; -} -return 1; -} + } else { + *status = HWIdle; + UpdateHipadabaPar(myStatus,MakeHdbText("idle"),pCon); + return 0; + } + return 1; + } /*------------------------------------------------------------------------------------*/ static void multiEndCounting(pCounter self, SConnection *pCon) { diff --git a/nxscript.c b/nxscript.c index 298d0dbb..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; } @@ -1499,7 +1500,7 @@ static int SPutPadding(void *message, void *userData) { pPutMessage self = (pPutMessage)message; char *pPtr = NULL, *pEnd = NULL; - unsigned int len, i; + unsigned int len = 0, i; if(self->v.dataType == HIPTEXT && strstr(self->v.v.text,"@len") != NULL){ pPtr = strchr(self->v.v.text,'='); @@ -1509,11 +1510,11 @@ static int SPutPadding(void *message, void *userData) *pEnd = '\0'; len = atoi(pPtr); } - pPtr = malloc((len+5)*sizeof(char)); + 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-1; i++){ + for(i = strlen(pPtr); i < len-2; i++){ pPtr[i] = ' '; } pPtr[len-1] = '!'; @@ -1550,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", 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" From be058abdefc5eafac6623d3c7f241c952bd317ab Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Tue, 21 Oct 2014 16:28:06 +0200 Subject: [PATCH 27/34] Fixed a sget bug from POLDI. Returns OK instead of number --- script.c | 7 +++++++ sicsget.c | 2 +- sicshipadaba.c | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/script.c b/script.c index 20497fe8..73a5303a 100644 --- a/script.c +++ b/script.c @@ -172,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); diff --git a/sicsget.c b/sicsget.c index 931cabbf..c764d107 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){ - SCWrite(pCon,GetCharArray(data),eValue); + SCWrite(pCon,trim(GetCharArray(data)),eValue); DeleteDynString(data); } else { SCPrintf(pCon,eError,"ERROR: formatting value for %s failed", argv[1]); diff --git a/sicshipadaba.c b/sicshipadaba.c index 365bddae..aed792d1 100644 --- a/sicshipadaba.c +++ b/sicshipadaba.c @@ -2524,7 +2524,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; From fd986402fffec75598d68d8a2b489894f4c29c9c Mon Sep 17 00:00:00 2001 From: Mark Koennecke Date: Fri, 24 Oct 2014 09:16:32 +0200 Subject: [PATCH 28/34] - Removed a trace message which flooded the trace whenever a Tcl task executed. --- taskobj.c | 2 ++ 1 file changed, 2 insertions(+) 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 { From a0ea2d5745431c560ed89f523e0b03c0069d49b7 Mon Sep 17 00:00:00 2001 From: Markus Zolliker Date: Wed, 29 Oct 2014 15:59:12 +0100 Subject: [PATCH 29/34] bug fix in syncedprot.c (treat stackoverflow correctly) --- syncedprot.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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; } From f7aad141d14f8104337a9b23a67b931abaea59d5 Mon Sep 17 00:00:00 2001 From: Markus Zolliker Date: Thu, 30 Oct 2014 11:24:05 +0100 Subject: [PATCH 30/34] - removed all stuff related to tecs - allow short make command by means of SICS_MAKE_VERSION env.variable --- make_gen | 10 ++-------- makefile | 24 +++--------------------- makefile_ | 25 +++++++++++++++++++++++++ makefile_alpha | 3 +-- makefile_linux | 3 +-- makefile_macosx | 3 +-- makefile_slinux | 2 +- 7 files changed, 34 insertions(+), 36 deletions(-) create mode 100644 makefile_ diff --git a/make_gen b/make_gen index 64962730..2572d126 100644 --- a/make_gen +++ b/make_gen @@ -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 590bf7c4..f8ee79c5 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 2dc98c99..6e81a4bf 100644 --- a/makefile_macosx +++ b/makefile_macosx @@ -22,8 +22,7 @@ CFLAGS = -I$(HDFROOT)/include -I/sw/include -DNXXML -DHDF5 -DHDF4 $(NI) -DMACOSX 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 -L/sw/lib $(SUBLIBS) $(NILIB)\ -ltcl $(HDFROOT)/lib/libhdf5.a -lmfhdf -ldf \ $(HDFROOT)/lib/libsz.a \ diff --git a/makefile_slinux b/makefile_slinux index a384635c..6be471f6 100644 --- a/makefile_slinux +++ b/makefile_slinux @@ -28,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 \ From f274f3bcdb9e30d986b1910598e86b59687c53ec Mon Sep 17 00:00:00 2001 From: Koennecke Mark Date: Tue, 18 Nov 2014 09:24:27 +0100 Subject: [PATCH 31/34] - Fixed a sget bug which caused text wrongly to be identified as numbers - Fixed a sput bug: SetHipadabaPar versus UpdateHipadabaPar - Modified hdelcb to be able to remove callbacks from SICS objects --- histmemsec.c | 2 +- make_gen | 2 +- sicsget.c | 30 +++++++++++++++++++++++++----- sicshipadaba.c | 13 ++++++++++--- trace.c | 7 +++++-- 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/histmemsec.c b/histmemsec.c index ed06e956..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);*/ diff --git a/make_gen b/make_gen index 64962730..09527280 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 MOTOROBJ = motor.o simdriv.o COUNTEROBJ = countdriv.o simcter.o counter.o diff --git a/sicsget.c b/sicsget.c index c764d107..6e96c93e 100644 --- a/sicsget.c +++ b/sicsget.c @@ -137,16 +137,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 +180,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); @@ -423,7 +443,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/sicshipadaba.c b/sicshipadaba.c index aed792d1..17880da1 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) @@ -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/trace.c b/trace.c index 7ae47edd..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,8 +469,10 @@ 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; From e23dff21418b5689ce673362cc7c7c13e39d44e8 Mon Sep 17 00:00:00 2001 From: Koennecke Mark Date: Thu, 4 Dec 2014 11:33:43 +0100 Subject: [PATCH 32/34] -Fixed a small bug in sicsdata copytonode where the start position was not honoured --- sicsdata.c | 2 +- sicsobj.c | 76 +++++++++++++++++++++++++++--------------------------- 2 files changed, 39 insertions(+), 39 deletions(-) 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/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; } /*---------------------------------------------------------------------------*/ From fb19bf9bf61216bccfb86d20d948c3e641295bd1 Mon Sep 17 00:00:00 2001 From: Koennecke Mark Date: Wed, 4 Feb 2015 14:35:21 +0100 Subject: [PATCH 33/34] Harmonized status text codes between second generation objects and sctdriveadpater, sctdriveobj --- sctdriveadapter.c | 4 ++-- sctdriveobj.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) 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; From 2eef24bf3c138456959257cf0270372887dbe006 Mon Sep 17 00:00:00 2001 From: Koennecke Mark Date: Tue, 17 Mar 2015 11:41:18 +0100 Subject: [PATCH 34/34] First version of remoteobject. In the implementation of this, the following sub problems were solved: - sicsget was not reporting geterrors on nodes properly - rwpuffer contained dirt after wrap - property change events were added to hipadaba - Some tuning of SICS output - The number of codes was wrong in outcode.c --- conman.c | 13 +- hipadaba.c | 16 + hipadaba.h | 19 +- make_gen | 2 +- motorsec.c | 25 +- nserver.c | 3 +- ofac.c | 1 + outcode.c | 2 +- protocol.c | 2 +- remoteobject.c | 1008 ++++++++++++++++++++++++++++++++++++++++++++++ rwpuffer.c | 1 + sicsget.c | 36 +- sicshdbfactory.c | 1 + 13 files changed, 1117 insertions(+), 12 deletions(-) create mode 100644 remoteobject.c diff --git a/conman.c b/conman.c index 70c1b25c..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); } 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 be087396..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 @@ -75,7 +77,8 @@ typedef struct __hipadaba { 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/make_gen b/make_gen index 09527280..0749dfa2 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 diff --git a/motorsec.c b/motorsec.c index 51853b70..6f0ed33a 100644 --- a/motorsec.c +++ b/motorsec.c @@ -375,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); @@ -465,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; @@ -526,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; } @@ -547,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; @@ -561,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; @@ -575,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; } diff --git a/nserver.c b/nserver.c index 6462eca5..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); 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/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 500a8595..68acf5e0 100644 --- a/rwpuffer.c +++ b/rwpuffer.c @@ -131,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/sicsget.c b/sicsget.c index 6e96c93e..2924a2a6 100644 --- a/sicsget.c +++ b/sicsget.c @@ -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); @@ -326,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 { @@ -381,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; } diff --git a/sicshdbfactory.c b/sicshdbfactory.c index 4cdf4e97..ef6356cc 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) {