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