- Added a SICS to Hipadaba adapter

- Added a separate polling module to SICS
This commit is contained in:
koennecke
2006-12-07 14:04:17 +00:00
parent 5b727dc784
commit 78fce0127d
32 changed files with 1899 additions and 183 deletions

View File

@ -64,6 +64,9 @@
"BATCHAREA",
"BATCHEND",
"DRIVSTAT",
"STATUS",
"POSITION",
"HDBVAL",
NULL
};

16
event.h
View File

@ -1,5 +1,5 @@
#line 89 "event.w"
#line 96 "event.w"
/*----------------------------------------------------------------------------
E V E N T
@ -18,7 +18,7 @@
int Text2Event(char *pText);
#line 102 "event.w"
#line 109 "event.w"
@ -42,14 +42,16 @@
#define BATCHAREA 15
#define BATCHEND 16
#define DRIVSTAT 17
#define STATUS 18
#define POSITION 19 /* Position event for motors - ffr */
#line 104 "event.w"
#define STATUS 18
#define POSITION 19
#define HDBVAL 20
#line 111 "event.w"
/*--------------- Signals for the Signalfunction of each task ------------*/
#line 73 "event.w"
#line 80 "event.w"
#define SICSINT 300
#define SICSBROADCAST 301
@ -57,6 +59,6 @@
#define TOKENRELEASE 303
#define COMLOG 304
#line 107 "event.w"
#line 114 "event.w"
#endif

View File

@ -53,6 +53,9 @@ $\langle$VE {\footnotesize ?}$\rangle\equiv$
\mbox{}\verb@#define BATCHAREA 15@\\
\mbox{}\verb@#define BATCHEND 16@\\
\mbox{}\verb@#define DRIVSTAT 17@\\
\mbox{}\verb@#define STATUS 18@\\
\mbox{}\verb@#define POSITION 19@\\
\mbox{}\verb@#define HDBVAL 20@\\
\mbox{}\verb@@$\diamond$
\end{list}
\vspace{-1ex}
@ -87,6 +90,10 @@ operation.
\item[BATCHEND] signals the end of the batch buffers processing.
\item[DRIVSTAT] signals a change in the status of a driving operation
(start, finished, fault)
\item[STATUS] ANSTO defined code.
\item[POSITION] ANSTO defined code
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
the object on which the data changed.
\end{description}
Furthermore event contains system wide signal codes which are interpreted in

View File

@ -36,6 +36,9 @@ if the event code is not known, else the apropriate event code.
#define BATCHAREA 15
#define BATCHEND 16
#define DRIVSTAT 17
#define STATUS 18
#define POSITION 19
#define HDBVAL 20
@}
\begin{description}
\item[VALUECHANGE] This is a variable changing its value. As event data a pointer to the
@ -62,6 +65,10 @@ operation.
\item[BATCHEND] signals the end of the batch buffers processing.
\item[DRIVSTAT] signals a change in the status of a driving operation
(start, finished, fault)
\item[STATUS] ANSTO defined code.
\item[POSITION] ANSTO defined code
\item[HDBVAL] The Hdb is notified of a value change. The eventData will be
the object on which the data changed.
\end{description}
Furthermore event contains system wide signal codes which are interpreted in

View File

