Files
sics/sicspoll.tc
2015-07-29 17:47:46 +10:00

307 lines
9.2 KiB
Plaintext

/**
* 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, TASK_PRIO_HIGH);
if(argc > 1){
AddCommand(pSics,argv[1],SICSPollWrapper,
killSicsPoll,pNew);
} else {
AddCommand(pSics,"sicspoll",SICSPollWrapper,
killSicsPoll,pNew);
}
return 1;
}