- allow scriptcontext objects to be dynamic

- enhancements in scriptcontext (error messages stored as properties)
This commit is contained in:
zolliker
2009-02-19 13:30:32 +00:00
parent 981534624f
commit 35f2b6b810
33 changed files with 753 additions and 310 deletions

View File

@@ -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,