@ -64,7 +64,7 @@ void AppendCommandParameter(pHdbCommand command, pHdb par){
assert(command != NULL);
assert(par != NULL);
AddHipadabaChild(command->parameters,par);
AddHipadabaChild(command->parameters,par,NULL);
}
/*--------------------------------------------------------------------------*/
void KillHdbCommandList(pHdbCommand commandList){
@ -79,7 +79,7 @@ void KillHdbCommandList(pHdbCommand commandList){
free(current->name);
}
if(current->parameters != NULL){
DeleteHipadabaNode(current->parameters);
DeleteHipadabaNode(current->parameters,NULL);
}
free(current);
current = next;

View File

@ -38,6 +38,7 @@ static void DeleteNodeData(pHdb node){
DeleteCallbackChain(node->writeCallbacks);
DeleteCallbackChain(node->updateCallbacks);
DeleteCallbackChain(node->readCallbacks);
DeleteCallbackChain(node->treeChangeCallbacks);
if(node->name != NULL){
free(node->name);
@ -52,8 +53,24 @@ static void DeleteNodeData(pHdb node){
}
free(node);
}
/*-------------------------------------------------------------------------*/
static int InvokeCallbackChain(pHdbCallback root, pHdb node,
void *callData, hdbValue v){
pHdbCallback current = root;
int status;
while(current != NULL){
status = current->userCallback(current->userData,callData,
node,v);
if(status != 1){
return status;
}
current = current->next;
}
return 1;
}
/*------------------------------------------------------------------------*/
void RemoveHdbNodeFromParent(pHdb node){
void RemoveHdbNodeFromParent(pHdb node, void *callData){
pHdb parent = NULL;
pHdb current = NULL;
@ -68,6 +85,8 @@ void RemoveHdbNodeFromParent(pHdb node){
current = current->next;
}
current->next = current->next->next;
InvokeCallbackChain(parent->treeChangeCallbacks,
parent,callData,parent->value);
}
}
/*-----------------------------------------------------------------------*/
@ -174,22 +193,6 @@ static pHdbCallback DeleteForInternalID(pHdbCallback root, int id){
}
return result;
}
/*-------------------------------------------------------------------------*/
static int InvokeCallbackChain(pHdbCallback root, pHdb node,
void *callData, hdbValue v){
pHdbCallback current = root;
int status;
while(current != NULL){
status = current->userCallback(current->userData,callData,
node,v);
if(status != 1){
return status;
}
current = current->next;
}
return 1;
}
/*----------------------------------------------------------------------*/
char *hdbTrim(char *str)
{
@ -553,7 +556,7 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length){
return pNew;
}
/*-------------------------------------------------------------------------*/
void AddHipadabaChild(pHdb parent, pHdb child){
void AddHipadabaChild(pHdb parent, pHdb child, void *callData){
pHdb current = NULL, prev = NULL;
assert(parent != NULL);
@ -577,16 +580,18 @@ void AddHipadabaChild(pHdb parent, pHdb child){
child->next = NULL;
prev->next = child;
}
InvokeCallbackChain(parent->treeChangeCallbacks,
parent,callData,parent->value);
}
/*--------------------------------------------------------------------------*/
void DeleteHipadabaNode(pHdb node){
void DeleteHipadabaNode(pHdb node, void *callData){
pHdb current = NULL, tmp = NULL;
if(node == NULL){
return;
}
RemoveHdbNodeFromParent(node);
RemoveHdbNodeFromParent(node, callData);
DeleteNodeData(node);
}
@ -733,6 +738,14 @@ void AppendHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
current = node->readCallbacks;
}
break;
case HCBTREE:
if(node->treeChangeCallbacks == NULL){
node->treeChangeCallbacks = newCB;
return;
} else {
current = node->treeChangeCallbacks;
}
break;
default:
assert(0);
break;
@ -778,6 +791,16 @@ void PrependHipadabaCallback(pHdb node, int type, pHdbCallback newCB){
node->readCallbacks = newCB;
}
break;
case HCBTREE:
if(node->treeChangeCallbacks == NULL){
node->treeChangeCallbacks = newCB;
return;
} else {
newCB->next = node->treeChangeCallbacks;
node->treeChangeCallbacks->previous = newCB;
node->treeChangeCallbacks = newCB;
}
break;
default:
assert(0);
break;
@ -790,6 +813,7 @@ void RemoveHipadabaCallback(pHdb root, int id){
root->writeCallbacks = DeleteForID(root->writeCallbacks,id);
root->updateCallbacks = DeleteForID(root->updateCallbacks,id);
root->readCallbacks = DeleteForID(root->readCallbacks,id);
root->treeChangeCallbacks = DeleteForID(root->treeChangeCallbacks,id);
current = root->child;
while(current != NULL){
@ -804,6 +828,7 @@ void InternalRemoveHipadabaCallback(pHdb root, int internalID){
root->writeCallbacks = DeleteForInternalID(root->writeCallbacks,internalID);
root->updateCallbacks = DeleteForInternalID(root->updateCallbacks,internalID);
root->readCallbacks = DeleteForInternalID(root->readCallbacks,internalID);
root->treeChangeCallbacks = DeleteForInternalID(root->treeChangeCallbacks,internalID);
current = root->child;
while(current != NULL){

View File

@ -20,6 +20,8 @@
* copyright: GPL
*
* Mark Koennecke, June 2006
*
* Added treeChange callback, Mark Koennecke, November 2006
*/
#ifndef HIPADABA
#define HIPADABA
@ -38,6 +40,7 @@
#define HCBSET 0
#define HCBUPDATE 1
#define HCBREAD 2
#define HCBTREE 3
/*--------- error codes */
#define HDBTYPEMISMATCH -7701
#define HDBLENGTHMISMATCH -7702
@ -63,12 +66,14 @@ typedef struct __hipadaba {
struct __hdbcallback *writeCallbacks;
struct __hdbcallback *updateCallbacks;
struct __hdbcallback *readCallbacks;
struct __hdbcallback *treeChangeCallbacks;
char *name;
hdbValue value;
int protected;
}Hdb, *pHdb;
/*-------------------------------------------------------------------------------*/
typedef int (*hdbCallbackFunction)(void *userData, void *callData,
pHdb currentNode, hdbValue v );
pHdb currentNode, hdbValue v);
typedef void (*killUserData)(void *data);
/*-------------------------------------------------------------------------------*/
typedef struct __hdbcallback {
@ -179,13 +184,15 @@ pHdb MakeHipadabaNode(char *name, int datatype, int length);
* add a child to a node at the end of the child list.
* @param parent The node to which to add the child
* @param child The node to add
* @param callData User data for the tree chnage callback. Can be NULL.
*/
void AddHipadabaChild(pHdb parent, pHdb child);
void AddHipadabaChild(pHdb parent, pHdb child, void *callData);
/**
* delete a hipadaba node and all its children
* @parma node The node to delete
* @param callData User data for the tree change callback
*/
void DeleteHipadabaNode(pHdb node);
void DeleteHipadabaNode(pHdb node, void *callData);
/*
* checks if a Hdb node is valid
* @param node The node to check
@ -209,8 +216,9 @@ char *GetHipadabaPath(pHdb node);
/**
* removes a node from the parents child list.
* @node the node to remove
* @param callData User data for the tree change callback
*/
void RemoveHdbNodeFromParent(pHdb node);
void RemoveHdbNodeFromParent(pHdb node, void *callData);
/**
* delete a callback chain
* @param root The callback chain to delete
@ -300,7 +308,7 @@ int SetHdbPar(pHdb node, int dataType, void *data, int length,
void *callData);
/**
* Updates a hipadaba parameter. This does not cause an active parameter to
* start driving but invokes all nitifications which may be regsitered on
* start driving but invokes all notifications which may be registered on
* this parameter.
* @param node The node for which to set the parameter
* param dataType The datatype the value ought to have

View File

@ -1238,13 +1238,19 @@ static int checkHMEnd(pHistMem self, char *text){
}
else if(strcmp(argv[1],"init") == 0)
{
if(GetStatus() != eEager)
{
SCWrite(pCon,"ERROR: cannot initialize HM while running",
eError);
return 0;
}
if(SCMatchRights(pCon,usMugger))
{
iRet = HistConfigure(self,pCon,pSics);
if(iRet)
{
self->iInit = 1;
SCSendOK(pCon);
SCSendOK(pCon);
}
else
{
@ -1362,6 +1368,31 @@ static int checkHMEnd(pHistMem self, char *text){
}
return iRet;
}
else if(strcmp(argv[1],"initfile") == 0) /* initialize from a file */
{
/* check user rights */
if(!SCMatchRights(pCon,self->iAccess))
{
return 0;
}
/* enough arguments */
if(argc < 3)
{
sprintf(pBueffel,"ERROR: insufficient number of arguments to %s %s",
argv[0], argv[1]);
SCWrite(pCon,pBueffel,eError);
return 0;
}
iRet = loadHMData(self->pDriv->data,pCon,argv[2]);
self->pDriv->SetHistogram(self->pDriv,pCon,0,0,GetHistLength(self),
self->pDriv->data->localBuffer);
if(iRet)
{
SCSendOK(pCon);
}
return iRet;
}
else if(strcmp(argv[1],"get") == 0) /* get a histogram */
{
/* check parameters, first required: no of Hist */
@ -1602,8 +1633,8 @@ static int checkHMEnd(pHistMem self, char *text){
return 0;
}
if(GetStatus() == eCounting)
{
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
{
SCWrite(pCon,"ERROR: cannot modify timebinning while counting",
eError);
return 0;
}

View File

@ -183,6 +183,13 @@
lData[ii-iStart] = iSetVal;
}
}
else if(iSet == 2)
{
for(ii = iStart; ii < iEnd; ii++)
{
lData[ii-iStart] = self->data->localBuffer[ii];
}
}
else
{
for(ii = iStart; ii < iEnd; ii++)
@ -196,7 +203,7 @@
static int SimSetHistogram(pHistDriver self, SConnection *pCon,
int i, int iStart, int iEnd, HistInt *lData)
{
iSet = 1;
iSet = 2;
iSetVal = lData[0];
return 1;
}

View File

@ -5,11 +5,15 @@
copyright: see file COPYRIGHT
Mark Koennecke, January 2003
Added loading HM data from file, Mark Koennecke, November 2006
-------------------------------------------------------------------------*/
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <math.h>
#include <time.h>
#include "splitter.h"
#include "fortify.h"
#include "hmdata.h"
#include "HistMem.h"
@ -410,7 +414,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
iStart[0], iEnd[0]);
break;
case 2:
/*
lSum = 0;
for(i = iStart[1]; i < iEnd[1]; i++){
iIndex = i*self->iDim[0];
@ -418,7 +422,8 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
iIndex+iStart[0], iIndex+iEnd[0]);
lSum += lRowSum;
}
*/
/*
* This is wrong, see the bit about x and y somewhere
lSum = 0;
for(i = iStart[0]; i < iEnd[0]; i++){
iIndex = i*self->iDim[1];
@ -426,6 +431,7 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
iIndex+iStart[1], iIndex+iEnd[1]);
lSum += lRowSum;
}
*/
break;
default:
sprintf(pBueffel,
@ -440,3 +446,43 @@ long sumHMDataRectangle(pHistMem hist, SConnection *pCon,
}
return lSum;
}
/*--------------------------------------------------------------------------*/
int loadHMData(pHMdata self, SConnection *pCon, char *filename){
FILE *fd = NULL;
char buffer[1024], pNumber[80], *pPtr;
long i = 0, length;
HistInt *data = NULL;
fd = fopen(filename,"r");
if(fd == NULL){
snprintf(buffer,1023,"ERROR: failed to open file %s", filename);
SCWrite(pCon,buffer,eError);
return 0;
}
length = getHMDataLength(self);
if(self->localBuffer == NULL || self->timeslave != NULL){
resizeBuffer(self);
}
data = self->localBuffer;
if(data == NULL){
SCWrite(pCon,"ERROR: failed to allocate HM", eError);
fclose(fd);
return 0;
}
while(i < length && fgets(buffer,1024,fd) != NULL){
pPtr = buffer;
while(pPtr != NULL){
pPtr = sicsNextNumber(pPtr,pNumber);
if(pPtr != NULL){
data[i] = atoi(pNumber);
i++;
}
}
}
if(i < length-1){
SCWrite(pCon,"WARNING: not enough data in file to fill HM",eWarning);
}
fclose(fd);
return 1;
}

View File

@ -57,6 +57,7 @@
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
int start[MAXDIM], int end[MAXDIM]);
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
#endif

View File

@ -53,6 +53,7 @@ The following functions work on this data structure:
long sumHMDataRectangle(pHistMem self, SConnection *pCon,
int start[MAXDIM], int end[MAXDIM]);
int loadHMData(pHMdata self, SConnection *pCon, char *filename);
@}
\begin{description}
@ -84,6 +85,8 @@ the histogram memory and not from the buffer the next time round.
pointer of HMdata. Use with extra care!
\item[sumHMDataRectangle] sums a rectangular box delimted by start and end
from the histogram memory.
\item[loadHMData] loads histogram memory data from a file. This is for
debugging purposes. The file must contain enough numbers to fill the HM.
\end{description}

View File

@ -31,14 +31,21 @@ SOBJ = network.o ifile.o conman.o SCinter.o splitter.o passwd.o \
hmdata.o nxscript.o tclintimpl.o sicsdata.o mcstascounter.o \
mcstashm.o initializer.o remob.o tclmotdriv.o protocol.o \
sinfox.o sicslist.o cone.o hipadaba.o sicshipadaba.o statistics.o \
moregress.o hdbcommand.o multicounter.o regresscter.o histregress.o
moregress.o hdbcommand.o multicounter.o regresscter.o histregress.o \
sicshdbadapter.o polldriv.o sicspoll.o
MOTOROBJ = motor.o simdriv.o
COUNTEROBJ = countdriv.o simcter.o counter.o
VELOOBJ = velo.o velosim.o
.SUFFIXES:
.SUFFIXES: .tcl .htm .c .o
.SUFFIXES: .tcl .htm .c .o .tc
.tc.c:
tjxp $*.tc $*.c
#--- This .SECONDARY. target is necessary to preserve generated .c files for debugging
.SECONDARY.: sicspoll.c polldriv.c
all: libmat libhlib libtecsl libpsi SICServer

13
motor.c
View File

@ -76,13 +76,6 @@
#define IGNOREFAULT 10
#define MOVECOUNT 11
/*------------------------------------------------------------------------
a tiny structure used in CallBack work
*/
typedef struct {
float fVal;
char *pName;
} MotCallback;
/*-------------------------------------------------------------------------*/
static void *MotorGetInterface(void *pData, int iID)
@ -416,7 +409,7 @@ static void handleMoveCallback(pMotor self, SConnection *pCon)
/* create and initialize parameters */
pM->ParArray = ObParCreate(12);
pM->ParArray = ObParCreate(MOTOBPARLENGTH);
if(!pM->ParArray)
{
free(pM);
@ -606,6 +599,7 @@ extern void KillPiPiezo(void *pData);
if(iRet == 1)
{
SCparChange(pCon);
InvokeCallBack(self->pCall,HDBVAL,self);
return iRet;
}
}
@ -631,6 +625,7 @@ extern void KillPiPiezo(void *pData);
fLimit -= fChange;
ObParSet(self->ParArray,self->name,"softlowerlim",fLimit,pCon);
SCparChange(pCon);
InvokeCallBack(self->pCall,HDBVAL,self);
return 1;
}
@ -652,6 +647,7 @@ extern void KillPiPiezo(void *pData);
ObParInit(self->ParArray,SZERO,"softzero",ZEROINACTIVE,usUser);
}
}
InvokeCallBack(self->pCall,HDBVAL,self);
SCparChange(pCon);
return iRet;
@ -785,6 +781,7 @@ extern void KillPiPiezo(void *pData);
self->retryCount = 0;
self->stopped = 0;
self->fTarget = fHard;
InvokeCallBack(self->pCall,HDBVAL,self);
self->posCount = 0;
iRet = self->pDriver->RunTo(self->pDriver,fHard);
if(iRet != OKOK)

View File

@ -14,6 +14,7 @@
#include "obdes.h"
#include "interface.h"
#define MOTOBPARLENGTH 12
typedef struct __Motor {
pObjectDescriptor pDescriptor;
ObPar *ParArray;
@ -32,6 +33,13 @@
int stopped;
} Motor;
typedef Motor *pMotor;
/*------------------------------------------------------------------------
a tiny structure used in CallBack work
--------------------------------------------------------------------------*/
typedef struct {
float fVal;
char *pName;
} MotCallback;
/*-------------------------------------------------------------------------*/
/* parameter management */

View File

@ -686,6 +686,9 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
int iRet, iStatus;
int iCount;
NetItem NItem;
int conCount = 0;
char num[50];
IPair *options = NULL;
self = (pNetRead)pData;
assert(self);
@ -716,9 +719,13 @@ extern int VerifyChannel(mkChannel *self); /* defined in network.c */
{
iCount = NItem.pSock->sockid;
}
conCount++;
iRet = LLDnodePtr2Next(self->iList);
}
snprintf(num,50,"%d", conCount);
IFSetOption(pSICSOptions,"ConnectionCount",num);
/* the select itself */
tmo.tv_usec = self->iReadTimeout;
iCount++;

View File

