- unified the 2 script context commands

- minor changes in hipadaba and ascon/devser
This commit is contained in:
zolliker
2008-05-30 09:29:44 +00:00
parent b03ddddd8f
commit b5b4da2776
9 changed files with 179 additions and 138 deletions

10
ascon.c
View File

@ -75,9 +75,9 @@ static void AsconError(Ascon *a, char *msg, int errorno) {
state = stateText[a->state]; state = stateText[a->state];
} }
if (errorno != 0) { if (errorno != 0) {
ErrPutMsg(&a->errList, NULL, "%s %s (during %s)", msg, strerror(errorno), state); ErrPutMsg(a->errList, "%s %s (during %s)", msg, strerror(errorno), state);
} else { } else {
ErrPutMsg(&a->errList, NULL, "%s (during %s)", msg, state); ErrPutMsg(a->errList, "%s (during %s)", msg, state);
} }
a->state |= AsconFailed; a->state |= AsconFailed;
} }
@ -400,7 +400,7 @@ Ascon *AsconMake(SConnection *con, int argc, char *argv[]) {
} }
a->rdBuffer = CreateDynString(60, 63); a->rdBuffer = CreateDynString(60, 63);
a->wrBuffer = CreateDynString(60, 63); a->wrBuffer = CreateDynString(60, 63);
a->errList.head = NULL; a->errList = NULL;
a->responseValid = 0; a->responseValid = 0;
a->timeout = 2.0; a->timeout = 2.0;
a->reconnectInterval = 10; a->reconnectInterval = 10;
@ -500,6 +500,6 @@ char *AsconRead(Ascon *a) {
return NULL; return NULL;
} }
ErrMsgList *AsconGetErrList(Ascon *a) { ErrMsg *AsconGetErrList(Ascon *a) {
return &a->errList; return a->errList;
} }

View File

@ -64,7 +64,7 @@ char *AsconRead(Ascon *a);
/** \brief get the connections error list /** \brief get the connections error list
* \return the error list * \return the error list
*/ */
ErrMsgList *AsconGetErrList(Ascon *a); ErrMsg *AsconGetErrList(Ascon *a);
/** \brief a helper function /** \brief a helper function
* \param argc the number of args * \param argc the number of args

View File

@ -64,7 +64,7 @@ struct Ascon {
int wrPos; /**< write buffer position */ int wrPos; /**< write buffer position */
double timeout; /**< read timeout (sec) */ double timeout; /**< read timeout (sec) */
char *hostport; /**< host:port to connect */ char *hostport; /**< host:port to connect */
ErrMsgList errList; /**< error message list */ ErrMsg *errList; /**< error message list */
double start; /**< unix time when read was started */ double start; /**< unix time when read was started */
void *private; /**< private data of protocol */ void *private; /**< private data of protocol */
int noResponse; /**< no response expected */ int noResponse; /**< no response expected */

View File

