Files
sics/sicshipadaba.c

4445 lines
117 KiB
C

/**
* This is a set of helper functions for SICS to work with the hierarchical parameter
* database hipadaba. In SICS, the calldata associated with any callback will always
* be the connection object.
*
* copyright: GPL
*
* Mark Koennecke, June 2006
*
* Introduced notification on tree changes, Mark Koennecke, November 2006
*
* Added property functions, Mark Koennecke, January 2007
*
* Added hmatchprop function. Mark Koennecke, February 2008
*
* TODO: separate this into two modules: sicshipadaba proper and sicshipadabaint for the
* interpreter interface.
*
* Refactored to new callback system, Markus Zolliker, Mark Koennecke, March 2008
*
* Added start and finished messages to commands. Mark Koennecke, November 2008
*
* Added SicsValueCheckCallback and implemented first version of haddcheck.
* Mark Koennecke, July 2013
*
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>
#include <sicshipadaba.h>
#include <sicshdbadapter.h>
#include "sicspoll.h"
#include <lld.h>
#include <stptok.h>
#include "protocol.h"
#include "statusfile.h"
#include <splitter.h>
#include "sicsobj.h"
#include <macro.h>
#include "arrayutil.h"
#include "HistMem.h"
#include "asynnet.h"
#include <json-c/json.h>
#define MAX_HDB_PATH 1024
/*== there can be only one hipadaba in SICS, some globals to care for that == */
static pHdb root = NULL;
static pSicsPoll poller = NULL;
typedef enum {
normal_protocol,
json_protocol,
} Protocol;
char *trim(char *str);
/*====================== Messages ==================================================*/
static char killID[] = { "killID" };
static char killInternalID[] = { "killInternalID" };
static char killPtr[] = { "killPtr" };
static char startID[] = { "start" };
static char stopID[] = { "stop" };
/*----------------------------------------------------------------------------------*/
pHdbIDMessage GetKillIDMessage(pHdbMessage message)
{
if (message->type == killID) {
return (pHdbIDMessage) message;
}
return NULL;
}
/*-----------------------------------------------------------------------------------*/
pHdbIDMessage GetKillInternalIDMessage(pHdbMessage message)
{
if (message->type == killInternalID) {
return (pHdbIDMessage) message;
}
return NULL;
}
/*-----------------------------------------------------------------------------------*/
pHdbPtrMessage GetKillPtrMessage(pHdbMessage message)
{
if (message->type == killPtr) {
return (pHdbPtrMessage) message;
}
return NULL;
}
/*-----------------------------------------------------------------------------------*/
pHdbMessage GetHdbStartMessage(pHdbMessage message)
{
if (message->type == startID) {
return (pHdbMessage) message;
}
return NULL;
}
/*-----------------------------------------------------------------------------------*/
pHdbMessage GetHdbStopMessage(pHdbMessage message)
{
if (message->type == stopID) {
return (pHdbMessage) message;
}
return NULL;
}
/*-----------------------------------------------------------------------------------*/
void SendHdbStatusMessage(pHdb node, char *status)
{
pHdbMessage pRes = NULL;
pRes = malloc(sizeof(hdbMessage));
if (pRes == NULL) {
return;
}
if (strcmp(status, "start") == 0) {
pRes->type = startID;
} else if (strcmp(status, "stop") == 0) {
pRes->type = stopID;
} else {
/* someone is trying to create an non existent message */
assert(0);
}
InvokeCallbackChain(node, pRes);
free(pRes);
}
/*=============== common callback functions used for SICS ===========================*/
static hdbCallbackReturn SICSCheckPermissionCallback(pHdb node,
void *userData,
pHdbMessage message)
{
int *testPriv = NULL;
SConnection *pCon = NULL;
pHdbDataMessage mm = NULL;
testPriv = (int *) userData;
mm = GetHdbSetMessage(message);
if (mm == NULL) {
return hdbContinue;
}
pCon = (SConnection *) mm->callData;
/*
* If pCon is NULL, then this is an internal call from some driver
* code where no permission check is necessary. However, when called
* through the hipadaba tree commands and other upper level code, the
* check will be honoured.
*/
if (pCon == NULL) {
return hdbContinue;
}
assert(testPriv != NULL);
if (SCMatchRights(pCon, *testPriv) == 1) {
return hdbContinue;
} else {
return hdbAbort;
}
}
/*--------------------------------------------------------------------------------------*/
pHdbCallback MakeCheckPermissionCallback(int priv)
{
int *testPriv = NULL;
testPriv = malloc(sizeof(int));
if (testPriv == NULL) {
return NULL;
}
*testPriv = priv;
return MakeHipadabaCallback(SICSCheckPermissionCallback, testPriv, free);
}
/*-------------------------------------------------------------------------------------*/
static char *removeSetUpdateID = "removeSetUpdate";
void RemoveSetUpdateCallback(pHdb node)
{
hdbPtrMessage m;
m.type = killPtr;
m.pPtr = removeSetUpdateID;
InvokeCallbackChain(node, (pHdbMessage) & m);
}
/*-------------------------------------------------------------------------------------*/
static hdbCallbackReturn SICSSetUpdateCallback(pHdb node, void *userData,
pHdbMessage message)
{
pHdbDataMessage mm = NULL;
pHdbPtrMessage pm = NULL;
int status;
pm = GetKillPtrMessage(message);
if (pm != NULL) {
if (pm->pPtr == removeSetUpdateID) {
return hdbKill;
}
return hdbContinue;
}
mm = GetHdbSetMessage(message);
if (mm == NULL) {
return hdbContinue;
}
status = UpdateHipadabaPar(node, *(mm->v), mm->callData);
if (status && mm->callData != NULL) {
SCSendOK(mm->callData);
}
return hdbContinue;
}
/*-------------------------------------------------------------------------------------*/
pHdbCallback MakeSetUpdateCallback()
{
return MakeHipadabaCallback(SICSSetUpdateCallback, NULL, NULL);
}
/*---------------------------------------------------------------------------------------*/
static hdbCallbackReturn SICSReadOnlyCallback(pHdb node, void *userData,
pHdbMessage message)
{
SConnection *pCon = NULL;
pHdbDataMessage mm = NULL;
mm = GetHdbSetMessage(message);
if (mm == NULL) {
return hdbContinue;
}
pCon = (SConnection *) mm->callData;
if (pCon != NULL) {
SCWrite(pCon, "ERROR: parameter is READ-ONLY", eError);
}
return hdbAbort;
}
/*-------------------------------------------------------------------------------------*/
pHdbCallback MakeReadOnlyCallback()
{
return MakeHipadabaCallback(SICSReadOnlyCallback, NULL, NULL);
}
/*------------------------------------------------------------------------------------*/
hdbCallbackReturn SICSValueCheckCallback(pHdb node, void *userData,
pHdbMessage message)
{
SConnection *pCon = NULL;
pHdbDataMessage mm = NULL;
char values[1024], *pPtr, pToken[80], *pVal;
int status;
hdbValue v;
mm = GetHdbSetMessage(message);
if (mm == NULL) {
return hdbContinue;
}
pCon = (SConnection *) mm->callData;
v = *(mm->v);
status = GetHdbProperty(node,"values",values,sizeof(values));
if(status != 1 && pCon != NULL){
SCPrintf(pCon,eLogError,"ERROR: configuration error, no values on node %s",
node->name);
return hdbAbort;
}
if(v.dataType != HIPTEXT && pCon != NULL){
SCPrintf(pCon,eLogError,"ERROR: need text data for node %s",
node->name);
return hdbAbort;
}
pPtr = values;
pVal = strdup(v.v.text);
strtolower(pVal);
while((pPtr = stptok(pPtr,pToken,sizeof(pToken),",")) != NULL){
if(strcmp(pToken,pVal) == 0) {
free(pVal);
return hdbContinue;
}
}
free(pVal);
if(pCon != NULL){
SCPrintf(pCon,eLogError,"ERROR: %s not allowed as value for %s, allowed are: %s",
v.v.text, node->name, values);
}
return hdbAbort;
}
/*-------------------------------------------------------------------------------------*/
static hdbCallbackReturn SICSDriveCallback(pHdb node, void *userData,
pHdbMessage message)
{
SConnection *pCon = NULL;
pDummy dum = NULL;
char pSicsdev[80];
int status;
pHdbDataMessage mm = NULL;
hdbValue v;
mm = GetHdbSetMessage(message);
if (mm == NULL) {
return hdbContinue;
}
pCon = (SConnection *) mm->callData;
v = *(mm->v);
dum = (pDummy) userData;
assert(pCon != NULL && dum != NULL);
if (GetHdbProperty(node, "sicsdev", pSicsdev, 79)) {
status = StartDevice(pServ->pExecutor, pSicsdev, dum->pDescriptor,
userData, pCon, RUNDRIVE, (float) v.v.doubleValue);
} else {
status = StartDevice(pServ->pExecutor, node->name, dum->pDescriptor,
userData, pCon, SCGetRunLevel(pCon), (float) v.v.doubleValue);
}
if (status == 1) {
return hdbContinue;
} else {
return hdbAbort;
}
}
/*---------------------------------------------------------------------------------------*/
pHdbCallback MakeSICSDriveCallback(void *sicsObject)
{
return MakeHipadabaCallback(SICSDriveCallback, sicsObject, NULL);
}
/*---------------------------------------------------------------------------------------*/
static hdbCallbackReturn SICSReadDriveCallback(pHdb node, void *userData,
pHdbMessage message)
{
static SConnection *defCon = NULL;
SConnection *pCon = NULL;
pDummy dum = NULL;
pIDrivable pDriv = NULL;
float value;
pHdbDataMessage mm = NULL;
mm = GetHdbGetMessage(message);
if (mm == NULL) {
return hdbContinue;
}
pCon = (SConnection *) mm->callData;
dum = (pDummy) userData;
assert(dum != NULL);
if (defCon == NULL) {
defCon = SCCreateDummyConnection(pServ->pSics);
}
pDriv = dum->pDescriptor->GetInterface(dum, DRIVEID);
assert(pDriv != NULL);
if (pCon != NULL) {
value = pDriv->GetValue(dum, pCon);
node->value.v.doubleValue = (double) value;
mm->v->v.doubleValue = (double) value;
} else {
if (defCon != NULL) {
value = pDriv->GetValue(dum, defCon);
node->value.v.doubleValue = (double) value;
mm->v->v.doubleValue = (double) value;
}
}
return hdbContinue;
}
/*--------------------------------------------------------------------------*/
static hdbCallbackReturn SICSFuncCallback(pHdb node, void *userData,
pHdbMessage message)
{
pHdb par[64], current = NULL;
int nPar = 0;
SICSOBJFunc func = NULL;
pHdbDataMessage mm = NULL;
int status;
mm = GetHdbSetMessage(message);
if (mm == NULL) {
return hdbContinue;
}
assert(node->value.dataType == HIPFUNC);
if (userData == NULL || mm->callData == NULL) {
printf("Great Badness in calling SICSFuncCallback\n");
return hdbAbort;
}
current = node->child;
while (current != NULL) {
par[nPar] = current;
nPar++;
current = current->next;
}
func = (SICSOBJFunc) node->value.v.func;
if (func != NULL) {
SendHdbStatusMessage(node, "start");
status = func((pSICSOBJ) userData, (SConnection *) mm->callData,
node, par, nPar);
SendHdbStatusMessage(node, "stop");
} else {
printf("Great Badness in calling SICSFuncCallback\n");
return hdbAbort;
}
if (status == 1) {
return hdbContinue;
} else {
return hdbAbort;
}
}
/*---------------------------------------------------------------------------*/
pHdbCallback MakeSICSFuncCallback(void *obj)
{
return MakeHipadabaCallback(SICSFuncCallback, obj, NULL);
}
/*--------------------------------------------------------------------------------------*/
pHdbCallback MakeSICSReadDriveCallback(void *sicsObject)
{
return MakeHipadabaCallback(SICSReadDriveCallback, sicsObject, NULL);
}
/*---------------------------------------------------------------------------------------*/
typedef struct {
SConnection *pCon;
int ID;
int internalID;
} HdbCBInfo;
static Protocol isJSON(SConnection * pCon, int notify)
{
char proName[128];
void *pData;
if (notify == 0 && SCinMacro(pCon)) {
return normal_protocol;
}
pData = FindCommandData(pServ->pSics, "protocol", "Protocol");
ProtocolGet(pCon, pData, proName, 128);
if (strcmp(proName, "json") == 0)
return json_protocol;
else
return normal_protocol;
}
/* Format a name,value pair according to the given protocol */
int formatNameValue(Protocol protocol, char *name, char *value,
pDynString result, int hdtype)
{
char *char_arr, *ptr;
char token[8], ch;
switch (protocol) {
case normal_protocol:
DynStringCopy(result, name);
DynStringConcat(result, " = ");
DynStringConcat(result, value);
break;
case json_protocol:
switch (hdtype) {
case HIPNONE:
DynStringCopy(result, "null");
break;
case HIPINT:
case HIPFLOAT:
DynStringCopy(result, "{\"");
DynStringConcat(result, name);
DynStringConcat(result, "\": ");
DynStringConcat(result, value);
DynStringConcat(result, "}");
break;
case HIPTEXT:
DynStringCopy(result, "{\"");
DynStringConcat(result, name);
DynStringConcat(result, "\": \"");
ptr = NULL;
for (ch=*value; ch!=0; ch=*++value) {
switch (ch) {
case '"': strcpy(token, "\\\"");
case '\\': strcpy(token, "\\\\");
default:
if (ch > 127 || ch < 32) {
snprintf(token, sizeof token, "\\u%4.4x", (unsigned char)ch);
} else {
if (!ptr) ptr = value;
continue;
}
}
if (ptr) {
DynStringConcatBytes(result, ptr, value - ptr);
}
DynStringConcat(result, token);
}
if (ptr) {
DynStringConcatBytes(result, ptr, value - ptr);
}
DynStringConcat(result, "\"}");
break;
case HIPINTAR:
case HIPINTVARAR:
case HIPFLOATAR:
case HIPFLOATVARAR:
char_arr = ptr = strdup(trim(value));
while (*ptr != '\0') {
if (isspace(*ptr))
*ptr = ',';
ptr++;
}
DynStringCopy(result, "{\"");
DynStringConcat(result, name);
DynStringConcat(result, "\": [ ");
DynStringConcat(result, char_arr);
DynStringConcat(result, " ]}");
if (char_arr != NULL)
free(char_arr);
break;
}
}
return protocol;
}
/*----------------------------------------------------------------------------*/
static int sendZippedNodeData(pHdb node, hdbValue newValue, SConnection * pCon)
{
int i, *iData = NULL, zip = 1;
char *path = NULL;
double sum = 0;
char value[80];
path = GetHipadabaPath(node);
if (GetHdbProperty(node, "transfer", value, 80) == 1) {
if(strstr(value,"bin") != NULL) {
zip = 0;
}
}
switch (newValue.dataType) {
case HIPINTAR:
case HIPINTVARAR:
if (newValue.v.intArray == NULL) {
free(path);
return 0;
}
iData = (int *) malloc(newValue.arrayLength * sizeof(int));
if (iData == NULL) {
SCWrite(pCon, "ERROR: out of memory in sendZippedData", eError);
free(path);
return 0;
}
memset(iData, 0, newValue.arrayLength * sizeof(int));
for (i = 0; i < newValue.arrayLength; i++) {
/* sum += (double)newValue.v.intArray[i]; */
iData[i] = htonl(newValue.v.intArray[i]);
}
if(zip == 1){
SCWriteZipped(pCon, path, iData, newValue.arrayLength * sizeof(int));
} else {
SCWriteBinary(pCon, path, iData, newValue.arrayLength * sizeof(int));
}
free(iData);
/* printf("Wrote zipped data %s, sum %lf\n", path, sum); */
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
if (newValue.v.floatArray == NULL) {
free(path);
return 0;
}
iData = (int *) malloc(newValue.arrayLength * sizeof(int));
if (iData == NULL) {
SCWrite(pCon, "ERROR: out of memory in sendZippedData", eError);
free(path);
return 0;
}
memset(iData, 0, newValue.arrayLength * sizeof(int));
for (i = 0; i < newValue.arrayLength; i++) {
sum+= newValue.v.floatArray[i];
iData[i] = htonl((int) (newValue.v.floatArray[i] * 65536.));
}
if(zip == 1) {
SCWriteZipped(pCon, path, iData, newValue.arrayLength * sizeof(int));
/* printf("Wrote zipped data %s, sum %lf\n", path, sum); */
} else {
SCWriteBinary(pCon, path, iData, newValue.arrayLength * sizeof(int));
}
free(iData);
break;
default:
SCPrintf(pCon, eError, "ERROR: zipped writing not supported for this datatype on node %s",
path);
free(path);
return 0;
}
free(path);
return 1;
}
/*----------------------------------------------------------------------------------------*/
static hdbCallbackReturn SICSNotifyCallback(pHdb node, void *userData,
pHdbMessage message)
{
HdbCBInfo *cbInfo = NULL;
pDynString printedData = NULL;
pDynString result = NULL;
char *pPath = NULL;
Protocol protocol = normal_protocol;
int outCode, macro, status;
char value[80];
pHdbIDMessage idm = NULL;
pHdbPtrMessage cmm = NULL;
pHdbDataMessage mm = NULL;
hdbPropertyChange *propm = NULL;
hdbValue *hvalue;
SConnection *tstCon;
char updatePath[1024];
char *geterror;
cbInfo = (HdbCBInfo *) userData;
/*
* handle kills first
*/
if ((idm = GetKillIDMessage(message)) != NULL) {
if (idm->ID == cbInfo->ID) {
return hdbKill;
} else {
return hdbContinue;
}
}
if ((idm = GetKillInternalIDMessage(message)) != NULL) {
if (idm->ID == cbInfo->internalID) {
return hdbKill;
} else {
return hdbContinue;
}
}
if ((cmm = GetKillPtrMessage(message)) != NULL) {
tstCon = cmm->pPtr;
if (tstCon != NULL && SCGetIdent(tstCon) == SCGetIdent(cbInfo->pCon)) {
return hdbKill;
} else {
return hdbContinue;
}
}
/**
* handle start and stop messages
*/
if (GetHdbStartMessage(message) != NULL) {
pPath = GetHipadabaPath(node);
result = CreateDynString(128, 128);
DynStringConcat(result, pPath);
DynStringConcat(result, " STARTED");
SCWrite(cbInfo->pCon, GetCharArray(result), eEvent);
DeleteDynString(result);
free(pPath);
return hdbContinue;
}
if (GetHdbStopMessage(message) != NULL) {
pPath = GetHipadabaPath(node);
result = CreateDynString(128, 128);
DynStringConcat(result, pPath);
DynStringConcat(result, " FINISHED");
SCWrite(cbInfo->pCon, GetCharArray(result), eEvent);
DeleteDynString(result);
free(pPath);
return hdbContinue;
}
/*
* Deal with update and geterror property messages
*/
if ((propm = GetPropertyChangeMessage(message)) != NULL) {
if (strcmp(propm->key, "geterror") != 0) {
/* this is a property change of an other property */
return hdbContinue;
}
geterror = propm->value;
hvalue = &node->value;
} else if ((mm = GetHdbUpdateMessage(message)) != NULL) {
geterror = GetHdbProp(node, "geterror");
hvalue = mm->v;
} else {
return hdbContinue;
}
GetHdbPath(node,updatePath,sizeof(updatePath));
result = CreateDynString(128, 128);
if ((protocol = isJSON(cbInfo->pCon, 1)) == 1)
outCode = eHdbEvent;
else
outCode = eEvent;
if (geterror && *geterror) {
/* send geterror */
strlcat(updatePath, ".geterror", sizeof updatePath);
formatNameValue(protocol, updatePath, geterror, result, HIPTEXT);
SCPureSockWrite(cbInfo->pCon, Dyn2Cstring(result), outCode);
return hdbContinue;
} /* else normal notify */
/**
* if transfer = zip always transfer data in zipped form
*/
if (GetHdbProperty(node, "transfer", value, 80) == 1) {
if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) {
status = sendZippedNodeData(node, *hvalue, cbInfo->pCon);
DeleteDynString(result);
return hdbContinue;
}
}
if (hvalue->arrayLength <= 400) {
printedData = formatValue(*hvalue, node);
if (printedData == NULL || result == NULL) {
SCWrite(cbInfo->pCon, "ERROR: out of memory formatting data",
eEvent);
/*
* no need to interrupt something because writing data to a client does
* not work
*/
return hdbContinue;
}
formatNameValue(protocol, updatePath, GetCharArray(printedData), result,
hvalue->dataType);
#ifdef SITE_ANSTO
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
#else
SCPureSockWrite(cbInfo->pCon, GetCharArray(result), outCode);
#endif
DeleteDynString(printedData);
} else {
formatNameValue(protocol, updatePath, "!!datachange!!", result, HIPTEXT);
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
}
DeleteDynString(result);
return hdbContinue;
}
/*-----------------------------------------------------------------------------------------*/
static void cbKill(void *pData)
{
HdbCBInfo *cbInfo = (HdbCBInfo *) pData;
if (cbInfo == NULL) {
return;
}
if (cbInfo->pCon != NULL) {
SCDeleteConnection(cbInfo->pCon);
}
free(cbInfo);
}
/*-----------------------------------------------------------------------------------------*/
pHdbCallback MakeNotifyCallback(SConnection * pCon, int id)
{
HdbCBInfo *cbInfo = NULL;
cbInfo = malloc(sizeof(HdbCBInfo));
if (cbInfo == NULL) {
return NULL;
}
cbInfo->pCon = SCCopyConnection(pCon);
if (cbInfo->pCon == NULL) {
return NULL;
}
SCsetMacro(cbInfo->pCon, 0);
cbInfo->ID = id;
cbInfo->internalID = -1;
return MakeHipadabaCallback(SICSNotifyCallback, cbInfo, cbKill);
}
/*-------------------------------------------------------------------------*/
static hdbCallbackReturn TreeChangeCallback(pHdb node, void *userData,
pHdbMessage message)
{
char *path = NULL;
char buffer[1024];
pDynString result = NULL;
Protocol protocol = normal_protocol;
pHdbIDMessage idm = NULL;
pHdbPtrMessage cmm = NULL;
int outCode;
pHdbTreeChangeMessage tm = NULL;
SConnection *tstCon = NULL;
HdbCBInfo *cbInfo = (HdbCBInfo *) userData;
/*
* handle kills first
*/
if ((idm = GetKillIDMessage(message)) != NULL) {
if (idm->ID == cbInfo->ID) {
return hdbKill;
} else {
return hdbContinue;
}
}
if ((idm = GetKillInternalIDMessage(message)) != NULL) {
if (idm->ID == cbInfo->internalID) {
return hdbKill;
} else {
return hdbContinue;
}
}
if ((cmm = GetKillPtrMessage(message)) != NULL) {
tstCon = cmm->pPtr;
if (tstCon != NULL && SCGetIdent(tstCon) == SCGetIdent(cbInfo->pCon)) {
return hdbKill;
} else {
return hdbContinue;
}
}
if ((tm = GetHdbTreeChangeMessage(message)) == NULL) {
return hdbContinue;
}
if (cbInfo != NULL && cbInfo->pCon != NULL) {
result = CreateDynString(128, 128);
if (result == NULL) {
SCWrite(cbInfo->pCon, "ERROR: out of memory in TreeChangeCallback",
eError);
return hdbAbort;
}
path = GetHipadabaPath(node);
if ((protocol = isJSON(cbInfo->pCon, 1)) == 1)
outCode = eHdbEvent;
else
outCode = eEvent;
/* formatNameValue(protocol, "treechange", path, result,
node->value.dataType); */
formatNameValue(protocol, "treechange", path, result,
HIPTEXT);
SCWrite(cbInfo->pCon, GetCharArray(result), outCode);
DeleteDynString(result);
free(path);
}
return hdbContinue;
}
/*-------------------------------------------------------------------------*/
pHdbCallback MakeTreeChangeCallback(SConnection * pCon, int id)
{
HdbCBInfo *cbInfo = NULL;
cbInfo = malloc(sizeof(HdbCBInfo));
if (cbInfo == NULL) {
return NULL;
}
cbInfo->pCon = SCCopyConnection(pCon);
if (cbInfo->pCon == NULL) {
return NULL;
}
SCsetMacro(cbInfo->pCon, 0);
cbInfo->ID = id;
cbInfo->internalID = -1;
return MakeHipadabaCallback(TreeChangeCallback, cbInfo, cbKill);
}
/*----------------------------------------------------------------------------------------*/
static hdbCallbackReturn SICSScriptWriteCallback(pHdb node, void *userData,
pHdbMessage message)
{
char *command = NULL;
SConnection *pCon = NULL;
pDynString newVal = NULL;
char error[1024];
int status;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
command = (char *) userData;
pCon = (SConnection *) mm->callData;
assert(command != NULL && pCon != NULL);
newVal = formatValue(*(mm->v), node);
if (newVal == NULL) {
SCWrite(pCon, "ERROR: out of memory setting parameter", eError);
return hdbAbort;
}
/**
* prepend command
*/
DynStringInsert(newVal, " ", 0);
DynStringInsert(newVal, command, 0);
/*
* evaluate
*/
status = Tcl_Eval(InterpGetTcl(pServ->pSics), GetCharArray(newVal));
if (status != TCL_OK) {
snprintf(error, 1023, "ERROR: tcl returned error: %s",
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
SCWrite(pCon, error, eError);
status = 0;
} else {
status = 1;
}
DeleteDynString(newVal);
if (status == 1) {
return hdbContinue;
} else {
return hdbAbort;
}
}
/*---------------------------------------------------------------------------------------*/
static pHdbCallback MakeSICSWriteScriptCallback(char *script)
{
return MakeHipadabaCallback(SICSScriptWriteCallback, strdup(script),
free);
}
/*----------------------------------------------------------------------------------------*/
static hdbCallbackReturn SICSScriptReadCallback(pHdb node, void *userData,
pHdbMessage message)
{
char *command = NULL, *data = NULL, *equal = NULL;
SConnection *pCon = NULL;
pDynString newVal = NULL;
char error[1024];
int status;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbGetMessage(message)) == NULL) {
return hdbContinue;
}
command = (char *) userData;
pCon = (SConnection *) mm->callData;
assert(command != NULL);
/*
* evaluate
*/
if (pCon != NULL) {
MacroPush(pCon);
}
status = Tcl_Eval(InterpGetTcl(pServ->pSics), command);
if (pCon != NULL) {
MacroPop();
}
if (status != TCL_OK) {
snprintf(error, 1023, "ERROR: Tcl returned error: %s",
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
if (pCon != NULL) {
SCWrite(pCon, error, eError);
}
status = 0;
} else {
status = 1;
}
/*
* decode result. This handles both the case of the standard SICS answer
* something = anything
* as well as a plain value alone
*/
data = (char *) Tcl_GetStringResult(InterpGetTcl(pServ->pSics));
if (data == NULL) {
if (pCon != NULL) {
SCWrite(pCon, "ERROR: no result returned from script", eError);
}
return hdbAbort;
}
/*
* do we need to copy?
*/
if (strstr(data, "@@NOCOPY@@") != NULL) {
return hdbContinue;
}
/*
* we need to copy: do it
*/
equal = strchr(data, '=');
if (equal != NULL) {
data = equal + 1;
}
strcpy(error, "ERROR: ");
status = readHdbValue(&node->value, data, error + 7, 1024 - 7);
if (status != 1) {
if (pCon != NULL) {
SCWrite(pCon, error, eError);
}
return hdbAbort;
}
if (status == 1) {
return hdbContinue;
} else {
return hdbAbort;
}
}
/*----------------------------------------------------------------------------*/
static pHdbCallback MakeSICSReadScriptCallback(char *script)
{
return MakeHipadabaCallback(SICSScriptReadCallback, strdup(script),
free);
}
/*---------------------------------------------------------------------------*/
typedef struct {
int min;
int max;
} hdbIntRange, *pHdbIntRange;
/*---------------------------------------------------------------------------*/
static hdbCallbackReturn SICSIntRangeCallback(pHdb node, void *userData,
pHdbMessage message)
{
char buffer[256];
pHdbIntRange range = NULL;
SConnection *pCon = NULL;
int status = 1;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
range = (pHdbIntRange) userData;
pCon = (SConnection *) mm->callData;
assert(range != NULL);
if (mm->v->v.intValue > range->max || mm->v->v.intValue < range->min) {
status = SICSCBRANGE;
if (pCon != NULL) {
snprintf(buffer, 255,
"ERROR: %d is not within permitted range: %d to %d",
(int) mm->v->v.intValue, range->min, range->max);
SCWrite(pCon, buffer, eError);
}
return hdbAbort;
}
return hdbContinue;
}
/*---------------------------------------------------------------------------*/
pHdbCallback MakeIntRangeCallback(int min, int max)
{
pHdbIntRange range = NULL;
range = malloc(sizeof(hdbIntRange));
if (range == NULL) {
return NULL;
}
range->min = min;
range->max = max;
return MakeHipadabaCallback(SICSIntRangeCallback, range, free);
}
/*---------------------------------------------------------------------------*/
typedef struct {
double min;
double max;
} hdbFloatRange, *pHdbFloatRange;
/*---------------------------------------------------------------------------*/
static hdbCallbackReturn SICSFloatRangeCallback(pHdb node, void *userData,
pHdbMessage message)
{
char buffer[256];
pHdbFloatRange range = NULL;
SConnection *pCon = NULL;
int status = 1;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
range = (pHdbFloatRange) userData;
pCon = (SConnection *) mm->callData;
assert(range != NULL);
if (mm->v->v.doubleValue > range->max
|| mm->v->v.doubleValue < range->min) {
status = SICSCBRANGE;
if (pCon != NULL) {
snprintf(buffer, 255,
"ERROR: %lf is not within permitted range: %lf to %lf",
mm->v->v.doubleValue, range->min, range->max);
SCWrite(pCon, buffer, eError);
}
return hdbAbort;
}
return hdbContinue;
}
/*---------------------------------------------------------------------------*/
pHdbCallback MakeFloatRangeCallback(double min, double max)
{
pHdbFloatRange range = NULL;
range = malloc(sizeof(hdbFloatRange));
if (range == NULL) {
return NULL;
}
range->min = min;
range->max = max;
return MakeHipadabaCallback(SICSFloatRangeCallback, range, free);
}
/*------------------------------------------------------------------------*/
static hdbCallbackReturn MemGenReadCallback(pHdb node, void *userData,
pHdbMessage message)
{
pHdbDataMessage mm = NULL;
if ((mm = GetHdbGetMessage(message)) == NULL) {
return hdbContinue;
}
switch (node->value.dataType) {
case HIPINT:
node->value.v.intValue = *(int *) userData;
break;
case HIPFLOAT:
node->value.v.doubleValue = *(double *) userData;
break;
case HIPTEXT:
if (node->value.v.text != NULL) {
free(node->value.v.text);
}
node->value.v.text = strdup((char *) userData);
break;
case HIPINTAR:
memcpy(&node->value.v.intArray, userData,
node->value.arrayLength * sizeof(int));
break;
case HIPFLOATAR:
memcpy(&node->value.v.floatArray, userData,
node->value.arrayLength * sizeof(double));
break;
default:
assert(0);
break;
}
return hdbContinue;
}
/*-------------------------------------------------------------------------*/
pHdbCallback MakeMemGenReadCallback(void *address)
{
return MakeHipadabaCallback(MemGenReadCallback, address, NULL);
}
/*-------------------------------------------------------------------------*/
static hdbCallbackReturn MemGenSetCallback(pHdb node, void *userData,
pHdbMessage message)
{
const char *pPtr = NULL;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
if (mm->v->dataType != node->value.dataType) {
assert(0);
return 0;
}
switch (node->value.dataType) {
case HIPINT:
memcpy(userData, &mm->v->v.intValue, sizeof(int));
break;
case HIPFLOAT:
memcpy(userData, &mm->v->v.doubleValue, sizeof(double));
break;
case HIPTEXT:
/* the use of strlcpy is probably buggy here (M.Z. 15.4.2010) */
strlcpy((char *) userData, (const char *) mm->v->v.text,
node->value.arrayLength);
break;
case HIPINTAR:
memcpy(userData, &mm->v->v.intArray,
node->value.arrayLength * sizeof(int));
break;
case HIPFLOATAR:
memcpy(userData, &mm->v->v.floatArray,
node->value.arrayLength * sizeof(double));
break;
default:
assert(0);
return 0;
break;
}
UpdateHipadabaPar(node, *(mm->v), mm->callData);
return hdbContinue;
}
/*-------------------------------------------------------------------------*/
pHdbCallback MakeMemGenSetCallback(void *address)
{
return MakeHipadabaCallback(MemGenSetCallback, address, NULL);
}
/*--------------------------------------------------------------------------*/
static void killHdbValue(void *pData)
{
hdbValue *v = NULL;
v = (hdbValue *) pData;
if (v == NULL) {
return;
}
ReleaseHdbValue(v);
free(v);
}
/*--------------------------------------------------------------------------*/
static hdbCallbackReturn SICSIntFixedCallback(pHdb node, void *userData,
pHdbMessage message)
{
hdbValue *allowed = NULL;
SConnection *pCon = NULL;
int i;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
allowed = (hdbValue *) userData;
pCon = (SConnection *) mm->callData;
assert(allowed != NULL && allowed->dataType == HIPINTAR);
for (i = 0; i < allowed->arrayLength; i++) {
if (mm->v->v.intValue == allowed->v.intArray[i]) {
return hdbContinue;
}
}
if (pCon != NULL) {
SCWrite(pCon, "ERROR: value is not in the list of allowed values",
eError);
}
return hdbAbort;
}
/*---------------------------------------------------------------------------*/
pHdbCallback MakeIntFixedCallback(int *data, int length)
{
pHdbCallback result = NULL;
hdbValue *v = NULL;
v = malloc(sizeof(hdbValue));
if (v == NULL) {
return NULL;
}
v->dataType = HIPINTAR;
v->arrayLength = length;
v->v.intArray = malloc(length * sizeof(int));
if (v->v.intArray == NULL) {
return NULL;
}
memcpy(v->v.intArray, data, length * sizeof(int));
return MakeHipadabaCallback(SICSIntFixedCallback, v, killHdbValue);
}
/*============= Parameter Creation ===========================================*/
pHdb MakeSICSHdbPar(char *name, int priv, hdbValue v)
{
pHdb result = NULL;
pHdbCallback pHcb = NULL;
char pPriv[20];
result = MakeHipadabaNode(name, v.dataType, v.arrayLength);
if (result == NULL) {
return NULL;
}
copyHdbValue(&v, &result->value);
pHcb = MakeCheckPermissionCallback(priv);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
pHcb = MakeSetUpdateCallback();
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
switch (priv) {
case 0:
strcpy(pPriv, "internal");
break;
case 1:
strcpy(pPriv, "manager");
break;
case 2:
strcpy(pPriv, "user");
break;
case 3:
strcpy(pPriv, "spy");
break;
}
SetHdbProperty(result, "priv", pPriv);
return result;
}
/*----------------------------------------------------------------------------*/
pHdb MakeSICSHdbDriv(char *name, int priv, void *sicsObject, int dataType)
{
pHdb result = NULL;
pHdbCallback pHcb = NULL;
result = MakeHipadabaNode(name, dataType, 0);
if (result == NULL) {
return NULL;
}
pHcb = MakeCheckPermissionCallback(priv);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
pHcb = MakeSICSDriveCallback(sicsObject);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
pHcb = MakeSICSReadDriveCallback(sicsObject);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
return result;
}
/*---------------------------------------------------------------------------*/
pHdb MakeSICSMemPar(char *name, int priv, float *address)
{
pHdb result = NULL;
pHdbCallback pHcb = NULL;
result = MakeHipadabaNode(name, HIPFLOAT, 1);
if (result == NULL) {
return NULL;
}
pHcb = MakeCheckPermissionCallback(priv);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
pHcb = MakeMemGenSetCallback(address);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
pHcb = MakeMemGenReadCallback(address);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
return result;
}
/*----------------------------------------------------------------------------*/
pHdb MakeSICSROPar(char *name, hdbValue v)
{
pHdb result = NULL;
pHdbCallback pHcb = NULL;
result = MakeHipadabaNode(name, v.dataType, v.arrayLength);
if (result == NULL) {
return NULL;
}
copyHdbValue(&v, &result->value);
pHcb = MakeReadOnlyCallback();
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
return result;
}
/*---------------------------------------------------------------------------*/
pHdb MakeSICSScriptPar(char *name, char *setScript, char *readScript,
hdbValue v)
{
pHdb result = NULL;
pHdbCallback pHcb = NULL;
result = MakeHipadabaNode(name, v.dataType, v.arrayLength);
if (result == NULL) {
return NULL;
}
copyHdbValue(&v, &result->value);
pHcb = MakeSICSWriteScriptCallback(setScript);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
pHcb = MakeSICSReadScriptCallback(readScript);
if (pHcb == NULL) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
AppendHipadabaCallback(result, pHcb);
/**
* put into the list of nodes to check with the update task
*/
/* LLDnodeAppend(scriptUpdate,&result); */
SetHdbProperty(result, "sicscommand", setScript);
return result;
}
/*--------------------------------------------------------------------------*/
static void removeNodeFromUpdateList(pHdb node)
{
pHdb current = NULL;
int status;
char *objName = NULL;
objName = GetHipadabaPath(node);
if (objName != NULL) {
removePollObject(poller, objName);
free(objName);
}
}
/*-----------------------------------------------------------------------*/
static void SICSDeleteNodeData(pHdb node)
{
pHdb tmp = NULL;
if (node == NULL) {
return;
}
removeNodeFromUpdateList(node);
DeleteCallbackChain(node);
while (node->child != NULL) {
tmp = node->child;
node->child = node->child->next;
SICSDeleteNodeData(tmp);
}
if (node->properties != NULL) {
DeleteStringDict(node->properties);
}
if (node->name != NULL) {
free(node->name);
}
ReleaseHdbValue(&node->value);
node->magic = 000000;
free(node);
}
/*--------------------------------------------------------------------------*/
void RemoveSICSPar(pHdb node, void *callData)
{
pHdb current = NULL, tmp = NULL;
if (node == NULL) {
return;
}
RemoveHdbNodeFromParent(node, NULL);
SICSDeleteNodeData(node);
}
/*===================== add functions =======================================*/
pHdb AddSICSHdbPar(pHdb parent, char *name, int priv, hdbValue v)
{
pHdb child = NULL;
child = MakeSICSHdbPar(name, priv, v);
if (child != NULL) {
AddHipadabaChild(parent, child, NULL);
}
return child;
}
/*---------------------------------------------------------------------------*/
pHdb AddSICSHdbROPar(pHdb parent, char *name, hdbValue v)
{
pHdb child = NULL;
child = MakeSICSROPar(name, v);
if (child != NULL) {
AddHipadabaChild(parent, child, NULL);
}
return child;
}
/*--------------------------------------------------------------------------*/
pHdb AddSICSHdbMemPar(pHdb parent, char *name, int priv,
void *data, int datalength, int type, int length)
{
pHdb child = NULL;
pHdbCallback pHcb = NULL;
if (type == HIPINTVARAR || type == HIPFLOATVARAR) {
assert(0);
return NULL;
}
child = MakeHipadabaNode(name, type, length);
if (child == NULL) {
return NULL;
}
pHcb = MakeCheckPermissionCallback(priv);
if (pHcb == NULL) {
DeleteHipadabaNode(child, NULL);
return NULL;
}
AppendHipadabaCallback(child, pHcb);
pHcb = MakeMemGenSetCallback(data);
if (pHcb == NULL) {
DeleteHipadabaNode(child, NULL);
return NULL;
}
AppendHipadabaCallback(child, pHcb);
pHcb = MakeMemGenReadCallback(data);
if (pHcb == NULL) {
DeleteHipadabaNode(child, NULL);
return NULL;
}
AppendHipadabaCallback(child, pHcb);
AddHipadabaChild(parent, child, NULL);
return child;
}
/*==================== access support functions ==============================
This has become an eierlegendewollmilchsau function. I do not know how and when
that happened
==============================================================================*/
pHdb FindHdbParent(char *rootpath, char *relpath, char **namePtr,
SConnection * pCon)
{
/* for namePtr == NULL, implements also "find node" */
char *element;
char buffer[MAX_HDB_PATH];
pHdb node = NULL;
pHdb parent = NULL;
char *name;
char *slash;
pObjectDescriptor pDes;
int iret;
if (relpath[0] == '/' || rootpath == NULL) { /* absolute path */
iret = snprintf(buffer, sizeof buffer, "%s", relpath);
} else {
iret = snprintf(buffer, sizeof buffer, "%s/%s", rootpath, relpath);
}
if (iret < 0 || iret >= (int) sizeof(buffer)) {
SCWrite(pCon, "ERROR: path too long", eError);
return NULL;
}
element = buffer;
if (strncmp(element, "/sics/", 6) == 0) {
/* sics object case */
slash = strchr(element + 6, '/');
if (slash != NULL)
*slash = '\0'; /* split off object name */
pDes = FindCommandDescriptor(pServ->pSics, element + 6);
if (pDes == NULL) {
SCPrintf(pCon, eError, "ERROR: object %s not found", element);
return NULL;
}
node = pDes->parNode;
if (node == NULL) {
SCPrintf(pCon, eError, "ERROR: object %s does not use hipadaba",
element);
return NULL;
}
if (slash == NULL)
goto nodeFound;
*slash = '/';
element = slash + 1;
parent = node;
/* parent is sics object, path is relative to it */
} else {
/* normal path */
parent = GetHipadabaRoot();
}
while (1) {
slash = strchr(element, '/');
if (slash != NULL)
*slash = '\0'; /* split off next path element */
if (strcmp(element, "") == 0 || strcmp(element, ".") == 0) {
/* cases "//" and "/./" : do not move in tree */
if (slash == NULL) {
node = parent;
goto nodeFound;
}
*slash = '/';
element = slash + 1;
} else {
for (node = parent->child; node != NULL; node = node->next) {
if (strcasecmp(element, node->name) == 0) {
break;
}
}
if (node == NULL) {
if (namePtr) { /* "find parent" case */
if (slash != NULL) { /* element is not the last in path */
*slash = '/';
SCPrintf(pCon, eError, "ERROR: parent of %s not found",
buffer);
return NULL;
}
/* the name must be taken from the end of relpath, as element is no longer valid */
*namePtr = relpath + (element - buffer);
return parent; /* parent found, and node does not yet exist */
}
/* "find node" case */
if (slash != NULL)
*slash = '/';
SCPrintf(pCon, eError, "ERROR: node %s not found", buffer);
return NULL;
}
/* node found */
if (slash == NULL)
goto nodeFound;
parent = node;
*slash = '/';
element = slash + 1;
}
}
nodeFound:
if (namePtr) { /* "find parent" case */
*namePtr = node->name;
SCPrintf(pCon, eError, "ERROR: node %s exists already", buffer);
return NULL;
}
return node; /* node found */
}
/*--------------------------------------------------------------------------*/
pHdb FindHdbNode(char *rootpath, char *relpath, SConnection * pCon)
{
return FindHdbParent(rootpath, relpath, NULL, pCon);
}
/*-------------------------------------------------------------------------*/
pHdb FindHdbIntern(char *path)
{
char *element, *slash;
pHdb parent = NULL;
pObjectDescriptor pDes = NULL;
element = path;
if(strncmp(element,"/sics/",6) == 0){
slash = strchr(element+6,'/');
if(slash != NULL){
*slash = '\0';
}
pDes = FindCommandDescriptor(pServ->pSics,element+6);
if(pDes == NULL){
return NULL;
}
parent = pDes->parNode;
if(parent == NULL){
return NULL;
}
if(slash == NULL){
return parent;
}
*slash = '/';
element = slash + 1;
} else {
parent = GetHipadabaRoot();
}
return GetHipadabaNode(parent,element);
}
/*--------------------------------------------------------------------------
* This does not use strlcpy, strlcat on purpose: it caused a bug
* There are so many length checks in the code anyway so that is
* not necessary either.
--------------------------------------------------------------------------*/
int GetHdbPath(pHdb nodeArg, char *path, size_t pathlen)
{
pHdb node, parent;
int len, pos, l;
static char *sics = "/sics";
pObjectDescriptor pDes;
path[0] = '\0';
if (nodeArg == NULL) {
return 0;
}
/* determine path length and root node */
parent = nodeArg;
len = 0;
for (node = nodeArg; node != NULL && node != root; node = node->mama) {
len += strlen(node->name) + 1;
if (len >= (int) pathlen)
return 0; /* buffer overflow (recursive path?) */
parent = node;
}
/* check root and add prefix */
if (parent->mama != root) { /* not anchored in root */
pDes = FindCommandDescriptor(pServ->pSics, parent->name);
if (!pDes) {
return 0; /* not a sics object */
}
if (pDes->parNode != parent) {
/* node named as a sics object, but command is not related to node */
return 0;
}
l = strlen(sics);
len += l;
if (len > (int) pathlen)
return 0; /* buffer overflow */
strncpy(path, sics, l);
}
/* build the path backwards */
path[len] = '\0';
pos = len;
for (node = nodeArg; node != NULL && node != root; node = node->mama) {
len = strlen(node->name);
pos -= len;
assert(pos > 0);
strncpy(path + pos, node->name, len);
pos--;
path[pos] = '/';
}
return 1;
}
/*--------------------------------------------------------------------------*/
void RemoveSICSInternalCallbackFrom(pHdb node, void *internalID)
{
hdbPtrMessage m;
m.type = killPtr;
m.pPtr = internalID;
RecurseCallbackChains(node, (pHdbMessage) & m);
}
/*--------------------------------------------------------------------------*/
static int RemoveParNodeCallback(char *name, pDummy object,
void *internalID)
{
if (object && object->pDescriptor->parNode) {
RemoveSICSInternalCallbackFrom(object->pDescriptor->parNode, internalID);
}
return 1;
}
/*--------------------------------------------------------------------------*/
void RemoveSICSInternalCallback(void *internalID)
{
RemoveSICSInternalCallbackFrom(GetHipadabaRoot(), internalID);
ForEachCommand(RemoveParNodeCallback, internalID);
}
/*--------------------------------------------------------------------------*/
int SICSHdbGetPar(void *obj, SConnection * pCon, char *path, hdbValue * v)
{
pHdb par = NULL;
int status;
char buffer[256];
pDummy pDum;
pDum = (pDummy) obj;
if (pDum == NULL || pDum->pDescriptor->parNode == NULL) {
if (pCon != NULL) {
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
SCWrite(pCon, buffer, eError);
}
return SICSNOPAR;
}
par = GetHipadabaNode(pDum->pDescriptor->parNode, path);
if (par == NULL) {
if (pCon != NULL) {
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
SCWrite(pCon, buffer, eError);
}
return SICSNOPAR;
}
status = GetHipadabaPar(par, v, pCon);
if (status < 0) {
return status;
}
return 1;
}
/*--------------------------------------------------------------------------*/
int SICSHdbUpdatePar(void *obj, SConnection * pCon, char *path, hdbValue v)
{
pHdb par = NULL;
int status;
char buffer[256];
pDummy pDum;
pDum = (pDummy) obj;
if (pDum == NULL || pDum->pDescriptor->parNode == NULL) {
if (pCon != NULL) {
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
SCWrite(pCon, buffer, eError);
}
return SICSNOPAR;
}
par = GetHipadabaNode(pDum->pDescriptor->parNode, path);
if (par == NULL) {
if (pCon != NULL) {
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
SCWrite(pCon, buffer, eError);
}
return SICSNOPAR;
}
status = UpdateHipadabaPar(par, v, pCon);
if (status < 0) {
return status;
}
return 1;
}
/*--------------------------------------------------------------------------*/
int SICSHdbSetPar(void *obj, SConnection * pCon, char *path, hdbValue v)
{
pHdb par = NULL;
int status;
char buffer[256];
pDummy pDum;
pDum = (pDummy) obj;
if (pDum == NULL || pDum->pDescriptor->parNode == NULL) {
if (pCon != NULL) {
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
SCWrite(pCon, buffer, eError);
}
return SICSNOPAR;
}
par = GetHipadabaNode(pDum->pDescriptor->parNode, path);
if (par == NULL) {
if (pCon != NULL) {
snprintf(buffer, 255, "ERROR: parameter %s not found", path);
SCWrite(pCon, buffer, eError);
}
return SICSNOPAR;
}
status = SetHipadabaPar(par, v, pCon);
if (status <= 0) {
return status;
}
return 1;
}
/*---------------------------------------------------------------------------*/
int InstallSICSNotify(pHdb node, SConnection * pCon, int id, int recurse)
{
pHdb currentChild = NULL;
pHdbCallback noty = NULL;
pHdbCallback treeChange = NULL;
treeChange = MakeTreeChangeCallback(pCon, id);
noty = MakeNotifyCallback(pCon, id);
if (noty == NULL || treeChange == NULL) {
SCWrite(pCon, "ERROR: out of memory installing callback", eError);
return 0;
}
AppendHipadabaCallback(node, noty);
AppendHipadabaCallback(node, treeChange);
if (recurse == 1) {
currentChild = node->child;
while (currentChild != NULL) {
InstallSICSNotify(currentChild, pCon, id, recurse);
currentChild = currentChild->next;
}
}
return 1;
}
/*---------------------------------------------------------------------------*/
void RemoveConnectionCallbacks(pHdb root, SConnection * pCon)
{
hdbPtrMessage dsm;
dsm.type = killPtr;
dsm.pPtr = pCon;
RecurseCallbackChains(root, (pHdbMessage) & dsm);
}
/*---------------------------------------------------------------------------*/
int ProcessSICSHdbPar(pHdb root, SConnection * pCon,
char *printPrefix, int argc, char *argv[])
{
hdbValue input;
pHdb parNode = NULL;
pDynString parData = NULL;
char error[512];
int i, status, firstValueArg;
float value;
assert(root != NULL && pCon != NULL);
if (argc < 1) {
SCWrite(pCon, "ERROR: no parameter to treat specified", eError);
return -1;
}
/* if the single argument is a number and the type of the root is a number
then we want to set the root itself to this number */
if (argc == 1
&& (root->value.dataType == HIPINT || root->value.dataType == HIPFLOAT)
&& sscanf(argv[0], "%f", &value) == 1) {
parNode = root;
firstValueArg = 0;
} else {
parNode = GetHipadabaNode(root, argv[0]);
firstValueArg = 1;
}
if (parNode == NULL) {
/* no error reporting here, upper level code might wish to continue
* processing commands after having tested for parameters.
*/
return -1;
}
if (argc > firstValueArg) {
/*
* setting the value is attempted.
*/
memset(&input, 0, sizeof(hdbValue));
input.dataType = parNode->value.dataType;
copyHdbValue(&parNode->value, &input);
parData = CreateDynString(64, 64);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory processing parameter", eError);
return 0;
}
for (i = firstValueArg; i < argc; i++) {
if (i > firstValueArg) {
DynStringConcat(parData, " ");
}
if (strchr(argv[i], ' ')) {
DynStringConcatChar(parData, '{');
DynStringConcat(parData, argv[i]);
DynStringConcatChar(parData, '}');
} else {
DynStringConcat(parData, argv[i]);
}
}
strcpy(error, "ERROR: ");
if (!readHdbValue(&input, GetCharArray(parData), error + 7, 512 - 7)) {
SCWrite(pCon, error, eError);
return 0;
}
DeleteDynString(parData);
status = SetHipadabaPar(parNode, input, pCon);
ReleaseHdbValue(&input);
if (status == 1) {
/* SCSendOK(pCon); do not send OK. this has to be done by the callback */
SCparChange(pCon);
}
return status;
} else {
/*
* reading is in demand
*/
status = GetHipadabaPar(parNode, &input, pCon);
if (status != 1) {
return 0;
}
parData = formatValue(input, parNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory reading parameter data", eError);
return 0;
}
DynStringInsert(parData, " = ", 0);
DynStringInsert(parData, argv[0], 0);
if (printPrefix != NULL) {
DynStringInsert(parData, printPrefix, 0);
}
SCWrite(pCon, GetCharArray(parData), eValue);
DeleteDynString(parData);
ReleaseHdbValue(&input);
return 1;
}
}
/*--------------------------------------------------------------------------*/
void PrintSICSParList(pHdb node, SConnection * pCon, char *prefix)
{
char childPrefix[1024];
pHdb child = NULL;
pDynString value = NULL;
hdbValue v;
child = node->child;
while (child != NULL) {
if (child->value.dataType != HIPNONE) {
GetHipadabaPar(child, &v, pCon);
value = formatValue(child->value, child);
if (value != NULL) {
SCPrintf(pCon, eValue, "%s%s = %s", prefix, child->name,
GetCharArray(value));
DeleteDynString(value);
}
}
if (child->child != NULL) {
strlcpy(childPrefix, prefix, 1024);
strlcat(childPrefix, child->name, 1024);
strlcat(childPrefix, "/", 1024);
PrintSICSParList(child, pCon, prefix);
}
child = child->next;
}
}
/*---------------------------------------------------------------------------*/
void SaveSICSHipadaba(FILE * fd, pHdb node, char *prefix)
{
pHdb currentChild = NULL;
pDynString data = NULL;
hdbValue v;
currentChild = node->child;
while (currentChild != NULL) {
if (currentChild->value.dataType != HIPNONE
&& !isSICSHdbRO(currentChild)) {
data = formatValue(currentChild->value, currentChild);
if (data != NULL) {
fprintf(fd, "%s%s %s\n", prefix, currentChild->name,
GetCharArray(data));
DeleteDynString(data);
}
}
if (currentChild->child != NULL) {
/*
* build a new prefix string and recurse
*/
data = CreateDynString(64, 64);
if (data != NULL) {
DynStringCopy(data, prefix);
DynStringConcat(data, currentChild->name);
DynStringConcat(data, "/");
SaveSICSHipadaba(fd, currentChild, GetCharArray(data));
DeleteDynString(data);
}
}
currentChild = currentChild->next;
}
}
/*================ value helpers ============================================*/
pDynString formatValue(hdbValue v, pHdb node)
{
pDynString result = NULL;
int i;
char number[30];
char format[16];
result = CreateDynString(64, 64);
if (result == NULL) {
return NULL;
}
if(v.arrayLength > 65536){
DynStringCopy(result,"Data to big to format into text");
return result;
}
switch (v.dataType) {
case HIPNONE:
break;
case HIPINT:
snprintf(number, 30, "%d", v.v.intValue);
DynStringCopy(result, number);
break;
case HIPFLOAT:
if (node != NULL && GetHdbProperty(node, "fmt", format, sizeof format - 1)) {
snprintf(number, 30, format, v.v.doubleValue);
} else {
snprintf(number, 30, "%.6g", v.v.doubleValue);
}
DynStringCopy(result, number);
break;
case HIPTEXT:
DynStringCopy(result, v.v.text);
break;
case HIPINTAR:
case HIPINTVARAR:
for (i = 0; i < v.arrayLength; i++) {
snprintf(number, 30, " %d", v.v.intArray[i]);
DynStringConcat(result, number);
}
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
if (node != NULL && GetHdbProperty(node, "fmt", format + 1, sizeof format - 2)) {
format[0] = ' ';
} else {
strcpy(format, " %.6g");
}
for (i = 0; i < v.arrayLength; i++) {
snprintf(number, 30, format, v.v.floatArray[i]);
DynStringConcat(result, number);
}
break;
case HIPFUNC:
DynStringConcat(result, "FUNCTION");
break;
case HIPOBJ:
DynStringConcat(result, "OBJECT");
break;
}
return result;
}
/*-------------------------------------------------------------------*/
static char *getNextHdbNumber(char *pStart, char pNumber[80])
{
int charCount = 0;
pNumber[0] = '\0';
/* advance to first digit */
while (isspace(*pStart) && *pStart != '\0') {
pStart++;
}
if (*pStart == '\0') {
return NULL;
}
/* copy */
while (!isspace(*pStart) && *pStart != '\0' && charCount < 78) {
pNumber[charCount] = *pStart;
pStart++;
charCount++;
}
pNumber[charCount] = '\0';
return pStart;
}
/*---------------------------------------------------------------------------------*/
static int adjustDataLength(hdbValue * v, char *data)
{
char number[80];
int count = 0;
char *pPtr = NULL;
pPtr = data;
while ((pPtr = getNextHdbNumber(pPtr, number)) != NULL) {
count++;
}
if (count != v->arrayLength) {
v->arrayLength = count;
if (v->dataType == HIPINTVARAR) {
if (v->v.intArray != NULL) {
free(v->v.intArray);
}
v->v.intArray = malloc(count * sizeof(int));
if (v->v.intArray == NULL) {
return 0;
}
memset(v->v.intArray, 0, count * sizeof(int));
}
if (v->dataType == HIPFLOATVARAR) {
if (v->v.floatArray != NULL) {
free(v->v.floatArray);
}
v->v.floatArray = malloc(count * sizeof(double));
if (v->v.floatArray == NULL) {
return 0;
}
memset(v->v.floatArray, 0, count * sizeof(double));
}
}
return 1;
}
/*---------------------------------------------------------------------------------*/
int readHdbValue(hdbValue * v, char *data, char *error, int errlen)
{
int i, status;
int lValue;
double dValue;
char number[80];
char *pPtr = NULL;
void *objData;
switch (v->dataType) {
case HIPNONE:
break;
case HIPINT:
getNextHdbNumber(data, number);
status = sscanf(number, "%d", &v->v.intValue);
if (status != 1) {
snprintf(error, errlen, "Failed to convert [%.32s] to integer", data);
return 0;
}
break;
case HIPFLOAT:
getNextHdbNumber(data, number);
status = sscanf(number, "%lf", &v->v.doubleValue);
if (status != 1) {
snprintf(error, errlen, "Failed to convert [%.32s] to double", data);
return 0;
}
break;
case HIPTEXT:
if (v->v.text != NULL) {
free(v->v.text);
}
v->v.text = strdup(data);
v->arrayLength = strlen(data);
break;
case HIPINTVARAR:
if (!adjustDataLength(v, data)) {
snprintf(error, errlen,
"Out of memory allocating variable length data");
return 0;
}
case HIPINTAR:
for (i = 0; i < v->arrayLength; i++) {
data = getNextHdbNumber(data, number);
if (data == NULL) {
snprintf(error, errlen,
"Not enough values to parse, current index %d", i);
return 0;
}
status = sscanf(number, "%d", &lValue);
if (status != 1) {
snprintf(error, errlen, "Failed to convert [%.32s] to integer", data);
return 0;
}
v->v.intArray[i] = lValue;
}
break;
case HIPFLOATVARAR:
if (!adjustDataLength(v, data)) {
snprintf(error, errlen,
"Out of memory allocating variable length data");
return 0;
}
case HIPFLOATAR:
for (i = 0; i < v->arrayLength; i++) {
data = getNextHdbNumber(data, number);
if (data == NULL) {
snprintf(error, errlen,
"Not enough values to parse, current index %d", i);
return 0;
}
status = sscanf(number, "%lf", &dValue);
if (status != 1) {
snprintf(error, errlen, "Failed to convert [%.32s] to double", data);
return 0;
}
v->v.floatArray[i] = dValue;
}
break;
case HIPOBJ:
break;
case HIPFUNC:
break;
default:
assert(0);
break;
}
return 1;
}
/*-------------------------------------------------------------------------*/
hdbValue MakeSICSFunc(SICSOBJFunc func)
{
return MakeHdbFunc((voidFunc *) func);
}
/*================ interpreter interface ==================================*/
pHdb GetHipadabaRoot()
{
return root;
}
/*-------------------------------------------------------------------------*/
static char *hdbTypes[] = { "none",
"int",
"float",
"text",
"intar",
"floatar",
"intvarar",
"floatvarar",
"object",
"func",
NULL
};
/*-------------------------------------------------------------------------*/
int convertHdbType(char *text)
{
int type;
type = 0;
while (hdbTypes[type] != NULL) {
if (strcasecmp(hdbTypes[type], text) == 0) {
break;
}
type++;
}
type--; /* we start counting at -1 */
return type;
}
/*-------------------------------------------------------------------------*/
static char *hdbTypeToText(int type)
{
return hdbTypes[type + 1];
}
/*--------------------------------------------------------------------------*/
static int MakeHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
int type = 0, i, length = 0, priv = -1;
char *name = NULL;
pHdb parent = NULL;
pHdb child = NULL;
char buffer[512], buffer2[512];
hdbValue val;
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
if (argc < 4) {
SCWrite(pCon, "ERROR: not enough arguments to MakeHdbNode", eError);
return 0;
}
/*
* convert privilege
*/
priv = decodeSICSPriv(argv[2]);
/*
* convert datatype
*/
type = convertHdbType(argv[3]);
if (type > HIPFLOATVARAR) {
SCWrite(pCon,
"ERROR: invalid type requested: none, int, float, text, intar, floatar, intvarar, floatvarar supported",
eError);
return 0;
}
if (type >= HIPINTAR) {
if (argc < 5) {
SCWrite(pCon, "ERROR: array length missing for array data type",
eError);
return 0;
} else {
length = atoi(argv[4]);
}
}
parent = FindHdbParent(NULL, argv[1], &name, pCon);
if (parent == NULL) {
return 0; /* error messages written inside FindHdbParent */
}
if (type != HIPNONE) {
val = makeHdbValue(type, length);
child = MakeSICSHdbPar(name, priv, val);
ReleaseHdbValue(&val);
} else {
child = MakeHipadabaNode(name, type, length);
}
if (child == NULL) {
SCWrite(pCon, "ERROR: out of memory creating node", eError);
return 0;
}
AddHipadabaChild(parent, child, pCon);
SCSendOK(pCon);
return 1;
}
/*--------------------------------------------------------------------------*/
static int MakeHdbScriptNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
int type = 0, i, length = 0;
char *name = NULL;
pHdb parent = NULL;
pHdb child = NULL;
pHdb current = NULL;
char *urgv[] = { "5", NULL };
char driver[] = { "hdb" };
char buffer[512], buffer2[512];
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
if (argc < 5) {
SCWrite(pCon, "ERROR: not enough arguments to MakeHdbNode", eError);
return 0;
}
/*
* convert datatype
*/
strtolower(argv[4]);
type = convertHdbType(argv[4]);
if (type >= 7) {
SCWrite(pCon,
"ERROR: invalid type requested: none, int, float, text, intar, floatar, intvarar, floatvarar supported",
eError);
return 0;
}
if (type > 2) {
if (argc < 6) {
SCWrite(pCon, "ERROR: array length missing for array data type",
eError);
return 0;
} else {
length = atoi(argv[5]);
}
}
parent = FindHdbParent(NULL, argv[1], &name, pCon);
if (parent == NULL) {
return 0; /* error messages written inside FindHdbParent */
}
child = MakeSICSScriptPar(name, argv[3], argv[2],
makeHdbValue(type, length));
if (child == NULL) {
SCWrite(pCon, "ERROR: out of memory creating node", eError);
return 0;
}
AddHipadabaChild(parent, child, pCon);
/*
* have it polled automatically
*/
addPollObject(poller, pCon, GetHipadabaPath(child), driver, 1, urgv);
SCSendOK(pCon);
return 1;
}
/*------------------------------------------------------------------------------*/
static int isNodeProtected(pHdb node)
{
pHdb current = NULL;
if (node->iprotected == 1) {
return 1;
}
current = node->child;
while (current != NULL) {
if (isNodeProtected(current)) {
return 1;
}
current = current->next;
}
return 0;
}
/*-----------------------------------------------------------------------------------------*/
static int DeleteHdbNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb killNode = NULL;
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node to delete", eError);
return 0;
}
killNode = FindHdbNode(NULL, argv[1], pCon);
if (killNode == NULL) {
SCWrite(pCon, "ERROR: node to delete not found", eError);
return 0;
}
if (isNodeProtected(killNode)) {
SCWrite(pCon, "ERROR: this node or one of its children is protected",
eError);
return 0;
}
RemoveSICSPar(killNode, pCon);
SCSendOK(pCon);
return 1;
}
/*---------------------------------------------------------------------------*/
static int SetHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb targetNode = NULL;
hdbValue newValue;
pDynString parData = NULL;
char error[512], value[132];
int i, status, priv;
pIDrivable pDriv = NULL;
pDummy data = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: insufficient number of arguments to SetHdbNode",
eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
status = GetHdbProperty(targetNode,"priv",value,sizeof(value));
if(status == 1){
priv = decodeSICSPriv(value);
} else {
priv = usUser;
}
if (!SCMatchRights(pCon, priv)) {
return 0;
}
/**
* special code to handle certain types of motors right
**/
status = GetHdbProperty(targetNode,"sicsdev",value,sizeof(value));
if(status == 1){
data = (pDummy)FindCommandData(pSics,value,NULL);
if(data != NULL){
pDriv = GetDrivableInterface(data);
if(pDriv != NULL){
status = StartDevice(pServ->pExecutor,value, data->pDescriptor,
data, pCon,RUNRUN, atof(argv[2]));
if(status == 1){
SCSendOK(pCon);
}
return status;
}
}
}
if (!cloneHdbValue(&targetNode->value, &newValue)) {
SCWrite(pCon, "ERROR: out of memory cloning node", eError);
return 0;
}
parData = CreateDynString(64, 64);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory reading parameter", eError);
return 0;
}
DynStringConcat(parData, argv[2]);
for (i = 3; i < argc; i++) {
DynStringConcat(parData, " ");
DynStringConcat(parData, argv[i]);
}
strcpy(error, "ERROR: ");
if (!readHdbValue(&newValue, GetCharArray(parData), error + 7, 512 - 7)) {
SCWrite(pCon, error, eError);
return 0;
}
DeleteDynString(parData);
status = SetHipadabaPar(targetNode, newValue, pCon);
ReleaseHdbValue(&newValue);
if (status == 1) {
/* SCSendOK(pCon); sending ok has to be done by the callback. */
}
return status;
}
/*---------------------------------------------------------------------------*/
static int UpdateHdbNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
hdbValue newValue;
pDynString parData = NULL;
char error[512];
int i, status;
/*
if(!SCMatchRights(pCon,usUser)){
return 0;
}
*/
if (argc < 2) {
SCWrite(pCon,
"ERROR: insufficient number of arguments to UpdateHdbNode",
eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
/* SCPrintf(pCon,eWarning, "Updating %s", argv[1]); */
if (argc > 2) {
if (!cloneHdbValue(&targetNode->value, &newValue)) {
SCWrite(pCon, "ERROR: out of memory cloning node", eError);
return 0;
}
parData = CreateDynString(64, 64);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory reading parameter", eError);
return 0;
}
DynStringConcat(parData, argv[2]);
for (i = 3; i < argc; i++) {
DynStringConcat(parData, " ");
DynStringConcat(parData, argv[i]);
}
strcpy(error, "ERROR: ");
if (!readHdbValue(&newValue, GetCharArray(parData),
error + 7, 512 - 7)) {
SCWrite(pCon, error, eError);
return 0;
}
DeleteDynString(parData);
} else {
memset(&newValue, 0, sizeof(hdbValue));
GetHipadabaPar(targetNode, &newValue, pCon);
}
status = UpdateHipadabaPar(targetNode, newValue, pCon);
ReleaseHdbValue(&newValue);
if (status == 1 && SCinMacro(pCon) == 0) {
SCSendOK(pCon);
}
return status;
}
/*-----------------------------------------------------------------------------*/
static int ZipGetHdbNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
char error[512], oriPath[512];
int status = 0;
hdbValue newValue;
pDynString parData = NULL, result= NULL;
Protocol protocol = normal_protocol;
OutCode outCode;
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node", eError);
return 0;
}
strlcpy(oriPath, argv[1], 511);
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
memset(&newValue, 0, sizeof(hdbValue));
GetHipadabaPar(targetNode, &newValue, pCon);
if(newValue.dataType == HIPTEXT){
parData = formatValue(newValue, targetNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
result = CreateDynString(128, 128);
formatNameValue(protocol, oriPath, GetCharArray(parData), result,
newValue.dataType);
SCWrite(pCon, GetCharArray(result), outCode);
DeleteDynString(parData);
DeleteDynString(result);
} else {
status = sendZippedNodeData(targetNode, newValue, pCon);
}
ReleaseHdbValue(&newValue);
return status;
}
/*-----------------------------------------------------------------------------*/
static int ZipReadHdbNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
char error[512], oriPath[512];
int status = 0;
pDynString parData = NULL, result= NULL;
Protocol protocol = normal_protocol;
OutCode outCode;
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node", eError);
return 0;
}
strlcpy(oriPath, argv[1], 511);
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
if(targetNode->value.dataType == HIPTEXT){
parData = formatValue(targetNode->value, targetNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
if ((protocol = isJSON(pCon,0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
result = CreateDynString(128, 128);
formatNameValue(protocol, oriPath, GetCharArray(parData), result,
targetNode->value.dataType);
SCWrite(pCon, GetCharArray(result), outCode);
DeleteDynString(parData);
DeleteDynString(result);
} else {
status = sendZippedNodeData(targetNode, targetNode->value, pCon);
}
return status;
}
/*---------------------------------------------------------------------------*/
static int BinReadHdbNode(SConnection *pCon, SicsInterp *pSics,
void *pData, int argc, char *argv[])
{
static int binMagic = 7333;
pHdb targetNode = NULL;
char oriPath[512];
hdbValue val;
int *data = NULL, i;
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node", eError);
return 0;
}
strlcpy(oriPath, argv[1], 511);
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
val = targetNode->value;
switch(val.dataType){
case HIPINTAR:
case HIPINTVARAR:
data = malloc(val.arrayLength+2*sizeof(int));
if(data == NULL){
SCWrite(pCon,"ERROR: out of memory in BinReadHdbNode",eError);
return 0;
}
data[0] = binMagic;
data[1] = val.arrayLength;
memcpy(data+2,val.v.intArray,val.arrayLength*sizeof(int));
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
data = malloc(val.arrayLength+2*sizeof(int));
if(data == NULL){
SCWrite(pCon,"ERROR: out of memory in BinReadHdbNode",eError);
return 0;
}
data[0] = binMagic;
data[1] = val.arrayLength;
for(i = 0; i < val.arrayLength; i++){
data[i+2] = (int)(val.v.floatArray[i]*65536.);
}
break;
default:
SCWrite(pCon,"ERROR: cannot send binary data for this node type",eError);
return 0;
}
if(data != NULL){
ANETwrite(SCGetSockHandle(pCon),data,(val.arrayLength+2)*sizeof(int));
free(data);
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int GetHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb targetNode = NULL;
hdbValue newValue;
pDynString parData = NULL, result = NULL;
char error[512], oriPath[512];;
int i, status;
Protocol protocol = normal_protocol;
int outCode;
char value[80];
/*
if(strstr(argv[1],"values") != NULL){
printf("Found!!\n");
}
*/
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node to print", eError);
return 0;
}
strlcpy(oriPath, argv[1], 511);
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
/*
* if transfer = zip or bin, redirect to zip
*/
if (GetHdbProperty(targetNode, "transfer", value, 80) == 1) {
if (strstr(value, "zip") != NULL || strstr(value,"bin") != NULL) {
return ZipGetHdbNode(pCon, pSics, pData, argc, argv);
}
}
memset(&newValue, 0, sizeof(hdbValue));
/* ffr XXX I expect if status=0 then we don't have a valid value
Original code was causing a segfault for hdb text nodes
*/
if (0 == GetHipadabaPar(targetNode, &newValue, pCon))
return 0;
parData = formatValue(newValue, targetNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
result = CreateDynString(128, 128);
formatNameValue(protocol, oriPath, GetCharArray(parData), result,
newValue.dataType);
SCWrite(pCon, GetCharArray(result), outCode);
DeleteDynString(parData);
DeleteDynString(result);
ReleaseHdbValue(&newValue);
return 1;
}
/*---------------------------------------------------------------------------*/
static int GetHdbVal(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb targetNode = NULL;
hdbValue newValue;
pDynString parData = NULL;
char error[512], oriPath[512];
int i, status, protocol, outCode;
char value[80];
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node to print", eError);
return 0;
}
strlcpy(oriPath, argv[1], 511);
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
memset(&newValue, 0, sizeof(hdbValue));
if (0 == GetHipadabaPar(targetNode, &newValue, pCon))
return 0;
parData = formatValue(newValue, targetNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
} else {
if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
SCWrite(pCon, GetCharArray(parData), outCode);
DeleteDynString(parData);
ReleaseHdbValue(&newValue);
return 1;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static int GetHdbValIgnoreError(
SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
pDynString parData = NULL;
int protocol, outCode;
if (argc != 2) {
SCWrite(pCon, "ERROR: syntax must be: hvali <path>", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
parData = formatValue(targetNode->value, targetNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
if ((protocol = isJSON(pCon, 0)) == 1)
outCode = eHdbEvent;
else
outCode = eValue;
SCWrite(pCon, GetCharArray(parData), outCode);
DeleteDynString(parData);
return 1;
}
/*--------------------------------------------------------------------------*/
static int countChildren(pHdb node)
{
pHdb current = NULL;
int count = 0;
current = node->child;
while (current != NULL) {
count++;
current = current->next;
}
return count;
}
/*---------------------------------------------------------------------------*/
static int HdbNodeInfo(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb targetNode = NULL;
char error[512], oriPath[512], info[512];
int i, status, length;
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node to get info", eError);
return 0;
}
strlcpy(oriPath, argv[1], 511);
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
length = targetNode->value.arrayLength;
if (length == 0) {
length = 1;
}
snprintf(info, 511, "%s,%d,%d",
hdbTypeToText(targetNode->value.dataType),
countChildren(targetNode), length);
SCWrite(pCon, info, eValue);
return 1;
}
/*---------------------------------------------------------------------------*/
static int HdbNodeVal(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb targetNode = NULL;
hdbValue newValue;
pDynString parData = NULL;
char error[512];
int i, status;
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node to print", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
return 0;
}
memset(&newValue, 0, sizeof(hdbValue));
GetHipadabaPar(targetNode, &newValue, pCon);
parData = formatValue(newValue, targetNode);
if (parData == NULL) {
SCWrite(pCon, "ERROR: out of memory formatting data", eError);
return 0;
}
SCWrite(pCon, GetCharArray(parData), eHdbValue);
DeleteDynString(parData);
ReleaseHdbValue(&newValue);
return 1;
}
/*---------------------------------------------------------------------------*/
int isSICSHdbRO(pHdb node)
{
pHdbCallback current = NULL;
current = node->callBackChain;
while (current != NULL) {
if (current->userCallback == SICSReadOnlyCallback) {
return 1;
}
current = current->next;
}
return 0;
}
/*---------------------------------------------------------------------------*/
static pDynString formatPlainList(pHdb node)
{
pHdb current;
pDynString result = NULL;
result = CreateDynString(128, 128);
if (result == NULL) {
return NULL;
}
current = node->child;
while (current != NULL) {
DynStringConcat(result, current->name);
DynStringConcat(result, "\n");
current = current->next;
}
return result;
}
/*---------------------------------------------------------------------------*/
static pDynString formatJSONList(pHdb node, int withValues)
{
pHdb current;
pDynString result = NULL;
pDynString data = NULL;
char *str;
if (node->child == NULL)
return NULL;
result = CreateDynString(128, 128);
if (result == NULL) {
return NULL;
}
if (withValues)
DynStringCopy(result, "{");
else
DynStringCopy(result, "[");
current = node->child;
while (current != NULL) {
DynStringConcatChar(result, '"');
DynStringConcat(result, current->name);
DynStringConcatChar(result, '"');
if (withValues) {
DynStringConcat(result, ": ");
if (current->value.dataType == HIPTEXT) {
DynStringConcatChar(result, '"');
data = formatValue(current->value, current);
if (data != NULL) {
/* lazy approach: remove \ and " */
for (str = GetCharArray(data); *str != 0; str++) {
if (*str == '\\' || *str == '"') {
*str = '_';
}
}
DynStringConcat(result, GetCharArray(data));
DeleteDynString(data);
}
DynStringConcatChar(result, '"');
} else {
if (current->value.dataType != HIPINT && current->value.dataType != HIPFLOAT) {
data = NULL;
} else {
data = formatValue(current->value, current);
}
if (data != NULL) {
DynStringConcat(result, GetCharArray(data));
DeleteDynString(data);
} else {
DynStringConcat(result, "null");
}
}
}
if (current->next != NULL)
DynStringConcat(result, ", ");
current = current->next;
}
if (withValues)
DynStringConcat(result, "}");
else
DynStringConcat(result, "]");
return result;
}
/*---------------------------------------------------------------------------*/
static pDynString formatListWithVal(pHdb node)
{
pHdb current;
pDynString result = NULL;
pDynString data = NULL;
result = CreateDynString(128, 128);
if (result == NULL) {
return NULL;
}
current = node->child;
while (current != NULL) {
if (current->value.dataType != HIPNONE) {
DynStringConcat(result, current->name);
data = formatValue(current->value, current);
if (data != NULL) {
DynStringConcat(result, " = ");
DynStringConcat(result, GetCharArray(data));
DeleteDynString(data);
}
DynStringConcat(result, "\n");
}
current = current->next;
}
return result;
}
/*---------------------------------------------------------------------------*/
static pDynString formatClientList(pHdb node)
{
pHdb current;
pDynString result = NULL;
int length;
int i;
char number[50];
result = CreateDynString(128, 128);
if (result == NULL) {
return NULL;
}
current = node->child;
while (current != NULL) {
DynStringConcat(result, current->name);
DynStringConcat(result, ",");
DynStringConcat(result, hdbTypeToText(current->value.dataType));
DynStringConcat(result, ",");
snprintf(number, 50, "%d", countChildren(current));
DynStringConcat(result, number);
DynStringConcat(result, ",");
if (current->value.dataType >= 3) {
length = current->value.arrayLength;
} else {
length = 1;
}
snprintf(number, 50, "%d", length);
DynStringConcat(result, number);
DynStringConcat(result, ",");
switch (current->value.dataType) {
case HIPNONE:
break;
case HIPINT:
snprintf(number, 50, "%d", current->value.v.intValue);
DynStringConcat(result, number);
break;
case HIPFLOAT:
snprintf(number, 50, "%lg", current->value.v.doubleValue);
DynStringConcat(result, number);
break;
case HIPTEXT:
DynStringConcat(result, current->value.v.text);
break;
case HIPINTAR:
case HIPINTVARAR:
for (i = 0; i < length; i++) {
snprintf(number, 50, "%d", current->value.v.intArray[i]);
DynStringConcat(result, number);
if (i > length - 1) {
DynStringConcat(result, ",");
}
}
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
for (i = 0; i < length; i++) {
snprintf(number, 50, "%lf", current->value.v.floatArray[i]);
DynStringConcat(result, number);
if (i > length - 1) {
DynStringConcat(result, ",");
}
}
break;
}
DynStringConcat(result, "\n");
current = current->next;
}
return result;
}
/*---------------------------------------------------------------------------*/
static int ListHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb node = NULL;
int pathArg = 1;
pDynString listData = NULL;
Protocol protocol = normal_protocol;
int outCode;
if (argc < 2) {
SCWrite(pCon, "ERROR: need path to node to print", eError);
return 0;
}
if (argv[1][0] == '-') {
pathArg = 2;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path to node to print", eError);
return 0;
}
}
node = FindHdbNode(NULL, argv[pathArg], pCon);
if (node == NULL) {
return 0;
}
/* do not modify arguments!
if (pathArg == 2) {
strtolower(argv[1]);
}
*/
outCode = eValue;
if (strcasecmp(argv[1], "-val") == 0) {
if (isJSON(pCon, 0)) {
listData = formatJSONList(node, 1);
outCode = eHdbEvent;
} else {
listData = formatListWithVal(node);
}
} else if (strcasecmp(argv[1], "-cli") == 0) {
listData = formatClientList(node);
} else {
if ((protocol = isJSON(pCon, 0)) == 1) {
listData = formatJSONList(node, 0);
outCode = eHdbEvent;
} else {
listData = formatPlainList(node);
}
}
if (listData == NULL) {
SCWrite(pCon, "ERROR: failed to format list", eError);
return 0;
}
SCWrite(pCon, GetCharArray(listData), outCode);
DeleteDynString(listData);
return 1;
}
/*---------------------------------------------------------------------------*/
static int AutoNotifyHdbNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb node = NULL;
int id, status, recurse = 1;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path and id in order to add notify",
eError);
return 0;
}
node = FindHdbNode(NULL, argv[1], pCon);
if (node == NULL) {
return 0;
}
id = atoi(argv[2]);
if(argc > 3) {
recurse = atoi(argv[3]);
}
status = InstallSICSNotify(node, pCon, id, recurse);
if (status == 1) {
SCSendOK(pCon);
}
return status;
}
/*---------------------------------------------------------------------------*/
static int RemoveHdbCallback(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
int id;
hdbIDMessage m;
pObjectDescriptor pObj = NULL;
if (argc < 2) {
SCWrite(pCon, "ERROR: need callback id to remove", eError);
return 0;
}
id = atoi(argv[1]);
m.type = killID;
m.ID = id;
if(argc < 3){
RecurseCallbackChains(root, (pHdbMessage) & m);
} else {
pObj = FindCommandDescriptor(pSics,argv[2]);
if(pObj != NULL && pObj->parNode != NULL){
RecurseCallbackChains(pObj->parNode,(pHdbMessage)&m);
}
}
SCSendOK(pCon);
return 1;
}
/*---------------------------------------------------------------------------*/
static int LinkHdbNode(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb node = NULL;
char buffer[256];
pObjectDescriptor pDes = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path and object name to link", eError);
return 0;
}
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
node = GetHipadabaNode(root, argv[1]);
if (node == NULL) {
snprintf(buffer, 255, "ERROR: path %s NOT found!", argv[1]);
SCWrite(pCon, buffer, eError);
return 0;
}
pDes = FindCommandDescriptor(pSics, argv[2]);
if (pDes == NULL) {
snprintf(buffer, 255, "ERROR: failed to find object %s", argv[2]);
SCWrite(pCon, buffer, eError);
return 0;
}
if (pDes->parNode == NULL) {
snprintf(buffer, 255,
"ERROR: Object %s does not use Hipadaba natively and thus cannot be linked",
argv[2]);
SCWrite(pCon, buffer, eError);
return 0;
}
if (pDes->parNode->mama != NULL) {
snprintf(buffer, 255,
"ERROR: Object %s is already linked somewhere else", argv[2]);
SCWrite(pCon, buffer, eError);
return 0;
}
AddHipadabaChild(node, pDes->parNode, pCon);
if (argc > 3) {
if (pDes->parNode->name != NULL) {
free(pDes->parNode->name);
}
pDes->parNode->name = strdup(argv[3]);
}
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------*/
static int isArrayNode(pHdb node)
{
switch(node->value.dataType) {
case HIPINTAR:
case HIPFLOATAR:
case HIPINTVARAR:
case HIPFLOATVARAR:
return 1;
default:
return 0;
}
return 0;
}
/*-------------------------------------------------------------------------*/
static int ArrayCopyNode(pHdb to, SConnection *pCon, int argc, char *argv[])
{
pHdb from = NULL;
int iStart, iLength;
hdbValue fromData;
from = FindHdbNode(NULL,argv[3],pCon);
if(from == NULL){
SCPrintf(pCon,eError,"ERROR: source node %s not found", argv[3]);
return 0;
}
if(!isArrayNode(from)){
SCPrintf(pCon,eError,"ERROR: %s is no array data node", argv[3]);
return 0;
}
iStart = 0;
iLength = from->value.arrayLength;
if(argc > 4) {
iStart = atoi(argv[4]);
if(iStart < 0) {
iStart = 0;
}
}
if(argc > 5) {
iLength = atoi(argv[5]);
if(iStart + iLength > from->value.arrayLength){
iLength = from->value.arrayLength - iStart - 1;
}
}
switch(from->value.dataType){
case HIPINTAR:
case HIPINTVARAR:
fromData = MakeHdbIntArray(iLength, from->value.v.intArray+iStart);
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
fromData = MakeHdbFloatArray(iLength, from->value.v.floatArray+iStart);
break;
default:
assert(0);
/* cannot really happen */
}
if(!copyHdbValue(&fromData, &to->value)) {
SCPrintf(pCon,eError,"ERROR: cannot copy data from %s to %s because of data type mismatch",
argv[3],argv[1]);
return 0;
}
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------*/
static int ArrayCopyOldHM(pHdb to, SConnection *pCon, int argc, char *argv[])
{
pHistMem hm = NULL;
int iStart, iLength;
int *data = NULL;
hdbValue copyData;
hm = (pHistMem)FindCommandData(pServ->pSics, argv[3],"HistMem");
if(hm == NULL){
SCPrintf(pCon,eError,"ERROR: cannot find HM %s", argv[3]);
return 0;
}
iStart = 0;
iLength = GetHistLength(hm);
if(argc > 4){
iStart = atoi(argv[4]);
iLength -= iStart;
}
if(argc > 5){
iLength = atoi(argv[5]);
}
if(iStart < 0){
iStart = 0;
}
if(iStart + iLength > GetHistLength(hm)){
iLength = GetHistLength(hm) - iStart - 1;
}
data = GetHistogramPointer(hm,pCon);
if(data == NULL){
SCPrintf(pCon,eError, "ERROR: failed to retrive HM data for %s", argv[3]);
return 0;
}
copyData = MakeHdbIntArray(iLength, data + iStart);
if(!copyHdbValue(&copyData, &to->value)) {
SCPrintf(pCon,eError,"ERROR: cannot copy data from %s to %s because of data type mismatch",
argv[3],argv[1]);
return 0;
}
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------*/
static int ArrayCopyOldTB(pHdb to, SConnection *pCon, int argc, char *argv[])
{
pHistMem hm = NULL;
int iStart, iLength, timeLength, i;
const float *data = NULL;
double *ddata = NULL;
hdbValue copyData;
hm = (pHistMem)FindCommandData(pServ->pSics, argv[3],"HistMem");
if(hm == NULL){
SCPrintf(pCon,eError,"ERROR: cannot find HM %s", argv[3]);
return 0;
}
iStart = 0;
data = GetHistTimeBin(hm,&timeLength);
if(data == NULL){
SCPrintf(pCon,eError, "ERROR: failed to retrive time binning for HM %s", argv[3]);
return 0;
}
iLength = timeLength;
if(argc > 4){
iStart = atoi(argv[4]);
iLength -= iStart;
}
if(argc > 5){
iLength = atoi(argv[5]);
}
if(iStart < 0){
iStart = 0;
}
if(iStart + iLength > timeLength){
iLength = timeLength - iStart - 1;
}
ddata = malloc(iLength*sizeof(double));
if(ddata == NULL){
SCPrintf(pCon,eError,"ERROR: out of memory copying %s time binning to %s",
argv[3],argv[1]);
return 0;
}
for(i = 0; i < iLength; i++){
ddata[i] = data[iStart+i];
}
copyData = MakeHdbFloatArray(iLength, ddata);
if(!copyHdbValue(&copyData, &to->value)) {
SCPrintf(pCon,eError,
"ERROR: cannot copy data from %s to %s because of data type mismatch",
argv[3],argv[1]);
return 0;
}
free(ddata);
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------*/
static int HdbArrayNode(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb node = NULL;
pObjectDescriptor pDes = NULL;
int length, idx, ival, i;
int xstart, xend, xlength, ystart, yend, ylength;
double dval;
hdbValue v;
long sum;
if (argc < 4) {
SCWrite(pCon, "ERROR: need at least three arguments to harray", eError);
return 0;
}
if (!SCMatchRights(pCon, usUser)) {
return 0;
}
node = FindHdbNode(NULL, argv[1], pCon);
if (node == NULL) {
SCPrintf(pCon, eError, "ERROR: path %s NOT found!", argv[1]);
return 0;
}
if(!isArrayNode(node)){
SCPrintf(pCon,eError,"ERROR: %s is no array node!", argv[1]);
return 0;
}
if(strcmp(argv[2], "resize") == 0){
length = atoi(argv[3]);
v = makeHdbValue(node->value.dataType, length);
UpdateHipadabaPar(node, v, pCon);
ReleaseHdbValue(&v);
SCSendOK(pCon);
return 1;
}
if(strcmp(argv[2], "init") == 0){
v = makeHdbValue(node->value.dataType, node->value.arrayLength);
switch(node->value.dataType){
case HIPINTAR:
case HIPINTVARAR:
ival = atoi(argv[3]);
for(i = 0; i < v.arrayLength; i++){
v.v.intArray[i] = ival;
}
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
dval = atof(argv[3]);
for(i = 0; i < v.arrayLength; i++){
v.v.intArray[i] = dval;
}
break;
}
UpdateHipadabaPar(node, v, pCon);
ReleaseHdbValue(&v);
SCSendOK(pCon);
return 1;
}
if(strcmp(argv[2],"sum") == 0){
if(argc < 9){
SCWrite(pCon,"ERROR: not enough arguments to harray sum", eError);
return 0;
}
xstart = atoi(argv[3]);
xend = atoi(argv[4]);
xlength = atoi(argv[5]);
ystart = atoi(argv[6]);
yend = atoi(argv[7]);
ylength = atoi(argv[8]);
sum = sumWindow(node->value.v.intArray,xstart,xend,xlength,ystart,yend,ylength);
SCPrintf(pCon,eValue,"sum = %ld", sum);
return 1;
}
if(strcmp(argv[2],"copynode") == 0){
return ArrayCopyNode(node, pCon, argc, argv);
}
if(strcmp(argv[2],"copyoldhm") == 0){
return ArrayCopyOldHM(node, pCon, argc, argv);
}
if(strcmp(argv[2],"copyoldtb") == 0){
return ArrayCopyOldTB(node, pCon, argc, argv);
}
idx = atoi(argv[2]);
if(idx < 0 || idx >= node->value.arrayLength ){
SCPrintf(pCon,eError,"ERROR: %d is out of range 0 - %d",
idx, node->value.arrayLength);
return 0;
}
switch(node->value.dataType){
case HIPINTAR:
case HIPINTVARAR:
node->value.v.intArray[idx] = atoi(argv[3]);
break;
case HIPFLOATAR:
case HIPFLOATVARAR:
node->value.v.floatArray[idx] = atof(argv[3]);
break;
}
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------*/
static hdbCallbackReturn ChainCallback(pHdb node, void *userData,
pHdbMessage message)
{
pHdb slave = (pHdb) userData;
hdbValue vv, old;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbUpdateMessage(message)) == NULL) {
return hdbContinue;
}
if (slave != NULL) {
memset(&vv, 0, sizeof(hdbValue));
/*
The GetHipadabaPar here has to happen. Otherwise
necessary calculations to update the slave are not
performed.
*/
GetHipadabaPar(slave, &vv, mm->callData);
UpdateHipadabaPar(slave, vv, mm->callData);
ReleaseHdbValue(&vv);
}
return hdbContinue;
}
/*--------------------------------------------------------------------------*/
static int ChainHdbNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb master = NULL, slave = NULL;
char buffer[512];
pHdbCallback kalle = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: insufficent number of arguments to hchain",
eError);
}
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
slave = GetHipadabaNode(root, argv[1]);
if (slave == NULL) {
snprintf(buffer, 511, "ERROR: slave %s not found", argv[1]);
SCWrite(pCon, buffer, eError);
return 0;
}
master = GetHipadabaNode(root, argv[2]);
if (master == NULL) {
snprintf(buffer, 511, "ERROR: master %s not found", argv[1]);
SCWrite(pCon, buffer, eError);
return 0;
}
kalle = MakeHipadabaCallback(ChainCallback, slave, NULL);
if (kalle == NULL) {
SCWrite(pCon, "ERROR: out of memory creating callback", eError);
return 0;
}
AppendHipadabaCallback(master, kalle);
SCSendOK(pCon);
return 1;
}
/* --------------------------------------------------------------------------
* This is actually SCInvoke but without advancing the context. I think this
* is only of local use. It makes sure that commands executed as Hipadaba
* commands get logged properly.
*/
static int HDBInvoke(SConnection * self, SicsInterp * pInter,
char *pCommand)
{
int iRet;
long lLen;
const char *pResult = NULL;
char *pBuffer = NULL, *pFile = NULL;
char pBueffel[80];
int i, iSpace;
assert(pInter);
/* print command to log files */
/*
for( i = 0; i < self->iFiles; i++)
{
if(self->pFiles[i])
{
fprintf(self->pFiles[i],"SICS>> %s\n",pCommand);
}
}
*/
/* print to command log if user or manager */
if (SCGetRights(self) <= usUser) {
if (self->pSock != NULL) {
sprintf(pBueffel, "sock %d>>", self->pSock->sockid);
}
}
/* invoke */
self->inUse++;
self->eInterrupt = eContinue;
/*
get first word of command
*/
iRet = InterpExecute(pInter, self, pCommand);
StatusFileTask(NULL); /* save changed parameters */
self->inUse--;
return iRet;
}
/*---------------------------------------------------------------------------*/
static hdbCallbackReturn CommandSetCallback(pHdb node, void *userData,
pHdbMessage message)
{
SConnection *pCon = NULL;
pDynString cmd = NULL, par = NULL;
pHdb current = NULL;
int status;
pHdbDataMessage mm = NULL;
hdbValue v;
/**
* TODO: this is a duplicate: resolve. It is still here because the old
* Hipadaba configuration commands still work
*/
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
pCon = (SConnection *) mm->callData;
v = *(mm->v);
if (pCon == NULL) {
printf("Cannot invoke command without connection\n");
return hdbAbort;
}
if (v.dataType == HIPTEXT) {
if (strstr(v.v.text, "start") != NULL) {
cmd = CreateDynString(64, 64);
if (cmd == 0) {
SCWrite(pCon, "ERROR: out of memory in CommandSetCallback",
eError);
return 0;
}
DynStringCopy(cmd, node->value.v.text);
DynStringConcat(cmd, " ");
current = node->child;
while (current != NULL) {
par = formatValue(current->value, current);
if (par != NULL) {
DynStringConcat(cmd, GetCharArray(par));
DynStringConcat(cmd, " ");
DeleteDynString(par);
}
current = current->next;
}
// SendHdbStatusMessage(node,"start");
status = HDBInvoke(pCon, pServ->pSics, GetCharArray(cmd));
// SendHdbStatusMessage(node,"stop");
DeleteDynString(cmd);
if (status == 1) {
return hdbContinue;
} else {
return hdbAbort;
}
} else {
SCWrite(pCon, "ERROR: this node only understands start as value",
eError);
return hdbAbort;
}
}
return hdbContinue;
}
/*---------------------------------------------------------------------------*/
static hdbCallbackReturn CommandGetCallback(pHdb node, void *userData,
pHdbMessage message)
{
pHdbDataMessage mm = NULL;
if ((mm = GetHdbGetMessage(message)) == NULL) {
return hdbContinue;
}
hdbValue v2 = MakeHdbText("Nothing to get");
copyHdbValue(&v2, mm->v); /* MakeHdbText makes no strdup ! */
return hdbContinue;
}
/*--------------------------------------------------------------------------*/
static int SicsCommandNode(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
char *name = NULL;
pHdbCallback kalle = NULL;
pHdb parent = NULL, node = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: insufficent number of arguments to hcommand",
eError);
return 0;
}
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
parent = FindHdbParent(NULL, argv[1], &name, pCon);
if (parent == NULL) {
return 0; /* error message already written */
}
node = MakeHipadabaNode(name, HIPTEXT, 1);
if (node == NULL) {
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
return 0;
}
node->value.v.text = strdup(argv[2]);
node->value.arrayLength = strlen(argv[2]);
SetHdbProperty(node, "sicscommand", argv[2]);
// Set privillege of the node
if (argc > 3) {
SetHdbProperty(node, "priv", argv[3]);
}
kalle = MakeHipadabaCallback(CommandSetCallback, NULL, NULL);
if (kalle == NULL) {
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
return 0;
}
AppendHipadabaCallback(node, kalle);
kalle = MakeHipadabaCallback(CommandGetCallback, NULL, NULL);
if (kalle == NULL) {
SCWrite(pCon, "ERROR: out of memory in hcommand", eError);
return 0;
}
AppendHipadabaCallback(node, kalle);
AddHipadabaChild(parent, node, pCon);
SCSendOK(pCon);
return 1;
}
/*======================= Property Functions ================================*/
static int SetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
char *val;
if (argc < 4) {
SCWrite(pCon, "ERROR: need path key value as parameters", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
return 0;
}
if (argc == 4) {
SetHdbProperty(targetNode, argv[2], argv[3]);
} else {
val = Arg2Tcl(argc - 3, &argv[3], NULL, 0);
if (val) {
SetHdbProperty(targetNode, argv[2], val);
free(val);
}
}
SCSendOK(pCon);
return 1;
}
/*-------------------------------------------------------------------------------*/
static int DelSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path and key as parameters", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
return 0;
}
SetHdbProperty(targetNode, argv[2], NULL);
SCSendOK(pCon);
return 1;
}
/*--------------------------------------------------------------------------*/
static int HasSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path key as parameters", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCWrite(pCon, "ERROR: node not found", eError);
return 0;
}
if (HasHdbProperty(targetNode, argv[2])) {
SCPrintf(pCon, eValue, "%s", "true");
return 1;
} else {
SCPrintf(pCon, eValue, "%s", "false");
return 1;
}
}
/*--------------------------------------------------------------------------*/
static int GetSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
char buffer[512];
int status;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path and key as parameters", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
return 0;
}
status = GetHdbProperty(targetNode, argv[2], buffer, 511);
if (status != 1) {
SCPrintf(pCon, eError, "ERROR: %s has no property %s", argv[1], argv[2]);
return 0;
}
SCPrintf(pCon, eValue, "%s.%s = %s", argv[1], argv[2], buffer);
return 1;
}
/*--------------------------------------------------------------------------*/
static int GetSICSHdbPropertyVal(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
char buffer[512];
int status;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path and key as parameters", eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
return 0;
}
status = GetHdbProperty(targetNode, argv[2], buffer, 511);
if (status != 1) {
SCPrintf(pCon, eError, "ERROR: %s has no property %s", argv[1], argv[2]);
return 0;
}
SCPrintf(pCon, eValue, "%s", buffer);
return 1;
}
/*--------------------------------------------------------------------------*/
static int ListSICSHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb targetNode = NULL;
char buffer[512];
const char *pKey = NULL;
pDynString data = NULL;
int genTclList = 0;
if (argc < 2) {
SCWrite(pCon, "ERROR: need path as parameter", eError);
return 0;
} else if (argc == 3) {
if (strncasecmp(argv[2], "tcl", 3) == 0)
genTclList = 1;
if (strncasecmp(argv[2], "tclesc", 6) == 0)
genTclList |= 2;
if (strncasecmp(argv[2], "tclnam", 6) == 0)
genTclList |= 4;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCPrintf(pCon, eError, "ERROR: node %s not found", argv[1]);
return 0;
}
data = CreateDynString(64, 64);
if (data == NULL) {
SCWrite(pCon, "ERROR: out of memory in ListSICSHdbProperty", eError);
return 0;
}
InitHdbPropertySearch(targetNode);
while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) {
DynStringConcat(data, (char *) pKey);
if (genTclList) {
char *bp;
DynStringConcatChar(data, ' ');
if (genTclList & 4)
continue;
DynStringConcatChar(data, '{');
for (bp = buffer; *bp; ++bp) {
if (genTclList & 2 && (*bp == '{' || *bp == '}'))
DynStringConcatChar(data, '\\');
DynStringConcatChar(data, *bp);
}
DynStringConcatChar(data, '}');
DynStringConcatChar(data, ' ');
} else {
DynStringConcat(data, "=");
DynStringConcat(data, buffer);
DynStringConcat(data, "\n");
}
}
SCWrite(pCon, GetCharArray(data), eValue);
DeleteDynString(data);
return 1;
}
/*---------------------------------------------------------------------------*/
static int CallNotify(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb node = NULL;
if(argc < 2) {
SCPrintf(pCon,eError, "ERROR: require path argument to %s", argv[0]);
return 0;
}
node = GetHipadabaNode(GetHipadabaRoot(), argv[1]);
if(node == NULL){
SCPrintf(pCon,eError,"ERROR: cannot find node %s to notify", argv[1]);
return 0;
}
NotifyHipadabaPar(node,pCon);
return 1;
}
static int ANSTO_ListSICSHdbProperty(SConnection * pCon,
SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb targetNode = NULL;
char buffer[512], *globPtr = NULL;
int cmpSize = 0;
const char *pKey = NULL;
pDynString data = NULL;
if (argc < 3) {
SCWrite(pCon, "ERROR: need path and search string as parameters",
eError);
return 0;
}
targetNode = FindHdbNode(NULL, argv[1], pCon);
if (targetNode == NULL) {
SCWrite(pCon, "ERROR: node not found", eError);
return 0;
}
data = CreateDynString(64, 64);
if (data == NULL) {
SCWrite(pCon, "ERROR: out of memory in ListSICSHdbProperty", eError);
return 0;
}
InitHdbPropertySearch(targetNode);
/* Allow simple glob matches with '*' as a suffix
Eg hfindprop /hpath @*
*/
if ((globPtr = index(argv[2], '*')) != NULL) {
*globPtr = '\0';
}
cmpSize = strlen(argv[2]);
while ((pKey = GetNextHdbProperty(targetNode, buffer, 511)) != NULL) {
if (strncasecmp(argv[2], pKey, cmpSize) == 0) {
DynStringConcat(data, (char *) pKey);
DynStringConcat(data, " ");
DynStringConcat(data, buffer);
DynStringConcat(data, "\n");
}
}
SCWrite(pCon, GetCharArray(data), eValue);
DeleteDynString(data);
return 1;
}
/*---------------------------------------------------------------------------*/
static pHdb matchHdbProp(pHdb root, char *propname, char *buffer,
pDynString result, int invertmatch)
{
char value[1024], *path = NULL;
pHdb current = NULL, search;
memset(value, 0, 1024);
if (strcmp(buffer, "*") == 0) {
if (GetHdbProperty(root, propname, value, 1023) == 1) {
if (!invertmatch) {
path = GetHipadabaPath(root);
DynStringConcat(result, path);
DynStringConcat(result, "\n");
free(path);
}
} else if (invertmatch) {
path = GetHipadabaPath(root);
DynStringConcat(result, path);
DynStringConcat(result, "\n");
free(path);
}
} else if (GetHdbProperty(root, propname, value, 1023) == 1) {
if (strstr(buffer, value) != NULL) {
if (!invertmatch) {
path = GetHipadabaPath(root);
DynStringConcat(result, path);
DynStringConcat(result, "\n");
free(path);
}
} else if (invertmatch) {
path = GetHipadabaPath(root);
DynStringConcat(result, path);
DynStringConcat(result, "\n");
free(path);
}
}
current = root->child;
while (current != NULL) {
search =
matchHdbProp(current, propname, buffer, result, invertmatch);
current = current->next;
}
return NULL;
}
/*---------------------------------------------------------------------------*/
static int MatchHdbProperty(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb root = NULL;
pHdb foundNode = NULL;
char buffer[1024], *path = NULL;
int node = 1, prop = 2, propval = 3, invertmatch = 0;
pDynString matchList = NULL;
if (argc < 4) {
SCWrite(pCon,
"ERROR: need root, property name and target string for search",
eError);
return 0;
}
if (argc >= 5) {
if (strcasecmp(argv[1], "invert") == 0) {
invertmatch = 1;
node++;
prop++;
propval++;
}
}
memset(buffer, 0, 1024);
Arg2Text(argc - propval, &argv[propval], buffer, 1023);
root = GetHipadabaNode(GetHipadabaRoot(), argv[node]);
if (root == NULL) {
SCWrite(pCon, "ERROR: start node for search not found", eError);
return 0;
}
strtolower(argv[prop]);
strtolower(buffer);
matchList = CreateDynString(128, 128);
foundNode =
matchHdbProp(root, argv[prop], buffer, matchList, invertmatch);
SCWrite(pCon, GetCharArray(matchList), eValue);
DeleteDynString(matchList);
return 1;
}
/*---------------------------------------------------------------------------*/
static int AddCheck(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb node = NULL;
if(argc < 3) {
SCPrintf(pCon,eLogError, "ERROR: need at least node and key argument for %s",
argv[0]);
return 0;
}
node = FindHdbNode(NULL, argv[1],pCon);
if (node == NULL) {
SCPrintf(pCon,eLogError, "ERROR: node %s to add check to not found", argv[1]);
return 0;
}
strtolower(argv[2]);
if(strcmp(argv[2],"values") == 0) {
PrependHipadabaCallback(node,MakeHipadabaCallback(SICSValueCheckCallback,
NULL,NULL));
SCSendOK(pCon);
return 1;
} else {
SCPrintf(pCon,eLogError,"ERROR: key %s for %s not recognized",
argv[2], argv[0]);
return 0;
}
return 1;
}
/*---------------------------------------------------------------------------*/
static hdbCallbackReturn SICSNotifyScriptCallback(pHdb node, void *userData,
pHdbMessage message)
{
char *pPath = NULL;
int macro, status;
pHdbDataMessage mm = NULL;
SConnection *tstCon;
char script[256];
/*
* Deal with update messages
*/
if ((mm = GetHdbUpdateMessage(message)) == NULL) {
return hdbContinue;
}
status = GetHdbProperty(node, "updatescript", script, sizeof(script));
if(status == 0){
tracePar(node->name,"ERROR: did not find updatescript property");
return hdbContinue;
}
if(mm->v != &node->value){
copyHdbValue(mm->v, &node->value);
}
status = Tcl_Eval(InterpGetTcl(pServ->pSics), script);
if (status != TCL_OK) {
tracePar(node->name,"ERROR: %s while evaluating updatescript %s",
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)), script);
}
return hdbContinue;
}
/*---------------------------------------------------------------------------*/
static int AddScriptNotify(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
pHdb node = NULL;
if(argc < 3) {
SCWrite(pCon,"ERROR: Parameter missing, Usage: hscriptnotify node script",
eError);
return 0;
}
node = FindHdbNode(NULL,argv[1],pCon);
if (node == NULL) {
SCPrintf(pCon,eLogError, "ERROR: node %s to add script update not found",
argv[1]);
return 0;
}
SetHdbProperty(node,"updatescript",strdup(argv[2]));
AppendHipadabaCallback(node,MakeHipadabaCallback(SICSNotifyScriptCallback,
NULL,NULL));
SCSendOK(pCon);
return 1;
}
/*======================= Factory Functions =================================*/
void killSICSHipadaba()
{
if (root != NULL) {
DeleteHipadabaNode(root, NULL);
}
root = NULL;
}
/*---------------------------------------------------------------------------*/
extern int HdbNodeFactory(SConnection * pCon, SicsInterp * pSics, void *pData, int argc, char *argv[]); /* from sicshdbfactory.c */
/*---------------------------------------------------------------------------*/
int InstallSICSHipadaba(SConnection * pCon, SicsInterp * pSics,
void *pData, int argc, char *argv[])
{
root = MakeHipadabaNode("/", HIPNONE, 0);
AddCommand(pSics, "hmake", MakeHdbNode, NULL, NULL);
AddCommand(pSics, "hfactory", HdbNodeFactory, NULL, NULL);
AddCommand(pSics, "hmakescript", MakeHdbScriptNode, NULL, NULL);
AddCommand(pSics, "hattach", SICSHdbAdapter, NULL, NULL);
AddCommand(pSics, "hsubsamplehm", HdbSubSample, NULL, NULL);
AddCommand(pSics, "hdel", DeleteHdbNode, NULL, NULL);
AddCommand(pSics, "hset", SetHdbNode, NULL, NULL);
AddCommand(pSics, "hupdate", UpdateHdbNode, NULL, NULL);
AddCommand(pSics, "hget", GetHdbNode, NULL, NULL);
AddCommand(pSics, "hval", GetHdbVal, NULL, NULL);
AddCommand(pSics, "hvali", GetHdbValIgnoreError, NULL, NULL);
AddCommand(pSics, "hzipget", ZipGetHdbNode, NULL, NULL);
AddCommand(pSics, "hzipread", ZipReadHdbNode, NULL, NULL);
AddCommand(pSics, "hbinread", BinReadHdbNode, NULL, NULL);
AddCommand(pSics, "hlist", ListHdbNode, NULL, NULL);
AddCommand(pSics, "hnotify", AutoNotifyHdbNode, NULL, NULL);
AddCommand(pSics, "hdelcb", RemoveHdbCallback, NULL, NULL);
AddCommand(pSics, "hlink", LinkHdbNode, NULL, NULL);
AddCommand(pSics, "hinfo", HdbNodeInfo, NULL, NULL);
AddCommand(pSics, "hchain", ChainHdbNode, NULL, NULL);
AddCommand(pSics, "hcommand", SicsCommandNode, NULL, NULL);
AddCommand(pSics, "harray", HdbArrayNode, NULL, NULL);
AddCommand(pSics, "hsetprop", SetSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hdelprop", DelSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hgetprop", GetSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hgetpropval", GetSICSHdbPropertyVal, NULL, NULL);
AddCommand(pSics, "hmatchprop", MatchHdbProperty, NULL, NULL);
AddCommand(pSics, "hpropexists", HasSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hlistprop", ListSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hfindprop", ANSTO_ListSICSHdbProperty, NULL, NULL);
AddCommand(pSics, "hcallnotify",CallNotify, NULL, NULL);
AddCommand(pSics, "haddcheck",AddCheck, NULL, NULL);
AddCommand(pSics, "hscriptnotify",AddScriptNotify, NULL, NULL);
InstallSICSPoll(pCon, pSics, pData, argc, argv);
poller = (pSicsPoll) FindCommandData(pSics, "sicspoll", "SicsPoll");
return 1;
}