@ -109,6 +109,8 @@
/* initialise tasker */
assert(TaskerInit(&self->pTasker));
pSICSOptions = IFAddOption(pSICSOptions, "ConnectionCount","0");
/* initialise the server from script */
if(file == NULL)
{

View File

@ -84,7 +84,7 @@
*/
if(self->parNode != NULL){
if(self->parNode->mama == NULL){
DeleteHipadabaNode(self->parNode);
DeleteHipadabaNode(self->parNode,NULL);
}
}
free(self);

3
ofac.c
View File

@ -120,6 +120,7 @@
#include "cone.h"
#include "sicshipadaba.h"
#include "multicounter.h"
#include "sicspoll.h"
/*----------------------- Server options creation -------------------------*/
static int IFServerOption(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[])
@ -331,6 +332,8 @@
MakeCone,NULL,NULL);
AddCommand(pInter,"MakeMultiCounter",
MakeMultiCounter,NULL,NULL);
AddCommand(pInter,"MakeSicsPoll",
InstallSICSPoll,NULL,NULL);
/*
install site specific commands

97
polldriv.c Normal file
View File

@ -0,0 +1,97 @@
/**
* This is the sister module to sicspoll which defines the drivers for the
* various modes of polling SICS objects.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, November-December 2006
*/
#include <stdlib.h>
#include <assert.h>
#include <sics.h>
#include <splitter.h>
#include "polldriv.h"
#include "splitter.h"
#include "sicshipadaba.h"
/*================ actual driver implementation =========================*/
static int timeDue(struct __POLLDRIV *self, time_t now, SConnection *pCon){
if(now > self->nextPoll){
return 1;
} else {
return 0;
}
}
/*------------------ HDB Driver -----------------------------------------*/
static int pollHdb(struct __POLLDRIV *self, SConnection *pCon){
hdbValue old, newVal;
pHdb node = NULL;
memset(&old,0,sizeof(hdbValue));
memset(&newVal,0,sizeof(hdbValue));
node = (pHdb)self->objPointer;
assert(node != NULL);
old = node->value;
self->nextPoll = time(NULL) + self->pollIntervall;
if(GetHipadabaPar(node, &newVal, pCon) == 1){
if(!compareHdbValue(old,newVal)){
UpdateHipadabaPar(node,newVal,pCon);
}
return 1;
} else {
return 0;
}
}
/*-----------------------------------------------------------------------*/
static pPollDriv makeHdbDriver(SConnection *pCon, char *objectIdentifier,
int argc, char *argv[]){
pHdb root = NULL, node = NULL;
pPollDriv pNew = NULL;
root = GetHipadabaRoot();
assert(root != NULL);
node = GetHipadabaNode(root,objectIdentifier);
if(node == NULL){
SCWrite(pCon,"ERROR: object to poll not found",eError);
return 0;
}
pNew = malloc(sizeof(PollDriv));
if(pNew == NULL){
return NULL;
}
memset(pNew,0,sizeof(PollDriv));
pNew->objectIdentifier = strdup(objectIdentifier);
pNew->objPointer = node;
pNew->isDue = timeDue;
pNew->poll = pollHdb;
if(argc > 0){
pNew->pollIntervall = atoi(argv[0]);
} else {
pNew->pollIntervall = 10;
}
return pNew;
}
/*================ external interface ====================================*/
pPollDriv makePollDriver(SConnection *pCon, char *driver,
char *objectIdentifier, int argc, char *argv[]){
strtolower(driver);
if(strcmp(driver,"hdb") == 0) {
return makeHdbDriver(pCon,objectIdentifier, argc, argv);
} else {
SCWrite(pCon,"ERROR: polling driver type unknown",eError);
return NULL;
}
}
/*------------------------------------------------------------------------*/
void deletePollDriv(pPollDriv self){
if(self->objectIdentifier != NULL){
free(self->objectIdentifier);
}
free(self);
}

42
polldriv.h Normal file
View File

@ -0,0 +1,42 @@
/**
* This is the sister module to sicspoll which defines the drivers for the
* various modes of polling SICS objects.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, November-December 2006
*/
#ifndef POLLDRIV_H_
#define POLLDRIV_H_
#include <time.h>
#include <sics.h>
/*==================== a data structure ===================================*/
typedef struct __POLLDRIV{
char *objectIdentifier; /* the object identifier */
void *objPointer; /* a pointer to the object */
time_t nextPoll; /* next polling time */
int pollIntervall; /* poll intervall */
int (*isDue)(struct __POLLDRIV *self, time_t now, SConnection *pCon);
/* function called to determine if this object must be polled */
int (*poll)(struct __POLLDRIV *self, SConnection *pCon);
/* the actual polling function */
}PollDriv, *pPollDriv;
/*==================== the interface =====================================*/
/*
* make a poll driver
* @param pCon A connection to report errors too
* @param driver the driver type to generate
* @param objectIdentifier An identifer for the object to poll
* @param argc number of additional parameter
* @param *argv[] Additional parameters.
* @return NULL on failure or a PollDriv strucure else.
*/
pPollDriv makePollDriver(SConnection *pCon, char *driver,
char *objectIdentifier, int argc, char *argv[]);
/**
* free all memory associated with this poll driver
* @param self The structure to delete
*/
void deletePollDriv(pPollDriv self);
#endif /*POLLDRIV_H_*/

88
polldriv.tc Normal file
View File

@ -0,0 +1,88 @@
/**
* This is the sister module to sicspoll which defines the drivers for the
* various modes of polling SICS objects.
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, November-December 2006
*/
<%! source sicstemplates.tcl %>
<% stdIncludes %>
#include "polldriv.h"
#include "splitter.h"
#include "sicshipadaba.h"
/*================ actual driver implementation =========================*/
static int timeDue(struct __POLLDRIV *self, time_t now, SConnection *pCon){
if(now > self->nextPoll){
return 1;
} else {
return 0;
}
}
/*------------------ HDB Driver -----------------------------------------*/
static int pollHdb(struct __POLLDRIV *self, SConnection *pCon){
hdbValue old, newVal;
pHdb node = NULL;
memset(&old,0,sizeof(hdbValue));
memset(&newVal,0,sizeof(hdbValue));
node = (pHdb)self->objPointer;
assert(node != NULL);
old = node->value;
self->nextPoll = time(NULL) + self->pollIntervall;
if(GetHipadabaPar(node, &newVal, pCon) == 1){
if(!compareHdbValue(old,newVal)){
UpdateHipadabaPar(node,newVal,pCon);
}
return 1;
} else {
return 0;
}
}
/*-----------------------------------------------------------------------*/
static pPollDriv makeHdbDriver(SConnection *pCon, char *objectIdentifier,
int argc, char *argv[]){
pHdb root = NULL, node = NULL;
pPollDriv pNew = NULL;
root = GetHipadabaRoot();
assert(root != NULL);
node = GetHipadabaNode(root,objectIdentifier);
if(node == NULL){
SCWrite(pCon,"ERROR: object to poll not found",eError);
return 0;
}
<%newStruc PollDriv 5 %>
pNew->objectIdentifier = strdup(objectIdentifier);
pNew->objPointer = node;
pNew->isDue = timeDue;
pNew->poll = pollHdb;
if(argc > 0){
pNew->pollIntervall = atoi(argv[0]);
} else {
pNew->pollIntervall = 10;
}
return pNew;
}
/*================ external interface ====================================*/
pPollDriv makePollDriver(SConnection *pCon, char *driver,
char *objectIdentifier, int argc, char *argv[]){
strtolower(driver);
if(strcmp(driver,"hdb") == 0) {
return makeHdbDriver(pCon,objectIdentifier, argc, argv);
} else {
SCWrite(pCon,"ERROR: polling driver type unknown",eError);
return NULL;
}
}
/*------------------------------------------------------------------------*/
void deletePollDriv(pPollDriv self){
if(self->objectIdentifier != NULL){
free(self->objectIdentifier);
}
free(self);
}

471
sicshdbadapter.c Normal file
View File

