- allow scriptcontext objects to be dynamic
- enhancements in scriptcontext (error messages stored as properties)
This commit is contained in:
188
scriptcontext.c
188
scriptcontext.c
@@ -47,7 +47,7 @@ typedef struct SctData {
|
||||
} SctData;
|
||||
|
||||
static ScriptContext *sct = NULL;
|
||||
static SConnection *currentCon = NULL;
|
||||
static SctData *queueData = NULL;
|
||||
|
||||
static struct {
|
||||
char *name;
|
||||
@@ -179,6 +179,7 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
||||
return 0;
|
||||
}
|
||||
UpdateHipadabaPar(node, v, con);
|
||||
ReleaseHdbValue(&v);
|
||||
SetHdbProperty(node, "geterror", NULL);
|
||||
return 1;
|
||||
}
|
||||
@@ -187,6 +188,9 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
||||
* print
|
||||
*/
|
||||
if (strcmp(argv[1], "print") == 0) {
|
||||
if (queueData != NULL) {
|
||||
queueData->answered = 1;
|
||||
}
|
||||
Arg2Text(argc - 2, argv + 2, value, sizeof value);
|
||||
SCWrite(con, value, eLog);
|
||||
return 1;
|
||||
@@ -201,7 +205,7 @@ int SctCommand(SConnection * con, SicsInterp * sics, void *object,
|
||||
}
|
||||
|
||||
/*
|
||||
* time stamping
|
||||
* time stamping (obsolete ? -> see SctActionHandler: timeKey, timeVal)
|
||||
*/
|
||||
if (strcmp(argv[1], "utime") == 0) {
|
||||
if (argc < 3) {
|
||||
@@ -248,7 +252,7 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
||||
|
||||
PushContext(node, controller->node);
|
||||
if (verbose) {
|
||||
SCPrintf(con, eLog, "\nscript: %s\n", script);
|
||||
SCPrintf(con, eLog, "script: %s", script);
|
||||
}
|
||||
|
||||
MacroPush(con);
|
||||
@@ -257,7 +261,7 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
||||
result = (char *) Tcl_GetStringResult(pTcl);
|
||||
if (ret != TCL_OK && result[0] != '\0') {
|
||||
if (verbose) {
|
||||
SCPrintf(con, eLog, "\nerror: %s\n", result);
|
||||
SCPrintf(con, eLog, "error: %s", result);
|
||||
}
|
||||
iRet = 0;
|
||||
}
|
||||
@@ -276,26 +280,38 @@ static int SctMatch(void *data1, void *data2)
|
||||
return a->node == b->node && strcasecmp(a->name, b->name) == 0;
|
||||
}
|
||||
|
||||
static char *SctActionHandler(void *actionData, char *lastReply)
|
||||
static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
int commError)
|
||||
{
|
||||
SctData *data = actionData;
|
||||
Hdb *node = data->node;
|
||||
SctController *controller = data->controller;
|
||||
char *state;
|
||||
char *result;
|
||||
char *script;
|
||||
char *script = NULL;
|
||||
char *errorScript = NULL;
|
||||
char *send = NULL;
|
||||
int i;
|
||||
SConnection *con;
|
||||
char eprop[80];
|
||||
char msg[1024];
|
||||
char path[1024];
|
||||
char origScript[80];
|
||||
char *blank;
|
||||
char *emsg;
|
||||
size_t l;
|
||||
int cnt;
|
||||
char timeKey[50], timeVal[50];
|
||||
|
||||
if (currentCon) {
|
||||
con = currentCon;
|
||||
if (queueData != NULL && queueData->conCtx != NULL) {
|
||||
con = queueData->conCtx;
|
||||
} else {
|
||||
con = controller->conn;
|
||||
}
|
||||
SetProp(node, controller->node, "result", lastReply);
|
||||
if (controller->verbose && lastReply != NULL && *lastReply != '\0') {
|
||||
script = NULL;
|
||||
if (!commError && controller->verbose && lastReply != NULL
|
||||
&& *lastReply != '\0') {
|
||||
SCPrintf(con, eLog, "reply : %s", lastReply);
|
||||
}
|
||||
state = GetProp(node, controller->node, "state");
|
||||
@@ -304,29 +320,75 @@ static char *SctActionHandler(void *actionData, char *lastReply)
|
||||
SetProp(node, controller->node, "state", state);
|
||||
}
|
||||
for (i = 0; i < 10; i++) {
|
||||
SetProp(node, controller->node, "sent",
|
||||
GetProp(node, controller->node, "send"));
|
||||
SetProp(node, controller->node, "send", NULL);
|
||||
script = GetProp(node, controller->node, state);
|
||||
if (script == NULL)
|
||||
script = state;
|
||||
|
||||
snprintf(origScript, sizeof origScript, "%s", script);
|
||||
if (commError) {
|
||||
errorScript = GetProp(node, controller->node, "commerror");
|
||||
if (errorScript != NULL)
|
||||
script = errorScript;
|
||||
commError = 0;
|
||||
}
|
||||
script = strdup(script);
|
||||
if (!SctCallInContext(con, script, node, data->controller, &result)) {
|
||||
SCPrintf(con, eError, "ERROR: %s", result);
|
||||
snprintf(eprop, sizeof eprop, "error_during_%s", data->name);
|
||||
if (strncmp(result, "ERROR: ", 7) == 0) {
|
||||
result += 7;
|
||||
}
|
||||
emsg = GetHdbProp(node, eprop);
|
||||
if (emsg == NULL) {
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
SCPrintf(con, eError,
|
||||
"ERROR: action <%s> in {%s} node %s:\nERROR: %s",
|
||||
data->name, origScript, path, result);
|
||||
}
|
||||
snprintf(msg, sizeof msg, "<%s> %s", origScript, result);
|
||||
SetHdbProperty(node, eprop, msg);
|
||||
blank = strchr(origScript, ' ');
|
||||
if (blank != NULL) {
|
||||
l = blank - origScript;
|
||||
} else {
|
||||
l = strlen(origScript);
|
||||
}
|
||||
snprintf(eprop, sizeof eprop, "error_in_%.*s", l, origScript);
|
||||
emsg = GetHdbProp(node, eprop);
|
||||
cnt = 0;
|
||||
if (emsg != NULL) {
|
||||
sscanf(emsg, "%d", &cnt);
|
||||
}
|
||||
cnt++;
|
||||
snprintf(msg, sizeof msg, "%dx {%s} %s", cnt, origScript, result);
|
||||
SetHdbProperty(node, eprop, msg);
|
||||
send = NULL;
|
||||
goto finish;
|
||||
}
|
||||
state = result;
|
||||
if (strcasecmp(state, "idle") == 0) {
|
||||
if (currentCon && !data->answered) {
|
||||
SCWrite(con, "o.k.", eValue);
|
||||
if (strcasecmp(state, "idle") == 0 || strcasecmp(state, "unpoll") == 0) {
|
||||
if (queueData == data && !data->answered) {
|
||||
SCWrite(con, "o.k.", eStatus);
|
||||
}
|
||||
if (strcmp(data->name, "write") == 0) {
|
||||
SetHdbProperty(data->node, "writestatus", "commandsent");
|
||||
snprintf(eprop, sizeof eprop, "error_during_%s", data->name);
|
||||
emsg = GetHdbProp(node, eprop);
|
||||
if (emsg != NULL) {
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
SCPrintf(con, eError,
|
||||
"action <%s>: success after error message (%s)\n %s",
|
||||
data->name, path, emsg);
|
||||
SetHdbProperty(node, eprop, NULL);
|
||||
}
|
||||
snprintf(timeKey, 50, "%s_time", data->name);
|
||||
snprintf(timeVal, 50, "%.3f", DoubleTime());
|
||||
snprintf(timeKey, sizeof timeKey, "%s_time", data->name);
|
||||
snprintf(timeVal, sizeof timeVal, "%.3f", DoubleTime());
|
||||
SetHdbProperty(data->node, timeKey, timeVal);
|
||||
send = NULL;
|
||||
goto finish;
|
||||
}
|
||||
SetProp(node, controller->node, "state", state);
|
||||
free(script);
|
||||
script = NULL;
|
||||
send = GetProp(node, controller->node, "send");
|
||||
if (send != NULL && send[0] != '\0') {
|
||||
if (controller->verbose) {
|
||||
@@ -337,6 +399,16 @@ static char *SctActionHandler(void *actionData, char *lastReply)
|
||||
}
|
||||
SCPrintf(con, eLogError, "ERROR: too many quick scripts chained");
|
||||
finish:
|
||||
if (strcmp(data->name, "write") == 0) {
|
||||
/* check if it would be ok to do this only when writestatus property exists:
|
||||
GetHdbProp(data->node, "writestatus") != NULL
|
||||
*/
|
||||
SetHdbProperty(data->node, "writestatus", "commandsent");
|
||||
}
|
||||
if (strcasecmp(state, "unpoll") == 0) {
|
||||
DevUnschedule(controller->devser, data, SctActionHandler, SctMatch);
|
||||
send = NULL;
|
||||
}
|
||||
SetProp(node, controller->node, "state", "idle");
|
||||
if (data->conCtx != NULL) {
|
||||
SCDeleteConnection(data->conCtx);
|
||||
@@ -345,16 +417,17 @@ finish:
|
||||
return send;
|
||||
}
|
||||
|
||||
static char *SctWriteHandler(void *actionData, char *lastReply)
|
||||
static char *SctWriteHandler(void *actionData, char *lastReply,
|
||||
int commError)
|
||||
{
|
||||
SctData *data = actionData;
|
||||
SConnection *old;
|
||||
SctData *old;
|
||||
char *result;
|
||||
|
||||
old = currentCon;
|
||||
currentCon = data->conCtx;
|
||||
result = SctActionHandler(data, lastReply);
|
||||
currentCon = old;
|
||||
old = queueData;
|
||||
queueData = data;
|
||||
result = SctActionHandler(data, lastReply, commError);
|
||||
queueData = old;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -379,6 +452,10 @@ static hdbCallbackReturn SctMainCallback(Hdb * node, void *userData,
|
||||
char *geterror;
|
||||
char error[256];
|
||||
|
||||
if (controller->devser == NULL) {
|
||||
/* defunct controller */
|
||||
return hdbContinue;
|
||||
}
|
||||
pm = GetKillPtrMessage(msg);
|
||||
if (pm != NULL) {
|
||||
if (controller == pm->pPtr) {
|
||||
@@ -440,7 +517,6 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
||||
char *writeprio;
|
||||
char *error;
|
||||
SConnection *con;
|
||||
SConnection *con2;
|
||||
char path[MAX_HDB_PATH];
|
||||
|
||||
pm = GetKillPtrMessage(msg);
|
||||
@@ -510,16 +586,16 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
||||
|
||||
mm = GetHdbUpdateMessage(msg);
|
||||
if (mm != NULL) {
|
||||
if (currentCon) { /* update called from a write action */
|
||||
if (queueData != NULL && queueData->conCtx != NULL && !data->answered) {
|
||||
/* update called from a write action */
|
||||
data->answered = 1;
|
||||
GetHdbPath(node, path, sizeof path);
|
||||
con = currentCon;
|
||||
text = formatValue(*(mm->v), node);
|
||||
/* Markus: who is receiving this message?
|
||||
It gave unwanted output to me. MK
|
||||
SCPrintf(con, eLog, "%s = %s", path, GetCharArray(text));
|
||||
It gave unwanted output to me. MK
|
||||
Answer: a commandline client -> outcode eStatus correct?
|
||||
*/
|
||||
|
||||
SCPrintf(queueData->conCtx, eStatus, "%s = %s", path, GetCharArray(text));
|
||||
DeleteDynString(text);
|
||||
}
|
||||
return hdbContinue;
|
||||
@@ -577,7 +653,9 @@ static void SctKillCBData(void *d)
|
||||
{
|
||||
SctData *data = d;
|
||||
|
||||
DevRemoveAction(data->controller->devser, data);
|
||||
if (data->controller->devser != NULL) {
|
||||
DevRemoveAction(data->controller->devser, data);
|
||||
}
|
||||
SctKillData(d);
|
||||
}
|
||||
|
||||
@@ -866,7 +944,8 @@ static void KillSctTransact(void *data)
|
||||
free(self);
|
||||
}
|
||||
|
||||
static char *TransactionHandler(void *actionData, char *lastReply)
|
||||
static char *TransactionHandler(void *actionData, char *lastReply,
|
||||
int commError)
|
||||
{
|
||||
pSctTransact st = (pSctTransact) actionData;
|
||||
|
||||
@@ -976,6 +1055,12 @@ static hdbCallbackReturn SctDebugCallback(Hdb * node, void *userData,
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
static int SctDeferredFree(void *data)
|
||||
{
|
||||
free(data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void SctKillController(void *c)
|
||||
{
|
||||
SctController *controller = c;
|
||||
@@ -987,7 +1072,13 @@ static void SctKillController(void *c)
|
||||
SCDeleteConnection(controller->conn);
|
||||
}
|
||||
DevKill(controller->devser);
|
||||
free(controller);
|
||||
controller->devser = NULL;
|
||||
if (pServ->pTasker) {
|
||||
TaskRegister(pServ->pTasker, SctDeferredFree, NULL, NULL, controller,
|
||||
0);
|
||||
} else {
|
||||
free(controller);
|
||||
}
|
||||
}
|
||||
|
||||
static int SctMakeController(SConnection * con, SicsInterp * sics,
|
||||
@@ -995,33 +1086,33 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
||||
{
|
||||
SICSOBJ *ccmd;
|
||||
Hdb *parent, *par, *cmd;
|
||||
char *nodeName;
|
||||
char *objName;
|
||||
hdbCallback *cb;
|
||||
SctController *controller;
|
||||
|
||||
if (argc < 2) {
|
||||
SCPrintf(con, eError,
|
||||
"ERROR: should be %s <path> <protocol args> ...", argv[0]);
|
||||
"ERROR: should be %s <path or objectname> <protocol args> ...",
|
||||
argv[0]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Install into the Hipadaba when full path given
|
||||
*/
|
||||
if(strstr(argv[1],"/") != NULL){
|
||||
parent = FindHdbParent(NULL, argv[1], &nodeName, con);
|
||||
if (parent == NULL)
|
||||
return 0; /* error message already written */
|
||||
if (strchr(argv[1], '/') == NULL) {
|
||||
/* object name only -> do not anchor in tree */
|
||||
parent = NULL;
|
||||
objName = argv[1];
|
||||
} else {
|
||||
nodeName = argv[1];
|
||||
parent = NULL;
|
||||
/* full path given -> install into the hipadaba */
|
||||
parent = FindHdbParent(NULL, argv[1], &objName, con);
|
||||
if (parent == NULL)
|
||||
return 0; /* error message already written */
|
||||
}
|
||||
|
||||
controller = calloc(1, sizeof(*controller));
|
||||
assert(controller);
|
||||
controller->verbose = 0;
|
||||
|
||||
ccmd = MakeSICSOBJv(nodeName, "SctController", HIPNONE, usSpy);
|
||||
ccmd = MakeSICSOBJv(objName, "SctController", HIPNONE, usSpy);
|
||||
controller->node = ccmd->objectNode;
|
||||
controller->conn = SCCreateDummyConnection(pServ->pSics);
|
||||
|
||||
@@ -1030,15 +1121,16 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
||||
ccmd->pPrivate = controller;
|
||||
ccmd->KillPrivate = SctKillController;
|
||||
|
||||
if(parent != NULL){
|
||||
AddHipadabaChild(parent, controller->node, con);
|
||||
if (parent != NULL) {
|
||||
AddHipadabaChild(parent, controller->node, con);
|
||||
}
|
||||
|
||||
controller->devser = DevMake(con, argc - 2, argv + 2);
|
||||
if (!controller->devser)
|
||||
return 0;
|
||||
|
||||
AddCommand(pServ->pSics, nodeName, InvokeSICSOBJ, KillSICSOBJ, ccmd);
|
||||
AddCommand(pServ->pSics, objName, InterInvokeSICSOBJ, KillSICSOBJ, ccmd);
|
||||
RegisterSICSOBJKillCmd(ccmd, objName);
|
||||
SetDescriptorKey(ccmd->pDes, "creationCommand", "0");
|
||||
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
|
||||
Reference in New Issue
Block a user