- IEC 61850 server: optimized dynamic memory management in control handling; memory will be initialized at server start

pull/72/head
Michael Zillgith 7 years ago
parent 6618093f7a
commit 713ca54cd0

@ -25,29 +25,89 @@
#define CONTROL_H_
#include "iec61850_model.h"
#include "iec61850_server.h"
#include "mms_server_connection.h"
#include "mms_device_model.h"
#include "iec61850_server.h"
#include "mms_mapping_internal.h"
#include "mms_client_connection.h"
#include "libiec61850_platform_includes.h"
typedef struct sControlObject ControlObject;
ControlObject*
ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char* name);
struct sControlObject
{
MmsDomain* mmsDomain;
IedServer iedServer;
char* lnName;
char* name;
void
ControlObject_destroy(ControlObject* self);
int state;
void
ControlObject_setOper(ControlObject* self, MmsValue* oper);
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore stateLock;
#endif
void
ControlObject_setCancel(ControlObject* self, MmsValue* cancel);
MmsValue* mmsValue;
MmsVariableSpecification* typeSpec;
MmsValue* oper;
MmsValue* sbo;
MmsValue* sbow;
MmsValue* cancel;
MmsValue* ctlVal;
MmsValue* ctlNum;
MmsValue* origin;
MmsValue* timestamp;
char ctlObjectName[130];
/* for LastAppIError */
MmsValue* error;
MmsValue* addCause;
bool selected;
uint64_t selectTime;
uint32_t selectTimeout;
MmsValue* sboClass;
MmsValue* sboTimeout;
bool timeActivatedOperate;
uint64_t operateTime;
bool operateOnce;
MmsServerConnection mmsConnection;
MmsValue* emptyString;
uint32_t ctlModel;
bool testMode;
bool interlockCheck;
bool synchroCheck;
uint32_t operateInvokeId;
ControlHandler operateHandler;
void* operateHandlerParameter;
ControlPerformCheckHandler checkHandler;
void* checkHandlerParameter;
ControlWaitForExecutionHandler waitForExecutionHandler;
void* waitForExecutionHandlerParameter;
};
ControlObject*
ControlObject_create(IedServer iedServer, MmsDomain* domain, char* lnName, char* name);
void
ControlObject_setSBO(ControlObject* self, MmsValue* sbo);
ControlObject_initialize(ControlObject* self);
void
ControlObject_setSBOw(ControlObject* self, MmsValue* sbow);
ControlObject_destroy(ControlObject* self);
void
ControlObject_setMmsValue(ControlObject* self, MmsValue* value);
@ -61,21 +121,6 @@ ControlObject_setTypeSpec(ControlObject* self, MmsVariableSpecification* typeSpe
MmsVariableSpecification*
ControlObject_getTypeSpec(ControlObject* self);
MmsValue*
ControlObject_getOper(ControlObject* self);
MmsValue*
ControlObject_getSBOw(ControlObject* self);
MmsValue*
ControlObject_getSBO(ControlObject* self);
MmsValue*
ControlObject_getCancel(ControlObject* self);
void
ControlObject_setCtlVal(ControlObject* self, MmsValue* ctlVal);
char*
ControlObject_getName(ControlObject* self);

@ -49,6 +49,9 @@ MmsMapping_create(IedModel* model, IedServer iedServer);
MmsDevice*
MmsMapping_getMmsDeviceModel(MmsMapping* mapping);
void
MmsMapping_initializeControlObjects(MmsMapping* self);
void
MmsMapping_configureSettingGroups(MmsMapping* self);

@ -119,18 +119,13 @@ createControlObjects(IedServer self, MmsDomain* domain, char* lnName, MmsVariabl
ControlObject_setTypeSpec(controlObject, coSpec);
MmsValue* operVal = MmsValue_getElement(structure, operIndex);
ControlObject_setOper(controlObject, operVal);
controlObject->oper = MmsValue_getElement(structure, operIndex);
if (hasCancel) {
MmsValue* cancelVal = MmsValue_getElement(structure, cancelIndex);
ControlObject_setCancel(controlObject, cancelVal);
}
if (hasCancel)
controlObject->cancel = MmsValue_getElement(structure, cancelIndex);
if (hasSBOw) {
MmsValue* sbowVal = MmsValue_getElement(structure, sBOwIndex);
ControlObject_setSBOw(controlObject, sbowVal);
}
if (hasSBOw)
controlObject->sbow = MmsValue_getElement(structure, sBOwIndex);
MmsMapping_addControlObject(mapping, controlObject);
}
@ -457,6 +452,8 @@ IedServer_createWithConfig(IedModel* dataModel, TLSConfiguration tlsConfiguratio
/* default write access policy allows access to SP, SE and SV FCDAs but denies access to DC and CF FCDAs */
self->writeAccessPolicies = ALLOW_WRITE_ACCESS_SP | ALLOW_WRITE_ACCESS_SV | ALLOW_WRITE_ACCESS_SE;
MmsMapping_initializeControlObjects(self->mmsMapping);
#if (CONFIG_IEC61850_REPORT_SERVICE == 1)
Reporting_activateBufferedReports(self->mmsMapping);
#endif

@ -1,7 +1,7 @@
/*
* control.c
*
* Copyright 2013 Michael Zillgith
* Copyright 2013-2018 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -22,17 +22,12 @@
*/
#include "control.h"
#include "mms_mapping.h"
#include "mms_mapping_internal.h"
#include "mms_client_connection.h"
#include "mms_mapping.h"
#include "iec61850_server.h"
#include "ied_server_private.h"
#include "mms_value_internal.h"
#include "libiec61850_platform_includes.h"
#if (CONFIG_IEC61850_CONTROL_SERVICE == 1)
#ifndef DEBUG_IED_SERVER
@ -51,71 +46,6 @@
#define STATE_WAIT_FOR_EXECUTION 4
#define STATE_OPERATE 5
struct sControlObject
{
MmsDomain* mmsDomain;
IedServer iedServer;
char* lnName;
char* name;
int state;
#if (CONFIG_MMS_THREADLESS_STACK != 1)
Semaphore stateLock;
#endif
MmsValue* mmsValue;
MmsVariableSpecification* typeSpec;
MmsValue* oper;
MmsValue* sbo;
MmsValue* sbow;
MmsValue* cancel;
MmsValue* ctlVal;
MmsValue* ctlNum;
MmsValue* origin;
MmsValue* timestamp;
char* ctlObjectName;
/* for LastAppIError */
MmsValue* error;
MmsValue* addCause;
bool selected;
uint64_t selectTime;
uint32_t selectTimeout;
MmsValue* sboClass;
MmsValue* sboTimeout;
bool timeActivatedOperate;
uint64_t operateTime;
bool operateOnce;
MmsServerConnection mmsConnection;
MmsValue* emptyString;
bool initialized;
uint32_t ctlModel;
bool testMode;
bool interlockCheck;
bool synchroCheck;
uint32_t operateInvokeId;
ControlHandler operateHandler;
void* operateHandlerParameter;
ControlPerformCheckHandler checkHandler;
void* checkHandlerParameter;
ControlWaitForExecutionHandler waitForExecutionHandler;
void* waitForExecutionHandlerParameter;
};
void
ControlObject_sendLastApplError(ControlObject* self, MmsServerConnection connection, char* ctlVariable, int error,
ControlAddCause addCause, MmsValue* ctlNum, MmsValue* origin, bool handlerMode);
@ -183,13 +113,13 @@ updateSboTimeoutValue(ControlObject* self)
static void
initialize(ControlObject* self)
{
if (!(self->initialized)) {
MmsServer mmsServer = IedServer_getMmsServer(self->iedServer);
self->emptyString = MmsValue_newVisibleString(NULL);
char* ctlModelName = StringUtils_createString(4, self->lnName, "$CF$", self->name, "$ctlModel");
char strBuf[129];
char* ctlModelName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$ctlModel");
if (DEBUG_IED_SERVER)
printf("initialize control for %s\n", ctlModelName);
@ -202,16 +132,10 @@ initialize(ControlObject* self)
printf("No control model found for variable %s\n", ctlModelName);
}
GLOBAL_FREEMEM(ctlModelName);
char* sboClassName = StringUtils_createString(4, self->lnName, "$CF$", self->name, "$sboClass");
char* sboClassName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$sboClass");
self->sboClass = MmsServer_getValueFromCache(mmsServer, self->mmsDomain, sboClassName);
GLOBAL_FREEMEM(sboClassName);
self->ctlObjectName = (char*) GLOBAL_MALLOC(130);
StringUtils_createStringInBuffer(self->ctlObjectName, 5, MmsDomain_getName(self->mmsDomain), "/",
self->lnName, "$CO$", self->name);
@ -227,13 +151,15 @@ initialize(ControlObject* self)
printf(" ctlModel: %i\n", ctlModelVal);
if ((ctlModelVal == 2) || (ctlModelVal == 4)) { /* SBO */
char* sboTimeoutName = StringUtils_createString(4, self->lnName, "$CF$", self->name, "$sboTimeout");
char* controlObjectReference = StringUtils_createString(6, self->mmsDomain->domainName, "/", self->lnName, "$",
self->name, "$SBO");
char* controlObjectReference = StringUtils_createStringInBuffer(strBuf, 6, self->mmsDomain->domainName,
"/", self->lnName, "$", self->name, "$SBO");
self->sbo = MmsValue_newVisibleString(controlObjectReference);
char* sboTimeoutName = StringUtils_createStringInBuffer(strBuf, 4, self->lnName, "$CF$", self->name, "$sboTimeout");
self->sboTimeout = MmsServer_getValueFromCache(mmsServer,
self->mmsDomain, sboTimeoutName);
@ -243,9 +169,6 @@ initialize(ControlObject* self)
if (DEBUG_IED_SERVER)
printf("timeout for %s is %i\n", sboTimeoutName, self->selectTimeout);
GLOBAL_FREEMEM(controlObjectReference);
GLOBAL_FREEMEM(sboTimeoutName);
}
else {
self->sbo = MmsValue_newVisibleString(NULL);
@ -253,9 +176,6 @@ initialize(ControlObject* self)
setState(self, STATE_READY);
}
}
self->initialized = true;
}
}
static bool
@ -467,6 +387,12 @@ exit_function:
return self;
}
void
ControlObject_initialize(ControlObject* self)
{
initialize(self);
}
void
ControlObject_destroy(ControlObject* self)
{
@ -479,9 +405,6 @@ ControlObject_destroy(ControlObject* self)
if (self->emptyString != NULL)
MmsValue_delete(self->emptyString);
if (self->ctlObjectName != NULL)
GLOBAL_FREEMEM(self->ctlObjectName);
if (self->error != NULL)
MmsValue_delete(self->error);
@ -508,36 +431,6 @@ ControlObject_destroy(ControlObject* self)
GLOBAL_FREEMEM(self);
}
void
ControlObject_setOper(ControlObject* self, MmsValue* oper)
{
self->oper = oper;
}
void
ControlObject_setCancel(ControlObject* self, MmsValue* cancel)
{
self->cancel = cancel;
}
void
ControlObject_setSBOw(ControlObject* self, MmsValue* sbow)
{
self->sbow = sbow;
}
void
ControlObject_setSBO(ControlObject* self, MmsValue* sbo)
{
self->sbo = sbo;
}
void
ControlObject_setCtlVal(ControlObject* self, MmsValue* ctlVal)
{
self->ctlVal = ctlVal;
}
char*
ControlObject_getName(ControlObject* self)
{
@ -556,30 +449,6 @@ ControlObject_getDomain(ControlObject* self)
return self->mmsDomain;
}
MmsValue*
ControlObject_getOper(ControlObject* self)
{
return self->oper;
}
MmsValue*
ControlObject_getSBOw(ControlObject* self)
{
return self->sbow;
}
MmsValue*
ControlObject_getSBO(ControlObject* self)
{
return self->sbo;
}
MmsValue*
ControlObject_getCancel(ControlObject* self)
{
return self->cancel;
}
void
ControlObject_setMmsValue(ControlObject* self, MmsValue* value)
{
@ -1122,13 +991,13 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
if (controlObject != NULL) {
initialize(controlObject);
//initialize(controlObject);
if (varName != NULL) {
if (strcmp(varName, "Oper") == 0)
value = ControlObject_getOper(controlObject);
value = controlObject->oper;
else if (strcmp(varName, "SBOw") == 0)
value = ControlObject_getSBOw(controlObject);
value = controlObject->sbow;
else if (strcmp(varName, "SBO") == 0) {
if (controlObject->ctlModel == 2) {
@ -1153,7 +1022,7 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
if (checkResult == CONTROL_ACCEPTED) {
selectObject(controlObject, currentTime, connection);
value = ControlObject_getSBO(controlObject);
value = controlObject->sbo;
}
}
@ -1162,12 +1031,12 @@ Control_readAccessControlObject(MmsMapping* self, MmsDomain* domain, char* varia
if (DEBUG_IED_SERVER)
printf("IED_SERVER: select not applicable for control model %i\n", controlObject->ctlModel);
value = ControlObject_getSBO(controlObject);
value = controlObject->sbo;
}
}
else if (strcmp(varName, "Cancel") == 0)
value = ControlObject_getCancel(controlObject);
value = controlObject->cancel;
else {
value = MmsValue_getSubElement(ControlObject_getMmsValue(controlObject),
ControlObject_getTypeSpec(controlObject), varName);
@ -1289,7 +1158,7 @@ Control_writeAccessControlObject(MmsMapping* self, MmsDomain* domain, char* vari
goto free_and_return;
}
initialize(controlObject);
//initialize(controlObject);
if (strcmp(varName, "SBOw") == 0) { /* select with value */

@ -599,6 +599,20 @@ MmsMapping_checkForSettingGroupReservationTimeouts(MmsMapping* self, uint64_t cu
}
}
void
MmsMapping_initializeControlObjects(MmsMapping* self)
{
LinkedList element = LinkedList_getNext(self->controlObjects);
while (element) {
ControlObject* controlObject = (ControlObject*) LinkedList_getData(element);
ControlObject_initialize(controlObject);
element = LinkedList_getNext(element);
}
}
void
MmsMapping_configureSettingGroups(MmsMapping* self)
{

Loading…
Cancel
Save