@ -0,0 +1,471 @@
/*
* Experience has shown that integrating existing SICS objects into the
* Hierarchical Parameter Database (Hdb) is a difficult task without reworking
* the complete SICS object model. Rather, it seems easier to adapt some
* critical objects to the Hdb with some glue code. Following the facade or
* adapter design pattern. This is the purpose of this module. For the moment
* the external interface is only an interpreter function which will be used to
* install suitable SICS objects into the Hdb tree and generates the necessary
* adapters internally. This code can be used to adapt to:
* - motors
* - the data segment of histogram memories
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, November 2006
*/
#include <stdlib.h>
#include <assert.h>
#include <sics.h>
#include "stptok.h"
#include "motor.h"
#include "HistMem.h"
#include "sicsvar.h"
#include "sicshipadaba.h"
#include "sicshdbadapter.h"
/*=================== motor code =======================================*/
static int MoveCallback(int iEvent, void *eventData, void *userData,
commandContext cc){
MotCallback *motData = (MotCallback *)eventData;
pHdb motor = (pHdb)userData;
pHdb pos = NULL;
if(iEvent == MOTDRIVE && motData != NULL && motor != NULL){
UpdateHipadabaPar(motor,MakeHdbFloat((double)motData->fVal)
,NULL);
pos = GetHipadabaNode(motor,"position");
if(pos != NULL){
UpdateHipadabaPar(pos,MakeHdbFloat((double)motData->fVal)
,NULL);
}
}
return 1;
}
/*---------------------------------------------------------------------*/
static int MotorValueCallback(int iEvent, void *eventData, void *userData,
commandContext cc){
pHdb motor = (pHdb)userData;
pMotor pMot = (pMotor)eventData;
pHdb current = NULL;
float fVal;
/*
* as setting some motor parameters might cause other motor
* parametes to change too, I opt for the cheap solution to check
* them all.
*/
if(iEvent == HDBVAL && motor != NULL && pMot != NULL){
current = motor->child;
while(current != NULL){
MotorGetPar(pMot,current->name,&fVal);
if(fVal != current->value.v.doubleValue) {
UpdateHipadabaPar(current,MakeHdbFloat((double)fVal),NULL);
}
current = current->next;
}
}
return 1;
}
/*---------------------------------------------------------------------*/
static int MotorParSetCallback(void *userData, void *callData,
pHdb currentNode, hdbValue v){
pMotor pMot = (pMotor)userData;
SConnection *pCon = (SConnection *)callData;
int status;
assert(pMot != NULL && pCon != NULL);
status = MotorSetPar(pMot,pCon,currentNode->name, (float)v.v.doubleValue);
return status;
}
/*----------------------------------------------------------------------*/
static int MotorParGetCallback(void *userData, void *callData,
pHdb currentNode, hdbValue v){
pMotor pMot = (pMotor)userData;
float fVal;
int status;
assert(pMot != NULL);
status = MotorGetPar(pMot,currentNode->name,&fVal);
currentNode->value.v.doubleValue = fVal;
return status;
}
/*---------------------------------------------------------------------*/
static pHdb MakeMotParNode(char *name, pMotor pMot){
pHdb node = NULL;
pHdbCallback pCall = NULL;
node = MakeHipadabaNode(name, HIPFLOAT, 1);
if(node != NULL) {
pCall = MakeHipadabaCallback(MotorParSetCallback,pMot,NULL,-1,-1);
if(pCall == NULL){
return NULL;
}
AppendHipadabaCallback(node,HCBSET,pCall);
pCall = MakeHipadabaCallback(MotorParGetCallback,pMot,NULL,-1,-1);
if(pCall == NULL){
return NULL;
}
AppendHipadabaCallback(node,HCBREAD,pCall);
}
return node;
}
/*---------------------------------------------------------------------*/
static int AddStdMotorPar(pHdb motorNode, pMotor pMot){
int i;
pHdb parNode = NULL;
char *addPar[] = {"position",
"target",
"hardlowerlim",
"hardupperlim",
NULL};
i = 0;
while(addPar[i] != NULL){
parNode = MakeMotParNode(addPar[i],pMot);
if(parNode == NULL){
return 0;
}
AddHipadabaChild(motorNode,parNode, NULL);
i++;
}
/*
* Add the parameters in the obpar array
*/
for(i = 0; i < MOTOBPARLENGTH; i++){
parNode = MakeMotParNode(pMot->ParArray[i].name,pMot);
if(parNode == NULL){
return 0;
}
AddHipadabaChild(motorNode,parNode, NULL);
}
return 1;
}
/*--------------------------------------------------------------------------*/
static char *getDriverParList(MotorDriver *pDriv){
SConnection *pCon = NULL;
pDynString list = NULL;
char *listData = NULL;
if(pDriv->ListDriverPar != NULL){
pCon = SCCreateDummyConnection(pServ->pSics);
if(pCon == NULL){
return NULL;
}
SCStartBuffering(pCon);
pDriv->ListDriverPar(pDriv,"test.", pCon);
list = SCEndBuffering(pCon);
if(list != NULL){
listData = strdup(GetCharArray(list));
SCDeleteConnection(pCon);
} else {
listData = NULL;
}
return listData;
}
return NULL;
}
/*--------------------------------------------------------------------------*/
extern char *trim(char *str);
/*--------------------------------------------------------------------------*/
static char *extractName(char *line){
char *name = NULL, *pEnd = NULL;
name = strchr(line,'.');
assert(name != NULL);
while(*name == '.'){
name++;
}
pEnd = strchr(name,'=');
assert(pEnd != NULL);
*pEnd = '\0';
return trim(name);
}
/*------------------------------------------------------------------------*/
static int CreateDriverParameters(pMotor pM, pHdb parent){
char *listPtr = NULL, line[80], *pPtr, *name;
pHdb node = NULL;
listPtr = getDriverParList(pM->pDriver);
if(listPtr == NULL){
/*
* no driver parameters
*/
return 1;
}
pPtr = listPtr;
while((pPtr = stptok(pPtr,line,79,"\n")) != NULL){
name = extractName(line);
node = MakeMotParNode(name,pM);
if(node != NULL){
AddHipadabaChild(parent,node,NULL);
}
}
free(listPtr);
return 1;
}
/*----------------------------------------------------------------------*/
static pHdb CreateMotorAdapter(char *name, pMotor pMot){
pHdb result = NULL;
commandContext comCom;
assert(pMot != NULL);
result = MakeSICSHdbDriv(name,usUser,pMot,HIPFLOAT);
if(result == NULL){
return NULL;
}
/*
* We want to be notified when this motor drives around. Or
* its parameters change.
*/
strncpy(comCom.deviceID,name,255);
comCom.transID = -77;
RegisterCallback(pMot->pCall,comCom, MOTDRIVE, MoveCallback,
result,NULL);
RegisterCallback(pMot->pCall,comCom, HDBVAL, MotorValueCallback,
result,NULL);
if(!AddStdMotorPar(result,pMot)){
DeleteHipadabaNode(result,NULL);
return NULL;
}
if(!CreateDriverParameters(pMot,result)){
DeleteHipadabaNode(result,NULL);
return NULL;
}
result->protected = 1;
return result;
}
/*============== histogram memory ======================================*/
static long totalSum(int *data, int length){
long result = 0l;
int i;
for(i = 0; i < length; i++){
result += data[i];
}
return result;
}
/*----------------------------------------------------------------------*/
static int HMDataGetCallback(void *userData, void *callData,
pHdb currentNode, hdbValue v){
pHistMem pHM = (pHistMem)userData;
SConnection *pCon = (SConnection *)callData;
long sum1, sum2;
assert(pHM != NULL);
if(pCon == NULL){
return 0;
}
sum1 = totalSum(currentNode->value.v.intArray, currentNode->value.arrayLength);
currentNode->value.arrayLength = GetHistLength(pHM);
currentNode->value.v.intArray = (int *)GetHistogramPointer(pHM,pCon);
sum2 = totalSum(currentNode->value.v.intArray, currentNode->value.arrayLength);
if(sum1 != sum2){
UpdateHipadabaPar(currentNode,currentNode->value,NULL);
}
return 1;
}
/*----------------------------------------------------------------------*/
static pHdb MakeHMDataNode(pHistMem pHM, char *name){
pHdb node = NULL;
pHdbCallback pCall = NULL;
node = MakeHipadabaNode(name,HIPINTVARAR,2);
if(node == NULL){
return NULL;
}
pCall = MakeHipadabaCallback(HMDataGetCallback,pHM,NULL,-1,-1);
if(pCall == NULL){
return NULL;
}
AppendHipadabaCallback(node,HCBREAD,pCall);
AppendHipadabaCallback(node,HCBSET,MakeReadOnlyCallback());
return node;
}
/*================ SICS Variable ======================================*/
static int SicsVarSetCallback(void *userData, void *callData,
pHdb currentNode, hdbValue v){
pSicsVariable pVar = (pSicsVariable)userData;
SConnection *pCon = (SConnection *)callData;
int userRights = usMugger;
assert(pVar != NULL);
if(pCon != NULL){
userRights = SCGetRights(pCon);
}
switch(currentNode->value.dataType){
case HIPINT:
VarSetInt(pVar, v.v.intValue, userRights);
break;
case HIPFLOAT:
VarSetFloat(pVar, (float)v.v.doubleValue, userRights);
break;
case HIPTEXT:
VarSetText(pVar, v.v.text, userRights);
break;
}
return 1;
}
/*----------------------------------------------------------------------*/
static int ValueCallback(int iEvent, void *eventData, void *userData,
commandContext cc){
pSicsVariable pVar = (pSicsVariable)eventData;
pHdb node = (pHdb)userData;
hdbValue v;
if(iEvent == VALUECHANGE && pVar != NULL && node != NULL){
switch(pVar->eType){
case veInt:
v = MakeHdbInt(pVar->iVal);
break;
case veFloat:
v = MakeHdbFloat((double)pVar->fVal);
break;
case veText:
v = MakeHdbText(pVar->text);
break;
}
UpdateHipadabaPar(node,v,NULL);
}
return 1;
}
/*----------------------------------------------------------------------*/
static pHdb MakeSicsVarNode(pSicsVariable pVar, char *name){
pHdb node = NULL;
pHdbCallback pCall = NULL;
commandContext comCom;
int type;
switch(pVar->eType){
case veInt:
type = HIPINT;
break;
case veFloat:
type = HIPFLOAT;
break;
case veText:
type = HIPTEXT;
break;
}
node = MakeHipadabaNode(name,type,1);
if(node == NULL){
return NULL;
}
pCall = MakeHipadabaCallback(SicsVarSetCallback,pVar,NULL,-1,-1);
if(pCall == NULL){
return NULL;
}
strncpy(comCom.deviceID,name,255);
comCom.transID = -77;
AppendHipadabaCallback(node,HCBSET,pCall);
RegisterCallback(pVar->pCall,comCom, VALUECHANGE, ValueCallback,
node,NULL);
node->protected = 1;
return node;
}
/*============== interpreter function ==================================*/
int SICSHdbAdapter(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){
pHdb root = NULL;
pHdb path = NULL;
pHdb node = NULL;
pMotor pMot = NULL;
pHistMem pHM = NULL;
CommandList *pCom = NULL;
pIDrivable pDriv = NULL;
pSicsVariable pVar = NULL;
char buffer[512];
root = GetHipadabaRoot();
assert(root != NULL);
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
if(argc < 4) {
SCWrite(pCon,"ERROR: Insufficient number of arguments",eError);
return 0;
}
path = GetHipadabaNode(root,argv[1]);
if(path == NULL){
SCWrite(pCon,"ERROR: path to attach object too not found",eError);
return 0;
}
/*
* look for motors
*/
pMot = (pMotor)FindCommandData(pSics,argv[2],"Motor");
if(pMot != NULL){
node = CreateMotorAdapter(argv[3],pMot);
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory creating motor node",eError);
return 0;
}
AddHipadabaChild(path,node,pCon);
SCSendOK(pCon);
return 1;
}
/*
* look for drivables
*/
pDriv = FindDrivable(pSics,argv[2]);
pCom = FindCommand(pSics,argv[2]);
if(pDriv != NULL && pCom != NULL && pCom->pData != NULL){
node = MakeSICSHdbDriv(argv[3],usUser,pCom->pData,HIPFLOAT);
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory creating drivable node",eError);
return 0;
}
AddHipadabaChild(path,node,pCon);
SCSendOK(pCon);
return 1;
}
/**
* look for SICS Variables
*/
pVar = (pSicsVariable)FindCommandData(pSics,argv[2],"SicsVariable");
if(pVar != NULL){
node = MakeSicsVarNode(pVar,argv[3]);
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory creating SICS variable node",
eError);
return 0;
}
AddHipadabaChild(path,node,pCon);
SCSendOK(pCon);
return 1;
}
/*
* look for histogram memories
*/
pHM = (pHistMem)FindCommandData(pSics,argv[2],"HistMem");
if(pHM != NULL){
node = MakeHMDataNode(pHM,argv[3]);
if(node == NULL){
SCWrite(pCon,"ERROR: out of memory creating HM node",eError);
return 0;
}
AddHipadabaChild(path,node,pCon);
SCSendOK(pCon);
return 1;
}
snprintf(buffer,511,
"ERROR: attaching this type of object: %s at %s not implemented",
argv[2], argv[1]);
SCWrite(pCon,buffer,eError);
return 0;
}

23
sicshdbadapter.h Normal file
View File

