- Added bridge functions to histmemsec to make it look more like histmem
- Modifed many modules using histmem to work also with histmemsec - Extended tasker with task names and task groups - There is a new taskobj which allows to list tasks and to interact with them. - Task now supports running Tcl functions as tasks - There is a new experimental sctcomtask module which allows to define communication tasks against a scriptcontext. This is a new feature which should facilitate writing sequential scripts using asynchronous communication. - A fix to make spss7 work when there are no switches - ORION support for single X. TRICS measures crystals hanging down, ORION standing up SKIPPED: psi/ease.c psi/faverage.c psi/jvlprot.c psi/make_gen psi/pardef.c psi/polterwrite.c psi/psi.c psi/sinq.c psi/spss7.c
This commit is contained in:
@ -1,5 +1,5 @@
|
||||
|
||||
#line 467 "histogram.w"
|
||||
#line 470 "histogram.w"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
H I S T D R I V
|
||||
@ -72,7 +72,7 @@
|
||||
void *pPriv;
|
||||
} HistDriver;
|
||||
|
||||
#line 479 "histogram.w"
|
||||
#line 482 "histogram.w"
|
||||
|
||||
|
||||
#line 232 "histogram.w"
|
||||
@ -84,7 +84,7 @@
|
||||
HistInt *DefaultSubSample(pHistDriver self, SConnection *pCon,
|
||||
int bank, char *command);
|
||||
|
||||
#line 480 "histogram.w"
|
||||
#line 483 "histogram.w"
|
||||
|
||||
|
||||
#endif
|
||||
|
16
HistMem.h
16
HistMem.h
@ -1,5 +1,5 @@
|
||||
|
||||
#line 440 "histogram.w"
|
||||
#line 443 "histogram.w"
|
||||
|
||||
/*--------------------------------------------------------------------------
|
||||
H I S T M E M
|
||||
@ -42,7 +42,7 @@ typedef enum {
|
||||
eReflect
|
||||
} OverFlowMode;
|
||||
|
||||
#line 460 "histogram.w"
|
||||
#line 463 "histogram.w"
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
@ -72,21 +72,23 @@ int HistDoCount(pHistMem self, SConnection * pCon);
|
||||
int HistBlockCount(pHistMem self, SConnection *pCon);
|
||||
void HistDirty(pHistMem self);
|
||||
|
||||
int isSecondGen(pHistMem self);
|
||||
pHistMem FindHM(SicsInterp *pSics, char *name);
|
||||
|
||||
#line 366 "histogram.w"
|
||||
|
||||
#line 369 "histogram.w"
|
||||
|
||||
int SetHistogram(pHistMem self, SConnection *pCon,
|
||||
int i,int iStart, int iEnd, HistInt *lData);
|
||||
int GetHistogram(pHistMem self, SConnection *pCon,
|
||||
int i, int iStart, int iEnd, HistInt * lData,
|
||||
int iDataLen);
|
||||
int i,int iStart, int iEnd, HistInt *lData, int iDataLen);
|
||||
HistInt *GetHistogramPointer(pHistMem self,SConnection *pCon);
|
||||
int GetHistogramDirect(pHistMem self, SConnection *pCon,
|
||||
int i, int iStart, int iEnd,
|
||||
HistInt *lData, int iDataLen);
|
||||
int PresetHistogram(pHistMem self, SConnection *pCon, HistInt lVal);
|
||||
|
||||
#line 409 "histogram.w"
|
||||
#line 412 "histogram.w"
|
||||
|
||||
int MakeHistMemory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
@ -95,7 +97,7 @@ int HistAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
|
||||
#line 462 "histogram.w"
|
||||
#line 465 "histogram.w"
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
#line 485 "histogram.w"
|
||||
#line 488 "histogram.w"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
H I S T M E M -- Internal
|
||||
@ -23,7 +23,7 @@
|
||||
pICallBack pCall;
|
||||
} HistMem;
|
||||
|
||||
#line 495 "histogram.w"
|
||||
#line 498 "histogram.w"
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -273,7 +273,7 @@ static int TclExecFunc(SConnection *pCon, SicsInterp *pInter, void *data,
|
||||
SCWrite(pCon,(char *)Tcl_GetStringResult(InterpGetTcl(pInter)), eValue );
|
||||
return 1;
|
||||
} else {
|
||||
SCWrite(pCon,(char *)Tcl_GetStringResult(InterpGetTcl(pInter)), eValue );
|
||||
SCWrite(pCon,(char *)Tcl_GetStringResult(InterpGetTcl(pInter)), eError );
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -58,7 +58,7 @@ int BackgroundCommand(SConnection * pCon, char *command)
|
||||
return 0;
|
||||
}
|
||||
|
||||
TaskRegister(pServ->pTasker, BackgroundTask, NULL, KillBckTask, self, 1);
|
||||
TaskRegisterN(pServ->pTasker, self->command, BackgroundTask, NULL, KillBckTask, self, 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -489,7 +489,7 @@ int CommandLog(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
SCWrite(pCon, "ERROR: autologging is already active", eError);
|
||||
return 0;
|
||||
}
|
||||
TaskRegister(pServ->pTasker, AutoTask, NULL, NULL, NULL, 1);
|
||||
TaskRegisterN(pServ->pTasker, "autologger", AutoTask, NULL, NULL, NULL, 1);
|
||||
SCSendOK(pCon);
|
||||
iAutoActive = 1;
|
||||
return 1;
|
||||
|
2
conman.c
2
conman.c
@ -1167,7 +1167,7 @@ int SCWriteZipped(SConnection * self, char *pName, void *pData,
|
||||
compStream.avail_in = iDataLen;
|
||||
compStream.avail_out = iDataLen;
|
||||
iRet = deflate(&compStream, Z_FINISH);
|
||||
if (iRet != Z_STREAM_END) {
|
||||
if (iRet != Z_STREAM_END && iRet != Z_OK) {
|
||||
sprintf(outBuf, "ERROR: zlib error: %d", iRet);
|
||||
SCWrite(self, outBuf, eError);
|
||||
return 0;
|
||||
|
@ -30,6 +30,8 @@ typedef struct __Counter{
|
||||
int iCallbackCounter;
|
||||
int badStatusCount;
|
||||
int haltFixFlag; /* solely here to prevent multiple calls to the halt function on overrun timers in countersec.c*/
|
||||
int tbLength; /* These two for caching float time bins in second generation HM's */
|
||||
float *timeBinning;
|
||||
int (*setMode)(struct __Counter *self, CounterMode eMode);
|
||||
CounterMode (*getMode)(struct __Counter *self);
|
||||
int (*getNMonitor)(struct __Counter *self);
|
||||
|
12
devexec.c
12
devexec.c
@ -376,7 +376,7 @@ int StartDevice(pExeList self, char *name, pObjectDescriptor pDes,
|
||||
self->iStatus = DEVDONE;
|
||||
/* if no task: start it */
|
||||
if (self->lTask < 0) {
|
||||
self->lTask = TaskRegister(self->pTask,
|
||||
self->lTask = TaskRegisterN(self->pTask,"devexec",
|
||||
DevExecTask,
|
||||
DevExecSignal, NULL, self, 1);
|
||||
self->iEnd = 0;
|
||||
@ -476,7 +476,7 @@ static int ForceStartDevice(pExeList self, char *name, pObjectDescriptor pDes,
|
||||
self->iStatus = DEVDONE;
|
||||
/* if no task: start it */
|
||||
if (self->lTask < 0) {
|
||||
self->lTask = TaskRegister(self->pTask,
|
||||
self->lTask = TaskRegisterN(self->pTask,"devexec",
|
||||
DevExecTask,
|
||||
DevExecSignal, NULL, self, 1);
|
||||
self->iEnd = 0;
|
||||
@ -962,12 +962,20 @@ int StopByData(pExeList self, void *data)
|
||||
} else if (pCountInt) {
|
||||
pCountInt->Halt(pDev->pData);
|
||||
}
|
||||
/*
|
||||
This is wrong: most devices will require some time
|
||||
before they really stop. CheckExeList has to run...
|
||||
This causes core dumps......
|
||||
|
||||
Mark
|
||||
|
||||
ExeInterest(self, pDev, "finished");
|
||||
DevexecLog("FINISHED", pDev->name);
|
||||
DeleteDevEntry(pDev);
|
||||
LLDnodeDelete(self->iList);
|
||||
self->iStatus = DEVDONE;
|
||||
SCWrite(self->pOwner, "", eFinish);
|
||||
*/
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
3
devser.c
3
devser.c
@ -308,7 +308,8 @@ DevSer *DevMake(SConnection * con, int argc, char *argv[])
|
||||
devser->steps = -1; /* no debugging by default */
|
||||
devser->status = AsconUnconnected;
|
||||
devser->startTime = -1;
|
||||
TaskRegister(pServ->pTasker, DevQueueTask, NULL, NULL, devser, 0);
|
||||
TaskRegisterN(pServ->pTasker, AsconHostport(ascon),
|
||||
DevQueueTask, NULL, NULL, devser, 0);
|
||||
return devser;
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ int RunDiffScan(pDiffScan self, pScanData pScan,
|
||||
InvokeCallBack(self->scanObject->pCall, SCANSTART, self->scanObject);
|
||||
|
||||
|
||||
lID = TaskRegister(pServ->pTasker, DiffScanTask, NULL, NULL, self, 10);
|
||||
lID = TaskRegisterN(pServ->pTasker,"diffscan", DiffScanTask, NULL, NULL, self, 10);
|
||||
TaskWait(pServ->pTasker, lID);
|
||||
|
||||
|
||||
|
@ -113,7 +113,8 @@ experiment.
|
||||
property on the node or as given on the command line. The alias is expected to match the size and type of
|
||||
the data. Please note that hipadaba stores all floats as double which is NX_FLOAT64 as number type. Writing
|
||||
data is started with the offset specified from the start of the data. This is useful to split a histogram
|
||||
memory area into separate detectors or whatever.
|
||||
memory area into separate detectors or whatever. The length of the amount of data to
|
||||
copy is implied by the dimension of the SDS alias points to.
|
||||
<dt>nxscript puthdbslab path start size
|
||||
<dd>Put a hipdaba node as a slab. The node must have a property nxalias to determine where to write to.
|
||||
Start and size are Tcl lists which give the start point where to write and the size of the data
|
||||
|
2
exeman.c
2
exeman.c
@ -1175,8 +1175,10 @@ static int printBuffer(pExeMan self, SConnection * pCon,
|
||||
}
|
||||
while (fgets(pLine, 511, fd) != NULL) {
|
||||
DynStringConcat(filePath, pLine);
|
||||
if(strrchr(pLine,(int)'\n') == NULL){
|
||||
DynStringConcatChar(filePath,'\n');
|
||||
}
|
||||
}
|
||||
fclose(fd);
|
||||
SCWrite(pCon, GetCharArray(filePath), eValue);
|
||||
DeleteDynString(filePath);
|
||||
|
13
fomerge.c
13
fomerge.c
@ -19,6 +19,9 @@
|
||||
extended to support nxscripted file writing: Mark Koennecke, May 2004
|
||||
|
||||
extended to support GTSE, Mark Koennecke, May 2008
|
||||
|
||||
modifed to support second generation HM's via the bridge,
|
||||
Mark Koennecke, December 2012
|
||||
--------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
@ -428,20 +431,20 @@ static int updateHMFMData(SicsInterp * pSics, SConnection * pCon)
|
||||
HistInt *data = NULL;
|
||||
pHistMem pMem = NULL;
|
||||
|
||||
pMem = (pHistMem) FindCommandData(pSics, "hm2", "HistMem");
|
||||
pMem = (pHistMem) FindHM(pSics, "hm2");
|
||||
if (pMem == NULL) {
|
||||
return 0;
|
||||
}
|
||||
fTimeBin = GetHistTimeBin(pMem, &iTime);
|
||||
setFMDataPointer(GetHistogramPointer(pMem, pCon), iTime, MIDDLE);
|
||||
|
||||
pMem = (pHistMem) FindCommandData(pSics, "hm1", "HistMem");
|
||||
pMem = (pHistMem) FindHM(pSics, "hm1");
|
||||
if (pMem == NULL) {
|
||||
return 0;
|
||||
}
|
||||
setFMDataPointer(GetHistogramPointer(pMem, pCon), iTime, LOWER);
|
||||
|
||||
pMem = (pHistMem) FindCommandData(pSics, "hm3", "HistMem");
|
||||
pMem = (pHistMem) FindHM(pSics, "hm3");
|
||||
if (pMem == NULL) {
|
||||
return 0;
|
||||
}
|
||||
@ -567,7 +570,7 @@ static int TOFLambda(SicsInterp * pSics, SConnection * pCon,
|
||||
float fCenter, fFWHM, fStdDev, fVal;
|
||||
float fMon, fData, distMonoDet, distFermiDet, tdiff, lambda;
|
||||
|
||||
pMem = (pHistMem) FindCommandData(pSics, "hm1", "HistMem");
|
||||
pMem = (pHistMem) FindHM(pSics, "hm1");
|
||||
if (pMem == NULL) {
|
||||
SCWrite(pCon,
|
||||
"ERROR: need lower detector bank for lambda calculation",
|
||||
@ -650,7 +653,7 @@ static float calcElastic(SicsInterp * pSics, SConnection * pCon)
|
||||
pHistMem pMem = NULL;
|
||||
float fCenter, fFWHM, fStdDev, fVal;
|
||||
|
||||
pMem = (pHistMem) FindCommandData(pSics, "hm2", "HistMem");
|
||||
pMem = (pHistMem) FindHM(pSics, "hm2");
|
||||
if (pMem == NULL) {
|
||||
SCWrite(pCon,
|
||||
"ERROR: need middle detector bank for elastic peak calculation",
|
||||
|
@ -647,7 +647,7 @@ void z1FromNormalBeam(double lambda, double omega, double gamma,
|
||||
/*--------------------------------------------------------------------*/
|
||||
double circlify(double val)
|
||||
{
|
||||
while (val > 360.) {
|
||||
while (val >= 359.8) {
|
||||
val -= 360.;
|
||||
}
|
||||
while (val < 0.) {
|
||||
|
6
frame.c
6
frame.c
@ -66,7 +66,7 @@ static int readHMFrame(SConnection * pCon, pHistMem pHM,
|
||||
if (nFrame >= noTimeBins) {
|
||||
nFrame = noTimeBins - 1;
|
||||
}
|
||||
if (isSINQHMDriv(pHM->pDriv) && noTimeBins > 2) {
|
||||
if (!isSecondGen(pHM) && isSINQHMDriv(pHM->pDriv) && noTimeBins > 2) {
|
||||
/*
|
||||
read from HM. The 5 is PROJECT__FRAME in Sinqhm_def.h
|
||||
Again: be friendly: fix out of range frames
|
||||
@ -81,7 +81,7 @@ static int readHMFrame(SConnection * pCon, pHistMem pHM,
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
} else if(isSINQHTTP(pHM->pDriv) && noTimeBins > 2){
|
||||
} else if(!isSecondGen(pHM) && isSINQHTTP(pHM->pDriv) && noTimeBins > 2){
|
||||
if(sansflag){
|
||||
snprintf(histCommand,132,"sample:0:%d:%d:%d", iDim[0]*iDim[1], nFrame, nFrame+1);
|
||||
} else {
|
||||
@ -244,7 +244,7 @@ int PSDFrameAction(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
pHM = (pHistMem) FindCommandData(pSics, argv[2], "HistMem");
|
||||
pHM = (pHistMem) FindHM(pSics, argv[2]);
|
||||
if (pHM == NULL) {
|
||||
SCWrite(pCon, "ERROR: Did not find histogram memory", eError);
|
||||
return 0;
|
||||
|
37
hipadaba.c
37
hipadaba.c
@ -10,6 +10,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include "hipadaba.h"
|
||||
|
||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||
@ -483,8 +484,32 @@ static unsigned short fletcher16( char *data, size_t len)
|
||||
result = result << 8 | checkB;
|
||||
return result ;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
#define MAXLEN 65536
|
||||
/*------------------------------------------------------------------------*/
|
||||
static unsigned short longfletcher16(char *data, size_t len)
|
||||
{
|
||||
char buffer[MAXLEN];
|
||||
int i, j, div, count;
|
||||
char *pPtr;
|
||||
|
||||
if(len < MAXLEN){
|
||||
return fletcher16(data,len);
|
||||
}
|
||||
|
||||
/**
|
||||
* sum together to run the more complex checksum on
|
||||
* more juicy data
|
||||
*/
|
||||
div = (int)trunc((float)len/(float)MAXLEN);
|
||||
for(i = 0; i < MAXLEN; i++){
|
||||
pPtr = data + div*i;
|
||||
for(j = 0; j < div; j++){
|
||||
buffer[i] += *(pPtr + j);
|
||||
}
|
||||
}
|
||||
return fletcher16(buffer,MAXLEN);
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
unsigned short getHdbCheckSum(hdbValue *val)
|
||||
{
|
||||
char *data;
|
||||
@ -928,12 +953,22 @@ static int canCopy(hdbValue * source, hdbValue * target)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(target->dataType == HIPINTAR &&
|
||||
(source->dataType == HIPINTAR || source->dataType == HIPINTVARAR)
|
||||
&& target->arrayLength == source->arrayLength){
|
||||
return 1;
|
||||
}
|
||||
if (target->dataType == HIPFLOATVARAR) {
|
||||
if (source->dataType == HIPFLOATAR ||
|
||||
source->dataType == HIPFLOATVARAR) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if(target->dataType == HIPFLOATAR &&
|
||||
(source->dataType == HIPFLOATAR || source->dataType == HIPFLOATVARAR)
|
||||
&& target->arrayLength == source->arrayLength){
|
||||
return 1;
|
||||
}
|
||||
if (source->dataType != target->dataType) {
|
||||
return 0;
|
||||
} else {
|
||||
|
47
histmem.c
47
histmem.c
@ -70,6 +70,7 @@
|
||||
#include "event.h"
|
||||
#include "status.h"
|
||||
#include "site.h"
|
||||
#include "histmemsec.h"
|
||||
#define ABS(x) (x < 0 ? -(x) : (x))
|
||||
|
||||
/*
|
||||
@ -84,6 +85,27 @@ extern pHistDriver CreateRegressHM(pStringDict pOpt);
|
||||
*/
|
||||
extern pHistDriver MakeHMSlaveHM(pStringDict pOpt);
|
||||
/*------------------------------------------------------------------------*/
|
||||
int isSecondGen(pHistMem self)
|
||||
{
|
||||
pDummy test = (pDummy)self;
|
||||
if(strcmp(test->pDescriptor->name,"HistMemSec") == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------*/
|
||||
pHistMem FindHM(SicsInterp *pSics, char *name)
|
||||
{
|
||||
pHistMem result = NULL;
|
||||
|
||||
result = (pHistMem)FindCommandData(pSics,name,"HistMem");
|
||||
if(result == NULL){
|
||||
result = (pHistMem)FindCommandData(pSics,name,"HistMemSec");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int HistHalt(void *pData)
|
||||
{
|
||||
pHistMem self = NULL;
|
||||
@ -715,6 +737,12 @@ long GetHistMonitor(pHistMem self, int i, SConnection * pCon)
|
||||
void HistDirty(pHistMem self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
if(isSecondGen(self)){
|
||||
SecHistDirty(self);
|
||||
return;
|
||||
}
|
||||
|
||||
if(self->pDriv != NULL){
|
||||
updateHMData(self->pDriv->data);
|
||||
}
|
||||
@ -724,6 +752,11 @@ void HistDirty(pHistMem self)
|
||||
const float *GetHistTimeBin(pHistMem self, int *iLength)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
if(isSecondGen(self)){
|
||||
return GetSecHistTimeBin(self,iLength);
|
||||
}
|
||||
|
||||
*iLength = getNoOfTimebins(self->pDriv->data);
|
||||
return getTimeBinning(self->pDriv->data);
|
||||
}
|
||||
@ -733,6 +766,10 @@ int GetHistLength(pHistMem self)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
if(isSecondGen(self)){
|
||||
return GetSecHistLength(self);
|
||||
}
|
||||
|
||||
return getHMDataLength(self->pDriv->data);
|
||||
}
|
||||
|
||||
@ -827,6 +864,11 @@ int GetHistogram(pHistMem self, SConnection * pCon,
|
||||
{
|
||||
assert(self);
|
||||
|
||||
if(isSecondGen(self)){
|
||||
return GetSecHistogram(self,pCon,i,iStart,iEnd,lData,iDataLen);
|
||||
}
|
||||
|
||||
|
||||
if (!self->iInit) {
|
||||
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
||||
return 0;
|
||||
@ -883,6 +925,11 @@ HistInt *GetHistogramPointer(pHistMem self, SConnection * pCon)
|
||||
{
|
||||
assert(self);
|
||||
|
||||
if(isSecondGen(self)){
|
||||
return GetSecHistogramPointer(self,pCon);
|
||||
}
|
||||
|
||||
|
||||
if (!self->iInit) {
|
||||
SCWrite(pCon, "ERROR: histogram memory not initialised", eError);
|
||||
return NULL;
|
||||
|
242
histmemsec.c
242
histmemsec.c
@ -10,10 +10,17 @@
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, May 2009
|
||||
*
|
||||
* Added bridging routines implementing first gen HM interfaces
|
||||
*
|
||||
* Mark Koennecke, December 2012
|
||||
*/
|
||||
#include <sics.h>
|
||||
#include <sicshipadaba.h>
|
||||
#include <counter.h>
|
||||
#include "HistMem.h"
|
||||
#include "HistMem.i"
|
||||
#include "arrayutil.h"
|
||||
|
||||
#define CONFIG 1005
|
||||
|
||||
@ -82,6 +89,45 @@ static int ResetCmd(pSICSOBJ ccmd, SConnection * pCon,
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int NoTimeBinCmd(pSICSOBJ ccmd, SConnection * pCon,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
pHdb timeNode = NULL;
|
||||
|
||||
timeNode = GetHipadabaNode(ccmd->objectNode,"time_binning");
|
||||
if(timeNode == NULL){
|
||||
SCWrite(pCon,"ERROR: HM has no time binning",eError);
|
||||
return 0;
|
||||
}
|
||||
SCPrintf(pCon,eValue,"%s.totimebin = %d", ccmd->objectNode->name,
|
||||
timeNode->value.arrayLength);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int TimebinsCmd(pSICSOBJ ccmd, SConnection * pCon,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
pHdb timeNode = NULL;
|
||||
pDynString data= NULL;
|
||||
|
||||
timeNode = GetHipadabaNode(ccmd->objectNode,"time_binning");
|
||||
if(timeNode == NULL){
|
||||
SCWrite(pCon,"ERROR: HM has no time binning",eError);
|
||||
return 0;
|
||||
}
|
||||
data = formatValue(timeNode->value,timeNode);
|
||||
if(data != NULL){
|
||||
SCPrintf(pCon,eValue,"%s.timebins = %s", ccmd->objectNode->name,
|
||||
GetCharArray(data));
|
||||
DeleteDynString(data);
|
||||
} else {
|
||||
SCWrite(pCon,"ERROR: out of memory formatting timebins", eError);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int GenbinCmd(pSICSOBJ ccmd, SConnection * pCon,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
@ -124,6 +170,96 @@ static int GenbinCmd(pSICSOBJ ccmd, SConnection * pCon,
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int ConfigureCmd(pSICSOBJ ccmd, SConnection * pCon,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
pHdb dimNode = NULL;
|
||||
|
||||
if(nPar < 1) {
|
||||
SCWrite(pCon,"ERROR: need a parameter to read", eError);
|
||||
return 0;
|
||||
}
|
||||
dimNode = GetHipadabaNode(ccmd->objectNode,"dim");
|
||||
|
||||
assert(dimNode != NULL);
|
||||
|
||||
if(strcmp(par[0]->value.v.text,"dim0") == 0){
|
||||
SCPrintf(pCon,eValue,"%s.dim0 = %d", ccmd->objectNode->name,
|
||||
dimNode->value.v.intArray[0]);
|
||||
} else if(strcmp(par[0]->value.v.text,"dim1") == 0){
|
||||
SCPrintf(pCon,eValue,"%s.dim1 = %d", ccmd->objectNode->name,
|
||||
dimNode->value.v.intArray[1]);
|
||||
} else {
|
||||
SCPrintf(pCon,eError,"ERROR: subcommand %s to configure not found",
|
||||
par[0]->value.v.text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int SumCmd(pSICSOBJ ccmd, SConnection * pCon,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
pHdb dimNode = NULL, dataNode = NULL;
|
||||
int xstart, xend, ystart, yend, i;
|
||||
long lSum;
|
||||
|
||||
dimNode = GetHipadabaNode(ccmd->objectNode,"dim");
|
||||
dataNode = GetHipadabaNode(ccmd->objectNode,"data");
|
||||
assert(dimNode != NULL && dataNode != NULL);
|
||||
|
||||
switch(dimNode->value.arrayLength){
|
||||
case 1:
|
||||
if(nPar < 2) {
|
||||
SCWrite(pCon,"ERROR: need start and end for summing 1D data",eError);
|
||||
return 0;
|
||||
}
|
||||
xstart = par[0]->value.v.intValue;
|
||||
xend = par[1]->value.v.intValue;
|
||||
if(xstart < 0){
|
||||
xstart = 0;
|
||||
}
|
||||
if(xend > dataNode->value.arrayLength){
|
||||
xend = dataNode->value.arrayLength;
|
||||
}
|
||||
for(i = xstart; i < xend; i++){
|
||||
lSum += dataNode->value.v.intArray[i];
|
||||
}
|
||||
SCPrintf(pCon,eValue,"%s.sum = %ld", ccmd->objectNode->name, lSum);
|
||||
break;
|
||||
case 2:
|
||||
if(nPar < 4) {
|
||||
SCWrite(pCon,"ERROR: need start and end in x and y for summing 2D data",eError);
|
||||
return 0;
|
||||
}
|
||||
xstart = par[0]->value.v.intValue;
|
||||
xend = par[1]->value.v.intValue;
|
||||
if(xstart < 0){
|
||||
xstart = 0;
|
||||
}
|
||||
if(xend > dimNode->value.v.intArray[0]){
|
||||
xend = dimNode->value.v.intArray[0];
|
||||
}
|
||||
ystart = par[2]->value.v.intValue;
|
||||
yend = par[3]->value.v.intValue;
|
||||
if(ystart < 0){
|
||||
ystart = 0;
|
||||
}
|
||||
if(yend > dimNode->value.v.intArray[1]){
|
||||
yend = dimNode->value.v.intArray[1];
|
||||
}
|
||||
lSum = sumWindow(dataNode->value.v.intArray, xstart,xend,dimNode->value.v.intArray[0],
|
||||
ystart, yend, dimNode->value.v.intArray[1]);
|
||||
SCPrintf(pCon,eValue,"%s.sum = %ld", ccmd->objectNode->name, lSum);
|
||||
default:
|
||||
SCPrintf(pCon,eError, "ERROR: summing not supported for %s dimensional data",
|
||||
dimNode->value.arrayLength);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
static int InitCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
@ -228,6 +364,12 @@ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
|
||||
child = AddSICSHdbPar(node,"init", usMugger, MakeSICSFunc(InitCmd));
|
||||
|
||||
child = AddSICSHdbPar(node,"sum", usSpy, MakeSICSFunc(SumCmd));
|
||||
AddSICSHdbPar(child, "xstart", usSpy, MakeHdbInt(0));
|
||||
AddSICSHdbPar(child, "xend", usSpy, MakeHdbInt(0));
|
||||
AddSICSHdbPar(child, "ystart", usSpy, MakeHdbInt(0));
|
||||
AddSICSHdbPar(child, "yend", usSpy, MakeHdbInt(0));
|
||||
|
||||
/*
|
||||
* test TOF option
|
||||
*/
|
||||
@ -245,6 +387,10 @@ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
AddSICSHdbPar(child, "start", usMugger, MakeHdbFloat(10.));
|
||||
AddSICSHdbPar(child, "step", usMugger, MakeHdbFloat(10.));
|
||||
AddSICSHdbPar(child, "np", usMugger, MakeHdbInt(10));
|
||||
|
||||
child = AddSICSHdbPar(node,"notimebin", usSpy, MakeSICSFunc(NoTimeBinCmd));
|
||||
child = AddSICSHdbPar(node,"timebins", usSpy, MakeSICSFunc(TimebinsCmd));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -257,3 +403,99 @@ int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*===========================================================================
|
||||
This is a set of adapter functions which make the second gen HM look like
|
||||
a first generation one. This saves me from rewriting all the calculation codes
|
||||
based on the first gen HM
|
||||
|
||||
!!!! BEWARE: In the functions below pHistMem should never be a pointer to a
|
||||
HistMem but rather a second generation HM which is a counter object !!!!
|
||||
===============================================================================*/
|
||||
const float *GetSecHistTimeBin(pHistMem self, int *iLength)
|
||||
{
|
||||
float *tb = NULL;
|
||||
pHdb tbNode = NULL;
|
||||
int i;
|
||||
pCounter pCter;
|
||||
|
||||
assert(self->pDes->parNode != NULL);
|
||||
|
||||
pCter = (pCounter)self;
|
||||
tbNode = GetHipadabaNode(self->pDes->parNode,"time_binning");
|
||||
if(tbNode == NULL){
|
||||
return NULL;
|
||||
}
|
||||
*iLength = tbNode->value.arrayLength;
|
||||
if(*iLength != pCter->tbLength){
|
||||
if(pCter->timeBinning){
|
||||
free(pCter->timeBinning);
|
||||
}
|
||||
pCter->timeBinning = malloc(*iLength*sizeof(float));
|
||||
}
|
||||
|
||||
for(i = 0; i < *iLength; i++){
|
||||
pCter->timeBinning[i] = tbNode->value.v.floatArray[i];
|
||||
}
|
||||
|
||||
return (const float*)pCter->timeBinning;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
HistInt *GetSecHistogramPointer(pHistMem self,SConnection *pCon)
|
||||
{
|
||||
pHdb dataNode = NULL;
|
||||
|
||||
assert(self->pDes->parNode != NULL);
|
||||
|
||||
dataNode = GetHipadabaNode(self->pDes->parNode,"data");
|
||||
if(dataNode == NULL){
|
||||
return NULL;
|
||||
}
|
||||
return (HistInt *)dataNode->value.v.intArray;
|
||||
}
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int GetSecHistogram(pHistMem self, SConnection *pCon,
|
||||
int i,int iStart, int iEnd, HistInt *lData, int iDataLen)
|
||||
{
|
||||
pHdb dataNode = NULL;
|
||||
|
||||
assert(self->pDes->parNode != NULL);
|
||||
|
||||
dataNode = GetHipadabaNode(self->pDes->parNode,"data");
|
||||
if(dataNode == NULL){
|
||||
return 0;
|
||||
}
|
||||
if(iEnd > dataNode->value.arrayLength){
|
||||
iEnd = dataNode->value.arrayLength;
|
||||
}
|
||||
if ((iEnd - iStart) > iDataLen / sizeof(HistInt)) {
|
||||
SCWrite(pCon, "WARNING: truncating request to fit data space",
|
||||
eWarning);
|
||||
iEnd = (iDataLen / sizeof(HistInt)) - 1;
|
||||
}
|
||||
memcpy(lData,dataNode->value.v.intArray+iStart, (iEnd-iStart)*sizeof(int));
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
void SecHistDirty(pHistMem self)
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int GetSecHistLength(pHistMem self)
|
||||
{
|
||||
pHdb dataNode = NULL;
|
||||
int i, length = 1;
|
||||
|
||||
assert(self->pDes->parNode != NULL);
|
||||
|
||||
dataNode = GetHipadabaNode(self->pDes->parNode,"dim");
|
||||
if(dataNode == NULL){
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i < dataNode->value.arrayLength; i++){
|
||||
length *= dataNode->value.v.intArray[i];
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
@ -17,4 +17,12 @@
|
||||
int MakeSecHM(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
const float *GetSecHistTimeBin(pHistMem self, int *iLength);
|
||||
HistInt *GetSecHistogramPointer(pHistMem self,SConnection *pCon);
|
||||
int GetSecHistogram(pHistMem self, SConnection *pCon,
|
||||
int i,int iStart, int iEnd, HistInt *lData, int iDataLen);
|
||||
void SecHistDirty(pHistMem self);
|
||||
int GetSecHistLength(pHistMem self);
|
||||
|
||||
|
||||
#endif /*HISTMEMSEC_H_*/
|
||||
|
@ -443,6 +443,9 @@ $\langle$Protos {\footnotesize ?}$\rangle\equiv$
|
||||
\mbox{}\verb@ int HistBlockCount(pHistMem self, SConnection *pCon);@\\
|
||||
\mbox{}\verb@ void HistDirty(pHistMem self); @\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@ int isSecondGen(pHistMem self);@\\
|
||||
\mbox{}\verb@ pHistMem FindHM(SicsInterp *pSics, char *name);@\\
|
||||
\mbox{}\verb@@\\
|
||||
\mbox{}\verb@@$\Diamond$
|
||||
\end{list}
|
||||
\vspace{-1ex}
|
||||
|
@ -347,6 +347,9 @@ controlled by the following functions:
|
||||
int HistBlockCount(pHistMem self, SConnection *pCon);
|
||||
void HistDirty(pHistMem self);
|
||||
|
||||
int isSecondGen(pHistMem self);
|
||||
pHistMem FindHM(SicsInterp *pSics, char *name);
|
||||
|
||||
@}
|
||||
The first four functions are simple parameter enquiry and manipulation
|
||||
functions. GetHistMonitor returns the count on monitor number i for the
|
||||
|
2
make_gen
2
make_gen
@ -42,7 +42,7 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
|
||||
singlenb.o simindex.o simidx.o uselect.o singletas.o motorsec.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
|
||||
singlebinb.o taskobj.o sctcomtask.o
|
||||
|
||||
MOTOROBJ = motor.o simdriv.o
|
||||
COUNTEROBJ = countdriv.o simcter.o counter.o
|
||||
|
10
nread.c
10
nread.c
@ -1090,6 +1090,7 @@ static int CommandAcceptCB(int handle, void *userData)
|
||||
{
|
||||
SConnection *pCon = NULL;
|
||||
pCommandCBData usData = NULL;
|
||||
char buffer[80];
|
||||
|
||||
pCon = SCreateConnection(pServ->pSics, handle, 3);
|
||||
usData = malloc(sizeof(CommandCBData));
|
||||
@ -1104,7 +1105,9 @@ static int CommandAcceptCB(int handle, void *userData)
|
||||
}
|
||||
usData->pCon = pCon;
|
||||
usData->state = COLLECT;
|
||||
TaskRegister(pServ->pTasker,
|
||||
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
|
||||
TaskRegisterN(pServ->pTasker,
|
||||
buffer,
|
||||
SCTaskFunction,
|
||||
SCSignalFunction, SCDeleteConnection, pCon, 1);
|
||||
ANETsetReadCallback(handle, CommandDataCB, usData, killCommandCBData);
|
||||
@ -1293,6 +1296,7 @@ static int TelnetAcceptCB(int handle, void *userData)
|
||||
SConnection *pCon = NULL;
|
||||
pCommandCBData usData = NULL;
|
||||
pTelTask pTel = NULL;
|
||||
char buffer[80];
|
||||
|
||||
pCon = SCreateConnection(pServ->pSics, handle, 3);
|
||||
usData = malloc(sizeof(CommandCBData));
|
||||
@ -1316,7 +1320,9 @@ static int TelnetAcceptCB(int handle, void *userData)
|
||||
}
|
||||
/* register connection and task */
|
||||
pCon->iTelnet = 1;
|
||||
TaskRegister(pServ->pTasker,
|
||||
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
|
||||
TaskRegisterN(pServ->pTasker,
|
||||
buffer,
|
||||
TelnetTask, TelnetSignal, DeleteTelnet, pTel, 1);
|
||||
ANETsetReadCallback(handle, ANETTelnetProcess,
|
||||
usData, killCommandCBData);
|
||||
|
12
nserver.c
12
nserver.c
@ -179,7 +179,8 @@ int InitServer(char *file, pServer * pServ)
|
||||
assert((pReader =
|
||||
CreateNetReader(self, iPasswordTimeOut,
|
||||
iCommandTimeOut)) != NULL);
|
||||
TaskRegister(self->pTasker, NetReaderTask, NetReaderSignal, NULL, /* call DeleteNetReader later than TaskerDelete */
|
||||
TaskRegisterN(self->pTasker, "Network Reader",
|
||||
NetReaderTask, NetReaderSignal, NULL, /* call DeleteNetReader later than TaskerDelete */
|
||||
pReader, 1);
|
||||
self->pReader = pReader;
|
||||
|
||||
@ -244,17 +245,18 @@ int InitServer(char *file, pServer * pServ)
|
||||
|
||||
/* install environment monitor */
|
||||
self->pMonitor = GetEnvMon(self->pSics);
|
||||
TaskRegister(self->pTasker,
|
||||
TaskRegisterN(self->pTasker,"EV Monitor",
|
||||
EnvMonTask, EnvMonSignal, NULL, self->pMonitor, 1);
|
||||
|
||||
/* install performance monitor */
|
||||
pMon = CreatePerfMon(20);
|
||||
AddCommand(self->pSics, "Performance", PerfMonWrapper, DeletePerfMon,
|
||||
pMon);
|
||||
TaskRegister(self->pTasker, PerfMonTask, PerfMonSignal, NULL, pMon, 1);
|
||||
TaskRegisterN(self->pTasker,"perfmon", PerfMonTask, PerfMonSignal, NULL, pMon, 1);
|
||||
/* Install a second one for higher granularity measurement */
|
||||
pMon = CreatePerfMon(2);
|
||||
TaskRegister(self->pTasker, PerfMonTask, PerfMonSignal, DeletePerfMon, pMon, 1);
|
||||
TaskRegisterN(self->pTasker,"perfmon2",
|
||||
PerfMonTask, PerfMonSignal, DeletePerfMon, pMon, 1);
|
||||
|
||||
|
||||
/* install telnet port */
|
||||
@ -469,7 +471,7 @@ int UserWait(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
SetStatus(eUserWait);
|
||||
sWait.dFinish = DoubleTime() + (double)fVal;
|
||||
sWait.iEnd = 0;
|
||||
lID = TaskRegister(pTask, WaitTask, WaitSignal, NULL, &sWait, 1);
|
||||
lID = TaskRegisterN(pTask,"wait", WaitTask, WaitSignal, NULL, &sWait, 1);
|
||||
TaskWait(pTask, lID);
|
||||
SetStatus(eOld);
|
||||
if (SCGetInterrupt(pCon) != eContinue) {
|
||||
|
2
nwatch.c
2
nwatch.c
@ -54,7 +54,7 @@ int NetWatchInit(void)
|
||||
return 0;
|
||||
memset(instance, 0, sizeof(NetWatch));
|
||||
instance->lMagic = NWMAGIC;
|
||||
TaskRegister(pServ->pTasker, NetWatchTask, NULL, NULL, NULL, 1);
|
||||
TaskRegisterN(pServ->pTasker,"nwatch", NetWatchTask, NULL, NULL, NULL, 1);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ static int CountCallback(int iEvent, void *pEventData, void *pUser)
|
||||
self->nextUpdate = time(NULL) + self->updateIntervall;
|
||||
self->iEnd = 0;
|
||||
self->pCon = pCon;
|
||||
TaskRegister(pServ->pTasker, UpdateTask, NULL, NULL, self, 1);
|
||||
TaskRegisterN(pServ->pTasker, "NXupdater", UpdateTask, NULL, NULL, self, 1);
|
||||
return 1;
|
||||
} else if (iEvent == COUNTEND) {
|
||||
self->iEnd = 1;
|
||||
|
1
ofac.c
1
ofac.c
@ -169,6 +169,7 @@ static void InitIniCommands(SicsInterp * pInter)
|
||||
SCMD("SicsAlias", SicsAlias);
|
||||
SCMD("SicsUser", PWSicsUser);
|
||||
SCMD("TokenInit", TokenInit);
|
||||
SCMD("MakeTask", TaskOBJFactory);
|
||||
SCMD("UpdateFactory", UpdateFactory);
|
||||
SCMD("VarMake", VarFactory);
|
||||
SCMD("VelocitySelector", VelSelFactory);
|
||||
|
@ -166,7 +166,8 @@ static int StartOscillation(pOscillator self, SConnection * pCon)
|
||||
/*
|
||||
start task
|
||||
*/
|
||||
self->taskID = TaskRegister(pServ->pTasker,
|
||||
snprintf(pBueffel,sizeof(pBueffel),"Oscillate-%s", self->pMot->name);
|
||||
self->taskID = TaskRegisterN(pServ->pTasker,pBueffel,
|
||||
OscillationTask, NULL, NULL, self, 10);
|
||||
if (self->taskID < 0) {
|
||||
SCWrite(pCon, "ERROR: failed to start oscillation task", eError);
|
||||
|
2
remob.c
2
remob.c
@ -953,7 +953,7 @@ static RemServer *RemServerInit(char *name, char *host, int port)
|
||||
remserver->taskActive = 1;
|
||||
remserver->interestActive = 0;
|
||||
remserver->forwardMessages = 1;
|
||||
TaskRegister(pServ->pTasker, RemServerTask, NULL, RemServerKill,
|
||||
TaskRegisterN(pServ->pTasker,name, RemServerTask, NULL, RemServerKill,
|
||||
remserver, 1);
|
||||
return remserver;
|
||||
}
|
||||
|
9
sansbc.c
9
sansbc.c
@ -101,8 +101,7 @@ static int COGCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
hm = FindCommandData(pServ->pSics,
|
||||
par[0]->value.v.text, "HistMem");
|
||||
hm = FindHM(pServ->pSics, par[0]->value.v.text);
|
||||
if(hm == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text);
|
||||
return 0;
|
||||
@ -137,8 +136,7 @@ static int COCCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
hm = FindCommandData(pServ->pSics,
|
||||
par[0]->value.v.text, "HistMem");
|
||||
hm = FindHM(pServ->pSics, par[0]->value.v.text);
|
||||
if(hm == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text);
|
||||
return 0;
|
||||
@ -173,8 +171,7 @@ static int StatCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
return 0;
|
||||
}
|
||||
|
||||
hm = FindCommandData(pServ->pSics,
|
||||
par[0]->value.v.text, "HistMem");
|
||||
hm = FindHM(pServ->pSics, par[0]->value.v.text);
|
||||
if(hm == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: hm %s not found", par[0]->value.v.text);
|
||||
return 0;
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "macro.h"
|
||||
#include "syncedprot.h"
|
||||
#include "scriptcontext.h"
|
||||
#include "sctcomtask.h"
|
||||
|
||||
typedef struct ContextItem {
|
||||
struct ContextItem *next;
|
||||
@ -862,7 +863,7 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
static char *ParText(Hdb * cmdNode, char *name,
|
||||
char *ParText(Hdb * cmdNode, char *name,
|
||||
int nPar, char *defaultValue)
|
||||
{
|
||||
Hdb *par;
|
||||
@ -1412,15 +1413,6 @@ static char *TransactionHandler(void *actionData, char *lastReply,
|
||||
return st->command;
|
||||
} else {
|
||||
st->sent = 2;
|
||||
/*
|
||||
if (st->controller->verbose) {
|
||||
SCPrintf(st->con, eLog, "%6.3f reply : %s", secondsOfMinute(), lastReply);
|
||||
}
|
||||
if (st->controller->fd != NULL) {
|
||||
fprintf(st->controller->fd,"%6.3f reply : %s\n", secondsOfMinute(), lastReply);
|
||||
}
|
||||
*/
|
||||
/* printf("Transact: %s got %s\n", st->command, lastReply); */
|
||||
if (lastReply == NULL) {
|
||||
lastReply = "";
|
||||
}
|
||||
@ -1487,12 +1479,6 @@ static int SctTransactCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
TransactionHandler, SctTransactMatch, NULL, NULL);
|
||||
while (st->sent != 2) {
|
||||
TaskYield(pServ->pTasker);
|
||||
/* not yet tested:
|
||||
if (SCGetInterrupt(con) != eContinue) {
|
||||
DevUnschedule(c->devser, st, TransactionHandler, SctTransactMatch);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
if (st->reply != NULL) {
|
||||
SCWrite(con,st->reply,eValue);
|
||||
@ -1722,7 +1708,7 @@ static void SctKillController(void *c)
|
||||
}
|
||||
|
||||
if (pServ->pTasker) {
|
||||
TaskRegister(pServ->pTasker, SctDeferredTask, NULL, SctDeferredFree,
|
||||
TaskRegisterN(pServ->pTasker,"killsct", SctDeferredTask, NULL, SctDeferredFree,
|
||||
controller, 0);
|
||||
} else {
|
||||
free(controller);
|
||||
@ -1899,6 +1885,7 @@ void SctInit(void)
|
||||
sct->desc = CreateDescriptor("ScriptContext");
|
||||
AddCommand(pServ->pSics, "sct", SctCommand, SctKill, sct);
|
||||
AddCmd("makesctcontroller", SctMakeController);
|
||||
AddCmd("makesctcomtask", SctMakeComTask);
|
||||
}
|
||||
|
||||
int SctVerbose(SctController * c)
|
||||
@ -1906,3 +1893,15 @@ int SctVerbose(SctController * c)
|
||||
return c->verbose;
|
||||
}
|
||||
|
||||
DevSer *SctGetDevser(void *data)
|
||||
{
|
||||
SctController *c;
|
||||
|
||||
pSICSOBJ ccmd = (pSICSOBJ)data;
|
||||
assert(ccmd);
|
||||
assert(strcmp(ccmd->pDes->name,"SctController") == 0);
|
||||
|
||||
|
||||
c = (SctController *) ccmd->pPrivate;
|
||||
return c->devser;
|
||||
}
|
||||
|
@ -35,5 +35,10 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
||||
* \return 1 for verbose, 0 for silent
|
||||
*/
|
||||
int SctVerbose(SctController * c);
|
||||
|
||||
/**
|
||||
* retrieve the device serializer
|
||||
* \param data A pointer to a SICSObject representing a SctController
|
||||
* \param A pointer the the device serializer
|
||||
*/
|
||||
DevSer *SctGetDevser(void *data);
|
||||
#endif
|
||||
|
517
sctcomtask.c
Normal file
517
sctcomtask.c
Normal file
@ -0,0 +1,517 @@
|
||||
/**
|
||||
* This is another approach at using the scriptcontext system. It introduces
|
||||
* the concept of a communication task which is executed against a device serializer,
|
||||
* accessed via a given ScriptContext. Clients can:
|
||||
* - Create CommTasks
|
||||
* - Figure out their state
|
||||
* - Retrieve reply data
|
||||
* - wait for a ComTask to finish.
|
||||
*
|
||||
* The the purpose sctcomtask will keep a cache of pending and finished communications.
|
||||
* Old runs will be deleted periodically. Nevertheless the cache can be listed in order
|
||||
* to figure out what happened.
|
||||
*
|
||||
* The intended use is for C-code or scripts to interact in a serial manner with
|
||||
* the asynchronous communication system implemented in devser and ascon. As a
|
||||
* standalone implementation would share tons of code with scriptcontext, this has
|
||||
* been implemented as an add on module to scriptcontext.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, December 2012
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "sctcomtask.h"
|
||||
#include "scriptcontext.h"
|
||||
#include "sicsobj.h"
|
||||
#include "sicsutil.h"
|
||||
#include "sicshipadaba.h"
|
||||
|
||||
static unsigned int mamaID = 0L;
|
||||
|
||||
extern char *ParText(Hdb * cmdNode, char *name,
|
||||
int nPar, char *defaultValue);
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
typedef struct{
|
||||
char *sendData;
|
||||
char *replyData;
|
||||
int replyDataLength;
|
||||
int ID;
|
||||
double startTime;
|
||||
double endTime;
|
||||
ComTaskState state;
|
||||
}ComTask, *pComTask;
|
||||
|
||||
/*----------------------------------------------------------------*/
|
||||
struct ComTaskManager{
|
||||
DevSer *devser;
|
||||
unsigned int halfQueueLength;
|
||||
ComTask *TaskQueue;
|
||||
unsigned int iPtr;
|
||||
};
|
||||
/*-----------------------------------------------------------------*/
|
||||
static void KillComTaskData(ComTask *queue, int length)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < length; i++){
|
||||
if(queue[i].sendData != NULL){
|
||||
free(queue[i].sendData);
|
||||
queue[i].sendData = NULL;
|
||||
}
|
||||
if(queue[i].replyData != NULL){
|
||||
free(queue[i].replyData);
|
||||
queue[i].replyData = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static char *ComTaskHandler(void *data, char *replyData, int commError)
|
||||
{
|
||||
pComTask task = (pComTask)data;
|
||||
assert(task != NULL);
|
||||
|
||||
if(replyData == NULL){
|
||||
task->state = eRunning;
|
||||
return task->sendData;
|
||||
} else {
|
||||
if(task->replyData != NULL){
|
||||
free(task->replyData);
|
||||
}
|
||||
task->replyData = strdup(replyData);
|
||||
task->replyDataLength = strlen(replyData);
|
||||
task->endTime = DoubleTime();
|
||||
task->state = eFinished;
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static int ComTaskMatch(void *data1, void *data2)
|
||||
{
|
||||
pComTask task1 = (pComTask)data1;
|
||||
pComTask task2 = (pComTask)data2;
|
||||
|
||||
assert(task1 && task2);
|
||||
|
||||
if(task1->ID == task2->ID){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
static char *stateName[] = {
|
||||
"waiting",
|
||||
"running",
|
||||
"finished",
|
||||
"unknown"
|
||||
};
|
||||
|
||||
static char* StateToText(ComTaskState state)
|
||||
{
|
||||
return stateName[(int)state];
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
static char* ComTaskInfo(void *data)
|
||||
{
|
||||
char *info = NULL;
|
||||
char buf[] = {"NA"};
|
||||
char *reply;
|
||||
int length = 256;
|
||||
|
||||
pComTask task = (pComTask)data;
|
||||
assert(data != NULL);
|
||||
|
||||
if(task->sendData != NULL){
|
||||
length += strlen(task->sendData);
|
||||
}
|
||||
if(task->replyData != NULL){
|
||||
length += strlen(task->replyData);
|
||||
}
|
||||
info = calloc(length,sizeof(char));
|
||||
if(info == NULL){
|
||||
return info;
|
||||
}
|
||||
if(task->replyData == NULL){
|
||||
reply = buf;
|
||||
} else {
|
||||
reply = task->replyData;
|
||||
}
|
||||
snprintf(info,length,"%s:%s:%lf:%s:%lf", StateToText(task->state),
|
||||
task->sendData,task->startTime, reply, task->endTime);
|
||||
return info;
|
||||
}
|
||||
/*----------------------------------------------------------------*/
|
||||
int StartComTask(ComTaskManager *manager, char *priority, char *sendData)
|
||||
{
|
||||
int ID, i;
|
||||
unsigned int ptr;
|
||||
DevPrio prio;
|
||||
|
||||
assert(manager != NULL && priority != NULL);
|
||||
|
||||
ID = mamaID;
|
||||
mamaID++;
|
||||
if(mamaID < 0){
|
||||
mamaID = 0;
|
||||
}
|
||||
|
||||
if(manager->iPtr >= 2*manager->halfQueueLength){
|
||||
KillComTaskData(manager->TaskQueue,manager->halfQueueLength);
|
||||
memmove(manager->TaskQueue,&manager->TaskQueue[manager->halfQueueLength],
|
||||
manager->halfQueueLength*sizeof(ComTask));
|
||||
/**
|
||||
* The pointers need to be cleared, not freed, in order to
|
||||
* prevent double freeing when reusing them.
|
||||
*/
|
||||
for(i = manager->halfQueueLength; i < 2*manager->halfQueueLength; i++){
|
||||
manager->TaskQueue[i].sendData = NULL;
|
||||
manager->TaskQueue[i].replyData = NULL;
|
||||
}
|
||||
manager->iPtr = manager->halfQueueLength;
|
||||
}
|
||||
ptr = manager->iPtr;
|
||||
manager->iPtr++;
|
||||
|
||||
manager->TaskQueue[ptr].ID = ID;
|
||||
manager->TaskQueue[ptr].startTime = DoubleTime();
|
||||
manager->TaskQueue[ptr].endTime = 0.;
|
||||
manager->TaskQueue[ptr].state = eWaiting;
|
||||
if(manager->TaskQueue[ptr].sendData != NULL){
|
||||
free(manager->TaskQueue[ptr].sendData);
|
||||
}
|
||||
manager->TaskQueue[ptr].sendData = strdup(sendData);
|
||||
if(manager->TaskQueue[ptr].replyData != NULL){
|
||||
free(manager->TaskQueue[ptr].replyData);
|
||||
}
|
||||
manager->TaskQueue[ptr].replyData = NULL;
|
||||
|
||||
prio = DevText2Prio(priority);
|
||||
DevQueue(manager->devser,
|
||||
&manager->TaskQueue[ptr],
|
||||
prio,
|
||||
ComTaskHandler,
|
||||
ComTaskMatch,
|
||||
NULL,
|
||||
ComTaskInfo);
|
||||
|
||||
return ID;
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static int StartComTaskCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
char *priority, *sendData;
|
||||
int lID;
|
||||
ComTaskManager *manni = NULL;
|
||||
|
||||
if(nPar < 2) {
|
||||
SCWrite(con,"ERROR: need priorty and send data as parameters",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
priority = ParText(cmdNode,"priority",nPar,"read");
|
||||
sendData = ParText(cmdNode,"send",nPar,"None");
|
||||
|
||||
manni = (ComTaskManager *)ccmd->pPrivate;
|
||||
lID = StartComTask(manni, priority, sendData);
|
||||
SCPrintf(con,eValue,"comtaskid = %ld", lID);
|
||||
return 1;
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static int ComTaskCompare(const void *data1, const void *data2)
|
||||
{
|
||||
pComTask task1 = (pComTask)data1;
|
||||
pComTask task2 = (pComTask)data2;
|
||||
|
||||
assert(task1 && task2);
|
||||
|
||||
if(task1->ID < task2->ID){
|
||||
return -1;
|
||||
} else if(task1->ID > task2->ID){
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
ComTaskState GetComTaskState(ComTaskManager *manager, int comTaskID)
|
||||
{
|
||||
ComTask key;
|
||||
ComTask *task = NULL;
|
||||
|
||||
key.ID = comTaskID;
|
||||
|
||||
task = bsearch(&key,manager->TaskQueue,manager->iPtr,
|
||||
sizeof(ComTask), ComTaskCompare);
|
||||
if(task == NULL){
|
||||
return eUnknown;
|
||||
} else {
|
||||
return task->state;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static int GetComTaskStateCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
int lID;
|
||||
ComTaskManager *manni = NULL;
|
||||
ComTaskState state;
|
||||
|
||||
if(nPar < 1) {
|
||||
SCWrite(con,"ERROR: need task ID parameter",eError);
|
||||
return 0;
|
||||
}
|
||||
lID = par[0]->value.v.intValue;
|
||||
|
||||
manni = (ComTaskManager *)ccmd->pPrivate;
|
||||
state = GetComTaskState(manni,lID);
|
||||
SCPrintf(con,eValue,"%d = %s", lID, StateToText(state));
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
const char *GetComTaskReply(ComTaskManager *manager,
|
||||
int comTaskID, int *length)
|
||||
{
|
||||
ComTask key;
|
||||
ComTask *task = NULL;
|
||||
|
||||
key.ID = comTaskID;
|
||||
|
||||
task = bsearch(&key,manager->TaskQueue,manager->iPtr,
|
||||
sizeof(ComTask), ComTaskCompare);
|
||||
if(task == NULL || task->state != eFinished){
|
||||
return NULL;
|
||||
} else {
|
||||
return (const char *)task->replyData;
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static int GetComTaskReplyCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
int lID;
|
||||
int length;
|
||||
ComTaskManager *manni = NULL;
|
||||
const char *reply;
|
||||
|
||||
if(nPar < 1) {
|
||||
SCWrite(con,"ERROR: need task ID parameter",eError);
|
||||
return 0;
|
||||
}
|
||||
lID = par[0]->value.v.intValue;
|
||||
|
||||
manni = (ComTaskManager *)ccmd->pPrivate;
|
||||
reply = GetComTaskReply(manni,lID,&length);
|
||||
if(reply == NULL){
|
||||
SCPrintf(con,eError,"No reply for %ld found", lID);
|
||||
return 0;
|
||||
} else {
|
||||
SCPrintf(con,eValue,"%d = %s", lID, reply);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
void ComTaskWait(ComTaskManager *manager, int comTaskID)
|
||||
{
|
||||
|
||||
ComTask key;
|
||||
ComTask *task = NULL;
|
||||
|
||||
key.ID = comTaskID;
|
||||
|
||||
task = bsearch(&key,manager->TaskQueue,manager->iPtr,
|
||||
sizeof(ComTask), ComTaskCompare);
|
||||
if(task == NULL){
|
||||
return;
|
||||
}
|
||||
/**
|
||||
* Hmmmmhhhh. It might be better to start a SICS task here and
|
||||
* wait for it terminate. But this would essentially also call
|
||||
* TaskYield or, worse, Taskwait.
|
||||
*/
|
||||
while(task->state != eFinished){
|
||||
TaskYield(pServ->pTasker);
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static int ComTaskWaitCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
int lID;
|
||||
ComTaskManager *manni = NULL;
|
||||
|
||||
if(nPar < 1) {
|
||||
SCWrite(con,"ERROR: need task ID parameter",eError);
|
||||
return 0;
|
||||
}
|
||||
lID = par[0]->value.v.intValue;
|
||||
|
||||
manni = (ComTaskManager *)ccmd->pPrivate;
|
||||
ComTaskWait(manni,lID);
|
||||
SCWrite(con,"Done",eValue);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static int ComTaskListAllCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
ComTaskManager *manni = NULL;
|
||||
pDynString list = NULL;
|
||||
int i;
|
||||
char *info;
|
||||
|
||||
manni = (ComTaskManager *)ccmd->pPrivate;
|
||||
list = CreateDynString(256,256);
|
||||
if(list == NULL){
|
||||
SCWrite(con,"ERROR: out of memory listing ComTasks", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i = 0; i < manni->iPtr; i++){
|
||||
info = ComTaskInfo((void *)&manni->TaskQueue[i]);
|
||||
DynStringConcat(list,info);
|
||||
DynStringConcatChar(list,'\n');
|
||||
free(info);
|
||||
}
|
||||
SCWrite(con,GetCharArray(list),eValue);
|
||||
DeleteDynString(list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int ComTaskListPendingCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
ComTaskManager *manni = NULL;
|
||||
pDynString list = NULL;
|
||||
int i;
|
||||
char *info;
|
||||
|
||||
manni = (ComTaskManager *)ccmd->pPrivate;
|
||||
list = CreateDynString(256,256);
|
||||
if(list == NULL){
|
||||
SCWrite(con,"ERROR: out of memory listing ComTasks", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(i = 0; i < manni->iPtr; i++){
|
||||
if(manni->TaskQueue[i].state != eFinished){
|
||||
info = ComTaskInfo((void *)&manni->TaskQueue[i]);
|
||||
DynStringConcat(list,info);
|
||||
DynStringConcatChar(list,'\n');
|
||||
free(info);
|
||||
}
|
||||
}
|
||||
SCWrite(con,GetCharArray(list),eValue);
|
||||
DeleteDynString(list);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------*/
|
||||
static ComTaskManager *MakeComTaskManager(int length)
|
||||
{
|
||||
ComTaskManager *manni = NULL;
|
||||
manni = calloc(1, sizeof(ComTaskManager));
|
||||
if(manni != NULL){
|
||||
manni->halfQueueLength=length;
|
||||
manni->TaskQueue = calloc(length*2,sizeof(ComTask));
|
||||
if(manni->TaskQueue == NULL){
|
||||
free(manni);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return manni;
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
static void KillComTaskManager(void *data)
|
||||
{
|
||||
ComTaskManager *manni = (ComTaskManager *)data;
|
||||
|
||||
if(manni == NULL){
|
||||
return;
|
||||
}
|
||||
|
||||
if(manni->TaskQueue != NULL){
|
||||
free(manni->TaskQueue);
|
||||
}
|
||||
KillComTaskData(manni->TaskQueue,manni->halfQueueLength*2);
|
||||
free(manni);
|
||||
|
||||
}
|
||||
/*-----------------------------------------------------------------*/
|
||||
int SctMakeComTask(SConnection * con, SicsInterp * sics,
|
||||
void *object, int argc, char *argv[])
|
||||
{
|
||||
SICSOBJ *ccmd;
|
||||
pHdb cmd = NULL;
|
||||
ComTaskManager *manni = NULL;
|
||||
int length = 64;
|
||||
|
||||
if (argc < 3) {
|
||||
SCWrite(con,"ERROR: need at least comtaskmanager name and sctcontroller as arguments",
|
||||
eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ccmd = (SICSOBJ *)FindCommandData(sics,argv[2],"SctController");
|
||||
if(ccmd == NULL){
|
||||
SCPrintf(con,eError,"ERROR: SctController %s not found",argv[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(argc > 3) {
|
||||
length = atoi(argv[3]);
|
||||
}
|
||||
|
||||
manni = MakeComTaskManager(length);
|
||||
if(manni == NULL){
|
||||
SCWrite(con,"ERROR: out of memory allocating ComTaskmanager",eError);
|
||||
return 0;
|
||||
}
|
||||
manni->devser = SctGetDevser(ccmd);
|
||||
assert(manni->devser != NULL);
|
||||
|
||||
ccmd = MakeSICSOBJv(argv[1], "SctComTask", HIPNONE, usSpy);
|
||||
assert(ccmd);
|
||||
ccmd->pPrivate = manni;
|
||||
ccmd->KillPrivate = KillComTaskManager;
|
||||
|
||||
AddCommand(pServ->pSics, argv[1], InterInvokeSICSOBJ, KillSICSOBJ, ccmd);
|
||||
RegisterSICSOBJKillCmd(ccmd, argv[1]);
|
||||
SetDescriptorKey(ccmd->pDes, "creationCommand", "0");
|
||||
|
||||
cmd = AddSICSHdbPar(ccmd->objectNode,
|
||||
"start", usUser, MakeSICSFunc(StartComTaskCmd));
|
||||
AddSICSHdbPar(cmd, "priority", usUser, MakeHdbText(""));
|
||||
AddSICSHdbPar(cmd, "send", usUser, MakeHdbText("None"));
|
||||
|
||||
cmd = AddSICSHdbPar(ccmd->objectNode,
|
||||
"state", usUser, MakeSICSFunc(GetComTaskStateCmd));
|
||||
AddSICSHdbPar(cmd, "id", usUser, MakeHdbInt(0));
|
||||
|
||||
cmd = AddSICSHdbPar(ccmd->objectNode,
|
||||
"reply", usUser, MakeSICSFunc(GetComTaskReplyCmd));
|
||||
AddSICSHdbPar(cmd, "id", usUser, MakeHdbInt(0));
|
||||
|
||||
cmd = AddSICSHdbPar(ccmd->objectNode,
|
||||
"wait", usUser, MakeSICSFunc(ComTaskWaitCmd));
|
||||
AddSICSHdbPar(cmd, "id", usUser, MakeHdbInt(0));
|
||||
|
||||
cmd = AddSICSHdbPar(ccmd->objectNode,
|
||||
"listall", usSpy, MakeSICSFunc(ComTaskListAllCmd));
|
||||
|
||||
cmd = AddSICSHdbPar(ccmd->objectNode,
|
||||
"listpend", usSpy, MakeSICSFunc(ComTaskListPendingCmd));
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------------*/
|
78
sctcomtask.h
Normal file
78
sctcomtask.h
Normal file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* This is another approach at using the scriptcontext system. It introduces
|
||||
* the concept of a communication task which is executed against a device serializer,
|
||||
* accessed via a given ScriptContext. Clients can:
|
||||
* - Create CommTasks
|
||||
* - Figure out their state
|
||||
* - Retrieve reply data
|
||||
* - wait for a ComTask to finish.
|
||||
*
|
||||
* The the purpose sctcomtask will keep a cache of pending and finished communications.
|
||||
* Old runs will be deleted periodically. Nevertheless the cache can be listed in order
|
||||
* to figure out what happened.
|
||||
*
|
||||
* The intended use is for C-code or scripts to interact in a serial manner with
|
||||
* the asynchronous communication system implemented in devser and ascon. As a
|
||||
* standalone implementation would share tons of code with scriptcontext, this has
|
||||
* been implemented as an add on module to scriptcontext.
|
||||
*
|
||||
* copyright: see file COPYRIGHT
|
||||
*
|
||||
* Mark Koennecke, December 2012
|
||||
*/
|
||||
#ifndef __SCTCOMTASK
|
||||
#define __SCTCOMTASK
|
||||
#include <sics.h>
|
||||
|
||||
typedef struct ComTaskManager ComTaskManager;
|
||||
|
||||
typedef enum {
|
||||
eWaiting,
|
||||
eRunning,
|
||||
eFinished,
|
||||
eUnknown
|
||||
} ComTaskState;
|
||||
|
||||
|
||||
/**
|
||||
* Standard SIS installation function
|
||||
*/
|
||||
int SctMakeComTask(SConnection * con, SicsInterp * sics,
|
||||
void *object, int argc, char *argv[]);
|
||||
/*============================ client interface section ===========================*/
|
||||
/**
|
||||
* Start a communication task
|
||||
* @param manager the communication task manager to start the communication with
|
||||
* @param priority The priority of the task
|
||||
* @param sendData The data to send to the device
|
||||
* @return A positive com task ID on success, -1 on failure.
|
||||
*/
|
||||
int StartComTask(ComTaskManager *manager, char *priority, char *sendData);
|
||||
/**
|
||||
* Retrive the state of a communication task
|
||||
* @param manager the communication task manager
|
||||
* @param comTaskID The ID of the communication task to test
|
||||
* @return The state of the task
|
||||
*/
|
||||
ComTaskState GetComTaskState(ComTaskManager *manager, int comTaskID);
|
||||
/**
|
||||
* Retrive the reply of a communication task
|
||||
* @param manager the communication task manager
|
||||
* @param comTaskID The ID of the communication task to test
|
||||
* @param length An output parameter set to the length of the data returned
|
||||
* @return NULL when this is called erroneously, the reply data else. The client is
|
||||
* not supposed to delete the reply data. On the other hand, the client cannot rely
|
||||
* on the data to be available for ever. Make a copy if long term storage of the reply
|
||||
* data is necessary.
|
||||
*/
|
||||
const char *GetComTaskReply(ComTaskManager *manager, int comTaskID, int *length);
|
||||
/**
|
||||
* Wait for a communication task to finish
|
||||
* @param manager the communication task manager
|
||||
* @param comTaskID The ID of the communication task to test
|
||||
* Please note that eventual timeouts are handled by devser and ascon.
|
||||
*/
|
||||
void ComTaskWait(ComTaskManager *manager, int comTaskID);
|
||||
|
||||
|
||||
#endif
|
@ -166,7 +166,7 @@ static long SCTDRIVSetValue(void *data, SConnection * pCon, float val)
|
||||
OKOK or HWIdle when the motor finished driving
|
||||
HWFault when a hardware problem ocurred
|
||||
HWPosFault when the hardware cannot reach a position
|
||||
Errors are duly to be printed to pCon
|
||||
Errors are duely to be printed to pCon
|
||||
For real motors CheckStatus again shall try hard to fix any
|
||||
issues with the motor
|
||||
------------------------------------------------------------------*/
|
||||
|
@ -194,7 +194,7 @@ int SerialSicsExecute(void **pData, char *pCommand,
|
||||
control.data = CreateDynString(1024, 1024);
|
||||
|
||||
/* start task */
|
||||
lTask = TaskRegister(pServ->pTasker,
|
||||
lTask = TaskRegisterN(pServ->pTasker,"serialwait",
|
||||
SWTask, SWSignal, NULL, &control, 1);
|
||||
/* wait for it to end */
|
||||
TaskWait(pServ->pTasker, lTask);
|
||||
|
@ -207,7 +207,7 @@ int MakeCron(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
}
|
||||
pNew->stat = StatisticsNew(cmd);
|
||||
|
||||
TaskRegister(pServ->pTasker, CronTask, CronSignal, KillCron, pNew, 1);
|
||||
TaskRegisterN(pServ->pTasker,"sicscron", CronTask, CronSignal, KillCron, pNew, 1);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
|
13
sicsdata.c
13
sicsdata.c
@ -11,6 +11,8 @@
|
||||
Mark Koennecke, June 2003
|
||||
|
||||
added addto. Mark Koennecke, August 2009
|
||||
|
||||
Make Hipadaba compatible, Mark Koennecke, November 2012
|
||||
----------------------------------------------------------------------*/
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
@ -47,7 +49,7 @@ static void KillSICSData(void *pData)
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
pSICSData createSICSData(void)
|
||||
pSICSData createSICSData(char *name)
|
||||
{
|
||||
pSICSData pNew = NULL;
|
||||
|
||||
@ -63,6 +65,13 @@ pSICSData createSICSData(void)
|
||||
KillSICSData(pNew);
|
||||
return NULL;
|
||||
}
|
||||
/* pNew->pDes->parNode = MakeHipadabaNode(name,HIPINTVARAR, 1); */
|
||||
/* if(pNew->pDes->parNode == NULL){ */
|
||||
/* KillSICSData(pNew); */
|
||||
/* return NULL; */
|
||||
/* } */
|
||||
/* pNew->pDes->parNode->value.doNotFree = 1; */
|
||||
/* pNew->pDes->parNode->value.v.intArray = pNew->data; */
|
||||
memset(pNew->data, 0, 1024 * sizeof(int));
|
||||
memset(pNew->dataType, 0, 1024 * sizeof(char));
|
||||
pNew->currentDataSize = 1024;
|
||||
@ -1115,7 +1124,7 @@ int SICSDataFactory(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
strtolower(argv[2]);
|
||||
|
||||
if (strcmp(argv[1], "new") == 0) {
|
||||
self = createSICSData();
|
||||
self = createSICSData(argv[2]);
|
||||
if (self == NULL) {
|
||||
SCWrite(pCon, "ERROR: not enough memory to create SICSData", eError);
|
||||
return 0;
|
||||
|
@ -28,15 +28,17 @@ typedef struct {
|
||||
|
||||
int *getSICSDataPointer(pSICSData self, int start, int end);
|
||||
|
||||
pSICSData createSICSData(void);
|
||||
pSICSData createSICSData(char *name);
|
||||
|
||||
void assignSICSType(pSICSData self, int start, int end, int type);
|
||||
|
||||
int SICSDataFactory(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[]);
|
||||
void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
int SICSDataAction(SConnection *pCon, SicsInterp *pSics,
|
||||
void *pData, int argc, char *argv[]);
|
||||
void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
void clearSICSData(pSICSData self);
|
||||
int getSICSDataInt(pSICSData self, int pos, int *value);
|
||||
|
@ -39,7 +39,7 @@ This object exports the following functions:
|
||||
@d sidafunc @{
|
||||
int *getSICSDataPointer(pSICSData self, int start, int end);
|
||||
|
||||
pSICSData createSICSData(void);
|
||||
pSICSData createSICSData(char *name);
|
||||
|
||||
void assignSICSType(pSICSData self, int start, int end, int type);
|
||||
|
||||
|
@ -76,7 +76,7 @@ int SicsExit(SConnection * pCon, SicsInterp * pInterp, void *pData,
|
||||
|
||||
if (SCMatchRights(pCon, usMugger)) { /* only Muggers are allowed to do it */
|
||||
SetInterrupt(eEndServer);
|
||||
lID = TaskRegister(pTask, WaitTask, NULL, NULL, NULL, 1);
|
||||
lID = TaskRegisterN(pTask,"exittask", WaitTask, NULL, NULL, NULL, 1);
|
||||
TaskWait(pTask, lID);
|
||||
TaskStop(pTask);
|
||||
return 1;
|
||||
|
245
sicshipadaba.c
245
sicshipadaba.c
@ -36,6 +36,7 @@
|
||||
#include <macro.h>
|
||||
#include "commandlog.h"
|
||||
#include "arrayutil.h"
|
||||
#include "HistMem.h"
|
||||
|
||||
#define MAX_HDB_PATH 1024
|
||||
|
||||
@ -2503,6 +2504,50 @@ static int ZipGetHdbNode(SConnection * pCon, SicsInterp * pSics,
|
||||
return status;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
static int ZipReadHdbNode(SConnection * pCon, SicsInterp * pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
{
|
||||
pHdb targetNode = NULL;
|
||||
char error[512], oriPath[512];
|
||||
int status;
|
||||
pDynString parData = NULL, result= NULL;
|
||||
Protocol protocol = normal_protocol;
|
||||
OutCode outCode;
|
||||
|
||||
if (argc < 2) {
|
||||
SCWrite(pCon, "ERROR: need path to node", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
strlcpy(oriPath, argv[1], 511);
|
||||
targetNode = FindHdbNode(NULL, argv[1], pCon);
|
||||
if (targetNode == NULL) {
|
||||
return 0;
|
||||
}
|
||||
if(targetNode->value.dataType == HIPTEXT){
|
||||
parData = formatValue(targetNode->value, targetNode);
|
||||
if (parData == NULL) {
|
||||
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
|
||||
return 0;
|
||||
}
|
||||
if ((protocol = isJSON(pCon)) == 1)
|
||||
outCode = eHdbEvent;
|
||||
else
|
||||
outCode = eValue;
|
||||
|
||||
result = CreateDynString(128, 128);
|
||||
formatNameValue(protocol, oriPath, GetCharArray(parData), result,
|
||||
targetNode->value.dataType);
|
||||
SCWrite(pCon, GetCharArray(result), outCode);
|
||||
DeleteDynString(parData);
|
||||
DeleteDynString(result);
|
||||
} else {
|
||||
status = sendZippedNodeData(targetNode, targetNode->value, pCon);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int GetHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
@ -2984,6 +3029,171 @@ static int isArrayNode(pHdb node)
|
||||
return 0;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int ArrayCopyNode(pHdb to, SConnection *pCon, int argc, char *argv[])
|
||||
{
|
||||
pHdb from = NULL;
|
||||
int iStart, iLength;
|
||||
hdbValue fromData;
|
||||
|
||||
from = FindHdbNode(NULL,argv[3],pCon);
|
||||
if(from == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: source node %s not found", argv[3]);
|
||||
return 0;
|
||||
}
|
||||
if(!isArrayNode(from)){
|
||||
SCPrintf(pCon,eError,"ERROR: %s is no array data node", argv[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
iStart = 0;
|
||||
iLength = from->value.arrayLength;
|
||||
|
||||
if(argc > 4) {
|
||||
iStart = atoi(argv[4]);
|
||||
if(iStart < 0) {
|
||||
iStart = 0;
|
||||
}
|
||||
}
|
||||
if(argc > 5) {
|
||||
iLength = atoi(argv[5]);
|
||||
if(iStart + iLength > from->value.arrayLength){
|
||||
iLength = from->value.arrayLength - iStart - 1;
|
||||
}
|
||||
}
|
||||
|
||||
switch(from->value.dataType){
|
||||
case HIPINTAR:
|
||||
case HIPINTVARAR:
|
||||
fromData = MakeHdbIntArray(iLength, from->value.v.intArray+iStart);
|
||||
break;
|
||||
case HIPFLOATAR:
|
||||
case HIPFLOATVARAR:
|
||||
fromData = MakeHdbFloatArray(iLength, from->value.v.floatArray+iStart);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
/* cannot really happen */
|
||||
}
|
||||
|
||||
if(!copyHdbValue(&fromData, &to->value)) {
|
||||
SCPrintf(pCon,eError,"ERROR: cannot copy data from %s to %s because of data type mismatch",
|
||||
argv[3],argv[1]);
|
||||
return 0;
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int ArrayCopyOldHM(pHdb to, SConnection *pCon, int argc, char *argv[])
|
||||
{
|
||||
pHistMem hm = NULL;
|
||||
int iStart, iLength;
|
||||
int *data = NULL;
|
||||
hdbValue copyData;
|
||||
|
||||
hm = (pHistMem)FindCommandData(pServ->pSics, argv[3],"HistMem");
|
||||
if(hm == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: cannot find HM %s", argv[3]);
|
||||
return 0;
|
||||
}
|
||||
iStart = 0;
|
||||
iLength = GetHistLength(hm);
|
||||
|
||||
if(argc > 4){
|
||||
iStart = atoi(argv[4]);
|
||||
iLength -= iStart;
|
||||
}
|
||||
|
||||
if(argc > 5){
|
||||
iLength = atoi(argv[5]);
|
||||
}
|
||||
|
||||
if(iStart < 0){
|
||||
iStart = 0;
|
||||
}
|
||||
|
||||
if(iStart + iLength > GetHistLength(hm)){
|
||||
iLength = GetHistLength(hm) - iStart - 1;
|
||||
}
|
||||
|
||||
data = GetHistogramPointer(hm,pCon);
|
||||
if(data == NULL){
|
||||
SCPrintf(pCon,eError, "ERROR: failed to retrive HM data for %s", argv[3]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
copyData = MakeHdbIntArray(iLength, data + iStart);
|
||||
if(!copyHdbValue(©Data, &to->value)) {
|
||||
SCPrintf(pCon,eError,"ERROR: cannot copy data from %s to %s because of data type mismatch",
|
||||
argv[3],argv[1]);
|
||||
return 0;
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int ArrayCopyOldTB(pHdb to, SConnection *pCon, int argc, char *argv[])
|
||||
{
|
||||
pHistMem hm = NULL;
|
||||
int iStart, iLength, timeLength, i;
|
||||
const float *data = NULL;
|
||||
double *ddata = NULL;
|
||||
hdbValue copyData;
|
||||
|
||||
hm = (pHistMem)FindCommandData(pServ->pSics, argv[3],"HistMem");
|
||||
if(hm == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: cannot find HM %s", argv[3]);
|
||||
return 0;
|
||||
}
|
||||
iStart = 0;
|
||||
data = GetHistTimeBin(hm,&timeLength);
|
||||
if(data == NULL){
|
||||
SCPrintf(pCon,eError, "ERROR: failed to retrive time binning for HM %s", argv[3]);
|
||||
return 0;
|
||||
}
|
||||
iLength = timeLength;
|
||||
|
||||
if(argc > 4){
|
||||
iStart = atoi(argv[4]);
|
||||
iLength -= iStart;
|
||||
}
|
||||
|
||||
if(argc > 5){
|
||||
iLength = atoi(argv[5]);
|
||||
}
|
||||
|
||||
if(iStart < 0){
|
||||
iStart = 0;
|
||||
}
|
||||
|
||||
if(iStart + iLength > timeLength){
|
||||
iLength = timeLength - iStart - 1;
|
||||
}
|
||||
|
||||
ddata = malloc(iLength*sizeof(double));
|
||||
if(ddata == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: out of memory copying %s time binning to %s",
|
||||
argv[3],argv[1]);
|
||||
return 0;
|
||||
}
|
||||
for(i = 0; i < iLength; i++){
|
||||
ddata[i] = data[iStart+i];
|
||||
}
|
||||
copyData = MakeHdbFloatArray(iLength, ddata);
|
||||
if(!copyHdbValue(©Data, &to->value)) {
|
||||
SCPrintf(pCon,eError,
|
||||
"ERROR: cannot copy data from %s to %s because of data type mismatch",
|
||||
argv[3],argv[1]);
|
||||
return 0;
|
||||
}
|
||||
free(ddata);
|
||||
SCSendOK(pCon);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int HdbArrayNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
@ -3062,6 +3272,16 @@ static int HdbArrayNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(strcmp(argv[2],"copynode") == 0){
|
||||
return ArrayCopyNode(node, pCon, argc, argv);
|
||||
}
|
||||
if(strcmp(argv[2],"copyoldhm") == 0){
|
||||
return ArrayCopyOldHM(node, pCon, argc, argv);
|
||||
}
|
||||
if(strcmp(argv[2],"copyoldtb") == 0){
|
||||
return ArrayCopyOldTB(node, pCon, argc, argv);
|
||||
}
|
||||
|
||||
idx = atoi(argv[2]);
|
||||
if(idx < 0 || idx >= node->value.arrayLength ){
|
||||
SCPrintf(pCon,eError,"ERROR: %d is out of range 0 - %d",
|
||||
@ -3078,7 +3298,6 @@ static int HdbArrayNode(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
node->value.v.floatArray[idx] = atof(argv[3]);
|
||||
break;
|
||||
}
|
||||
NotifyHipadabaPar(node, pCon);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
@ -3408,6 +3627,27 @@ static int ListSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
||||
DeleteDynString(data);
|
||||
return 1;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int CallNotify(SConnection * pCon, SicsInterp * pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
{
|
||||
pHdb node = NULL;
|
||||
|
||||
if(argc < 2) {
|
||||
SCPrintf(pCon,eError, "ERROR: require path argument to %s", argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
node = GetHipadabaNode(GetHipadabaRoot(), argv[1]);
|
||||
if(node == NULL){
|
||||
SCPrintf(pCon,eError,"ERROR: cannot find node %s to notify", argv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NotifyHipadabaPar(node,pCon);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static pHdb matchHdbProp(pHdb root, char *propname, char *buffer)
|
||||
@ -3432,7 +3672,6 @@ static pHdb matchHdbProp(pHdb root, char *propname, char *buffer)
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int MatchHdbProperty(SConnection * pCon, SicsInterp * pSics,
|
||||
void *pData, int argc, char *argv[])
|
||||
@ -3495,6 +3734,7 @@ int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics,
|
||||
AddCommand(pSics, "hget", GetHdbNode, NULL, NULL);
|
||||
AddCommand(pSics, "hval", GetHdbVal, NULL, NULL);
|
||||
AddCommand(pSics, "hzipget", ZipGetHdbNode, NULL, NULL);
|
||||
AddCommand(pSics, "hzipread", ZipReadHdbNode, NULL, NULL);
|
||||
AddCommand(pSics, "hlist", ListHdbNode, NULL, NULL);
|
||||
AddCommand(pSics, "hnotify", AutoNotifyHdbNode, NULL, NULL);
|
||||
AddCommand(pSics, "hdelcb", RemoveHdbCallback, NULL, NULL);
|
||||
@ -3508,6 +3748,7 @@ int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics,
|
||||
AddCommand(pSics, "hgetpropval", GetSICSHdbPropertyVal, NULL, NULL);
|
||||
AddCommand(pSics, "hmatchprop", MatchHdbProperty, NULL, NULL);
|
||||
AddCommand(pSics, "hlistprop", ListSICSHdbProperty, NULL, NULL);
|
||||
AddCommand(pSics, "hcallnotify",CallNotify, NULL, NULL);
|
||||
|
||||
InstallSICSPoll(pCon, pSics, pData, argc, argv);
|
||||
poller = (pSicsPoll) FindCommandData(pSics, "sicspoll", "SicsPoll");
|
||||
|
84
sicsobj.c
84
sicsobj.c
@ -36,56 +36,6 @@ void DefaultFree(void *data)
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void saveSICSNodeBroken(pHdb node, char *prefix, FILE * fd)
|
||||
{
|
||||
/*
|
||||
nodes with the property __save are saved
|
||||
special cases:
|
||||
__save=update: a hupdate command is used instead of a set command
|
||||
__save=kids: save kids, but not the value of this node
|
||||
*/
|
||||
char newprefix[1024], val[20];
|
||||
char path[MAX_HDB_PATH];
|
||||
pHdb child;
|
||||
hdbValue v;
|
||||
pDynString data = NULL;
|
||||
char *cmd;
|
||||
char *str, *value;
|
||||
|
||||
cmd = GetHdbProp(node, "creationCmd");
|
||||
if (cmd != NULL) {
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
fprintf(fd, cmd, prefix, path);
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
if (GetHdbProperty(node, "__save", val, 20) == 1) {
|
||||
if (strcasecmp(val, "kids") != 0) {
|
||||
GetHipadabaPar(node, &v, NULL);
|
||||
data = formatValue(v, node);
|
||||
if (data != NULL) {
|
||||
value = GetCharArray(data);
|
||||
str = Arg2Tcl(1, &value, NULL, 0);
|
||||
if (strcasecmp(val, "update") == 0) {
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
fprintf(fd, "hupdate %s %s\n", path, str);
|
||||
} else {
|
||||
fprintf(fd, "%s %s\n", prefix, str);
|
||||
}
|
||||
DeleteDynString(data);
|
||||
free(str);
|
||||
}
|
||||
ReleaseHdbValue(&v);
|
||||
}
|
||||
}
|
||||
child = node->child;
|
||||
while (child != NULL) {
|
||||
snprintf(newprefix, 1024, "%s/%s", prefix, child->name);
|
||||
saveSICSNodeBroken(child, newprefix, fd);
|
||||
child = child->next;
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void saveSICSNode(pHdb node, char *prefix, FILE * fd)
|
||||
{
|
||||
@ -144,40 +94,6 @@ int SaveSICSOBJ(void *data, char *name, FILE * fd)
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
int SaveSICSOBJBroken(void *data, char *name, FILE * fd)
|
||||
{
|
||||
pSICSOBJ self = (pSICSOBJ) data;
|
||||
char prefix[1024];
|
||||
char path[MAX_HDB_PATH];
|
||||
pHdb node;
|
||||
char *cmd;
|
||||
|
||||
if (self != NULL && self->objectNode != NULL) {
|
||||
/*
|
||||
node = self->objectNode->child;
|
||||
cmd = GetHdbProp(self->objectNode, "creationCmd");
|
||||
if (cmd != NULL) {
|
||||
GetHdbPath(self->objectNode, path, sizeof path);
|
||||
fprintf(fd, cmd, name, path);
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
while (node != NULL) {
|
||||
snprintf(prefix, 1024, "%s %s", name, node->name);
|
||||
saveSICSNode(node, prefix, fd);
|
||||
node = node->next;
|
||||
}
|
||||
*/
|
||||
node = self->objectNode;
|
||||
snprintf(prefix, 1024, "%s %s", name, node->name);
|
||||
saveSICSNode(node, prefix, fd);
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static void KillSICSOBJfromNode(void *userData)
|
||||
{
|
||||
|
@ -379,7 +379,7 @@ int InstallSICSPoll(SConnection * pCon, SicsInterp * pSics, void *pData,
|
||||
pNew->pCon = defCon;
|
||||
pNew->nPoll = 3;
|
||||
|
||||
TaskRegister(pServ->pTasker, PollTask, SicsPollSignal, NULL, pNew, 10);
|
||||
TaskRegisterN(pServ->pTasker,"sicspoll", PollTask, SicsPollSignal, NULL, pNew, 10);
|
||||
|
||||
if (argc > 1) {
|
||||
AddCommand(pSics, argv[1], SICSPollWrapper, killSicsPoll, pNew);
|
||||
|
@ -12,4 +12,5 @@
|
||||
#include "singlediff.h"
|
||||
|
||||
void initializeSingleBisecting(pSingleDiff diff);
|
||||
void initializeSingleBisectingOrion(pSingleDiff diff);
|
||||
#endif /*SINGELBI_H_ */
|
||||
|
100
singlebi.c
100
singlebi.c
@ -228,6 +228,46 @@ static int hklInRange(void *data, double fSet[4], int mask[4])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int hklInRangeOrion(void *data, double fSet[4], int mask[4])
|
||||
{
|
||||
pSingleDiff self = (pSingleDiff) data;
|
||||
float fHard, fLimit;
|
||||
char pError[132];
|
||||
int i, test;
|
||||
double dTheta;
|
||||
pMotor pOmega, pChi, pPhi;
|
||||
|
||||
pOmega = SXGetMotor(Omega);
|
||||
pChi = SXGetMotor(Chi);
|
||||
pPhi = SXGetMotor(Phi);
|
||||
if (pOmega == NULL || pChi == NULL || pPhi == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check two theta */
|
||||
dTheta = fSet[0];
|
||||
mask[0] = checkTheta(self, &dTheta);
|
||||
fSet[0] = dTheta;
|
||||
|
||||
/* Orion is not upside down... */
|
||||
fSet[2] = -1.*(fSet[2]+180.) + 360. ;
|
||||
fSet[3] = circlify(fSet[3]+180.);
|
||||
|
||||
mask[1] = MotorCheckBoundary(pOmega, fSet[1], &fHard, pError, 131);
|
||||
mask[2] = MotorCheckBoundary(pChi, fSet[2], &fHard, pError, 131);
|
||||
mask[3] = MotorCheckBoundary(pPhi, fSet[3], &fHard, pError, 131);
|
||||
for (i = 0, test = 0; i < 4; i++) {
|
||||
test += mask[i];
|
||||
}
|
||||
if (test != 4) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int calculateBiSettings(pSingleDiff self,
|
||||
double *hkl, double *settings)
|
||||
@ -282,6 +322,60 @@ static int calculateBiSettings(pSingleDiff self,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int calculateBiSettingsOrion(pSingleDiff self,
|
||||
double *hkl, double *settings)
|
||||
{
|
||||
MATRIX z1;
|
||||
double stt, om, chi, phi, psi, ompsi, chipsi, phipsi, myPsi;
|
||||
int i, test, mask[4], iRetry;
|
||||
double lambda;
|
||||
|
||||
myPsi = hkl[3];
|
||||
if (myPsi > 0.1) {
|
||||
iRetry = 1;
|
||||
} else {
|
||||
iRetry = 699;
|
||||
}
|
||||
|
||||
z1 = calculateScatteringVector(self, hkl);
|
||||
|
||||
/*
|
||||
just the plain angle calculation
|
||||
*/
|
||||
if (!z1mToBisecting(self->lambda, z1, &stt, &om, &chi, &phi)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
settings[0] = stt;
|
||||
settings[1] = om;
|
||||
settings[2] = -1.*(180.+chi) + 360.;
|
||||
settings[3] = phi+180.;
|
||||
if (iRetry == 1) {
|
||||
rotatePsi(om, chi, phi, myPsi, &ompsi, &chipsi, &phipsi);
|
||||
settings[1] = ompsi;
|
||||
settings[2] = circlify(chipsi);
|
||||
settings[3] = circlify(phipsi);
|
||||
return 1;
|
||||
} else {
|
||||
if (hklInRange(self, settings, mask) == 1) {
|
||||
return 1;
|
||||
} else {
|
||||
if (tryOmegaTweak(self, z1, &stt, &om, &chi, &phi) == 1) {
|
||||
settings[0] = stt;
|
||||
settings[1] = om;
|
||||
settings[2] = chi;
|
||||
settings[3] = phi;
|
||||
return 1;
|
||||
} else {
|
||||
return findAllowedBisecting(self->lambda, z1, settings, hklInRangeOrion,
|
||||
self);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
static int settingsToBiList(struct __SingleDiff *self, double *settings)
|
||||
{
|
||||
@ -471,3 +565,9 @@ void initializeSingleBisecting(pSingleDiff diff)
|
||||
diff->calcUBFromThree = calcBiUBFromThree;
|
||||
diff->calcZ1 = calcBiZ1;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
void initializeSingleBisectingOrion(pSingleDiff diff)
|
||||
{
|
||||
initializeSingleBisecting(diff);
|
||||
diff->calculateSettings = calculateBiSettingsOrion;
|
||||
}
|
||||
|
22
singlex.c
22
singlex.c
@ -227,6 +227,7 @@ static int findModeIndex(char *mode)
|
||||
"nb",
|
||||
"tas",
|
||||
"binb",
|
||||
"bio",
|
||||
NULL
|
||||
};
|
||||
int count = 0;
|
||||
@ -254,6 +255,7 @@ static hdbCallbackReturn SetModeCB(pHdb node, void *userData,
|
||||
pTest = trim(set->v->v.text);
|
||||
pCon = set->callData;
|
||||
modeIdx = findModeIndex(pTest);
|
||||
|
||||
switch (modeIdx) {
|
||||
case Bisecting:
|
||||
if (priv->chi == NULL || priv->om == NULL || priv->phi == NULL
|
||||
@ -269,6 +271,22 @@ static hdbCallbackReturn SetModeCB(pHdb node, void *userData,
|
||||
initializeSingleBisecting(priv->diffractometer);
|
||||
return hdbContinue;
|
||||
break;
|
||||
case BiO:
|
||||
if (priv->chi == NULL || priv->om == NULL || priv->phi == NULL
|
||||
|| priv->stt == NULL) {
|
||||
if (pCon != NULL) {
|
||||
SCWrite(pCon,
|
||||
"ERROR: required motor for bisecting not configured",
|
||||
eError);
|
||||
}
|
||||
return hdbAbort;
|
||||
}
|
||||
priv->mode = Bisecting;
|
||||
initializeSingleBisectingOrion(priv->diffractometer);
|
||||
free(set->v->v.text);
|
||||
set->v->v.text = strdup("bi");
|
||||
return hdbContinue;
|
||||
break;
|
||||
case NB:
|
||||
if (priv->nu == NULL || priv->om == NULL || priv->stt == NULL) {
|
||||
if (pCon != NULL) {
|
||||
@ -874,8 +892,12 @@ pSICSOBJ SXGetReflectionList()
|
||||
SingleXModes SXGetMode()
|
||||
{
|
||||
pSingleX priv = (pSingleX) singlex->pPrivate;
|
||||
if(priv->mode == BiO){
|
||||
return Bisecting;
|
||||
} else {
|
||||
return priv->mode;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
T_SgInfo *SXGetSpaceGroup()
|
||||
|
@ -35,7 +35,7 @@ double SXGetLambda();
|
||||
pSICSOBJ SXGetReflectionList();
|
||||
|
||||
typedef enum {
|
||||
Bisecting, NB, Tas, BiNB,
|
||||
Bisecting, NB, Tas, BiNB, BiO,
|
||||
} SingleXModes;
|
||||
|
||||
SingleXModes SXGetMode();
|
||||
|
@ -297,5 +297,5 @@ void StatusFileDirty(void)
|
||||
/*-----------------------------------------------------------------------*/
|
||||
void StatusFileInit(void)
|
||||
{
|
||||
TaskRegister(pServ->pTasker, StatusFileTask, NULL, NULL, NULL, 0);
|
||||
TaskRegisterN(pServ->pTasker, "statusfile", StatusFileTask, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
@ -723,11 +723,11 @@ static int calculateQMAndDrive(ptasMot self, SConnection * pCon)
|
||||
&angles);
|
||||
switch (status) {
|
||||
case ENERGYTOBIG:
|
||||
SCWrite(pCon, "ERROR: desired energy to big", eError);
|
||||
SCWrite(pCon, "ERROR: desired energy to big", eLogError);
|
||||
return HWFault;
|
||||
break;
|
||||
case TRIANGLENOTCLOSED:
|
||||
SCWrite(pCon, "ERROR: cannot close scattering triangle", eError);
|
||||
SCWrite(pCon, "ERROR: cannot close scattering triangle", eLogError);
|
||||
return HWFault;
|
||||
break;
|
||||
default:
|
||||
|
216
task.c
216
task.c
@ -10,9 +10,15 @@
|
||||
|
||||
NO WARRANTIES OF ANY KIND WHATSOEVER TAKEN BY ME OR MY EMPLOYER.
|
||||
YOU ARE AT YOUR OWN!
|
||||
|
||||
Reworked to have a task name, stop by task name and better listing.
|
||||
|
||||
Mark Koennecke, December 2012
|
||||
----------------------------------------------------------------------------*/
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include "fortify.h"
|
||||
#include "task.h"
|
||||
#define READY 1
|
||||
@ -21,8 +27,11 @@
|
||||
/*--------------------------------------------------------------------------*/
|
||||
typedef struct __TaskHead {
|
||||
long lID;
|
||||
long groupID;
|
||||
int iStatus;
|
||||
long lWait;
|
||||
char *name;
|
||||
time_t start_time;
|
||||
TaskFunc pRun;
|
||||
SignalFunc pSignal;
|
||||
void *pData;
|
||||
@ -34,7 +43,7 @@ typedef struct __TaskHead {
|
||||
typedef struct __TaskMan {
|
||||
int iID;
|
||||
int iStop;
|
||||
pTaskHead pCurrent;
|
||||
pTaskHead pCurrent; /* Think trice before you interfere with this! */
|
||||
pTaskHead pHead;
|
||||
} TaskMan;
|
||||
/*---------------------------------------------------------------------------*/
|
||||
@ -42,7 +51,7 @@ static long lIDMama = 0L;
|
||||
#define TASKERID 123399
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
static pTaskHead MakeTaskHead(TaskFunc pTask, SignalFunc pSignal,
|
||||
static pTaskHead MakeTaskHead(char *name, TaskFunc pTask, SignalFunc pSignal,
|
||||
void *pData, TaskKillFunc pKill)
|
||||
{
|
||||
pTaskHead pNew = NULL;
|
||||
@ -53,6 +62,8 @@ static pTaskHead MakeTaskHead(TaskFunc pTask, SignalFunc pSignal,
|
||||
}
|
||||
memset(pNew, 0, sizeof(TaskHead));
|
||||
|
||||
pNew->name = strdup(name);
|
||||
pNew->start_time = time(NULL);
|
||||
pNew->pRun = pTask;
|
||||
pNew->pSignal = pSignal;
|
||||
pNew->pData = pData;
|
||||
@ -60,6 +71,10 @@ static pTaskHead MakeTaskHead(TaskFunc pTask, SignalFunc pSignal,
|
||||
pNew->lID = lIDMama++;
|
||||
pNew->iStatus = READY;
|
||||
|
||||
if(lIDMama < 0){
|
||||
lIDMama = 0;
|
||||
}
|
||||
|
||||
return pNew;
|
||||
}
|
||||
|
||||
@ -73,6 +88,9 @@ static void DeleteTaskHead(pTaskHead self)
|
||||
self->pKill(self->pData);
|
||||
}
|
||||
}
|
||||
if(self->name != NULL){
|
||||
free(self->name);
|
||||
}
|
||||
/* unlink */
|
||||
if (self->pPrevious != NULL) {
|
||||
self->pPrevious->pNext = self->pNext;
|
||||
@ -105,7 +123,7 @@ int TaskerInit(pTaskMan * self)
|
||||
pNew->iID = TASKERID;
|
||||
|
||||
/* create a dummy task as start point */
|
||||
pDummyTask = MakeTaskHead(DummyTask, NULL, NULL, NULL);
|
||||
pDummyTask = MakeTaskHead("init",DummyTask, NULL, NULL, NULL);
|
||||
if (!pDummyTask) {
|
||||
free(pNew);
|
||||
return 0;
|
||||
@ -140,10 +158,15 @@ int TaskerDelete(pTaskMan * pData)
|
||||
*pData = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*----------------------- temporary for backwards compatability -------------*/
|
||||
long TaskRegister(pTaskMan self,TaskFunc pTask, SignalFunc pSignal,
|
||||
TaskKillFunc pKill, void *pData, int iPriority)
|
||||
{
|
||||
return TaskRegisterN(self,"Unknown", pTask, pSignal, pKill, pData, iPriority);
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
long TaskRegisterN(pTaskMan self, char *name, TaskFunc pTask, SignalFunc pSignal,
|
||||
TaskKillFunc pKill, void *pData, int iPriority)
|
||||
{
|
||||
pTaskHead pNew = NULL;
|
||||
|
||||
@ -151,7 +174,7 @@ long TaskRegister(pTaskMan self, TaskFunc pTask, SignalFunc pSignal,
|
||||
assert(self->iID == TASKERID);
|
||||
assert(pTask);
|
||||
|
||||
pNew = MakeTaskHead(pTask, pSignal, pData, pKill);
|
||||
pNew = MakeTaskHead(name, pTask, pSignal, pData, pKill);
|
||||
if (!pNew) {
|
||||
return -1;
|
||||
}
|
||||
@ -166,7 +189,6 @@ long TaskRegister(pTaskMan self, TaskFunc pTask, SignalFunc pSignal,
|
||||
|
||||
return pNew->lID;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static void IncrTaskPointer(pTaskMan self)
|
||||
{
|
||||
@ -359,6 +381,10 @@ void TaskRemove(pTaskMan self, TaskFunc pTaskRun, void *pData)
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (pCurrent->pRun == pTaskRun && pCurrent->pData == pData) {
|
||||
if(pCurrent == self->pCurrent){
|
||||
/* cannot kill myself */
|
||||
return;
|
||||
}
|
||||
/* unlink */
|
||||
if (pCurrent->pPrevious != NULL) {
|
||||
pCurrent->pPrevious->pNext = pCurrent->pNext;
|
||||
@ -366,8 +392,184 @@ void TaskRemove(pTaskMan self, TaskFunc pTaskRun, void *pData)
|
||||
if (pCurrent->pNext != NULL) {
|
||||
pCurrent->pNext->pPrevious = pCurrent->pPrevious;
|
||||
}
|
||||
if(pCurrent->name != NULL){
|
||||
free(pCurrent->name);
|
||||
}
|
||||
free(pCurrent);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
int StopTask(pTaskMan self, char *name)
|
||||
{
|
||||
int iRet;
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) return 0;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
pNext = self->pHead->pNext; /* skip dummy task */
|
||||
while (pNext != NULL) {
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (strcmp(pCurrent->name,name) == 0) {
|
||||
if(self->pCurrent == pCurrent){
|
||||
/**
|
||||
* cannot kill myself
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
/* unlink */
|
||||
if (pCurrent->pPrevious != NULL) {
|
||||
pCurrent->pPrevious->pNext = pCurrent->pNext;
|
||||
}
|
||||
if (pCurrent->pNext != NULL) {
|
||||
pCurrent->pNext->pPrevious = pCurrent->pPrevious;
|
||||
}
|
||||
if(pCurrent->name != NULL){
|
||||
free(pCurrent->name);
|
||||
}
|
||||
free(pCurrent);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
int isTaskRunning(pTaskMan self, char *name)
|
||||
{
|
||||
int iRet;
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) return 0;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
pNext = self->pHead->pNext; /* skip dummy task */
|
||||
while (pNext != NULL) {
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (strcmp(pCurrent->name,name) == 0) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
pTaskHead TaskIteratorStart(pTaskMan self)
|
||||
{
|
||||
if (self == NULL) return NULL;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
return self->pHead->pNext; /* skip dummy task */
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
pTaskHead TaskIteratorNext(pTaskHead it)
|
||||
{
|
||||
if(it != NULL){
|
||||
return it->pNext;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
char *TaskDescription(pTaskHead it)
|
||||
{
|
||||
char *result;
|
||||
int length;
|
||||
const struct tm *tm;
|
||||
|
||||
if(it == NULL){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
length = strlen(it->name) + 120;
|
||||
result = malloc(length*sizeof(char));
|
||||
if(result == NULL){
|
||||
return NULL;
|
||||
}
|
||||
memset(result,0,length*sizeof(char));
|
||||
strcpy(result,it->name);
|
||||
strcat(result,":");
|
||||
|
||||
length = strlen(result);
|
||||
tm = localtime((const time_t *)&it->start_time);
|
||||
strftime(result+length,100,"%F-%k-%m-%S",tm);
|
||||
length = strlen(result);
|
||||
snprintf(result+length,120-20,":%ld", it->lID);
|
||||
length = strlen(result);
|
||||
snprintf(result+length,120-40,":%ld", it->groupID);
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
long GetTaskGroupID(pTaskMan self)
|
||||
{
|
||||
lIDMama++;
|
||||
return lIDMama;
|
||||
}
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
void AddTaskToGroup(pTaskMan self, long taskID, long groupID)
|
||||
{
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) return;
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
pNext = self->pHead->pNext; /* skip dummy task */
|
||||
while (pNext != NULL) {
|
||||
pCurrent = pNext;
|
||||
pNext = pCurrent->pNext;
|
||||
if (pCurrent->lID == taskID) {
|
||||
pCurrent->groupID = groupID;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*---------------------------------------------------------------------------------
|
||||
This simply checks if there are any more tasks with the desired groupID in the
|
||||
list. If none, then all sub tasks have finished.
|
||||
-----------------------------------------------------------------------------------*/
|
||||
int isTaskGroupRunning(pTaskMan self, long groupID)
|
||||
{
|
||||
pTaskHead pCurrent, pNext;
|
||||
|
||||
if (self == NULL) 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) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*------------------------------------------------------------------------------*/
|
||||
int TaskGroupTask(void *data)
|
||||
{
|
||||
pTaskGroupData self = (pTaskGroupData)data;
|
||||
|
||||
return isTaskGroupRunning(self->tasker,self->groupID);
|
||||
}
|
||||
/*-------------------------------------------------------------------------------*/
|
||||
int TaskSignalGroup(pTaskMan self, int iSignal, void *pSigData, long groupID)
|
||||
{
|
||||
pTaskHead pTemp, pEnd;
|
||||
|
||||
assert(self);
|
||||
assert(self->iID == TASKERID);
|
||||
|
||||
/* Do one cycle until we are at the caller, then return to him */
|
||||
pEnd = self->pCurrent;
|
||||
IncrTaskPointer(self);
|
||||
while (self->pCurrent != pEnd) {
|
||||
if (self->pCurrent->pSignal && self->pCurrent->groupID == groupID) {
|
||||
self->pCurrent->pSignal(self->pCurrent->pData, iSignal, pSigData);
|
||||
}
|
||||
IncrTaskPointer(self);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
92
task.h
92
task.h
@ -78,6 +78,23 @@ long TaskRegister(pTaskMan self, TaskFunc pTaskRun,
|
||||
On Success a positive value denoting the ID of the task is returned.
|
||||
On error a negative value is returned.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
long TaskRegisterN(pTaskMan self, char *name, TaskFunc pTaskRun,
|
||||
SignalFunc pSignalFunc,
|
||||
TaskKillFunc pKillFunc, void *pData, int iPriority);
|
||||
/*
|
||||
This call enter a new task into the system. The caller has to
|
||||
specify:
|
||||
a TaskFunction [Required]
|
||||
a SignalFunction [Optional, can be NULL]
|
||||
a KillFunction for task private data.
|
||||
[Optional, can be NULL]
|
||||
a pointer to task private data
|
||||
[Optional, can be NULL]
|
||||
a priority for this task. This is currently unused.
|
||||
On Success a positive value denoting the ID of the task is returned.
|
||||
On error a negative value is returned.
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int TaskSchedule(pTaskMan self);
|
||||
/*
|
||||
@ -117,5 +134,80 @@ int TaskSignal(pTaskMan self, int iSignal, void *pSigData);
|
||||
/*
|
||||
remove the task with the given task function and the given data pointer
|
||||
*/
|
||||
/*-------------------------------------------------------------------------*/
|
||||
int StopTask(pTaskMan self, char *name);
|
||||
/*
|
||||
stop the task with the given name. Returns 0 on failure, 1 on success
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int isTaskRunning(pTaskMan self, char *name);
|
||||
/*
|
||||
returns 1 when task name is running, 0 else
|
||||
*/
|
||||
/*===========================================================================
|
||||
Iterating the task list. This works like:
|
||||
|
||||
pTaskHead it;
|
||||
char *des;
|
||||
|
||||
for(it = TaskIteratorStart(self); it != NULL; it = TaskIteratorNext(it)){
|
||||
des = TaskDescription(it);
|
||||
}
|
||||
|
||||
There are two limitations of the implementation here:
|
||||
|
||||
- Never, ever delete the Iterator it
|
||||
- Do your iteration in one go or abandon it mid iteration. If another task
|
||||
gets in between and registers new tasks or removes one, then the whole
|
||||
iterator may be messed up.
|
||||
=============================================================================*/
|
||||
|
||||
pTaskHead TaskIteratorStart(pTaskMan self);
|
||||
/*
|
||||
starts iterating on the TaskList. Do NOT delete the returned pointer!
|
||||
*/
|
||||
pTaskHead TaskIteratorNext(pTaskHead it);
|
||||
/*
|
||||
Steps to the next element in the task list. Returns NULL when node.
|
||||
Do NOT delete the returned pointer!
|
||||
*/
|
||||
|
||||
char *TaskDescription(pTaskHead it);
|
||||
/*
|
||||
get a description of the task at the current iterator
|
||||
You are responsible for deleting the returned character array.
|
||||
*/
|
||||
/*=============================================================================
|
||||
Task Groups. The implementation has the limit that any given task can
|
||||
only be member of one task group
|
||||
===============================================================================*/
|
||||
long GetTaskGroupID(pTaskMan self);
|
||||
/*
|
||||
get the ID for a task group
|
||||
*/
|
||||
void AddTaskToGroup(pTaskMan self, long taskID, long groupID);
|
||||
/*
|
||||
Add taskID to the task group groupID
|
||||
*/
|
||||
int isTaskGroupRunning(pTaskMan self, long groupID);
|
||||
/*
|
||||
Returns 1 when the task group is still running, 0 else
|
||||
*/
|
||||
|
||||
typedef struct{
|
||||
pTaskMan tasker;
|
||||
long groupID;
|
||||
} TaskGroupData, *pTaskGroupData;
|
||||
|
||||
int TaskGroupTask(void *data);
|
||||
/*
|
||||
This is a task function which implements the common task of waiting
|
||||
for a group of tasks to finish. It expects as data a TaskGroupData
|
||||
structure.
|
||||
*/
|
||||
/*--------------------------------------------------------------------------*/
|
||||
int TaskSignalGroup(pTaskMan self, int iSignal, void *pSigData, long groupID);
|
||||
/*
|
||||
signal only tasks in the group groupID
|
||||
*/
|
||||
#endif
|
||||
|
185
taskobj.c
Normal file
185
taskobj.c
Normal file
@ -0,0 +1,185 @@
|
||||
/**
|
||||
* This is the SICS interface object to the tasker module
|
||||
*
|
||||
* copyright: GPL
|
||||
*
|
||||
* Mark Koennecke, December 2012
|
||||
*/
|
||||
#include <sics.h>
|
||||
#include "sicsobj.h"
|
||||
#include "sicshipadaba.h"
|
||||
#include "stptok.h"
|
||||
#include "macro.h"
|
||||
|
||||
typedef struct {
|
||||
char *scriptName;
|
||||
SConnection *con;
|
||||
} TclFunc, *pTclFunc;
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int ListCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
pDynString result = NULL;
|
||||
char buffer[256], *pDes, *pPtr, name[80], time[80],id[80];
|
||||
pTaskHead it = NULL;
|
||||
|
||||
result = CreateDynString(128,128);
|
||||
if(result == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory in ListCmd", eError);
|
||||
return 0;
|
||||
}
|
||||
snprintf(buffer,sizeof(buffer),"%20s %20s %12s",
|
||||
"Task", "Start_Time", "ID");
|
||||
DynStringConcat(result,buffer);
|
||||
DynStringConcatChar(result,'\n');
|
||||
for(it = TaskIteratorStart(pServ->pTasker); it != NULL; it = TaskIteratorNext(it)){
|
||||
pDes = TaskDescription(it);
|
||||
if(pDes != NULL){
|
||||
pPtr = stptok(pDes,name,sizeof(name),":");
|
||||
pPtr = stptok(pPtr,time,sizeof(name),":");
|
||||
pPtr = stptok(pPtr,id,sizeof(name),":");
|
||||
snprintf(buffer,sizeof(buffer),"%20s %20s %12s",
|
||||
name,time,id);
|
||||
DynStringConcat(result,buffer);
|
||||
DynStringConcatChar(result,'\n');
|
||||
free(pDes);
|
||||
}
|
||||
}
|
||||
SCWrite(pCon,GetCharArray(result),eValue);
|
||||
DeleteDynString(result);
|
||||
|
||||
return 1;
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int KillCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
int status;
|
||||
|
||||
if(nPar < 1){
|
||||
SCWrite(pCon,"ERROR: need name of task to stop", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
status = StopTask(pServ->pTasker,par[0]->value.v.text);
|
||||
if(status == 0) {
|
||||
SCWrite(pCon,"ERROR: cannot commit suicide!", eError);
|
||||
return 0;
|
||||
}
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static int TclTaskFunction(void *pData)
|
||||
{
|
||||
int retVal, status ;
|
||||
Tcl_Interp *pTcl;
|
||||
|
||||
pTclFunc self = (pTclFunc)pData;
|
||||
assert(self != NULL);
|
||||
|
||||
pTcl = InterpGetTcl(pServ->pSics);
|
||||
assert(pTcl != NULL);
|
||||
|
||||
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 {
|
||||
return 1;
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
static void KillTclFunc(void *pData)
|
||||
{
|
||||
pTclFunc self = (pTclFunc)pData;
|
||||
if(self == NULL){
|
||||
return;
|
||||
}
|
||||
if(self->scriptName){
|
||||
free(self->scriptName);
|
||||
}
|
||||
if(self->con) {
|
||||
SCDeleteConnection(self->con);
|
||||
}
|
||||
free(self);
|
||||
}
|
||||
/*------------------------------------------------------------------*/
|
||||
static void TclFuncSignal(void *pData, int iSignal, void *pSigData)
|
||||
{
|
||||
int *iInt;
|
||||
pTclFunc self = NULL;
|
||||
|
||||
self = (pTclFunc) pData;
|
||||
assert(self);
|
||||
|
||||
if (iSignal == SICSINT) {
|
||||
iInt = (int *) pSigData;
|
||||
SCSetInterrupt(self->con,*iInt);
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------*/
|
||||
static int RunCmd(pSICSOBJ self, SConnection *pCon, pHdb commandNode,
|
||||
pHdb par[], int nPar)
|
||||
{
|
||||
pTclFunc data = NULL;
|
||||
|
||||
if(nPar < 1) {
|
||||
SCWrite(pCon,"ERROR: need the name of a script to run",eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = malloc(sizeof(TclFunc));
|
||||
if(data == NULL){
|
||||
SCWrite(pCon,"ERROR: out of memory in RunCmd",eError);
|
||||
return 0;
|
||||
}
|
||||
memset(data,0,sizeof(TclFunc));
|
||||
data->con = SCCreateDummyConnection(pServ->pSics);
|
||||
data->scriptName = strdup(par[0]->value.v.text);
|
||||
TaskRegisterN(pServ->pTasker,
|
||||
data->scriptName,
|
||||
TclTaskFunction,
|
||||
TclFuncSignal,
|
||||
KillTclFunc,
|
||||
data, 0);
|
||||
traceSys("task","Started task %s",data->scriptName);
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*--------------------------------------------------------------------*/
|
||||
int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[])
|
||||
{
|
||||
pSICSOBJ pNew = NULL;
|
||||
pHdb cmd = NULL, node;
|
||||
|
||||
pNew = SetupSICSOBJ(pCon,pSics,pData,argc,argv);
|
||||
if(pNew == NULL){
|
||||
return 0;
|
||||
}
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode, "ps", usSpy,
|
||||
MakeSICSFunc(ListCmd));
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode, "kill", usSpy,
|
||||
MakeSICSFunc(KillCmd));
|
||||
SetHdbProperty(cmd,"type","command");
|
||||
SetHdbProperty(cmd,"priv","spy");
|
||||
node = MakeSICSHdbPar("task",usSpy,MakeHdbText("banana"));
|
||||
AddHipadabaChild(cmd,node,NULL);
|
||||
|
||||
cmd = AddSICSHdbPar(pNew->objectNode, "run", usSpy,
|
||||
MakeSICSFunc(RunCmd));
|
||||
SetHdbProperty(cmd,"type","command");
|
||||
SetHdbProperty(cmd,"priv","spy");
|
||||
node = MakeSICSHdbPar("script",usSpy,MakeHdbText("banana"));
|
||||
AddHipadabaChild(cmd,node,NULL);
|
||||
|
||||
|
||||
return 1;
|
||||
}
|
13
taskobj.h
Normal file
13
taskobj.h
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* This is the SICS interface object to the tasker module
|
||||
*
|
||||
* copyright: GPL
|
||||
*
|
||||
* Mark Koennecke, December 2012
|
||||
*/
|
||||
#ifndef TASKOBJ_
|
||||
#define TASOBJ_
|
||||
int TaskOBJFactory(SConnection *pCon, SicsInterp *pSics, void *pData,
|
||||
int argc, char *argv[]);
|
||||
|
||||
#endif /*TASKOBJ_*/
|
@ -1,4 +1,3 @@
|
||||
|
||||
exe batchpath ./
|
||||
exe syspath ./
|
||||
|
||||
@ -212,27 +211,22 @@ tasub outofplane 1
|
||||
tasub const ki
|
||||
tasub ss 1
|
||||
tasub setub 1.000000 0.000000 0.000000 0.000000 1.000000 0.000000 0.000000 0.000000 1.000000
|
||||
tasub setnormal 0.000000 0.000000 0.000000
|
||||
tasub setnormal 0.000000 0.000000 1.000000
|
||||
tasub settarget 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
|
||||
tasub r1 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
|
||||
tasub r2 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00
|
||||
tasub update
|
||||
#----- MultiMotor sa
|
||||
sa recovernampos noeff a3 24 a4 48
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ref anglesheader stt,om,chi,phi
|
||||
ref clear
|
||||
singlex cell { 0 0 0 0 0 0}
|
||||
singlex oldub { 0 0 0 0 0 0 0 0 0}
|
||||
singlex ub { 0 0 0 0 0 0 0 0 0}
|
||||
singlex planenormal { 0 0 0}
|
||||
singlex cell 0 0 0 0 0 0
|
||||
singlex oldub 0 0 0 0 0 0 0 0 0
|
||||
singlex ub 0 0 0 0 0 0 0 0 0
|
||||
singlex planenormal 0 0 0
|
||||
singlex mode bi
|
||||
singlex spacegroup P
|
||||
singlex peaksearch {}
|
||||
singlex peaksearch
|
||||
singlex peaksearch/min2t 5
|
||||
singlex peaksearch/step2t 1
|
||||
singlex peaksearch/max2t 15
|
||||
@ -244,7 +238,6 @@ singlex peaksearch/phimin 0
|
||||
singlex peaksearch/phimax 180
|
||||
singlex peaksearch/chimin 90
|
||||
singlex peaksearch/chimax 180
|
||||
|
||||
#HKL Settings
|
||||
hkl scantolerance 2.500000
|
||||
ubcalcint difftheta 0.300000
|
||||
@ -256,25 +249,21 @@ messref clear
|
||||
fmess weak 0
|
||||
fmess weakthreshold 20
|
||||
fmess fast 0
|
||||
fmess hkllim { -10 -10 10 10 10 10}
|
||||
fmess sttlim { 5 180}
|
||||
|
||||
fmess hkllim -10 -10 10 10 10 10
|
||||
fmess sttlim 5 180
|
||||
fmess table clear
|
||||
cone target { 0 0 0}
|
||||
cone target 0 0 0
|
||||
cone qscale 1
|
||||
cone center unknown
|
||||
|
||||
simidx sttlim 0.2
|
||||
simidx anglim 0.5
|
||||
|
||||
simi preset 0
|
||||
simi mode monitor
|
||||
|
||||
eva targetposition 5
|
||||
eva sign -1
|
||||
eva softzero -2
|
||||
eva softlowerlim -38
|
||||
eva softupperlim 38
|
||||
eva targetposition 0
|
||||
eva sign 1
|
||||
eva softzero 0
|
||||
eva softlowerlim -40
|
||||
eva softupperlim 40
|
||||
eva fixed -1
|
||||
eva interruptmode 0
|
||||
eva precision 0.01
|
||||
@ -283,5 +272,4 @@ eva failafter 3
|
||||
eva maxretry 3
|
||||
eva ignorefault 0
|
||||
eva movecount 10
|
||||
eva staticoffset -3
|
||||
|
||||
eva staticoffset 0
|
||||
|
@ -387,11 +387,12 @@ hsetprop /sics/farm/schneggecon readCommand schget
|
||||
hsetprop /sics/farm/schneggecon replyCommand schreply
|
||||
}
|
||||
|
||||
set farm 1
|
||||
set farm 0
|
||||
|
||||
if {$farm == 1} {
|
||||
#-------------- Test new async protocol controller
|
||||
makesctcontroller farmser std localhost:7070
|
||||
makesctcontroller farmser std localhost:8080
|
||||
makesctcomtask farmcom farmser
|
||||
MakeSICSObj farm TestObj
|
||||
#---------------------------
|
||||
proc farmparcom {par} {
|
||||
@ -474,7 +475,7 @@ farmser poll /sics/farm/schneggerunning
|
||||
hfactory /sics/farm/stone plain spy int
|
||||
hsetprop /sics/farm/stone read farmparcom stone
|
||||
hsetprop /sics/farm/stone parread farmparread
|
||||
farmser poll /sics/farm/stone
|
||||
#farmser poll /sics/farm/stone
|
||||
|
||||
farmser debug -1
|
||||
|
||||
|
Reference in New Issue
Block a user