Files
sics/sicshdbadapter.c

999 lines
26 KiB
C

/*
* Experience has shown that integrating existing SICS objects into the
* Hierarchical Parameter Database (Hdb) is a difficult task without reworking
* the complete SICS object model. Rather, it seems easier to adapt some
* critical objects to the Hdb with some glue code. Following the facade or
* adapter design pattern. This is the purpose of this module. For the moment
* the external interface is only an interpreter function which will be used to
* install suitable SICS objects into the Hdb tree and generates the necessary
* adapters internally. This code can be used to adapt to:
* - motors
* - the data segment of histogram memories
*
* copyright: see file COPYRIGHT
*
* Mark Koennecke, November 2006
*/
#include <stdlib.h>
#include <assert.h>
#include <sics.h>
#include "stptok.h"
#include "motor.h"
#include "HistMem.h"
#include "HistMem.i"
#include "HistDriv.i"
#include "sicsvar.h"
#include "counter.h"
#include "lld.h"
#include "sicshipadaba.h"
#include "sicshdbadapter.h"
#include "sicsdata.h"
#include "HistMem.i"
#define PRIVNAM "priv"
/*==================== support code ====================================*/
static void AddPrivProperty(pHdb node, int priv)
{
char pPriv[80];
switch (priv) {
case usInternal:
strcpy(pPriv, "internal");
break;
case usMugger:
strcpy(pPriv, "manager");
break;
case usUser:
strcpy(pPriv, "user");
break;
case usSpy:
strcpy(pPriv, "spy");
break;
default:
assert(0);
break;
}
SetHdbProperty(node, PRIVNAM, pPriv);
}
/*=================== motor code =======================================*/
static int MoveCallback(int iEvent, void *eventData, void *userData)
{
MotCallback *motData = (MotCallback *) eventData;
pHdb motor = (pHdb) userData;
pHdb pos = NULL;
if (iEvent == MOTDRIVE && motData != NULL && motor != NULL) {
UpdateHipadabaPar(motor, MakeHdbFloat((double) motData->fVal)
, NULL);
pos = GetHipadabaNode(motor, "position");
if (pos != NULL) {
UpdateHipadabaPar(pos, MakeHdbFloat((double) motData->fVal)
, NULL);
}
}
return 1;
}
/*---------------------------------------------------------------------*/
static int MotorValueCallback(int iEvent, void *eventData, void *userData)
{
pHdb motor = (pHdb) userData;
pMotor pMot = (pMotor) eventData;
pHdb current = NULL;
float fVal;
/*
* as setting some motor parameters might cause other motor
* parametes to change too, I opt for the cheap solution to check
* them all.
*/
if (iEvent == HDBVAL && motor != NULL && pMot != NULL) {
current = motor->child;
while (current != NULL) {
MotorGetPar(pMot, current->name, &fVal);
if (fVal != current->value.v.doubleValue) {
UpdateHipadabaPar(current, MakeHdbFloat((double) fVal), NULL);
}
current = current->next;
}
}
return 1;
}
/*---------------------------------------------------------------------*/
static hdbCallbackReturn MotorParSetCallback(pHdb currentNode,
void *userData,
pHdbMessage message)
{
pMotor pMot = (pMotor) userData;
SConnection *pCon = NULL;
int status;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
pCon = mm->callData;
assert(pMot != NULL && pCon != NULL);
status = MotorSetPar(pMot, pCon, currentNode->name,
(float) mm->v->v.doubleValue);
if (status == 1) {
return hdbContinue;
} else {
return hdbAbort;
}
}
/*----------------------------------------------------------------------*/
static hdbCallbackReturn MotorParGetCallback(pHdb currentNode,
void *userData,
pHdbMessage message)
{
pMotor pMot = (pMotor) userData;
float fVal;
int status;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbGetMessage(message)) == NULL) {
return hdbContinue;
}
assert(pMot != NULL);
status = MotorGetPar(pMot, currentNode->name, &fVal);
currentNode->value.v.doubleValue = fVal;
if (status == 1) {
return hdbContinue;
} else {
return hdbAbort;
}
}
/*---------------------------------------------------------------------*/
static pHdb MakeMotParNode(char *name, pMotor pMot)
{
pHdb node = NULL;
pHdbCallback pCall = NULL;
char command[1024];
node = MakeHipadabaNode(name, HIPFLOAT, 1);
if (node != NULL) {
pCall = MakeHipadabaCallback(MotorParSetCallback, pMot, NULL);
if (pCall == NULL) {
return NULL;
}
AppendHipadabaCallback(node, pCall);
pCall = MakeHipadabaCallback(MotorParGetCallback, pMot, NULL);
if (pCall == NULL) {
return NULL;
}
AppendHipadabaCallback(node, pCall);
snprintf(command, 1023, "%s %s ", pMot->name, name);
SetHdbProperty(node, "sicscommand", command);
}
return node;
}
/*---------------------------------------------------------------------*/
static int AddStdMotorPar(pHdb motorNode, pMotor pMot)
{
int i;
pHdb parNode = NULL;
char *addPar[] = { "target",
"hardlowerlim",
"hardupperlim",
NULL
};
i = 0;
while (addPar[i] != NULL) {
parNode = MakeMotParNode(addPar[i], pMot);
SetHdbProperty(parNode, PRIVNAM, "internal");
if (parNode == NULL) {
return 0;
}
AddHipadabaChild(motorNode, parNode, NULL);
i++;
}
/*
* Add the parameters in the obpar array
*/
for (i = 0; i < MOTOBPARLENGTH; i++) {
parNode = MakeMotParNode(pMot->ParArray[i].name, pMot);
if (parNode == NULL) {
return 0;
}
AddHipadabaChild(motorNode, parNode, NULL);
AddPrivProperty(parNode, pMot->ParArray[i].iCode);
}
return 1;
}
/*--------------------------------------------------------------------------*/
static char *getDriverParList(MotorDriver * pDriv)
{
SConnection *pCon = NULL;
pDynString list = NULL;
char *listData = NULL;
if (pDriv->ListDriverPar != NULL) {
pCon = SCCreateDummyConnection(pServ->pSics);
if (pCon == NULL) {
return NULL;
}
SCStartBuffering(pCon);
pDriv->ListDriverPar(pDriv, "test.", pCon);
list = SCEndBuffering(pCon);
if (list != NULL) {
listData = strdup(GetCharArray(list));
SCDeleteConnection(pCon);
} else {
listData = NULL;
}
return listData;
}
return NULL;
}
/*--------------------------------------------------------------------------*/
extern char *trim(char *str);
/*--------------------------------------------------------------------------*/
static char *extractName(char *line)
{
char *name = NULL, *pEnd = NULL;
name = strchr(line, '.');
assert(name != NULL);
while (*name == '.') {
name++;
}
pEnd = strchr(name, '=');
assert(pEnd != NULL);
*pEnd = '\0';
return trim(name);
}
/*------------------------------------------------------------------------*/
static int CreateDriverParameters(pMotor pM, pHdb parent)
{
char *listPtr = NULL, line[80], *pPtr, *name;
pHdb node = NULL;
listPtr = getDriverParList(pM->pDriver);
if (listPtr == NULL) {
/*
* no driver parameters
*/
return 1;
}
pPtr = listPtr;
while ((pPtr = stptok(pPtr, line, 79, "\n")) != NULL) {
name = extractName(line);
node = MakeMotParNode(name, pM);
SetHdbProperty(node, PRIVNAM, "manager");
if (node != NULL) {
AddHipadabaChild(parent, node, NULL);
}
}
free(listPtr);
return 1;
}
/*----------------------------------------------------------------------*/
static pHdb CreateMotorAdapter(char *name, pMotor pMot)
{
pHdb result = NULL;
commandContext comCom;
float access;
assert(pMot != NULL);
result = MakeSICSHdbDriv(name, usUser, pMot, HIPFLOAT);
if (result == NULL) {
return NULL;
}
MotorGetPar(pMot, "accesscode", &access);
AddPrivProperty(result, (int) access);
SetHdbProperty(result, "type", "drivable");
SetHdbProperty(result, "sicsdev", pMot->name);
/*
* We want to be notified when this motor drives around. Or
* its parameters change.
*/
strlcpy(comCom.deviceID, name, 255);
comCom.transID = -77;
RegisterCallback(pMot->pCall, MOTDRIVE, MoveCallback, result, NULL);
RegisterCallback(pMot->pCall, HDBVAL, MotorValueCallback, result, NULL);
if (!AddStdMotorPar(result, pMot)) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
if (!CreateDriverParameters(pMot, result)) {
DeleteHipadabaNode(result, NULL);
return NULL;
}
result->iprotected = 1;
return result;
}
/*============== histogram memory ======================================*/
static long totalSum(int *data, int length)
{
long result = 0l;
int i;
if (data == NULL) {
return 0;
}
for (i = 0; i < length; i++) {
result += data[i];
}
return result;
}
/*----------------------------------------------------------------------*/
typedef struct {
pHistMem pHM;
pHdb node;
} HMAdapter, *pHMAdapter;
/*-------------------------------------------------------------------------*/
static hdbCallbackReturn HMDataGetCallback(pHdb currentNode,
void *userData,
pHdbMessage message)
{
pHMAdapter pHMA = (pHMAdapter) userData;
SConnection *pCon = NULL;
long sum1;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbGetMessage(message)) == NULL) {
return hdbContinue;
}
pCon = mm->callData;
assert(pHMA != NULL && pHMA->pHM != NULL);
if (pCon == NULL) {
return hdbAbort;
}
currentNode->value.arrayLength = GetHistLength(pHMA->pHM);
currentNode->value.v.intArray =
(int *) GetHistogramPointer(pHMA->pHM, pCon);
NotifyHipadabaPar(pHMA->node, NULL);
return hdbContinue;
}
/*----------------------------------------------------------------------*/
static int DimCallback(int iEvent, void *eventData, void *userData)
{
pHMAdapter pHMA = (pHMAdapter)userData;
if(iEvent == DIMCHANGE){
pHMA->node->value.arrayLength = GetHistLength(pHMA->pHM);
pHMA->node->value.v.intArray =
(int *) GetHistogramPointer(pHMA->pHM, pServ->dummyCon);
}
return 1;
}
/*----------------------------------------------------------------------*/
static pHdb MakeHMDataNode(pHistMem pHM, char *name)
{
pHdb node = NULL;
pHdbCallback pCall = NULL;
pHMAdapter pHMA = NULL;
node = MakeHipadabaNode(name, HIPINTVARAR, GetHistLength(pHM));
pHMA = malloc(sizeof(HMAdapter));
if (node == NULL || pHMA == NULL) {
return NULL;
}
pHMA->pHM = pHM;
pHMA->node = node;
node->value.doNotFree = 1;
node->value.v.intArray = (int *)GetHistogramPointer(pHM, pServ->dummyCon);
pCall = MakeHipadabaCallback(HMDataGetCallback, pHMA, free);
if (pCall == NULL) {
return NULL;
}
AppendHipadabaCallback(node, pCall);
AppendHipadabaCallback(node, MakeReadOnlyCallback());
RegisterCallback(pHM->pCall,DIMCHANGE, DimCallback, pHMA, NULL);
return node;
}
/*================ SICS Variable ======================================*/
static hdbCallbackReturn SicsVarSetCallback(pHdb currentNode,
void *userData,
pHdbMessage message)
{
pSicsVariable pVar = (pSicsVariable) userData;
SConnection *pCon = NULL;
int userRights = usMugger;
pHdbDataMessage mm = NULL;
if ((mm = GetHdbSetMessage(message)) == NULL) {
return hdbContinue;
}
pCon = mm->callData;
assert(pVar != NULL);
if (pCon != NULL) {
userRights = SCGetRights(pCon);
}
switch (currentNode->value.dataType) {
case HIPINT:
VarSetInt(pVar, mm->v->v.intValue, userRights);
break;
case HIPFLOAT:
VarSetFloat(pVar, (float) mm->v->v.doubleValue, userRights);
break;
case HIPTEXT:
VarSetText(pVar, mm->v->v.text, userRights);
break;
}
return hdbContinue;
}
/*----------------------------------------------------------------------*/
static int ValueCallback(int iEvent, void *eventData, void *userData)
{
pSicsVariable pVar = (pSicsVariable) eventData;
pHdb node = (pHdb) userData;
hdbValue v;
if (iEvent == VALUECHANGE && pVar != NULL && node != NULL) {
switch (pVar->eType) {
case veInt:
v = MakeHdbInt(pVar->iVal);
break;
case veFloat:
v = MakeHdbFloat((double) pVar->fVal);
break;
case veText:
v = MakeHdbText(pVar->text);
break;
}
UpdateHipadabaPar(node, v, NULL);
}
return 1;
}
/*----------------------------------------------------------------------*/
static pHdb MakeSicsVarNode(pSicsVariable pVar, char *name)
{
pHdb node = NULL;
pHdbCallback pCall = NULL;
commandContext comCom;
int type;
char command[1024];
switch (pVar->eType) {
case veInt:
type = HIPINT;
break;
case veFloat:
type = HIPFLOAT;
break;
case veText:
type = HIPTEXT;
break;
}
node = MakeHipadabaNode(name, type, 1);
if (node == NULL) {
return NULL;
}
if (pVar->iLock == 1) {
AddPrivProperty(node, usInternal);
} else {
AddPrivProperty(node, pVar->iAccessCode);
}
pCall = MakeHipadabaCallback(SicsVarSetCallback, pVar, NULL);
if (pCall == NULL) {
return NULL;
}
AppendHipadabaCallback(node, pCall);
RegisterCallback(pVar->pCall, VALUECHANGE, ValueCallback, node, NULL);
snprintf(command, 1023, "%s ", pVar->name);
SetHdbProperty(node, "sicscommand", command);
node->iprotected = 1;
return node;
}
/*================ counter =============================================*/
typedef struct {
pHdb node;
int monitor; /* -1 == time */
pCounter counter;
} CountEntry;
static int countList = -10;
/*---------------------------------------------------------------------*/
static void updateCountList()
{
int status;
hdbValue v;
CountEntry hugo;
long monitor;
float time;
SConnection *pDummy = NULL;
if (countList < 0) {
return;
}
pDummy = SCCreateDummyConnection(pServ->pSics);
if (pDummy == NULL) {
return;
}
status = LLDnodePtr2First(countList);
while (status != 0) {
LLDnodeDataTo(countList, &hugo);
if (hugo.monitor < 0) {
time = GetCountTime(hugo.counter, pDummy);
v = MakeHdbFloat((double) time);
UpdateHipadabaPar(hugo.node, v, NULL);
} else {
monitor = GetMonitor(hugo.counter, hugo.monitor, pDummy);
v = MakeHdbInt((int) monitor);
UpdateHipadabaPar(hugo.node, v, NULL);
}
status = LLDnodePtr2Next(countList);
}
SCDeleteConnection(pDummy);
}
/*---------------------------------------------------------------------------*/
static int CounterCallback(int iEvent, void *eventData, void *userData)
{
if (iEvent == MONITOR || iEvent == COUNTEND) {
updateCountList();
}
return 1;
}/*=================== SICSData ========================================*/
static void copyIntSicsData(pHdb node, pSICSData data)
{
if (node->value.arrayLength != data->dataUsed) {
if (node->value.v.intArray != NULL) {
free(node->value.v.intArray);
}
node->value.arrayLength = data->dataUsed;
node->value.v.intArray = malloc(data->dataUsed * sizeof(int));
if (node->value.v.intArray == NULL) {
node->value.arrayLength = 0;
return;
}
}
memcpy(node->value.v.intArray, data->data, data->dataUsed * sizeof(int));
}
/*-----------------------------------------------------------------------*/
static void copyFloatSicsData(pHdb node, pSICSData data)
{
int i;
float val;
if (node->value.arrayLength != data->dataUsed) {
if (node->value.v.floatArray != NULL) {
free(node->value.v.floatArray);
}
node->value.arrayLength = data->dataUsed;
node->value.v.floatArray = malloc(data->dataUsed * sizeof(double));
if (node->value.v.floatArray == NULL) {
node->value.arrayLength = 0;
return;
}
}
for (i = 0; i < data->dataUsed; i++) {
getSICSDataFloat(data, i, &val);
node->value.v.floatArray[i] = val;
}
}
/*----------------------------------------------------------------------*/
static hdbCallbackReturn SICSDataCallback(pHdb node, void *userData,
pHdbMessage message)
{
pSICSData self = (pSICSData) userData;
pHdbDataMessage mm = NULL;
int i, status;
char script[256], error[1024];
assert(self != NULL);
/*
* I have to make copies because the floats in SICSData
* are floats but doubles in Hipdaba. Siiiigggghhhh!
* But it is cleaner in some way anyway.
*/
if ((mm = GetHdbGetMessage(message)) != NULL) {
memset(script, 0, 256);
if (GetHdbProperty(node, "readscript", script, 256) == 1) {
status = Tcl_Eval(InterpGetTcl(pServ->pSics), script);
if (status != TCL_OK) {
snprintf(error, 1023, "ERROR: Tcl returned error: %s",
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
if (mm->callData != NULL) {
SCWrite((SConnection *) mm->callData, error, eError);
return hdbAbort;
}
}
}
if (node->value.dataType == HIPINTVARAR) {
copyIntSicsData(node, self);
} else if (node->value.dataType == HIPFLOATVARAR) {
copyFloatSicsData(node, self);
}
return hdbContinue;
}
if ((mm = GetHdbSetMessage(message)) != NULL) {
if (node->value.dataType == HIPINTVARAR) {
for (i = 0; i < mm->v->arrayLength; i++) {
setSICSDataInt(self, i, mm->v->v.intArray[i]);
}
} else if (node->value.dataType == HIPFLOATVARAR) {
for (i = 0; i < mm->v->arrayLength; i++) {
setSICSDataFloat(self, i, (float) mm->v->v.floatArray[i]);
}
}
memset(script, 0, 256);
if (GetHdbProperty(node, "writescript", script, 256) == 1) {
status = Tcl_Eval(InterpGetTcl(pServ->pSics), script);
if (status != TCL_OK) {
snprintf(error, 1023, "ERROR: Tcl returned error: %s",
Tcl_GetStringResult(InterpGetTcl(pServ->pSics)));
if (mm->callData != NULL) {
SCWrite((SConnection *) mm->callData, error, eError);
return hdbAbort;
}
}
}
return hdbContinue;
}
return hdbContinue;
}
/*================= targets ============================================*/
typedef struct {
char *name;
pHdb node;
}TargetData, *pTargetData ;
/*----------------------------------------------------------------------*/
static void KillTargetData(void *data)
{
pTargetData self = (pTargetData) data;
if(self == NULL){
return;
}
if(self->name != NULL){
free(self->name);
}
free(self);
}
/*----------------------------------------------------------------------*/
static int TargetCallback(int iEvent, void *pEventData, void *pUserData)
{
pTargetData user = NULL;
pNewTarget event = NULL;
hdbValue v;
if(iEvent != NEWTARGET){
return 0;
}
user = (pTargetData)pUserData;
event = (pNewTarget)pEventData;
assert(user != NULL && event != NULL);
if(strcmp(user->name,event->name) == 0){
v = MakeHdbFloat((double)event->target);
UpdateHipadabaPar(user->node, v, NULL);
}
return 1;
}
/*----------------------------------------------------------------------*/
static int AttachTarget(SConnection *pCon, SicsInterp *pSics,
char *drivename, char *nodename)
{
pTargetData tData = NULL;
pHdb node = NULL;
pIDrivable pDriv = NULL;
CommandList *pCom = NULL;
float val;
pDriv = FindDrivable(pSics, drivename);
if(pDriv == NULL){
SCPrintf(pCon,eError,"ERROR: drivable %s not found", drivename);
return 0;
}
node = FindHdbNode(NULL, nodename, pCon);
if(node == NULL){
SCPrintf(pCon,eError,"ERROR: node %s not found", nodename);
return 0;
}
tData = malloc(sizeof(TargetData));
if(tData == NULL){
SCWrite(pCon,"ERROR: out of memory in AttachTarget", eError);
return 0;
}
tData->name = strdup(drivename);
tData->node = node;
pCom = FindCommand(pSics,drivename);
/* This cannot fail as we already located the drivable */
GetDrivablePosition(pCom->pData, pCon,&val);
UpdateHipadabaPar(node,MakeHdbFloat(val), pCon);
RegisterCallback((pICallBack)GetExecutorCallback(pServ->pExecutor),
NEWTARGET,
TargetCallback,
tData,
KillTargetData);
SCSendOK(pCon);
return 1;
}
/*============== interpreter function ==================================*/
int SICSHdbAdapter(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHdb path = NULL;
pHdb node = NULL;
pMotor pMot = NULL;
pHistMem pHM = NULL;
CommandList *pCom = NULL;
pIDrivable pDriv = NULL;
pSicsVariable pVar = NULL;
char buffer[512];
pCounter pCount = NULL;
CountEntry hugo;
pSICSData data = NULL;
int type;
pHdbCallback pCall = NULL;
if (!SCMatchRights(pCon, usMugger)) {
return 0;
}
if (argc < 4) {
SCWrite(pCon, "ERROR: Insufficient number of arguments", eError);
return 0;
}
if(strcmp(argv[1],"target") == 0){
return AttachTarget(pCon,pSics,argv[2], argv[3]);
}
path = FindHdbNode(NULL, argv[1], pCon);
if (path == NULL) {
SCWrite(pCon, "ERROR: path to attach object too not found", eError);
return 0;
}
/*
* look for motors
*/
pMot = (pMotor) FindCommandData(pSics, argv[2], "Motor");
if (pMot != NULL) {
if(pMot->ParArray == NULL){
SCWrite(pCon,"ERROR: second generation motors need to be linked rather then adapted",
eError);
return 0;
}
node = CreateMotorAdapter(argv[3], pMot);
if (node == NULL) {
SCWrite(pCon, "ERROR: out of memory creating motor node", eError);
return 0;
}
AddHipadabaChild(path, node, pCon);
SCSendOK(pCon);
return 1;
}
/*
* look for drivables
*/
pDriv = FindDrivable(pSics, argv[2]);
pCom = FindCommand(pSics, argv[2]);
if (pDriv != NULL && pCom != NULL && pCom->pData != NULL) {
node = MakeSICSHdbDriv(argv[3], usUser, pCom->pData, HIPFLOAT);
if (node == NULL) {
SCWrite(pCon, "ERROR: out of memory creating drivable node", eError);
return 0;
}
SetHdbProperty(node, PRIVNAM, "user");
SetHdbProperty(node, "type", "drivable");
SetHdbProperty(node, "sicsdev", argv[2]);
AddHipadabaChild(path, node, pCon);
SCSendOK(pCon);
return 1;
}
/**
* look for SICS Variables
*/
pVar = (pSicsVariable) FindCommandData(pSics, argv[2], "SicsVariable");
if (pVar != NULL) {
node = MakeSicsVarNode(pVar, argv[3]);
if (node == NULL) {
SCWrite(pCon, "ERROR: out of memory creating SICS variable node",
eError);
return 0;
}
AddHipadabaChild(path, node, pCon);
SCSendOK(pCon);
return 1;
}
/*
* look for histogram memories
*/
pHM = (pHistMem) FindCommandData(pSics, argv[2], "HistMem");
if (pHM != NULL) {
node = MakeHMDataNode(pHM, argv[3]);
if (node == NULL) {
SCWrite(pCon, "ERROR: out of memory creating HM node", eError);
return 0;
}
AddHipadabaChild(path, node, pCon);
SCSendOK(pCon);
return 1;
}
/**
* look for counters
*/
pCount = (pCounter) FindCommandData(pSics, argv[2], "SingleCounter");
if (pCount != NULL) {
hugo.monitor = atoi(argv[3]);
hugo.counter = pCount;
hugo.node = path;
if (countList < 0) {
countList = LLDcreate(sizeof(CountEntry));
RegisterCallback(pCount->pCall,
COUNTSTART, CounterCallback, NULL, NULL);
RegisterCallback(pCount->pCall,
COUNTEND, CounterCallback, NULL, NULL);
RegisterCallback(pCount->pCall,
MONITOR, CounterCallback, NULL, NULL);
}
LLDnodeAppendFrom(countList, &hugo);
SCSendOK(pCon);
return 1;
}
/**
* look for SICSData
*/
data = (pSICSData) FindCommandData(pSics, argv[2], "SICSData");
if (data != NULL) {
if (argc < 5) {
SCWrite(pCon, "ERROR: need type and name to create SICSData adapter",
eError);
return 0;
}
type = convertHdbType(argv[3]);
if (type != HIPINTVARAR && type != HIPFLOATVARAR) {
SCWrite(pCon,
"ERROR: need intvarar or floatvarar type for SICSData adapter",
eError);
return 0;
}
node = MakeHipadabaNode(argv[4], type, 0);
if (node == NULL) {
SCWrite(pCon, "ERROR: out of memory in SICSHdbAdapter", eError);
return 0;
}
pCall = MakeHipadabaCallback(SICSDataCallback, data, NULL);
if (pCall == NULL) {
SCWrite(pCon, "ERROR: out of memory in SICSHdbAdapter", eError);
return 0;
}
AppendHipadabaCallback(node, pCall);
AddHipadabaChild(path, node, pCon);
SCSendOK(pCon);
return 1;
}
snprintf(buffer, 511,
"ERROR: attaching this type of object: %s at %s not implemented",
argv[2], argv[1]);
SCWrite(pCon, buffer, eError);
return 0;
}
/*====================== SubSample =========================================*/
int HdbSubSample(SConnection * pCon, SicsInterp * pSics, void *pData,
int argc, char *argv[])
{
pHistMem pHM = NULL;
pHdb node = NULL;
int bank = 0, length = -1, status, i;
HistInt *data = NULL;
char *pPtr = NULL;
char error[132];
hdbValue v;
HMdata hdata;
pHdb hmnode = NULL;
if (argc < 4) {
SCWrite(pCon,
"ERROR: insufficient number of arguments to HdbSubSample",
eError);
return 0;
}
pPtr = strchr(argv[1], ':');
if (pPtr != NULL) {
*pPtr = '\0';
pPtr++;
sscanf(pPtr, "%d", &bank);
}
node = FindHdbNode(NULL, argv[2], pCon);
if (node == NULL) {
SCWrite(pCon, "ERROR: node not found!",
eError);
return 0;
}
/*
old HM
*/
pHM = (pHistMem) FindCommandData(pSics, argv[1], "HistMem");
if(pHM != NULL){
if (pHM->pDriv->SubSample == NULL) {
SCWrite(pCon, "ERROR: hm does not support subsampling", eError);
return 0;
}
data = pHM->pDriv->SubSample(pHM->pDriv, pCon, bank, argv[3]);
if (data == NULL) {
SCWrite(pCon, "ERROR: sub sampling failed", eError);
return 0;
}
}
/*
new HM
*/
pHM = (pHistMem) FindCommandData(pSics, argv[1], "HistMemSec");
if(pHM != NULL){
memset(&hdata,0,sizeof(HMdata));
hmnode = GetHipadabaNode(pHM->pDes->parNode,"dim");
if(hmnode == NULL){
SCWrite(pCon,"ERROR: dim node not found",eError);
return 0;
}
hdata.rank = hmnode->value.arrayLength;
for(i = 0; i < hdata.rank; i++){
hdata.iDim[i] = hmnode->value.v.intArray[i];
}
hmnode = GetHipadabaNode(pHM->pDes->parNode,"data");
if(hmnode == NULL){
SCWrite(pCon,"ERROR: data node not found",eError);
return 0;
}
hdata.localBuffer = hmnode->value.v.intArray;
data = subSample(&hdata, argv[3], error, sizeof(error));
if(data == NULL){
SCPrintf(pCon,eError,"ERROR: %s while processing %s with %s",
error, argv[1], argv[3]);
return 0;
}
} else {
SCPrintf(pCon,eError,"ERROR: hm %s not found", argv[1]);
return 0;
}
v.dataType = HIPINTVARAR;
v.arrayLength = data[0];
v.v.intArray = data + 1;
UpdateHipadabaPar(node, v, pCon);
free(data);
SCSendOK(pCon);
return 1;
}