@ -117,7 +117,8 @@ int DevQueueTask(void *ds) {
while (action != NULL) { while (action != NULL) {
status = AsconTask(devser->asyncConn); status = AsconTask(devser->asyncConn);
if (status == AsconFailure) { if (status == AsconFailure) {
/* TODO: error handling */ devser->errmsg = AsconGetErrList(devser->asyncConn);
return 1;
} else if (status != AsconReady) { } else if (status != AsconReady) {
return 1; return 1;
} }

View File

@ -4,13 +4,30 @@
#include <string.h> #include <string.h>
#include "errormsg.h" #include "errormsg.h"
/* ErrMsgList implementation */ /* compare two strings for euqality, ignoring text within square brackets */
#define MC_NAME(T) ErrMsg##T int ErrEqual(char *str1, char *str2) {
#define MC_IMPLEMENTATION char *p;
#include "mclist.c"
ErrMsg *ErrPutMsg(ErrMsgList *dump, char *data, char *fmt, ...) { while (*str1 != '\0' || *str2 != '\0') {
ErrMsg *m, *p; if (*str1 != *str2) {
return 0;
}
if (*str1 == '[') {
str1 = strchr(str1, ']');
str2 = strchr(str2, ']');
if (str1 == NULL || str2 == NULL) {
return str1 == str2;
}
str1++;
str2++;
}
}
return 1;
}
ErrMsg *ErrPutMsg(ErrMsg *dump, char *fmt, ...) {
ErrMsg *m;
ErrMsg **last;
va_list ap; va_list ap;
char buf[256]; char buf[256];
char *text; char *text;
@ -28,36 +45,23 @@ ErrMsg *ErrPutMsg(ErrMsgList *dump, char *data, char *fmt, ...) {
vsnprintf(text, l, fmt, ap); vsnprintf(text, l, fmt, ap);
va_end(ap); va_end(ap);
} }
for (last = &dump; *last != NULL; last = &m->next) {
m = NULL; m = *last;
for (p = ErrMsgFirst(dump); p!= NULL; p = ErrMsgNext(dump)) { if (ErrEqual(text, m->text)) {
if (strcmp(text, p->text) == 0) { *last = m->next;
m = ErrMsgTake(dump);
break; break;
} }
} }
if (m == NULL) { if (m == NULL) {
if (text == buf) text = strdup(buf);
m = calloc(1, sizeof(*m)); m = calloc(1, sizeof(*m));
if (text == buf) { m->text = text;
m->text = strdup(text);
} else {
m->text = text;
}
m->data = NULL;
m->cnt = 1; m->cnt = 1;
} else { } else {
if (text != buf) free(text); if (text != buf) free(text);
m->cnt++; m->cnt++;
} }
if (m->data) { m->next = dump;
free(m->data);
m->data = NULL;
}
if (data) {
m->data = strdup(data);
}
ErrMsgFirst(dump);
ErrMsgInsert(dump, m);
time(&m->last); time(&m->last);
return m; return m;
} }

View File

@ -11,20 +11,22 @@
typedef struct ErrMsg { typedef struct ErrMsg {
struct ErrMsg *next; struct ErrMsg *next;
char *text; /**< the message text */ char *text; /**< the message text */
char *data; /**< additional text which may be different for the same message */ char *cmpr; /**< compressed message text */
int cnt; /**< count */ int cnt; /**< count */
time_t last; /**< time of last message */ time_t last; /**< time of last message */
} ErrMsg; } ErrMsg;
/* define type ErrMsgList and functions ErrMsgAdd etc. */
#define MC_NAME(T) ErrMsg##T
#include "mclist.h"
/** \brief Put a formatted message to the error message list /** \brief Put a formatted message to the error message list
*
* The error message list contains only one entry for all messages
* with the same text, storing only the count and the last used time.
* Characters within sqaure brackets are not taken into account
* when comparing messages.
*
* \param dump the error message list * \param dump the error message list
* \param data some additional text (may be NULL)
* \param fmt the format for the message * \param fmt the format for the message
* \return the new error message list head
*/ */
ErrMsg *ErrPutMsg(ErrMsgList *dump, char *data, char *fmt, ...); ErrMsg *ErrPutMsg(ErrMsg *dump, char *fmt, ...);
#endif #endif

View File

@ -914,7 +914,9 @@ static int calcDataLength(pHdb node, int testLength){
/*============================= Property Functions ==========================*/ /*============================= Property Functions ==========================*/
void SetHdbProperty(pHdb node, char *key, char *value){ void SetHdbProperty(pHdb node, char *key, char *value){
if(node != NULL && key != NULL && node->properties != NULL){ if(node != NULL && key != NULL && node->properties != NULL){
if(StringDictExists(node->properties, key)){ if (value == NULL) {
StringDictDelete(node->properties, key);
} else if(StringDictExists(node->properties, key)){
StringDictUpdate(node->properties,key,value); StringDictUpdate(node->properties,key,value);
} else { } else {
StringDictAddPair(node->properties,key,value); StringDictAddPair(node->properties,key,value);

View File

@ -17,16 +17,19 @@
#define MAX_HDB_PATH 1024 #define MAX_HDB_PATH 1024
typedef struct ContextItem {
struct ContextItem *next;
Hdb *node;
Hdb *controllerNode;
} ContextItem;
typedef struct ScriptContext { typedef struct ScriptContext {
ObjectDescriptor *desc; ObjectDescriptor *desc;
Hdb *node; ContextItem *nodes;
ContextItem *trash;
ContextItem *base;
} ScriptContext; } ScriptContext;
typedef struct ContextStack {
struct ContextStack *next;
Hdb *node;
} ContextStack;
typedef struct SctController { typedef struct SctController {
DevSer *devser; DevSer *devser;
Hdb *node; /* the controller node */ Hdb *node; /* the controller node */
@ -43,9 +46,7 @@ typedef struct SctData {
Hdb *node; /* back link used by SctMatchWrite/SctMatchPoll */ Hdb *node; /* back link used by SctMatchWrite/SctMatchPoll */
} SctData; } SctData;
static ScriptContext *nctx = NULL; /* the node context */ static ScriptContext *sct = NULL;
static ScriptContext *cctx = NULL; /* the controller context */
static ContextStack *stack, *stackTrash;
static SCStore *currentCon = NULL; static SCStore *currentCon = NULL;
static struct { static struct {
@ -54,31 +55,60 @@ static struct {
static char *mainCallback = "main callback"; static char *mainCallback = "main callback";
void PushContext(Hdb *node) { void PushContext(Hdb *node, Hdb *controllerNode) {
ContextStack *new; ContextItem *new;
if (stackTrash == NULL) { if (sct->trash == NULL) {
new = calloc(1, sizeof(*new)); new = calloc(1, sizeof(*new));
} else { } else {
new = stackTrash; new = sct->trash;
stackTrash = stackTrash->next; sct->trash = sct->trash->next;
} }
new->next = stack; new->next = sct->nodes;
sct->nodes = new;
new->node = node; new->node = node;
stack = new; new->controllerNode = controllerNode;
} }
Hdb *PopContext(void) { void PopContext(void) {
ContextStack *c; ContextItem *c;
c = stack; c = sct->nodes;
stack = stack->next; assert(c);
c->next = stackTrash; sct->nodes = c->next;
stackTrash = c; c->next = sct->trash;
return c->node; sct->trash = c;
} }
static void SetProp(Hdb *node, char *key, char *value) { void CleanStack(Hdb *node) {
ContextItem *s;
/* clean context from killed nodes */
for (s = sct->nodes; s != NULL; s = s->next) {
if (s->node == node) {
s->node = NULL;
}
if (s->controllerNode == node) {
s->controllerNode = NULL;
}
}
}
static void SetProp(Hdb *node, Hdb *cNode, char *key, char *value) {
char *val;
if (node == NULL) {
if (cNode == NULL) return;
node = cNode;
} else {
val = GetHdbProp(node, key);
if (val == NULL && cNode != NULL) {
val = GetHdbProp(cNode, key);
if (val != NULL) {
node = cNode;
}
}
}
if (value == NULL) { if (value == NULL) {
if (GetHdbProperty(node, key, NULL, 0) > 0) { if (GetHdbProperty(node, key, NULL, 0) > 0) {
SetHdbProperty(node, key, ""); SetHdbProperty(node, key, "");
@ -88,14 +118,28 @@ static void SetProp(Hdb *node, char *key, char *value) {
} }
} }
static char *GetProp(Hdb *node, Hdb *cNode, char *key) {
char *val;
if (node != NULL) {
val = GetHdbProp(node, key);
if (val != NULL) return val;
}
if (cNode != NULL) {
val = GetHdbProp(node, key);
}
return val;
}
int SctCommand(SConnection *con, SicsInterp *sics, void *object, int SctCommand(SConnection *con, SicsInterp *sics, void *object,
int argc, char *argv[]) { int argc, char *argv[]) {
ScriptContext *ctx = object;
static char value[1024]; static char value[1024];
char *val; char *val;
Hdb *node = ctx->node; Hdb *node = sct->nodes->node;
Hdb *cNode = sct->nodes->controllerNode;
if (node == NULL) { assert(sct == object);
if (node == NULL && cNode == NULL) {
SCPrintf(con, eError, "ERROR: %s may be called only in proper context", SCPrintf(con, eError, "ERROR: %s may be called only in proper context",
argv[0]); argv[0]);
return 0; return 0;
@ -106,7 +150,7 @@ int SctCommand(SConnection *con, SicsInterp *sics, void *object,
return 1; return 1;
} }
if (argc == 2) { /* get case */ if (argc == 2) { /* get case */
val = GetHdbProp(node, argv[1]); val = GetProp(node, cNode, argv[1]);
if (val == NULL) { if (val == NULL) {
SCPrintf(con, eError, "ERROR: %s %s not found", argv[0], argv[1]); SCPrintf(con, eError, "ERROR: %s %s not found", argv[0], argv[1]);
return 0; return 0;
@ -114,10 +158,8 @@ int SctCommand(SConnection *con, SicsInterp *sics, void *object,
SCWrite(con, val, eValue); SCWrite(con, val, eValue);
} else { /* set case */ } else { /* set case */
val = Arg2Tcl(argc-2, argv+2, value, sizeof value); val = Arg2Tcl(argc-2, argv+2, value, sizeof value);
if (val != NULL) { SetProp(node, cNode, argv[1], val);
SetHdbProperty(node, argv[1], val); if (val != NULL && val != value) free(val);
if (val != value) free(val);
}
} }
return 1; return 1;
} }
@ -130,10 +172,7 @@ int SctCallInContext(SConnection *con, char *script, Hdb *node,
int iRet = 1; int iRet = 1;
int verbose = controller->verbose; int verbose = controller->verbose;
PushContext(nctx->node); PushContext(node, controller->node);
PushContext(cctx->node);
nctx->node = node;
cctx->node = controller->node;
if (verbose) { if (verbose) {
SCPrintf(con, eInError, "\nscript: %s\n", script); SCPrintf(con, eInError, "\nscript: %s\n", script);
} }
@ -149,32 +188,11 @@ int SctCallInContext(SConnection *con, char *script, Hdb *node,
} }
*resPtr = result; *resPtr = result;
cctx->node = PopContext(); PopContext();
nctx->node = PopContext(); PopContext();
return iRet; return iRet;
} }
void SctKill(void *object) {
ScriptContext *ctx = object;
if (ctx == nctx) nctx = NULL;
if (ctx == cctx) cctx = NULL;
if (ctx->desc != NULL) {
DeleteDescriptor(ctx->desc);
}
free(object);
}
ScriptContext *SctMake(char *name) {
ScriptContext *ctx;
ctx = calloc(1, sizeof(*ctx));
assert(ctx);
ctx->desc = CreateDescriptor("ScriptContext");
ctx->node = NULL;
AddCommand(pServ->pSics, name, SctCommand, SctKill, ctx);
return ctx;
}
static int SctMatch(void *data1, void *data2) { static int SctMatch(void *data1, void *data2) {
SctData *a = data1; SctData *a = data1;
SctData *b = data2; SctData *b = data2;
@ -198,18 +216,18 @@ static char *SctActionHandler(void *actionData, char *lastReply) {
} else { } else {
con = SCStorePush(controller->conn); con = SCStorePush(controller->conn);
} }
SetProp(controller->node, "result", lastReply); SetProp(node, controller->node, "result", lastReply);
if (controller->verbose && lastReply != NULL && *lastReply != '\0') { if (controller->verbose && lastReply != NULL && *lastReply != '\0') {
SCPrintf(con, eWarning, "reply : %s", lastReply); SCPrintf(con, eWarning, "reply : %s", lastReply);
} }
state = GetHdbProp(controller->node, "state"); state = GetProp(node, controller->node, "state");
if (state == NULL || state[0] == '\0') { if (state == NULL || strcasecmp(state, "idle") == 0) {
state = data->name; state = data->name;
SetProp(controller->node, "state", state); SetProp(node, controller->node, "state", state);
} }
for (i = 0; i < 10; i++) { for (i = 0; i < 10; i++) {
SetProp(controller->node, "send", NULL); SetProp(node, controller->node, "send", NULL);
script = GetHdbProp(node, state); script = GetProp(node, controller->node, state);
if (script == NULL) script = state; if (script == NULL) script = state;
if (! SctCallInContext(con, script, node, data->controller, &result)) { if (! SctCallInContext(con, script, node, data->controller, &result)) {
@ -227,8 +245,8 @@ static char *SctActionHandler(void *actionData, char *lastReply) {
} }
goto finish; goto finish;
} }
SetProp(controller->node, "state", state); SetProp(node, controller->node, "state", state);
send = GetHdbProp(controller->node, "send"); send = GetProp(node, controller->node, "send");
if (send != NULL && send[0] != '\0') { if (send != NULL && send[0] != '\0') {
if (controller->verbose) { if (controller->verbose) {
SCPrintf(con, eWarning, "send : %s", send); SCPrintf(con, eWarning, "send : %s", send);
@ -238,7 +256,7 @@ static char *SctActionHandler(void *actionData, char *lastReply) {
} }
SCPrintf(con, eError, "ERROR: too many quick scripts chained"); SCPrintf(con, eError, "ERROR: too many quick scripts chained");
finish: finish:
SetProp(controller->node, "state", ""); SetProp(node, controller->node, "state", "idle");
quit: quit:
if (currentCon) { if (currentCon) {
SCStorePop(currentCon); SCStorePop(currentCon);
@ -267,7 +285,7 @@ static hdbCallbackReturn SctMainCallback(Hdb *node, void *userData,
hdbDataMessage *mm; hdbDataMessage *mm;
hdbPtrMessage *pm; hdbPtrMessage *pm;
hdbMessage *km; hdbMessage *km;
ContextStack *s; ContextItem *s;
SConnection *con; SConnection *con;
char *geterror; char *geterror;
@ -288,14 +306,7 @@ static hdbCallbackReturn SctMainCallback(Hdb *node, void *userData,
} }
km = GetHdbKillNodeMessage(msg); km = GetHdbKillNodeMessage(msg);
if (km != NULL) { if (km != NULL) {
/* clean context from killed nodes */ CleanStack(node);
for (s = stack; s != NULL; s = s->next) {
if (s->node == node) {
s->node = NULL;
}
}
if (cctx->node == node) cctx->node = NULL;
if (nctx->node == node) nctx->node = NULL;
return hdbContinue; return hdbContinue;
} }
mm = GetHdbGetMessage(msg); mm = GetHdbGetMessage(msg);
@ -353,7 +364,7 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData,
con = mm->callData; con = mm->callData;
/* call check script, if available */ /* call check script, if available */
script = GetHdbProp(node, "check"); script = GetProp(node, data->controller->node, "check");
if (script != NULL) { if (script != NULL) {
if (SctCallInContext(con, script, node, data->controller, &error) == 0) { if (SctCallInContext(con, script, node, data->controller, &error) == 0) {
SCPrintf(con, eError, "ERROR: %s", error); SCPrintf(con, eError, "ERROR: %s", error);
@ -366,7 +377,7 @@ static hdbCallbackReturn SctActionCallback(Hdb *node, void *userData,
SetHdbProperty(node, "target", GetCharArray(text)); SetHdbProperty(node, "target", GetCharArray(text));
/* enqueue write action */ /* enqueue write action */
writeprio = GetHdbProp(node, "writeprio"); writeprio = GetProp(node, data->controller->node, "writeprio");
if (writeprio != NULL) { if (writeprio != NULL) {
prio = DevText2Prio(writeprio); prio = DevText2Prio(writeprio);
if (prio < 0) prio = WritePRIO; if (prio < 0) prio = WritePRIO;
@ -492,9 +503,7 @@ static int SctPollCmd(pSICSOBJ ccmd, SConnection *con,
SctAddPollNode(controller, node, interval, prio, action); SctAddPollNode(controller, node, interval, prio, action);
if (stack == NULL) { sct->base->node = node;
nctx->node = node;
}
return 1; return 1;
} }
@ -555,9 +564,7 @@ static int SctWriteCmd(pSICSOBJ ccmd, SConnection *con,
return 0; return 0;
} }
if (stack == NULL) { sct->base->node = node;
nctx->node = node;
}
return 1; return 1;
} }
@ -642,6 +649,7 @@ static hdbCallbackReturn SctDebugCallback(Hdb *node, void *userData,
static void SctKillController(void *c) { static void SctKillController(void *c) {
SctController *controller = c; SctController *controller = c;
CleanStack(controller->node);
RemoveSICSInternalCallback(controller); RemoveSICSInternalCallback(controller);
DevKill(controller->devser); DevKill(controller->devser);
} }
@ -680,8 +688,6 @@ static int SctMakeController(SConnection *con, SicsInterp *sics,
AddCommand(pServ->pSics, nodeName, InvokeSICSOBJ, KillSICSOBJ, ccmd); AddCommand(pServ->pSics, nodeName, InvokeSICSOBJ, KillSICSOBJ, ccmd);
SetDescriptorKey(ccmd->pDes, "creationCommand", "0"); SetDescriptorKey(ccmd->pDes, "creationCommand", "0");
SetProp(controller->node, "state", "");
AddHipadabaChild(parent, controller->node, con); AddHipadabaChild(parent, controller->node, con);
controller->devser = DevMake(con, argc - 2, argv + 2); controller->devser = DevMake(con, argc - 2, argv + 2);
@ -710,16 +716,38 @@ static int SctMakeController(SConnection *con, SicsInterp *sics,
cb = MakeHipadabaCallback(SctDebugCallback, controller, NULL); cb = MakeHipadabaCallback(SctDebugCallback, controller, NULL);
if (cb) AppendHipadabaCallback(par, cb); if (cb) AppendHipadabaCallback(par, cb);
if (stack == NULL) { sct->base->controllerNode = controller->node;
cctx->node = controller->node; sct->base->node = NULL;
nctx->node = NULL;
}
return 1; return 1;
} }
void SctKill(void *object) {
assert(sct == object);
ContextItem *p, *q;
for (p = sct->nodes; p != NULL; p = q) {
q = p->next;
free(p);
}
for (p = sct->trash; p != NULL; p = q) {
q = p->next;
free(p);
}
if (sct->desc != NULL) {
DeleteDescriptor(sct->desc);
}
free(sct);
sct = NULL;
}
void SctInit(void) { void SctInit(void) {
nctx = SctMake("nctx"); if (sct) return;
cctx = SctMake("cctx"); sct = calloc(1, sizeof(*sct));
assert(sct);
sct->desc = CreateDescriptor("ScriptContext");
PushContext(NULL, NULL);
sct->base = sct->nodes;
AddCommand(pServ->pSics, "sct", SctCommand, SctKill, sct);
AddCmd("makesctcontroller", SctMakeController); AddCmd("makesctcontroller", SctMakeController);
} }

View File

@ -2932,6 +2932,7 @@ static int SetSICSHdbProperty(SConnection *pCon, SicsInterp *pSics, void *pData,
int argc, char *argv[]){ int argc, char *argv[]){
pHdb targetNode = NULL; pHdb targetNode = NULL;
char buffer[512]; char buffer[512];
char *val;
if(argc < 4) { if(argc < 4) {
SCWrite(pCon,"ERROR: need path key value as parameters",eError); SCWrite(pCon,"ERROR: need path key value as parameters",eError);
@ -2942,8 +2943,11 @@ static int SetSICSHdbProperty(SConnection *pCon, SicsInterp *pSics, void *pData,
SCWrite(pCon,"ERROR: node not found",eError); SCWrite(pCon,"ERROR: node not found",eError);
return 0; return 0;
} }
Arg2Tcl(argc-3, &argv[3], buffer,512); val = Arg2Tcl(argc-3, &argv[3], buffer, sizeof buffer);
SetHdbProperty(targetNode,argv[2], buffer); if (val) {
SetHdbProperty(targetNode,argv[2], val);
if (val != buffer) free(val);
}
SCSendOK(pCon); SCSendOK(pCon);
return 1; return 1;
} }