/* * 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 #include #include #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; }