@ -0,0 +1,23 @@
/*
* Experience has shown that integrating existing SICS objects into the
* Hierarchical Parameter Database (Hdb) is a difficult task without reworking
* the complete SICS object model. Rather, it seems easier to adapt some
* critical objects to the Hdb with some glue code. Following the facade or
* adapter design pattern. This is the purpose of this module. For the moment
* the external interface is only an interpreter function which will be used to
* install suitable SICS objects into the Hdb tree and generates the necessary
* adapters internally. This code can be used to adapt to:
* - motors
* - the data segment of histogram memories
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, November 2006
*/
#ifndef SICSHDBADAPTER_H_
#define SICSHDBADAPTER_H_
int SICSHdbAdapter(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
#endif /*SICSHDBADAPTER_H_*/

View File

@ -6,19 +6,22 @@
* copyright: GPL
*
* Mark Koennecke, June 2006
*
* Introduced notification on tree changes, Mark Koennecke, November 2006
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <sicshipadaba.h>
#include <sicshdbadapter.h>
#include "sicspoll.h"
#include <lld.h>
#include <stptok.h>
/*== there can be only hipadaba in SICS, some globals to care for that == */
static pHdb root = NULL;
static int scriptUpdate = -1;
static hdbUpdateTask taskData;
static pSicsPoll poller = NULL;
/*=============== common callback functions used for SICS ===========================*/
static int SICSCheckPermissionCallback(void *userData, void *callData, pHdb node,
hdbValue v){
@ -79,7 +82,7 @@ static int SICSReadOnlyCallback(void *userData, void *callData, pHdb node,
return SICSCBRO;
}
/*-------------------------------------------------------------------------------------*/
static pHdbCallback MakeReadOnlyCallback(){
pHdbCallback MakeReadOnlyCallback(){
return MakeHipadabaCallback(SICSReadOnlyCallback, NULL,NULL,-1,-1);
}
/*-------------------------------------------------------------------------------------*/
@ -101,6 +104,7 @@ pHdbCallback MakeSICSDriveCallback(void *sicsObject){
/*---------------------------------------------------------------------------------------*/
static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
hdbValue v){
static SConnection *defCon = NULL;
SConnection *pCon = NULL;
pDummy dum = NULL;
pIDrivable pDriv = NULL;
@ -108,7 +112,11 @@ static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
pCon = (SConnection *)callData;
dum = (pDummy)userData;
assert(pCon != NULL && dum != NULL);
assert(dum != NULL);
if(defCon == NULL){
defCon = SCCreateDummyConnection(pServ->pSics);
}
pDriv = dum->pDescriptor->GetInterface(dum,DRIVEID);
assert(pDriv != NULL);
@ -116,6 +124,12 @@ static int SICSReadDriveCallback(void *userData, void *callData, pHdb node,
value = pDriv->GetValue(dum,pCon);
node->value.v.doubleValue = (double)value;
v.v.doubleValue = (double)value;
} else {
if(defCon != NULL){
value = pDriv->GetValue(dum,defCon);
node->value.v.doubleValue = (double)value;
v.v.doubleValue = (double)value;
}
}
return 1;
}
@ -172,6 +186,33 @@ pHdbCallback MakeNotifyCallback(SConnection *pCon, int id){
cbInfo->context = SCGetContext(pCon);
return MakeHipadabaCallback(SICSNotifyCallback, cbInfo,free,id,pCon->ident);
}
/*-------------------------------------------------------------------------*/
static int TreeChangeCallback(void *userData, void *callData, pHdb node,
hdbValue v){
char *path = NULL;
char buffer[1024];
HdbCBInfo *cbInfo = (HdbCBInfo *)userData;
if(cbInfo != NULL && cbInfo->pCon != NULL){
path = GetHipadabaPath(node);
snprintf(buffer,1023,"treechange = %s", path);
SCWriteInContext(cbInfo->pCon,buffer,eEvent,cbInfo->context);
free(path);
}
return 1;
}
/*-------------------------------------------------------------------------*/
pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id){
HdbCBInfo *cbInfo = NULL;
cbInfo = malloc(sizeof(HdbCBInfo));
if(cbInfo == NULL){
return NULL;
}
cbInfo->pCon = pCon;
cbInfo->context = SCGetContext(pCon);
return MakeHipadabaCallback(TreeChangeCallback, cbInfo,free,id,pCon->ident);
}
/*----------------------------------------------------------------------------------------*/
static int SICSScriptWriteCallback(void *userData, void *callData, pHdb node,
hdbValue v){
@ -527,14 +568,14 @@ pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v){
pHcb = MakeCheckPermissionCallback(priv);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBSET,pHcb);
pHcb = MakeSetUpdateCallback();
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBSET,pHcb);
@ -559,21 +600,21 @@ pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType){
pHcb = MakeCheckPermissionCallback(priv);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBSET,pHcb);
pHcb = MakeSICSDriveCallback(sicsObject);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBSET,pHcb);
pHcb = MakeSICSReadDriveCallback(sicsObject);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBREAD,pHcb);
@ -592,21 +633,21 @@ pHdb MakeSICSMemPar(char *name, int priv, float *address){
pHcb = MakeCheckPermissionCallback(priv);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBSET,pHcb);
pHcb = MakeMemSetCallback(address);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBSET,pHcb);
pHcb = MakeMemReadCallback(address);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBREAD,pHcb);
@ -626,7 +667,7 @@ pHdb MakeSICSROPar(char *name, hdbValue v){
pHcb = MakeReadOnlyCallback();
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBSET,pHcb);
@ -647,22 +688,22 @@ pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript,
pHcb = MakeSICSWriteScriptCallback(setScript);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBSET,pHcb);
pHcb = MakeSICSReadScriptCallback(readScript);
if(pHcb == NULL){
DeleteHipadabaNode(result);
DeleteHipadabaNode(result,NULL);
return NULL;
}
AppendHipadabaCallback(result,HCBREAD,pHcb);
/**
* put into the list of nodes to check with the update task
*/
LLDnodeAppend(scriptUpdate,&result);
/* LLDnodeAppend(scriptUpdate,&result); */
return result;
}
/*-------------------------------------------------------------------------*/
@ -675,24 +716,28 @@ pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
static void removeNodeFromUpdateList(pHdb node){
pHdb current = NULL;
int status;
char *objName = NULL;
status = LLDnodePtr2First(scriptUpdate);
while(status != 0){
current = LLDnodePtr(scriptUpdate);
if(current == node){
LLDnodeDelete(scriptUpdate);
return;
}
status = LLDnodePtr2Next(scriptUpdate);
objName = GetHipadabaPath(node);
if(objName != NULL){
removePollObject(poller, objName);
free(objName);
}
}
/*-----------------------------------------------------------------------*/
static void SICSDeleteNodeData(pHdb node){
pHdb tmp = NULL;
if(node == NULL){
return;
}
removeNodeFromUpdateList(node);
while(node->child != NULL){
tmp = node->child;
node->child = node->child->next;
SICSDeleteNodeData(tmp);
}
DeleteCallbackChain(node->writeCallbacks);
DeleteCallbackChain(node->updateCallbacks);
DeleteCallbackChain(node->readCallbacks);
@ -703,23 +748,17 @@ static void SICSDeleteNodeData(pHdb node){
ReleaseHdbValue(&node->value);
node->magic = 000000;
while(node->child != NULL){
tmp = node->child;
node->child = node->child->next;
SICSDeleteNodeData(tmp);
}
removeNodeFromUpdateList(node);
free(node);
}
/*--------------------------------------------------------------------------*/
void RemoveSICSPar(pHdb node){
void RemoveSICSPar(pHdb node, void *callData){
pHdb current = NULL, tmp = NULL;
if(node == NULL){
return;
}
RemoveHdbNodeFromParent(node);
RemoveHdbNodeFromParent(node,NULL);
SICSDeleteNodeData(node);
}
@ -731,7 +770,7 @@ int AddSICSHdbPar(pHdb node, char *name, int priv, hdbValue v){
if(child == NULL){
return 0;
}
AddHipadabaChild(node,child);
AddHipadabaChild(node,child,NULL);
return 1;
}
/*---------------------------------------------------------------------------*/
@ -742,7 +781,7 @@ int AddSICSHdbROPar(pHdb node, char *name, hdbValue v){
if(child == NULL){
return 0;
}
AddHipadabaChild(node,child);
AddHipadabaChild(node,child,NULL);
return 1;
}
/*--------------------------------------------------------------------------*/
@ -763,25 +802,25 @@ int AddSICSHdbMemPar(pHdb node, char *name, int priv,
pHcb = MakeCheckPermissionCallback(priv);
if(pHcb == NULL){
DeleteHipadabaNode(child);
DeleteHipadabaNode(child,NULL);
return 0;
}
AppendHipadabaCallback(child,HCBSET,pHcb);
pHcb = MakeMemGenSetCallback(data);
if(pHcb == NULL){
DeleteHipadabaNode(child);
DeleteHipadabaNode(child,NULL);
return 0;
}
AppendHipadabaCallback(child,HCBSET,pHcb);
pHcb = MakeMemGenReadCallback(data);
if(pHcb == NULL){
DeleteHipadabaNode(child);
DeleteHipadabaNode(child,NULL);
return 0;
}
AppendHipadabaCallback(child,HCBREAD,pHcb);
AddHipadabaChild(node,child);
AddHipadabaChild(node,child,NULL);
return 1;
}
@ -887,13 +926,16 @@ int SICSHdbSetPar(void *obj, SConnection *pCon,
int InstallSICSNotify(pHdb node, SConnection *pCon, int id, int recurse){
pHdb currentChild = NULL;
pHdbCallback noty = NULL;
pHdbCallback treeChange = NULL;
treeChange = MakeTreeChangeCallback(pCon,id);
noty = MakeNotifyCallback(pCon,id);
if(noty == NULL){
if(noty == NULL || treeChange == NULL){
SCWrite(pCon,"ERROR: out of memory installing callback", eError);
return 0;
}
AppendHipadabaCallback(node, HCBUPDATE, noty);
AppendHipadabaCallback(node, HCBTREE, treeChange);
if(recurse == 1){
currentChild = node->child;
@ -1041,60 +1083,6 @@ void SaveSICSHipadaba(FILE *fd, pHdb node, char *prefix){
currentChild = currentChild->next;
}
}
/*---------------------------------------------------------------------------*/
int SICSHipadabaTask(void *pData){
pHdbUpdateTask self = NULL;
hdbValue old, newValue;
pHdb currentNode = NULL;
int status;
self = (pHdbUpdateTask)pData;
assert(self != NULL);
if(self->iEnd == 1){
return 0;
}
if(LLDcheck(self->updateList) == LIST_EMPTY){
return 1;
}
memset(&old,0,sizeof(hdbValue));
memset(&newValue,0,sizeof(hdbValue));
currentNode = (pHdb)LLDnodePtr(self->updateList);
if(currentNode != NULL){
old.dataType = currentNode->value.dataType;
copyHdbValue(&currentNode->value,&old);
if(GetHipadabaPar(currentNode,&newValue, self->pCon) == 1){
if(!compareHdbValue(old,newValue)){
UpdateHipadabaPar(currentNode,newValue,self->pCon);
}
}
ReleaseHdbValue(&old);
ReleaseHdbValue(&newValue);
}
status = LLDnodePtr2Next(self->updateList);
if(status == 0){
LLDnodePtr2First(self->updateList);
}
return 1;
}
/*---------------------------------------------------------------------------*/
void SICSHipadabaSignal(void *pData, int iSignal, void *pSigData){
pHdbUpdateTask self = NULL;
int *iInt;
self = (pHdbUpdateTask)pData;
if(iSignal == SICSINT){
iInt = (int *)pSigData;
if(*iInt == eEndServer){
self->iEnd = 1;
}
}
}
/*================ value helpers ============================================*/
pDynString formatValue(hdbValue v){
pDynString result = NULL;
@ -1162,8 +1150,10 @@ static char *getNextHdbNumber(char *pStart, char pNumber[80]){
static int adjustDataLength(hdbValue *v, char *data){
char number[80];
int count = 0;
char *pPtr = NULL;
while(getNextHdbNumber(data,number) != NULL){
pPtr = data;
while((pPtr = getNextHdbNumber(pPtr,number)) != NULL){
count++;
}
if(count != v->arrayLength){
@ -1315,6 +1305,7 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
char *pPtr = NULL;
pHdb parent = NULL;
pHdb child = NULL;
char buffer[512], buffer2[512];
if(!SCMatchRights(pCon,usMugger)){
return 0;
@ -1351,7 +1342,8 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
}
/* split off last path element */
pPtr = strrchr(argv[1],'/');
strncpy(buffer,argv[1],511);
pPtr = strrchr(buffer,'/');
if(pPtr == NULL){
SCWrite(pCon,"ERROR: invalid path specification",
eError);
@ -1362,10 +1354,12 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
if(strlen(pPtr) < 1) {
parent = root;
} else {
parent = GetHipadabaNode(root,argv[1]);
parent = GetHipadabaNode(root,buffer);
}
if(parent == NULL){
SCWrite(pCon,"ERROR: parent for new node does not exist",eError);
snprintf(buffer2,512,"ERROR: parent %s for new node does not exist",
buffer);
SCWrite(pCon,buffer2,eError);
return 0;
}
if(type != HIPNONE){
@ -1378,7 +1372,7 @@ static int MakeHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
return 0;
}
AddHipadabaChild(parent,child);
AddHipadabaChild(parent,child,pCon);
SCSendOK(pCon);
return 1;
}
@ -1390,6 +1384,10 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
pHdb parent = NULL;
pHdb child = NULL;
pHdb current = NULL;
char *urgv[] = {"5", NULL};
char driver[] = {"hdb"};
char buffer[512], buffer2[512];
if(!SCMatchRights(pCon,usMugger)){
return 0;
@ -1422,7 +1420,8 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
}
/* split off last path element */
pPtr = strrchr(argv[1],'/');
strncpy(buffer,argv[1],511);
pPtr = strrchr(buffer,'/');
if(pPtr == NULL){
SCWrite(pCon,"ERROR: invalid path specification",
eError);
@ -1433,10 +1432,12 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
if(strlen(pPtr) < 1) {
parent = root;
} else {
parent = GetHipadabaNode(root,argv[1]);
parent = GetHipadabaNode(root,buffer);
}
if(parent == NULL){
SCWrite(pCon,"ERROR: parent for new node does not exist",eError);
snprintf(buffer2,512,"ERROR: parent %s for new node does not exist",
buffer);
SCWrite(pCon,buffer2,eError);
return 0;
}
child = MakeSICSScriptPar(pPtr, argv[3], argv[2],
@ -1446,11 +1447,32 @@ static int MakeHdbScriptNode(SConnection *pCon, SicsInterp *pSics, void *pData,
return 0;
}
AddHipadabaChild(parent,child);
AddHipadabaChild(parent,child,pCon);
/*
* have it polled automatically
*/
addPollObject(poller,pCon, GetHipadabaPath(child),driver,1,urgv);
SCSendOK(pCon);
return 1;
}
/*------------------------------------------------------------------------------*/
static int isNodeProtected(pHdb node){
pHdb current = NULL;
if(node->protected == 1){
return 1;
}
current = node->child;
while(current != NULL){
if(isNodeProtected(current)){
return 1;
}
current = current->next;
}
return 0;
}
/*-----------------------------------------------------------------------------------------*/
static int DeleteHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){
@ -1469,7 +1491,13 @@ static int DeleteHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
SCWrite(pCon,"ERROR: node to delete not found",eError);
return 0;
}
RemoveSICSPar(killNode);
if(isNodeProtected(killNode)){
SCWrite(pCon,"ERROR: this node or one of its children is protected",
eError);
return 0;
}
RemoveSICSPar(killNode, pCon);
SCSendOK(pCon);
return 1;
}
@ -1927,7 +1955,7 @@ static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
return 0;
}
AddHipadabaChild(node,pDum->pDescriptor->parNode);
AddHipadabaChild(node,pDum->pDescriptor->parNode,pCon);
if(argc > 3){
if(pDum->pDescriptor->parNode->name != NULL){
@ -1939,41 +1967,75 @@ static int LinkHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------*/
static int ChainCallback(void *userData, void *callData, pHdb node,
hdbValue v){
pHdb slave = (pHdb)userData;
hdbValue vv, old;
if(slave != NULL){
old = slave->value;
memset(&vv,0,sizeof(hdbValue));
GetHipadabaPar(slave,&vv,callData);
if(!compareHdbValue(old,vv)){
UpdateHipadabaPar(slave, vv, callData);
}
}
return 1;
}
/*--------------------------------------------------------------------------*/
static int ChainHdbNode(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){
pHdb master = NULL, slave = NULL;
char buffer[512];
pHdbCallback kalle = NULL;
if(argc < 3) {
SCWrite(pCon,"ERROR: insufficent number of arguments to hchain",
eError);
}
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
slave = GetHipadabaNode(root,argv[1]);
if(slave == NULL){
snprintf(buffer,511,"ERROR: slave %s not found",argv[1]);
SCWrite(pCon,buffer,eError);
return 0;
}
master = GetHipadabaNode(root,argv[2]);
if(master == NULL){
snprintf(buffer,511,"ERROR: master %s not found",argv[1]);
SCWrite(pCon,buffer,eError);
return 0;
}
kalle = MakeHipadabaCallback(ChainCallback,slave, NULL, -1,-1);
if(kalle == NULL){
SCWrite(pCon,"ERROR: out of memory creating callback",eError);
return 0;
}
AppendHipadabaCallback(master,HCBUPDATE, kalle);
SCSendOK(pCon);
return 1;
}
/*---------------------------------------------------------------------------*/
void killSICSHipadaba(){
if(root != NULL){
DeleteHipadabaNode(root);
DeleteHipadabaNode(root,NULL);
}
root = NULL;
/**
* children have already been removed when killing the
* main tree
*/
if(scriptUpdate > 0 && LLDcheck(scriptUpdate) != LIST_EMPTY){
LLDdelete(scriptUpdate);
}
}
/*---------------------------------------------------------------------------*/
int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){
root = MakeHipadabaNode("/",HIPNONE,0);
scriptUpdate = LLDcreate(sizeof(void *));
taskData.updateList = scriptUpdate;
taskData.iEnd = 0;
taskData.pCon = SCCreateDummyConnection(pSics);
if(taskData.pCon == NULL){
SCWrite(pCon,"ERROR: out of memory creating Hipadaba",eError);
return 0;
}
TaskRegister(pServ->pTasker,
SICSHipadabaTask,
SICSHipadabaSignal,
NULL,
&taskData,1);
AddCommand(pSics,"hmake", MakeHdbNode, NULL, NULL);
AddCommand(pSics,"hmakescript", MakeHdbScriptNode, NULL, NULL);
AddCommand(pSics,"hattach", SICSHdbAdapter, NULL, NULL);
AddCommand(pSics,"hdel", DeleteHdbNode, NULL, NULL);
AddCommand(pSics,"hset", SetHdbNode, NULL, NULL);
AddCommand(pSics,"hget", GetHdbNode, NULL, NULL);
@ -1983,6 +2045,10 @@ int InstallSICSHipadaba(SConnection *pCon, SicsInterp *pSics, void *pData,
AddCommand(pSics,"hlink", LinkHdbNode, NULL, NULL);
AddCommand(pSics,"hinfo", HdbNodeInfo, NULL, NULL);
AddCommand(pSics,"hval", HdbNodeVal, NULL, NULL);
AddCommand(pSics,"hchain", ChainHdbNode, NULL, NULL);
InstallSICSPoll(pCon,pSics,pData,argc,argv);
poller = (pSicsPoll)FindCommandData(pSics,"sicspoll","SicsPoll");
return 1;
}

View File

@ -25,6 +25,11 @@ typedef struct {
int iEnd;
}hdbUpdateTask, *pHdbUpdateTask;
/*======================== common callbacks =====================================*/
/**
* make a ReadOnly callback
* @return a callback which disallows setting of a parameter.
*/
pHdbCallback MakeReadOnlyCallback();
/**
* make a callback which checks permissions. To be used on write
* @param priv The privilege to check against
@ -107,6 +112,13 @@ pHdbCallback MakeMemReadCallback(float *address);
* @return a suitable callback for setting this parameter.
*/
pHdbCallback MakeMemSetCallback(float *address);
/**
* make a tree chnage callback
* @param pCon The connection to notfy on tree chnages
* @id The ID of this callback
* @return a suitable callback for notififications about tree changes.
*/
pHdbCallback MakeTreeChangeCallback(SConnection *pCon, int id);
/*======================== parameter creation ===================================*/
/**
* make a simple SICS hdb parameter. Setting it will call update immediately. Use
@ -184,8 +196,9 @@ pHdb CreateSICSScriptPar(char *name, char *setScript, char *readScript,
* normal DeletHipadabaNode, this function also takes care of
* clearing scipted nodes out of the update tasks watch list.
* @param node The node to delete
* @param callData User data for the tree change callback
*/
void RemoveSICSPar(pHdb node);
void RemoveSICSPar(pHdb node, void *callData);
/*=============== Add par functions =======================================*/
/**
* add a new simple hdb parameter as child to node

360
sicspoll.c Normal file
View File

@ -0,0 +1,360 @@
/**
* This is a generalized polling module for SICS. With this module
* SICS variables can be polled regulary for updates. For different types of
* SICS variables different polling mechanisms are required. In order to cope with
* this requirement a polling interface and different drivers are defined in the
* sister module polldriv.h and polldriv.c. This module implements the interface
* to configure polling and the SICS task to run polling.
*
* Copyright: see COPYRIGHT
*
* Mark Koennecke, November-December 2006
*/
#include <stdlib.h>
#include <assert.h>
#include <sics.h>
#include <splitter.h>
#include "polldriv.h"
#include "splitter.h"
#include <sicspoll.h>
#include "lld.h"
/*================== data structure =====================================*/
static SConnection *defCon = NULL;
struct __SICSPOLL{
pObjectDescriptor pDes;
int pollList; /* list with polled objects */
int listDirty; /* a flag to set when the list has been modified. This will
cause the list polling task to go back to the start. */
SConnection *pCon; /* connection to use for polling */
int iEnd; /* flag ending this */
int nPoll; /* how many to poll in one run */
long taskID;
};
/*-----------------------------------------------------------------------*/
void killSicsPoll(void *data){
pSicsPoll self = (pSicsPoll)data;
int status;
pPollDriv poll = NULL;
self->iEnd = 1;
status = LLDnodePtr2First(self->pollList);
while(status != 0){
poll = LLDnodePtr(self->pollList);
if(poll != NULL){
deletePollDriv(poll);
}
status = LLDnodePtr2Next(self->pollList);
}
LLDdelete(self->pollList);
free(self);
if(defCon != NULL){
SCDeleteConnection(defCon);
}
}
/*----------------- list access -----------------------------------------*/
static pPollDriv locateObject(int list, char *objectIdentifier){
int status;
pPollDriv data = NULL;
status = LLDnodePtr2First(list);
while(status != 0){
data = (pPollDriv)LLDnodePtr(list);
if(data != NULL){
if(strcmp(data->objectIdentifier,objectIdentifier) == 0){
return data;
}
}
status = LLDnodePtr2Next(list);
}
return NULL;
}
/*===================== task function ==================================*/
static int incrList(int list){
int status;
if(LLDcheck(list) == LIST_EMPTY){
return 0;
}
status = LLDnodePtr2Next(list);
if(status == 0) {
status = LLDnodePtr2First(list);
}
return status;
}
/*---------------------------------------------------------------------------*/
void SicsPollSignal(void *pData, int iSignal, void *pSigData){
pSicsPoll self = NULL;
int *iInt;
self = (pSicsPoll)pData;
if(iSignal == SICSINT){
iInt = (int *)pSigData;
if(*iInt == eEndServer){
self->iEnd = 1;
}
}
}
/*----------------------------------------------------------------------*/
static int PollTask(void *data){
pSicsPoll self = (pSicsPoll) data;
pPollDriv poll = NULL;
int status, i;
time_t now = time(NULL);
if(self == NULL || self->iEnd == 1){
return 0;
}
if(LLDcheck(self->pollList) == LIST_EMPTY){
return 1;
}
/*
* increment list
*/
if(self->listDirty == 1){
self->listDirty = 0;
status = LLDnodePtr2First(self->pollList);
}
/*
* actually do poll
*/
for(i = 0; i < self->nPoll; i++){
status = incrList(self->pollList);
poll = (pPollDriv)LLDnodePtr(self->pollList);
if(status != 0 && poll != NULL){
if(poll->isDue(poll,now,self->pCon)){
poll->poll(poll,self->pCon);
}
}
}
return 1;
}
/*==================== interface functions ==============================*/
int removePollObject(pSicsPoll self, char *objectIdentifier){
pPollDriv target = NULL;
self->listDirty = 1;
target = locateObject(self->pollList, objectIdentifier);
if(target != NULL){
LLDnodeDelete(self->pollList);
deletePollDriv(target);
return 1;
} else{
return 0;
}
}
/*------------------------------------------------------------------------*/
int addPollObject(SicsPoll *self, SConnection *pCon, char *objectIdentifier,
char *driver, int argc, char *argv[]){
int status;
pPollDriv driv = NULL;
driv = makePollDriver(pCon, driver,objectIdentifier,
argc,argv);
if(driv == NULL){
return 0;
}
LLDnodeAppend(self->pollList,&driv);
return 1;
}
/*-----------------------------------------------------------------------*/
static void printPollList(pSicsPoll self, SConnection *pCon){
int status;
pPollDriv driv = NULL;
char buffer[512];
status = LLDnodePtr2First(self->pollList);
while(status != 0){
driv = (pPollDriv)LLDnodePtr(self->pollList);
if(driv != NULL){
snprintf(buffer,512,"%60s %3d",
driv->objectIdentifier, driv->pollIntervall);
SCWrite(pCon,buffer,eValue);
}
status = LLDnodePtr2Next(self->pollList);
}
}
/*================== interpreter interface ===============================*/
int SICSPollWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
int argc, char *argv[]){
pSicsPoll self = (pSicsPoll)pData;
pPollDriv driv = NULL;
int status, iVal;
char buffer[512];
pDynString txt = NULL;
assert(self != NULL);
if(argc < 2){
SCWrite(pCon,"ERROR: Not enough arguments",eError);
return 0;
}
strtolower(argv[1]);
if(strcmp(argv[1],"del") == 0) {
if(argc < 3){
SCWrite(pCon,"ERROR: Not enough arguments",eError);
return 0;
}
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
status = removePollObject(self,argv[2]);
if(status == 0) {
SCWrite(pCon,"ERROR: object to remove from poll list not found",eError);
return 0;
} else {
SCSendOK(pCon);
return 1;
}
} else if(strcmp(argv[1],"add") == 0) {
if(argc < 4){
SCWrite(pCon,"ERROR: Not enough arguments",eError);
return 0;
}
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
driv = makePollDriver(pCon,argv[3], argv[2],
argc-3, &argv[4]);
if(driv != NULL){
LLDnodeAppend(self->pollList,&driv);
SCSendOK(pCon);
return 1;
} else {
return 0;
}
} else if (strcmp(argv[1],"npoll") == 0) {
if(argc < 3) {
snprintf(buffer,512,"%s.%s = %d", argv[0], "npoll", self->nPoll);
} else {
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
status = sscanf(argv[2],"%d",&self->nPoll);
if(status != 1) {
snprintf(buffer,512,"ERROR: failed to convert %s to int",argv[2]);
SCWrite(pCon,buffer,eError);
return 0;
} else {
SCSendOK(pCon);
return 1;
}
}
} else if (strcmp(argv[1],"listen") == 0) {
self->pCon = pCon;
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1],"unlisten") == 0) {
self->pCon = defCon;
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1],"intervall") == 0){
if(argc < 3){
SCWrite(pCon,"ERROR: Not enough arguments",eError);
return 0;
}
if(!SCMatchRights(pCon,usMugger)){
return 0;
}
driv = locateObject(self->pollList,argv[2]);
if(driv == NULL){
SCWrite(pCon,"ERROR: object not in polling list",eError);
return 0;
}
if(argc > 3){
status = sscanf(argv[3],"%d", &iVal);
if(status != 1){
snprintf(buffer,511,"ERROR: failed to convert %s to int",
argv[3]);
SCWrite(pCon,buffer,eError);
return 0;
}
if(iVal < 0) {
SCWrite(pCon,"ERROR: new value for intervall out of range",eError);
return 0;
}
driv->pollIntervall = iVal;
SCSendOK(pCon);
return 1;
} else {
snprintf(buffer,511,"%s.intervall = %d",driv->objectIdentifier,
driv->pollIntervall);
SCWrite(pCon,buffer,eValue);
return 1;
}
} else if (strcmp(argv[1],"list") == 0) {
SCStartBuffering(pCon);
printPollList(self,pCon);
txt = SCEndBuffering(pCon);
if(txt != NULL){
SCWrite(pCon,GetCharArray(txt),eValue);
}
return 1;
} else if (strcmp(argv[1],"poll") == 0) {
if(argc < 3){
SCWrite(pCon,"ERROR: Not enough arguments",eError);
return 0;
}
driv = locateObject(self->pollList,argv[2]);
if(driv == NULL){
SCWrite(pCon,"ERROR: object not in polling list",eError);
return 0;
}
status = driv->poll(driv,pCon);
if(status != 1){
SCWrite(pCon,"ERROR: polling object",eError);
return 0;
}
SCWrite(pCon,"Object polled OK",eError);
return 1;
}
return 1;
}
/*------------------------------------------------------------------------*/
int InstallSICSPoll(SConnection *pCon,SicsInterp *pSics, void *pData,
int argc, char *argv[]){
pSicsPoll pNew = NULL;
pNew = malloc(sizeof(SicsPoll));
if(pNew == NULL){
return 0;
}
memset(pNew,0,sizeof(SicsPoll));
pNew->pDes = CreateDescriptor("SicsPoll");
pNew->pollList = LLDcreate(sizeof(void *));
defCon = SCCreateDummyConnection(pSics);
if(pNew->pDes == NULL|| pNew->pollList < 0 || defCon == NULL){
SCWrite(pCon,"ERROR: out of memory creating SicsPoll",eError);
return 0;
}
pNew->pCon = defCon;
pNew->nPoll = 3;
TaskRegister(pServ->pTasker,PollTask,SicsPollSignal,NULL,pNew, 10);
if(argc > 1){
AddCommand(pSics,argv[1],SICSPollWrapper,
killSicsPoll,pNew);
} else {
AddCommand(pSics,"sicspoll",SICSPollWrapper,
killSicsPoll,pNew);
}
return 1;
}

53
sicspoll.h Normal file
View File

@ -0,0 +1,53 @@
/**
* This is a generalized polling module for SICS. With this module
* SICS variables can be polled regulary for updates. For different types of
* SICS variables different polling mechanisms are required. In order to cope with
* this requirement a polling interface and different drivers are defined in the
* sister module polldriv.h and polldriv.c. This module implements the interface
* to configure polling and the SICS task to run polling.
*
* Copyright: see COPYRIGHT
*
* Mark Koennecke, November-December 2006
*/
#ifndef SICSPOLL_H_
#define SICSPOLL_H_
/*=================== interpreter interface ================================*/
/**
* the factory function
*/
int InstallSICSPoll(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
/*
* the actual wrapper which allows to configure and query the polling
* module
*/
int SICSPollWrapper(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]);
/*================== Internal Interface ===================================*/
typedef struct __SICSPOLL SicsPoll, *pSicsPoll;
/**
* add an object to the list of pollable objects.
* @param self A pointer to a sicsPoll object managing the poll loop.
* @param pCon a connection to report errors to
* @param objectidentifier A string describing the object to poll.
* This parameter will be used by the poll driver to locate the
* pollable obejct.
* @param The driver to use for polling
* @param argc The number of additional parameters to pass to the
* poll driver
* @param argv[] The parameters to pass to the poll driver.
* @return 1 on success or a negative error code when things go wrong.
*/
int addPollObject(SicsPoll *self, SConnection *pCon, char *objectIdentifier,
char *driver, int argc, char *argv[]);
/**
* remove an object from the polling loop.
* @param self A pointer to a sicsPoll object managing the poll loop.
* @param objectIdentifier The identifier of the object to remove from
* the poll loop.
* @return 1 on success, a negative error code on failure.
*/
int removePollObject(SicsPoll *self, char *objectIdentifier);
#endif /*SICSPOLL_H_*/

306
sicspoll.tc Normal file
View File

@ -0,0 +1,306 @@
/**
* This is a generalized polling module for SICS. With this module
* SICS variables can be polled regulary for updates. For different types of
* SICS variables different polling mechanisms are required. In order to cope with
* this requirement a polling interface and different drivers are defined in the
* sister module polldriv.h and polldriv.c. This module implements the interface
* to configure polling and the SICS task to run polling.
*
* Copyright: see COPYRIGHT
*
* Mark Koennecke, November-December 2006
*/
<%! source sicstemplates.tcl %>
<% stdIncludes %>
#include "polldriv.h"
#include "splitter.h"
#include <sicspoll.h>
#include "lld.h"
/*================== data structure =====================================*/
static SConnection *defCon = NULL;
struct __SICSPOLL{
pObjectDescriptor pDes;
int pollList; /* list with polled objects */
int listDirty; /* a flag to set when the list has been modified. This will
cause the list polling task to go back to the start. */
SConnection *pCon; /* connection to use for polling */
int iEnd; /* flag ending this */
int nPoll; /* how many to poll in one run */
long taskID;
};
/*-----------------------------------------------------------------------*/
void killSicsPoll(void *data){
pSicsPoll self = (pSicsPoll)data;
int status;
pPollDriv poll = NULL;
self->iEnd = 1;
status = LLDnodePtr2First(self->pollList);
while(status != 0){
poll = LLDnodePtr(self->pollList);
if(poll != NULL){
deletePollDriv(poll);
}
status = LLDnodePtr2Next(self->pollList);
}
LLDdelete(self->pollList);
free(self);
if(defCon != NULL){
SCDeleteConnection(defCon);
}
}
/*----------------- list access -----------------------------------------*/
static pPollDriv locateObject(int list, char *objectIdentifier){
int status;
pPollDriv data = NULL;
status = LLDnodePtr2First(list);
while(status != 0){
data = (pPollDriv)LLDnodePtr(list);
if(data != NULL){
if(strcmp(data->objectIdentifier,objectIdentifier) == 0){
return data;
}
}
status = LLDnodePtr2Next(list);
}
return NULL;
}
/*===================== task function ==================================*/
static int incrList(int list){
int status;
if(LLDcheck(list) == LIST_EMPTY){
return 0;
}
status = LLDnodePtr2Next(list);
if(status == 0) {
status = LLDnodePtr2First(list);
}
return status;
}
/*---------------------------------------------------------------------------*/
void SicsPollSignal(void *pData, int iSignal, void *pSigData){
pSicsPoll self = NULL;
int *iInt;
self = (pSicsPoll)pData;
if(iSignal == SICSINT){
iInt = (int *)pSigData;
if(*iInt == eEndServer){
self->iEnd = 1;
}
}
}
/*----------------------------------------------------------------------*/
static int PollTask(void *data){
pSicsPoll self = (pSicsPoll) data;
pPollDriv poll = NULL;
int status, i;
time_t now = time(NULL);
if(self == NULL || self->iEnd == 1){
return 0;
}
if(LLDcheck(self->pollList) == LIST_EMPTY){
return 1;
}
/*
* increment list
*/
if(self->listDirty == 1){
self->listDirty = 0;
status = LLDnodePtr2First(self->pollList);
}
/*
* actually do poll
*/
for(i = 0; i < self->nPoll; i++){
status = incrList(self->pollList);
poll = (pPollDriv)LLDnodePtr(self->pollList);
if(status != 0 && poll != NULL){
if(poll->isDue(poll,now,self->pCon)){
poll->poll(poll,self->pCon);
}
}
}
return 1;
}
/*==================== interface functions ==============================*/
int removePollObject(pSicsPoll self, char *objectIdentifier){
pPollDriv target = NULL;
self->listDirty = 1;
target = locateObject(self->pollList, objectIdentifier);
if(target != NULL){
LLDnodeDelete(self->pollList);
deletePollDriv(target);
return 1;
} else{
return 0;
}
}
/*------------------------------------------------------------------------*/
int addPollObject(SicsPoll *self, SConnection *pCon, char *objectIdentifier,
char *driver, int argc, char *argv[]){
int status;
pPollDriv driv = NULL;
driv = makePollDriver(pCon, driver,objectIdentifier,
argc,argv);
if(driv == NULL){
return 0;
}
LLDnodeAppend(self->pollList,&driv);
return 1;
}
/*-----------------------------------------------------------------------*/
static void printPollList(pSicsPoll self, SConnection *pCon){
int status;
pPollDriv driv = NULL;
char buffer[512];
status = LLDnodePtr2First(self->pollList);
while(status != 0){
driv = (pPollDriv)LLDnodePtr(self->pollList);
if(driv != NULL){
snprintf(buffer,512,"%60s %3d",
driv->objectIdentifier, driv->pollIntervall);
SCWrite(pCon,buffer,eValue);
}
status = LLDnodePtr2Next(self->pollList);
}
}
/*================== interpreter interface ===============================*/
<%makeSicsFunc SICSPollWrapper%>{
pSicsPoll self = (pSicsPoll)pData;
pPollDriv driv = NULL;
int status, iVal;
char buffer[512];
pDynString txt = NULL;
assert(self != NULL);
<%testNoPar 2 5%>
strtolower(argv[1]);
if(strcmp(argv[1],"del") == 0) {
<%testNoPar 3 9%>
<%testPriv usMugger 9%>
status = removePollObject(self,argv[2]);
if(status == 0) {
SCWrite(pCon,"ERROR: object to remove from poll list not found",eError);
return 0;
} else {
SCSendOK(pCon);
return 1;
}
} else if(strcmp(argv[1],"add") == 0) {
<%testNoPar 4 9%>
<%testPriv usMugger 9%>
driv = makePollDriver(pCon,argv[3], argv[2],
argc-3, &argv[4]);
if(driv != NULL){
LLDnodeAppend(self->pollList,&driv);
SCSendOK(pCon);
return 1;
} else {
return 0;
}
} else if (strcmp(argv[1],"npoll") == 0) {
<%# sicsPar name, c-name nargs priv type indent
sicsPar npoll self->nPoll 3 usMugger int 9%>
} else if (strcmp(argv[1],"listen") == 0) {
self->pCon = pCon;
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1],"unlisten") == 0) {
self->pCon = defCon;
SCSendOK(pCon);
return 1;
} else if (strcmp(argv[1],"intervall") == 0){
<%testNoPar 3 9%>
<%testPriv usMugger 9%>
driv = locateObject(self->pollList,argv[2]);
if(driv == NULL){
SCWrite(pCon,"ERROR: object not in polling list",eError);
return 0;
}
if(argc > 3){
status = sscanf(argv[3],"%d", &iVal);
if(status != 1){
snprintf(buffer,511,"ERROR: failed to convert %s to int",
argv[3]);
SCWrite(pCon,buffer,eError);
return 0;
}
if(iVal < 0) {
SCWrite(pCon,"ERROR: new value for intervall out of range",eError);
return 0;
}
driv->pollIntervall = iVal;
SCSendOK(pCon);
return 1;
} else {
snprintf(buffer,511,"%s.intervall = %d",driv->objectIdentifier,
driv->pollIntervall);
SCWrite(pCon,buffer,eValue);
return 1;
}
} else if (strcmp(argv[1],"list") == 0) {
SCStartBuffering(pCon);
printPollList(self,pCon);
txt = SCEndBuffering(pCon);
if(txt != NULL){
SCWrite(pCon,GetCharArray(txt),eValue);
}
return 1;
} else if (strcmp(argv[1],"poll") == 0) {
<%testNoPar 3 9%>
driv = locateObject(self->pollList,argv[2]);
if(driv == NULL){
SCWrite(pCon,"ERROR: object not in polling list",eError);
return 0;
}
status = driv->poll(driv,pCon);
if(status != 1){
SCWrite(pCon,"ERROR: polling object",eError);
return 0;
}
SCWrite(pCon,"Object polled OK",eError);
return 1;
}
return 1;
}
/*------------------------------------------------------------------------*/
<%makeSicsFunc InstallSICSPoll%>{
pSicsPoll pNew = NULL;
<%newStrucRet SicsPoll 5 0%>
pNew->pDes = CreateDescriptor("SicsPoll");
pNew->pollList = LLDcreate(sizeof(void *));
defCon = SCCreateDummyConnection(pSics);
if(pNew->pDes == NULL|| pNew->pollList < 0 || defCon == NULL){
SCWrite(pCon,"ERROR: out of memory creating SicsPoll",eError);
return 0;
}
pNew->pCon = defCon;
pNew->nPoll = 3;
TaskRegister(pServ->pTasker,PollTask,SicsPollSignal,NULL,pNew, 10);
if(argc > 1){
AddCommand(pSics,argv[1],SICSPollWrapper,
killSicsPoll,pNew);
} else {
AddCommand(pSics,"sicspoll",SICSPollWrapper,
killSicsPoll,pNew);
}
return 1;
}

View File

@ -479,6 +479,29 @@ char *Arg2Tcl0(int argc, char *argv[], char *buffer, int buffersize, char *prepe
char *Arg2Tcl(int argc, char *argv[], char *buffer, int buffersize) {
return Arg2Tcl0(argc, argv, buffer, buffersize, NULL);
}
/*----------------------------------------------------------------------------*/
char *sicsNextNumber(char *pStart, char pNumber[80]){
int charCount = 0;
pNumber[0] = '\0';
/* advance to first digit */
while(isspace(*pStart) && *pStart != '\0'){
pStart++;
}
if(*pStart == '\0'){
return NULL;
}
/* copy */
while(!isspace(*pStart) && *pStart != '\0' && charCount < 78){
pNumber[charCount] = *pStart;
pStart++;
charCount++;
}
pNumber[charCount] = '\0';
return pStart;
}
/*============================================================================
Testprogram, can be activated by defining MAIN

View File

@ -93,4 +93,10 @@ typedef struct _TokenEntry {
If prepend is not NULL, its contents appear untreated before the args.
A space is used as separator.
!*/
char *sicsNextNumber(char *pStart, char pNumber[80]);
/*!
This function reads the next number from the string in pStart.
The number is put into pNumber, a pointer to the string after
the number is returned or NULL whne the string is exhausted.
!*/
#endif

View File

@ -1610,9 +1610,13 @@ int TasUBWrapper(SConnection *pCon,SicsInterp *pSics, void *pData,
strtolower(argv[1]);
if(strcmp(argv[1],"mono") == 0){
return handleCrystalCommands(&self->machine.monochromator,pCon,argc,argv);
status = handleCrystalCommands(&self->machine.monochromator,pCon,argc,argv);
self->mustRecalculate = 1;
return status;
} else if(strcmp(argv[1],"ana") == 0){
return handleCrystalCommands(&self->machine.analyzer,pCon,argc,argv);
status = handleCrystalCommands(&self->machine.analyzer,pCon,argc,argv);
self->mustRecalculate = 1;
return status;
}else if(strcmp(argv[1],"cell") == 0){
if(argc > 2){
return tasReadCell(pCon,self,argc,argv);