Cleaned up ANSTO code to merge with sinqdev.sics
This is our new RELEASE-4_0 branch which was taken from ansto/93d9a7c Conflicts: .gitignore SICSmain.c asynnet.c confvirtualmot.c counter.c devexec.c drive.c event.h exebuf.c exeman.c histmem.c interface.h motor.c motorlist.c motorsec.c multicounter.c napi.c napi.h napi4.c network.c nwatch.c nxscript.c nxxml.c nxxml.h ofac.c reflist.c scan.c sicshipadaba.c sicsobj.c site_ansto/docs/Copyright.txt site_ansto/instrument/lyrebird/config/tasmad/sicscommon/nxsupport.tcl site_ansto/instrument/lyrebird/config/tasmad/taspub_sics/tasscript.tcl statusfile.c tasdrive.c tasub.c tasub.h tasublib.c tasublib.h
This commit is contained in:
156
scriptcontext.c
156
scriptcontext.c
@@ -15,6 +15,7 @@
|
||||
#include "macro.h"
|
||||
#include "syncedprot.h"
|
||||
#include "scriptcontext.h"
|
||||
#include "sctcomtask.h"
|
||||
|
||||
typedef struct ContextItem {
|
||||
struct ContextItem *next;
|
||||
@@ -47,6 +48,7 @@ typedef struct SctData {
|
||||
int inMacro;
|
||||
Hdb *node;
|
||||
long syncid;
|
||||
int busy;
|
||||
} SctData;
|
||||
|
||||
/* data for updatescript */
|
||||
@@ -351,9 +353,9 @@ int SctCallInContext(SConnection * con, char *script, Hdb * node,
|
||||
ret = Tcl_EvalEx(pTcl, script, l, 0);
|
||||
result = (char *) Tcl_GetStringResult(pTcl);
|
||||
if (ret != TCL_OK && result[0] != '\0') {
|
||||
if (strncmp(result, "ERROR:", 6) == 0) {
|
||||
/* remove "ERROR:", as it will be added later */
|
||||
result += 6;
|
||||
if (strncmp(result, "ERROR: ", 7) == 0) {
|
||||
/* remove "ERROR: ", as it will be added later */
|
||||
result += 7;
|
||||
if (result[0] == ' ') {
|
||||
result++;
|
||||
}
|
||||
@@ -422,7 +424,10 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
} else {
|
||||
con = controller->conn;
|
||||
}
|
||||
data->busy = 1;
|
||||
|
||||
/*
|
||||
* Check if this is a followup call.
|
||||
* If this is a followup call, the I/O system will have set the
|
||||
* property result to the data from the device. Read this now and
|
||||
* print it if diagnostics is required.
|
||||
@@ -446,6 +451,8 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the state property is set to the name of the property
|
||||
* which holds the name of the script to run at this stage.
|
||||
* When this is a followup, we use the content of the
|
||||
* state field as the property storing the next script to
|
||||
* run. If this is the start of a chain this is set to the
|
||||
@@ -486,8 +493,15 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
sct->sendCalled = 0;
|
||||
SyncedBegin(data->syncid);
|
||||
ret = SctCallInContext(con, script, node, controller, &result);
|
||||
if (result[0] == '\0') {
|
||||
ret = 0;
|
||||
result = "empty response - probably missing return statement";
|
||||
}
|
||||
SyncedEnd(data->syncid);
|
||||
sct->sendNode = NULL;
|
||||
/*
|
||||
* Process the results of the script run
|
||||
*/
|
||||
if (ret == 0) {
|
||||
/*
|
||||
* an error occurred in the script: store error message in
|
||||
@@ -615,7 +629,8 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
free(script);
|
||||
script = NULL;
|
||||
/*
|
||||
* If there is data to send, check it and do so
|
||||
* If there is data to send, check it and do so. This also exits the
|
||||
* quick script loop by returning the data to send to Devser.
|
||||
*/
|
||||
if (sct->sendCalled) {
|
||||
send = GetProp(node, controller->node, "send");
|
||||
@@ -637,6 +652,10 @@ static char *SctActionHandler(void *actionData, char *lastReply,
|
||||
}
|
||||
SCPrintf(con, eLogError, "ERROR: too many quick scripts chained");
|
||||
finish:
|
||||
/*
|
||||
* This section is always called when the script chain ends: either due to
|
||||
* error or by successfull termination.
|
||||
*/
|
||||
if (strcmp(data->name, "write") == 0) {
|
||||
if (GetHdbProp(node, "writestatus") != NULL) {
|
||||
SetHdbProperty(node, "writestatus", "commandsent");
|
||||
@@ -651,6 +670,7 @@ finish:
|
||||
SCDeleteConnection(data->conCtx);
|
||||
data->conCtx = NULL;
|
||||
}
|
||||
data->busy = 0;
|
||||
return send;
|
||||
}
|
||||
|
||||
@@ -862,6 +882,7 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
||||
data->inMacro = SCinMacro(con);
|
||||
tracePar(node->name,"Queued %s to %s",node->name, GetCharArray(text));
|
||||
data->syncid = SyncedIncr(0);
|
||||
data->busy = 1;
|
||||
DevQueue(data->controller->devser, data, prio,
|
||||
SctWriteHandler, SctMatch, SctEndData, SctDataInfo);
|
||||
/* kill function SctEndData does not kill, data is owned by the node (callback list) */
|
||||
@@ -894,7 +915,7 @@ static hdbCallbackReturn SctActionCallback(Hdb * node, void *userData,
|
||||
return hdbContinue;
|
||||
}
|
||||
|
||||
static char *ParText(Hdb * cmdNode, char *name,
|
||||
char *ParText(Hdb * cmdNode, char *name,
|
||||
int nPar, char *defaultValue)
|
||||
{
|
||||
Hdb *par;
|
||||
@@ -1179,7 +1200,7 @@ void SctQueueNode(SctController * controller, Hdb * node,
|
||||
data->answered = 1;
|
||||
|
||||
data->syncid = SyncedIncr(0);
|
||||
|
||||
data->busy = 1;
|
||||
if (DevQueue(data->controller->devser, data, prio,
|
||||
SctWriteHandler, SctMatch, SctKillData, SctDataInfo)) {
|
||||
if (con != NULL) {
|
||||
@@ -1408,6 +1429,13 @@ typedef struct SctTransact {
|
||||
SctController *controller;
|
||||
} SctTransact, *pSctTransact;
|
||||
|
||||
static char * SctTransactInfo(void *d)
|
||||
{
|
||||
SctTransact *st = d;
|
||||
return strdup(st->command);
|
||||
}
|
||||
|
||||
|
||||
static void KillSctTransact(void *data)
|
||||
{
|
||||
pSctTransact self = (pSctTransact) data;
|
||||
@@ -1447,16 +1475,7 @@ static char *TransactionHandler(void *actionData, char *lastReply,
|
||||
return st->command;
|
||||
} else {
|
||||
st->sent = 2;
|
||||
/*
|
||||
if (st->controller->verbose) {
|
||||
SCPrintf(st->con, eLog, "%6.3f reply : %s", secondsOfMinute(), lastReply);
|
||||
}
|
||||
if (st->controller->fd != NULL) {
|
||||
fprintf(st->controller->fd,"%6.3f reply : %s\n", secondsOfMinute(), lastReply);
|
||||
}
|
||||
*/
|
||||
/* printf("Transact: %s got %s\n", st->command, lastReply); */
|
||||
if (lastReply == NULL) {
|
||||
if (lastReply == NULL) {
|
||||
lastReply = "";
|
||||
}
|
||||
if(st->controller != NULL){
|
||||
@@ -1519,15 +1538,9 @@ static int SctTransactCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
st->reply = NULL;
|
||||
|
||||
DevQueue(c->devser, st, WritePRIO,
|
||||
TransactionHandler, SctTransactMatch, NULL, NULL);
|
||||
TransactionHandler, SctTransactMatch, NULL, SctTransactInfo);
|
||||
while (st->sent != 2) {
|
||||
TaskYield(pServ->pTasker);
|
||||
/* not yet tested:
|
||||
if (SCGetInterrupt(con) != eContinue) {
|
||||
DevUnschedule(c->devser, st, TransactionHandler, SctTransactMatch);
|
||||
break;
|
||||
}
|
||||
*/
|
||||
}
|
||||
if (st->reply != NULL) {
|
||||
SCWrite(con,st->reply,eValue);
|
||||
@@ -1565,7 +1578,53 @@ static int SctSendCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
|
||||
SetHdbProperty(c->node, "reply", "");
|
||||
DevQueue(c->devser, st, prio,
|
||||
SendHandler, SctTransactMatch, KillSctTransact, NULL);
|
||||
SendHandler, SctTransactMatch, KillSctTransact, SctTransactInfo);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SctProcessCmd(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
SctData *data = NULL;
|
||||
SctController *c;
|
||||
time_t startTime;
|
||||
|
||||
c = (SctController *) ccmd->pPrivate;
|
||||
|
||||
if(nPar < 1 || par[0] == NULL){
|
||||
SCWrite(con,"ERROR: no node to process found", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data = calloc(sizeof(SctData), 1);
|
||||
if (data == NULL) {
|
||||
SCWrite(con, "ERROR: out of memory in SctProcessCommand", eError);
|
||||
return 0;
|
||||
}
|
||||
|
||||
data->node = FindHdbNode(NULL,par[0]->value.v.text, con);
|
||||
if(data->node == NULL){
|
||||
SCPrintf(con,eError,"ERROR: node %s to process not found", par[0]->value.v.text);
|
||||
return 0;
|
||||
}
|
||||
if(nPar > 1) {
|
||||
data->name = strdup(par[1]->value.v.text);
|
||||
} else {
|
||||
data->name = strdup("read");
|
||||
}
|
||||
data->controller = c;
|
||||
data->conCtx = SCCopyConnection(con);
|
||||
data->busy = 1;
|
||||
data->inMacro = SCinMacro(con);
|
||||
|
||||
startTime = time(NULL);
|
||||
DevQueue(c->devser, data, WritePRIO,
|
||||
SctWriteHandler, SctTransactMatch, NULL, SctDataInfo);
|
||||
while (data->busy == 1 && time(NULL) < startTime + 20) {
|
||||
TaskYield(pServ->pTasker);
|
||||
}
|
||||
SctKillData(data);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1584,8 +1643,14 @@ static int SctReconnect(pSICSOBJ ccmd, SConnection * con,
|
||||
{
|
||||
SctController *c;
|
||||
char *reconnectScript, *result;
|
||||
char *hostport;
|
||||
|
||||
c = (SctController *) ccmd->pPrivate;
|
||||
hostport = ParText(cmdNode, "hostport", nPar, "");
|
||||
if (strcmp(hostport, "unconnected") == 0) {
|
||||
DevDisconnect(c->devser);
|
||||
return 1;
|
||||
}
|
||||
DevReconnect(c->devser, ParText(cmdNode, "hostport", nPar, ""));
|
||||
reconnectScript = GetProp(c->node, c->node, "reconnect_script");
|
||||
if (reconnectScript && reconnectScript[0] != '\0') {
|
||||
@@ -1659,6 +1724,25 @@ static int SctTimeout(pSICSOBJ ccmd, SConnection * con,
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SctReconnectInterval(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
SctController *c;
|
||||
char *result;
|
||||
hdbValue *v = &cmdNode->child->value;
|
||||
int interval;
|
||||
|
||||
c = (SctController *) ccmd->pPrivate;
|
||||
if (nPar == 0) {
|
||||
interval = -1; /* read only */
|
||||
} else {
|
||||
interval = v->v.intValue;
|
||||
}
|
||||
v->v.intValue = DevReconnectInterval(c->devser, interval);
|
||||
SCPrintf(con, eValue, "%d", v->v.intValue);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int SctStatus(pSICSOBJ ccmd, SConnection * con,
|
||||
Hdb * cmdNode, Hdb * par[], int nPar)
|
||||
{
|
||||
@@ -1757,7 +1841,7 @@ static void SctKillController(void *c)
|
||||
}
|
||||
|
||||
if (pServ->pTasker) {
|
||||
TaskRegister(pServ->pTasker, SctDeferredTask, NULL, SctDeferredFree,
|
||||
TaskRegisterN(pServ->pTasker,"killsct", SctDeferredTask, NULL, SctDeferredFree,
|
||||
controller, 0);
|
||||
} else {
|
||||
free(controller);
|
||||
@@ -1870,6 +1954,11 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
||||
AddSICSHdbPar(cmd, "data", usMugger, MakeHdbText(""));
|
||||
AddSICSHdbPar(cmd, "prio", usMugger, MakeHdbText(""));
|
||||
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"processnode", usUser, MakeSICSFunc(SctProcessCmd));
|
||||
AddSICSHdbPar(cmd, "node", usUser, MakeHdbText(""));
|
||||
AddSICSHdbPar(cmd, "command", usUser, MakeHdbText("read"));
|
||||
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"disconnect", usMugger, MakeSICSFunc(SctDisconnect));
|
||||
|
||||
@@ -1895,6 +1984,10 @@ static int SctMakeController(SConnection * con, SicsInterp * sics,
|
||||
"timeout", usSpy, MakeSICSFunc(SctTimeout));
|
||||
AddSICSHdbPar(cmd, "value", usUser, MakeHdbFloat(-1.0));
|
||||
|
||||
cmd = AddSICSHdbPar(controller->node,
|
||||
"reconnectinterval", usSpy, MakeSICSFunc(SctReconnectInterval));
|
||||
AddSICSHdbPar(cmd, "value", usUser, MakeHdbInt(-1));
|
||||
|
||||
/* get the actual timeout value */
|
||||
SctTimeout(ccmd, con, cmd, &par, 0);
|
||||
|
||||
@@ -1934,6 +2027,7 @@ void SctInit(void)
|
||||
sct->desc = CreateDescriptor("ScriptContext");
|
||||
AddCommand(pServ->pSics, "sct", SctCommand, SctKill, sct);
|
||||
AddCmd("makesctcontroller", SctMakeController);
|
||||
AddCmd("makesctcomtask", SctMakeComTask);
|
||||
}
|
||||
|
||||
int SctVerbose(SctController * c)
|
||||
@@ -1941,3 +2035,15 @@ int SctVerbose(SctController * c)
|
||||
return c->verbose;
|
||||
}
|
||||
|
||||
DevSer *SctGetDevser(void *data)
|
||||
{
|
||||
SctController *c;
|
||||
|
||||
pSICSOBJ ccmd = (pSICSOBJ)data;
|
||||
assert(ccmd);
|
||||
assert(strcmp(ccmd->pDes->name,"SctController") == 0);
|
||||
|
||||
|
||||
c = (SctController *) ccmd->pPrivate;
|
||||
return c->devser;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user