Files
microser/mmslib/mvlu/mvl_obj.c

1132 lines
38 KiB
C
Raw Normal View History

2026-06-15 15:48:16 +08:00
/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1998 - 2005, All Rights Reserved */
/* */
/* MODULE NAME : mvl_obj.c */
/* PRODUCT(S) : MMSEASE-LITE */
/* */
/* MODULE DESCRIPTION : */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* mvl_vmd_dom_add */
/* mvl_vmd_var_add */
/* mvl_vmd_nvl_add */
/* mvl_vmd_jou_add */
/* mvl_vmd_dom_remove */
/* mvl_vmd_var_remove */
/* mvl_vmd_nvl_remove */
/* mvl_vmd_jou_remove */
/* mvl_nvl_create */
/* mvl_nvl_destroy */
/* mvl_vmd_create */
/* mvl_vmd_destroy */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 02/26/08 JRB 28 mvl_vmd_destroy: do NOT free var->data (do */
/* not know if it was allocated). */
/* Check var or NVL is deletable before delete. */
/* mvl_vmd_dom_remove: remove dom objects first.*/
/* mvl_dom_destroy: do NOT remove dom objects. */
/* Add mvl_var_add_alloc, mvl_var_create_alloc. */
/* Add mvl_var_create_derived. */
/* Remove unused functions. */
/* 02/21/07 JRB 27 Fix funct names in this module header. */
/* 12/04/06 JRB 26 mvl_vmd_destroy: add arg to specify which VMD*/
/* and DO NOT destroy all rpt_ctrl (let user). */
/* 10/30/06 JRB 25 Add vmd_ctrl arg to several functions & chg */
/* prefix from "mvl_" to "mvl_vmd_". */
/* Add vmd_ctrl, net_info args to mvl_nvl_create.*/
/* Check that (net_info!=NULL) before using it. */
/* Move "*_delete" to mvl_objb.c with other */
/* insert/delete functions. */
/* Add mvl_vmd_create. */
/* 08/09/06 JRB 24 Free "last_data" only in mvl_var_destroy. */
/* Save type_ctrl in MVL_VAR_ASSOC. */
/* mvl_vmd_destroy: free mvl61850_rpt_ctrl_list.*/
/* 01/30/06 GLB 23 Integrated porting changes for VMS */
/* 10/25/05 EJV 22 Fix "last_data" memory leaks: alloc only if */
/* last_data==NULL, free only if last_data!=NULL.*/
/* 09/22/05 JRB 21 mvl_vmd_destroy: del VMD-spec vars, NVLs too.*/
/* 06/29/05 CRM 20 Add mvl_vmd_destroy. */
/* 06/27/05 JRB 19 Alloc "va->last_data" in mvl_nvl_create & */
/* free it in mvl_nvl_destroy so special NVL */
/* functs not needed for IEC/UCA reports. */
/* 06/27/05 JRB 18 mvl_var_create: chk type. */
/* 04/27/05 CRM 17 Added code to free dom->jou_tbl in */
/* mvl_dom_destroy */
/* 06/04/04 JRB 16 mvl_var_create: if (data), set use_static_data.*/
/* 10/03/03 JRB 15 mvl_nvl_add: set nvl_scope in MVL_NVLIST_CTRL*/
/* mvl_nvl_add/mvl_var_add: chk for valid dom first*/
/* 02/25/02 MDE 14 Now get max PDU size from mvl_cfg_info */
/* 01/23/02 EJV 13 Added journals to domain: */
/* mvl_init_dom - added max_num_jou param */
/* mvl_dom_resize - added max_num_jou param */
/* mvl_dom_create - added max_num_jou param */
/* mvl_dom_add - added max_num_jou param */
/* mvl_clear_dom_objs -added code for journals*/
/* mvl_jou_delete - added DOM_SPEC case */
/* 10/25/00 JRB 12 Del u_mvl funct ptrs. Call functs directly. */
/* Control with #ifdefs. */
/* 04/14/00 JRB 11 Move sort & compare code to mvl_objb.c */
/* 04/12/00 MDE 10 Moved AA resize code to mvl_acse.c */
/* 01/21/00 MDE 09 Now use MEM_SMEM for dynamic memory */
/* 09/15/99 JRB 08 Mv mvl_obj_nosort to mvl_objb.c for DOS link */
/* 09/13/99 MDE 07 Added SD_CONST modifiers */
/* 09/07/99 MDE 06 Changed MVL_VA_SCOPE to MVL_SCOPE */
/* 07/12/99 MDE 05 Fixed problem 'destroying' dom w/NVL or VAR */
/* 04/07/99 MDE 04 Logging improvements */
/* 03/18/99 MDE 03 Enhanced dynamic object facilities */
/* 01/20/99 JRB 02 Reduce # of functions. Chg names and args. */
/* Call new "mvl_???_insert" functions. */
/* Add ..nvl_remove, ..nvl_create, ..nvl_destroy*/
/* 11/18/98 MDE 01 Created */
/************************************************************************/
#include "glbtypes.h"
#include "sysincs.h"
#include "mvl_acse.h"
#include "mvl_log.h"
#if defined(MVL_UCA)
#include "mvl_uca.h" /* need "MVLU_RPT_*" */
#endif
/************************************************************************/
/* For debug version, use a static pointer to avoid duplication of */
/* __FILE__ strings. */
/************************************************************************/
#ifdef DEBUG_SISCO
SD_CONST static ST_CHAR *SD_CONST thisFileName = __FILE__;
#endif
ST_VOID (*u_mvl_dom_destroy) (MVL_DOM_CTRL *dom);
ST_VOID (*u_mvl_var_destroy)(MVL_VAR_ASSOC *va);
ST_VOID (*u_mvl_nvl_destroy) (MVL_NVLIST_CTRL *nvl);
ST_VOID (*u_mvl_jou_destroy) (MVL_JOURNAL_CTRL *jou);
/************************************************************************/
/* SCOPE RESIZING FUNCTIONS */
/************************************************************************/
/************************************************************************/
/* mvl_vmd_resize */
/************************************************************************/
ST_VOID mvl_vmd_resize (ST_INT max_num_dom, ST_INT max_num_var,
ST_INT max_num_nvl, ST_INT max_num_jou)
{
if (max_num_dom < mvl_vmd.num_dom)
{
MVL_LOG_NERR0 ("Resizing VMD: new max DOM is less than current");
max_num_dom = mvl_vmd.num_dom;
}
if (max_num_var < mvl_vmd.num_var_assoc)
{
MVL_LOG_NERR0 ("Resizing VMD: new max VA is less than current");
max_num_var = mvl_vmd.num_var_assoc;
}
if (max_num_nvl < mvl_vmd.num_nvlist)
{
MVL_LOG_NERR0 ("Resizing VMD: new max NVL is less than current");
max_num_nvl = mvl_vmd.num_nvlist;
}
if (max_num_jou < mvl_vmd.num_jou)
{
MVL_LOG_NERR0 ("Resizing VMD: new max JOU is less than current");
max_num_jou = mvl_vmd.num_jou;
}
_mvl_resize_ptr_tbl (&(mvl_vmd.max_num_dom),
(ST_VOID ***)&(mvl_vmd.dom_tbl), max_num_dom);
_mvl_resize_ptr_tbl (&(mvl_vmd.max_num_var_assoc),
(ST_VOID ***)&(mvl_vmd.var_assoc_tbl), max_num_var);
_mvl_resize_ptr_tbl (&(mvl_vmd.max_num_nvlist),
(ST_VOID ***)&(mvl_vmd.nvlist_tbl), max_num_nvl);
_mvl_resize_ptr_tbl (&(mvl_vmd.max_num_jou),
(ST_VOID ***)&(mvl_vmd.jou_tbl), max_num_jou);
}
/************************************************************************/
/* mvl_dom_resize */
/************************************************************************/
ST_VOID mvl_dom_resize (MVL_DOM_CTRL *dom, ST_INT max_num_var,
ST_INT max_num_nvl, ST_INT max_num_jou)
{
if (max_num_var < dom->num_var_assoc)
{
MVL_LOG_NERR0 ("Resizing Domain: new max VA is less than current");
max_num_var = dom->num_var_assoc;
}
if (max_num_nvl < dom->num_nvlist)
{
MVL_LOG_NERR0 ("Resizing Domain: new max NVL is less than current");
max_num_nvl = dom->num_nvlist;
}
if (max_num_jou < dom->num_jou)
{
MVL_LOG_NERR0 ("Resizing Domain: new max JOU is less than current");
max_num_jou = dom->num_jou;
}
_mvl_resize_ptr_tbl (&(dom->max_num_var_assoc),
(ST_VOID ***)&(dom->var_assoc_tbl), max_num_var);
_mvl_resize_ptr_tbl (&(dom->max_num_nvlist),
(ST_VOID ***)&(dom->nvlist_tbl), max_num_nvl);
_mvl_resize_ptr_tbl (&(dom->max_num_jou),
(ST_VOID ***)&(dom->jou_tbl), max_num_jou);
}
/************************************************************************/
/* _mvl_resize_ptr_tbl */
/************************************************************************/
ST_VOID _mvl_resize_ptr_tbl (ST_INT *p_max_num,
ST_VOID ***p_ptr_tbl, ST_INT new_size)
{
/* See if something needs to be done at all */
if (*p_max_num == new_size)
return;
/* See if the table is going away altogether */
if (new_size != 0)
{
if (*p_max_num != 0)
*p_ptr_tbl = (ST_VOID **) M_REALLOC (MSMEM_GEN, *p_ptr_tbl, (new_size * sizeof (ST_VOID *)));
else /* We did not have a table, but need one now */
*p_ptr_tbl = (ST_VOID **) M_CALLOC (MSMEM_GEN, new_size, sizeof (ST_VOID *));
}
else
{ /* If we had a table, we need to free it */
if (*p_max_num != 0)
M_FREE (MSMEM_GEN, *p_ptr_tbl);
}
*p_max_num = new_size;
}
/************************************************************************/
/* mvl_nvl_remove_all */
/* Remove all VMD-Specific NVLs & Domain-Specific NVLs in this VMD. */
/* CRITICAL: Use "mvl_vmd_nvl_remove". It makes sure it is safe to */
/* remove each NVL. */
/* RETURNS: SD_SUCCESS or SD_FAILURE */
/************************************************************************/
ST_RET mvl_nvl_remove_all (MVL_VMD_CTRL *vmd_ctrl)
{
ST_INT didx;
MVL_DOM_CTRL *dom;
/* Destroy VMD-Specific NVLs. */
while (vmd_ctrl->num_nvlist)
{
MVL_NVLIST_CTRL *nvl;
OBJECT_NAME obj;
nvl = vmd_ctrl->nvlist_tbl[vmd_ctrl->num_nvlist-1]; /* point to last nvl*/
obj.obj_name.vmd_spec = nvl->name;
obj.object_tag = VMD_SPEC;
if (mvl_vmd_nvl_remove (vmd_ctrl, &obj, NULL) != SD_SUCCESS)
{
MVL_LOG_ERR1 ("Error removing VMD-specific NVL='%s'", nvl->name);
return (SD_FAILURE);
}
}
/* Destroy Domain-Specific NVLs in all domains. */
for (didx = 0; didx < vmd_ctrl->num_dom; didx++)
{
dom = vmd_ctrl->dom_tbl [didx];
while (dom->num_nvlist)
{
MVL_NVLIST_CTRL *nvl;
OBJECT_NAME obj;
nvl = dom->nvlist_tbl[dom->num_nvlist-1]; /* point to last nvl*/
obj.obj_name.item_id = nvl->name;
obj.domain_id = dom->name;
obj.object_tag = DOM_SPEC;
if (mvl_vmd_nvl_remove (vmd_ctrl, &obj, NULL) != SD_SUCCESS)
{
MVL_LOG_ERR2 ("Error removing NVL='%s' in domain '%s'", nvl->name, dom->name);
return (SD_FAILURE);
}
}
}
return (SD_SUCCESS);
}
/************************************************************************/
/* mvl_var_in_nvl */
/* Is this var used in this NVL? */
/************************************************************************/
ST_BOOLEAN mvl_var_in_nvl (MVL_NVLIST_CTRL *nvl, MVL_VAR_ASSOC *var)
{
ST_INT vidx;
MVL_VAR_ASSOC *nvl_var; /* variable used in a NVL */
for (vidx = 0; vidx < nvl->num_of_entries; vidx++)
{
nvl_var = nvl->entries[vidx];
if (nvl_var == var || nvl_var->base_va == var)
{ /* This variable (or a variable derived from it) is used in the NVL. */
return(SD_TRUE);
}
}
return (SD_FALSE); /* This variable is NOT used in the NVL. */
}
/************************************************************************/
/* mvl_var_deletable */
/* Is this var deletable (i.e. NOT referenced by other objects)? */
/************************************************************************/
ST_BOOLEAN mvl_var_deletable (MVL_VMD_CTRL *vmd_ctrl, MVL_VAR_ASSOC *var)
{
ST_INT didx, nvlidx;
MVL_DOM_CTRL *dom;
MVL_NVLIST_CTRL *nvl;
assert (var->base_va == NULL); /* DEBUG: these are always base variables.*/
/* Make sure var is not used in any VMD-specific NVL. */
for (nvlidx = 0; nvlidx < vmd_ctrl->num_nvlist; ++nvlidx)
{
nvl = vmd_ctrl->nvlist_tbl[nvlidx];
if (mvl_var_in_nvl (nvl, var))
{
MVL_LOG_ERR2 ("Variable=%s cannot be deleted because it is used in VMD-specific NVL=%s",
var->name, nvl->name);
return(SD_FALSE);
}
}
/* Make sure var is not used in any Domain-specific NVL in any Domain. */
for (didx = 0; didx < vmd_ctrl->num_dom; didx++)
{
dom = vmd_ctrl->dom_tbl [didx];
for (nvlidx = 0; nvlidx < dom->num_nvlist; nvlidx++)
{
nvl = dom->nvlist_tbl[nvlidx];
if (mvl_var_in_nvl (nvl, var))
{
MVL_LOG_ERR2 ("Variable=%s cannot be deleted because it is used in Domain-specific NVL=%s",
var->name, nvl->name);
return(SD_FALSE);
}
}
}
return (SD_TRUE); /* ok to delete it */
}
/************************************************************************/
/* mvl_nvl_deletable */
/* Is this NVL deletable (i.e. NOT referenced by other objects)? */
/************************************************************************/
ST_BOOLEAN mvl_nvl_deletable (MVL_VMD_CTRL *vmd_ctrl, MVL_NVLIST_CTRL *nvl)
{
#if defined(MVL_UCA) /* check for IEC 61850 or UCA RCBs using this NVL*/
MVLU_RPT_CTRL *rptCtrl;
/* NOTE: the flag "nvl->mms_deletable" is only used by the MMS service*/
/* DeleteNamedVariableList, not to prevent MVL from deleting this NVL.*/
/* See if NVL is used in any IEC 61850 Report Control Block. */
//lnk编译修改原前置程序未使用
/*for (rptCtrl = mvl61850_rpt_ctrl_list;
rptCtrl != NULL;
rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvl61850_rpt_ctrl_list, rptCtrl))
{
if (rptCtrl->dsNvl == nvl)
{
MVL_LOG_ERR1 ("NVL='%s' cannot be deleted because it is used in a IEC 61850 Report Control Block",
nvl->name);
return (SD_FALSE);
}
}*/
/* See if NVL is used in any UCA Report Control Block. */
//lnk编译修改原前置程序未使用
/*for (rptCtrl = mvlu_rpt_ctrl_list;
rptCtrl != NULL;
rptCtrl = (MVLU_RPT_CTRL *) list_get_next (mvlu_rpt_ctrl_list, rptCtrl))
{
if (rptCtrl->dsNvl == nvl)
{
MVL_LOG_ERR1 ("NVL='%s' cannot be deleted because it is used in a UCA Report Control Block",
nvl->name);
return (SD_FALSE);
}
}*/
#endif /* defined(MVL_UCA) */
/* NOTE: if not MVL_UCA, nothing to check. */
return (SD_TRUE); /* ok to delete it */
}
/************************************************************************/
/************************************************************************/
/* DOMAIN */
/************************************************************************/
/************************************************************************/
/* mvl_vmd_dom_add */
/* Add a domain. Allocate, fill in, and insert into table. */
/************************************************************************/
MVL_DOM_CTRL *mvl_vmd_dom_add (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *name, ST_INT max_num_var,
ST_INT max_num_nvl, ST_INT max_num_jou,
ST_BOOLEAN copy_name)
{
MVL_DOM_CTRL *dom;
dom = mvl_dom_create (name, max_num_var, max_num_nvl, max_num_jou, copy_name);
/* Insert it in table. */
if (mvl_vmd_dom_insert (vmd_ctrl, dom))
{ /* Failed. */
M_FREE (MSMEM_GEN, dom);
return (NULL);
}
return (dom);
}
/************************************************************************/
/* mvl_dom_create */
/************************************************************************/
MVL_DOM_CTRL *mvl_dom_create (ST_CHAR *name, ST_INT max_num_var,
ST_INT max_num_nvl, ST_INT max_num_jou,
ST_BOOLEAN copy_name)
{
MVL_DOM_CTRL *dom;
/* Allocate object and fill in "name". */
if (copy_name)
{
dom = (MVL_DOM_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_DOM_CTRL)
+ strlen (name) + 1);
dom->name = (ST_CHAR *) (dom+1);
strcpy (dom->name, name); /* copy name */
}
else
{
dom = (MVL_DOM_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_DOM_CTRL));
dom->name = name; /* point to user buffer */
}
/* Allocate the pointer tables */
mvl_dom_resize (dom, max_num_var, max_num_nvl, max_num_jou);
return (dom);
}
/************************************************************************/
/* mvl_dom_cleanup */
/* Remove all objects (NVLs, variables, journals) from this domain. */
/* CRITICAL: Use "*_remove" functions. They make sure it is safe to */
/* remove each object. */
/************************************************************************/
ST_RET mvl_dom_cleanup (MVL_VMD_CTRL *vmd_ctrl, MVL_DOM_CTRL *dom)
{
ST_INT i;
if (dom->foundry_objects)
{
MVL_LOG_NERR1 ("Cannot remove objects from domain '%s' because Foundry objects present", dom->name);
return (SD_FAILURE);
}
/* Remove all NVL from this domain. Stop on first error. */
while (dom->num_nvlist)
{
MVL_NVLIST_CTRL *nvl;
OBJECT_NAME obj;
nvl = dom->nvlist_tbl[dom->num_nvlist-1]; /* point to last nvl*/
obj.obj_name.item_id = nvl->name;
obj.domain_id = dom->name;
obj.object_tag = DOM_SPEC;
if (mvl_vmd_nvl_remove (vmd_ctrl, &obj, NULL) != SD_SUCCESS)
{
MVL_LOG_ERR2 ("Error removing NVL='%s' from domain='%s'",
nvl->name, dom->name);
return (SD_FAILURE);
}
}
/* Remove all variables from this domain. Stop on first error. */
while (dom->num_var_assoc > 0)
{
MVL_VAR_ASSOC *var;
OBJECT_NAME obj;
var = dom->var_assoc_tbl[dom->num_var_assoc-1]; /* point to last var*/
obj.obj_name.item_id = var->name;
obj.domain_id = dom->name;
obj.object_tag = DOM_SPEC;
if (mvl_vmd_var_remove (vmd_ctrl, &obj, NULL) != SD_SUCCESS)
{
MVL_LOG_ERR2 ("Error removing variable='%s' from domain='%s'",
var->name, dom->name);
return (SD_FAILURE);
}
}
/* Delete the Journal control table. */
/* DEBUG: Should use mvl_vmd_jou_remove here but it can't fail, so */
/* using mvl_jou_destroy is just as good for now. */
if (dom->max_num_jou)
{
for (i = 0; i < dom->num_jou; ++i)
mvl_jou_destroy (dom->jou_tbl[i]);
}
dom->num_jou = 0;
return (SD_SUCCESS);
}
/************************************************************************/
/* mvl_vmd_dom_remove */
/************************************************************************/
ST_RET mvl_vmd_dom_remove (MVL_VMD_CTRL *vmd_ctrl, ST_CHAR *dom_name)
{
MVL_DOM_CTRL *dom;
ST_RET retcode = SD_FAILURE;
dom = mvl_vmd_find_dom (vmd_ctrl, dom_name);
if (dom != NULL)
{
/* Remove all objects in domain before delete/destroy.*/
retcode = mvl_dom_cleanup (vmd_ctrl, dom);
if (retcode)
MVL_LOG_ERR1 ("Error removing objects from domain, so cannot remove domain '%s'",
dom->name);
else
{ /* cleanup successful */
/* NOTE: this delete should never fail because we already found it.*/
dom = mvl_vmd_dom_delete (vmd_ctrl, dom_name);
if (dom != NULL)
mvl_dom_destroy (dom); /* cannot fail. retcode already = SD_SUCCESS*/
else
retcode = SD_FAILURE; /* delete failed. Should never happen */
}
}
return (retcode);
}
/************************************************************************/
/* mvl_dom_destroy */
/* NOTE: this assumes all objects already removed from domain. */
/************************************************************************/
ST_VOID mvl_dom_destroy (MVL_DOM_CTRL *dom)
{
if (u_mvl_dom_destroy != NULL)
(*u_mvl_dom_destroy)(dom);
if (dom->max_num_var_assoc != 0)
M_FREE (MSMEM_GEN, dom->var_assoc_tbl);
if (dom->max_num_nvlist != 0)
M_FREE (MSMEM_GEN, dom->nvlist_tbl);
if (dom->max_num_jou != 0)
M_FREE (MSMEM_GEN, dom->jou_tbl);
M_FREE (MSMEM_GEN, dom);
}
/************************************************************************/
/**** VARIABLE ASSOCIATIONS */
/************************************************************************/
/* mvl_vmd_var_add */
/* Add a variable association. Allocate, fill in, and insert into table.*/
/* NOT RECOMMENDED: use mvl_var_add_alloc. */
/************************************************************************/
MVL_VAR_ASSOC *mvl_vmd_var_add (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info,
ST_INT type_id,
ST_VOID *data,
MVL_VAR_PROC *proc,
ST_BOOLEAN copy_name)
{
MVL_VAR_ASSOC *va;
MVL_DOM_CTRL *dom = NULL;
/* Find domain, if necessary, before allocating anything. */
if (obj->object_tag==DOM_SPEC && (dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id)) == NULL)
{
MVL_LOG_ERR2 ("Error creating VAR '%s': domain '%s' not found",
obj->obj_name.vmd_spec, obj->domain_id);
return (NULL);
}
va = mvl_var_create (obj, type_id, data, proc, copy_name);
/* Insert it in table. */
if (va)
{
if (mvl_vmd_var_insert (vmd_ctrl, va, obj, net_info))
{ /* Failed. */
mvl_var_destroy (va); /* destroy var just created */
return (NULL);
}
}
return (va);
}
/************************************************************************/
/* mvl_var_create */
/* NOT RECOMMENDED: use mvl_var_create_alloc. */
/************************************************************************/
MVL_VAR_ASSOC *mvl_var_create (OBJECT_NAME *obj, ST_INT type_id,
ST_VOID *data, MVL_VAR_PROC *proc,
ST_BOOLEAN copy_name)
{
MVL_VAR_ASSOC *va;
MVL_TYPE_CTRL *type_ctrl;
type_ctrl = mvl_type_ctrl_find (type_id);
if (type_ctrl == NULL)
{
MVL_LOG_ERR0 ("Cannot create variable (type_id invalid).");
return (NULL);
}
/* Allocate object and fill in "name". */
if (copy_name)
{
va = (MVL_VAR_ASSOC *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_VAR_ASSOC)
+ strlen (obj->obj_name.vmd_spec) + 1);
va->name = (ST_CHAR *) (va+1);
strcpy (va->name, obj->obj_name.vmd_spec); /* copy name */
}
else
{
va = (MVL_VAR_ASSOC *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_VAR_ASSOC));
va->name = obj->obj_name.vmd_spec; /* point to user buffer */
}
/* Fill in rest of object. */
va->type_id = type_id;
va->type_ctrl = type_ctrl; /* don't need to call mvl_get_runtime */
/* to get type details. */
va->data = data;
#if defined(MVL_UCA)
/* If caller set the data ptr (!=NULL), assume they want to use static data.*/
if (data!=NULL)
va->use_static_data = SD_TRUE;
#endif
va->proc = proc;
return (va);
}
/************************************************************************/
/* mvl_var_add_alloc */
/* Add a variable association. Allocate, fill in, and insert into table.*/
/************************************************************************/
MVL_VAR_ASSOC *mvl_var_add_alloc (MVL_VMD_CTRL *vmd_ctrl,
OBJECT_NAME *obj,
MVL_NET_INFO *net_info,
ST_INT type_id,
MVL_VAR_PROC *proc)
{
MVL_VAR_ASSOC *va;
MVL_DOM_CTRL *dom = NULL;
/* Find domain, if necessary, before allocating anything. */
if (obj->object_tag==DOM_SPEC && (dom = mvl_vmd_find_dom (vmd_ctrl, obj->domain_id)) == NULL)
{
MVL_LOG_ERR2 ("Error creating VAR '%s': domain '%s' not found",
obj->obj_name.vmd_spec, obj->domain_id);
return (NULL);
}
va = mvl_var_create_alloc (obj->obj_name.vmd_spec, type_id, proc);
/* Insert it in table. */
if (va)
{
if (mvl_vmd_var_insert (vmd_ctrl, va, obj, net_info))
{ /* Failed. */
mvl_var_destroy (va); /* destroy var just created */
return (NULL);
}
}
return (va);
}
/************************************************************************/
/* mvl_var_create_alloc */
/* Create a new variable. ALWAYS allocate a buffer for */
/* the data (buffer is automatically freed when variable is destroyed). */
/* CRITICAL: DO NOT use for "derived" variables. Instead use */
/* mvl_var_create_derived. */
/************************************************************************/
MVL_VAR_ASSOC *mvl_var_create_alloc (ST_CHAR *name,
ST_INT type_id,
MVL_VAR_PROC *proc)
{
MVL_VAR_ASSOC *va;
MVL_TYPE_CTRL *type_ctrl;
type_ctrl = mvl_type_ctrl_find (type_id);
if (type_ctrl == NULL)
{
MVL_LOG_ERR0 ("Cannot create variable (type_id invalid).");
return (NULL);
}
/* Allocate one buffer for MVL_VAR_ASSOC plus "data" plus "name". */
va = (MVL_VAR_ASSOC *) chk_calloc (1,
sizeof (MVL_VAR_ASSOC) /* space for struct*/
+ type_ctrl->data_size /* space for "data"*/
+ strlen (name) + 1); /* space for "name"*/
/* Set data ptr right after MVL_VAR_ASSOC struct. */
/* NOTE: data is before name so alignment should be good for any data.*/
va->data = (va+1);
/* Set name ptr right after data. */
va->name = ((ST_CHAR *) (va->data)) + type_ctrl->data_size;
strcpy (va->name, name); /* copy name */
/* Fill in rest of object. */
va->type_id = type_id;
va->type_ctrl = type_ctrl; /* save for easy access later. */
va->use_static_data = SD_TRUE; /* always SD_TRUE */
va->proc = proc;
return (va);
}
/************************************************************************/
/* mvl_var_create_derived */
/* Create a "derived" variable. */
/* NOTE: Structure member "proc" always set to NULL. */
/* Structure member "data" points inside base variable. */
/************************************************************************/
MVL_VAR_ASSOC *mvl_var_create_derived (ST_CHAR *name,
ST_INT type_id,
MVL_VAR_ASSOC *baseVa, /* base variable from which to derive */
ST_INT offset_from_base,
ST_RTINT prim_num)
{
MVL_VAR_ASSOC *va;
MVL_TYPE_CTRL *type_ctrl;
type_ctrl = mvl_type_ctrl_find (type_id);
if (type_ctrl == NULL)
{
MVL_LOG_ERR0 ("Cannot create variable (type_id invalid).");
return (NULL);
}
/* Allocate object and fill in "name". */
va = (MVL_VAR_ASSOC *) chk_calloc (1, sizeof (MVL_VAR_ASSOC)
+ strlen (name) + 1);
va->name = (ST_CHAR *) (va+1);
strcpy (va->name, name); /* copy name */
/* Fill in rest of object. */
va->type_id = type_id;
va->type_ctrl = type_ctrl; /* save for easy access later. */
/* va->proc = NULL (due to calloc above) */
/* Set special "va" elements only for derived variables. */
va->base_va = baseVa;
va->user_info = baseVa->user_info;
/* Save offset_from_base & prim_num passed as arguments. */
va->offset_from_base = offset_from_base;
va->prim_num = prim_num;
if (va->base_va->use_static_data)
va->data = (((ST_CHAR *) va->base_va->data) + va->offset_from_base);
/* else caller must set va->data. */
return (va);
}
/************************************************************************/
/* mvl_vmd_var_remove */
/************************************************************************/
ST_RET mvl_vmd_var_remove (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info)
{
MVL_VAR_ASSOC *va;
/* First find it & make sure it is deletable. */
va = mvl_vmd_find_var (vmd_ctrl, obj, net_info);
if (va == NULL || mvl_var_deletable (vmd_ctrl, va) == SD_FALSE)
{
MVL_LOG_ERR1 ("Error deleting variable='%s': not found or not deletable.",
obj->obj_name.vmd_spec);
return (SD_FAILURE);
}
va = mvl_vmd_var_delete (vmd_ctrl, obj, net_info);
if (va == NULL)
return (SD_FAILURE);
mvl_var_destroy (va);
return (SD_SUCCESS);
}
/************************************************************************/
/* mvl_var_destroy */
/************************************************************************/
ST_VOID mvl_var_destroy (MVL_VAR_ASSOC *va)
{
if (u_mvl_var_destroy != NULL)
(*u_mvl_var_destroy)(va);
/* "last_data" may have been allocated if this var used in NVL. */
if (va->last_data)
chk_free (va->last_data);
/* renxiaobao 日志
if (va->last_log_data)
chk_free (va->last_log_data);*/
M_FREE (MSMEM_GEN, va);
}
/************************************************************************/
/**** NAMED VARIABLE LISTS */
/************************************************************************/
/* mvl_vmd_nvl_add */
/* Add a Named Variable List. Allocate, fill in, and insert into table. */
/************************************************************************/
MVL_NVLIST_CTRL *mvl_vmd_nvl_add (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *nvl_obj, MVL_NET_INFO *net_info,
ST_INT num_var,
OBJECT_NAME *var_obj, /* array of var names */
ST_BOOLEAN copy_name)
{
MVL_NVLIST_CTRL *nvl;
MVL_DOM_CTRL *dom = NULL;
/* Find domain, if necessary, before allocating anything. */
if (nvl_obj->object_tag==DOM_SPEC && (dom = mvl_vmd_find_dom (vmd_ctrl, nvl_obj->domain_id)) == NULL)
{
MVL_LOG_ERR2 ("Error creating NVL '%s': domain '%s' not found",
nvl_obj->obj_name.vmd_spec, nvl_obj->domain_id);
return (NULL);
}
/* Allocate it AND fill it in. */
nvl = mvl_nvl_create (vmd_ctrl, nvl_obj->obj_name.vmd_spec, num_var, var_obj, net_info, copy_name);
if (nvl == NULL)
return (NULL);
/* Add scope info to "nvl". */
nvl->nvl_scope.scope = nvl_obj->object_tag;
nvl->nvl_scope.dom = dom; /* NOTE: NULL if not DOM_SPEC (see above) */
/* Insert it in table. */
if (mvl_vmd_nvl_insert (vmd_ctrl, nvl, nvl_obj, net_info))
{ /* Failed. */
mvl_nvl_destroy (nvl);
return (NULL);
}
return (nvl);
}
/************************************************************************/
/* mvl_nvl_create */
/************************************************************************/
/* Given a list of MMS object names, create a MVL Named Variable List. */
/* This can include both configured and MVLU manufactured variables */
/* Use 'mvl_nvl_destroy' to free this NVL. */
MVL_NVLIST_CTRL *mvl_nvl_create (MVL_VMD_CTRL *vmd_ctrl,
ST_CHAR *nvlName,
ST_INT numNames,
OBJECT_NAME *var_obj, /* array of var obj names*/
MVL_NET_INFO *net_info, /* where to find var_obj*/
/* if it is AA_SPEC */
ST_BOOLEAN copy_name)
{
MVL_NVLIST_CTRL *nvl;
ST_INT j;
/* Allocate object and fill in "name". */
if (copy_name)
{
nvl = (MVL_NVLIST_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_NVLIST_CTRL)
+ strlen (nvlName) + 1);
nvl->name = (ST_CHAR *) (nvl+1);
strcpy (nvl->name, nvlName); /* copy name */
}
else
{
nvl = (MVL_NVLIST_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_NVLIST_CTRL));
nvl->name = nvlName; /* point to user buffer */
}
/* Fill in rest of object. */
nvl->entries = (MVL_VAR_ASSOC **) M_CALLOC (MSMEM_GEN, numNames,
sizeof (MVL_VAR_ASSOC *));
nvl->va_scope = (MVL_SCOPE *) M_CALLOC (MSMEM_GEN, numNames,
sizeof (MVL_SCOPE));
nvl->num_of_entries = numNames;
for (j = 0; j < nvl->num_of_entries; ++j, ++var_obj)
{
MVL_VAR_ASSOC *var;
if ((nvl->entries[j] = var = _mvl_objname_to_va (vmd_ctrl, net_info, MMSOP_INFO_RPT,
var_obj, &nvl->va_scope[j], SD_FALSE, NULL, NULL)) == NULL)
{
MVL_LOG_ERR2 ("Error creating NVL '%s': member variable '%s' not found",
nvlName, var_obj->obj_name.vmd_spec);
mvl_nvl_destroy (nvl);
return (NULL);
}
else
{
#if defined(MVL_UCA)
/* Alloc buffer for last data (used for IEC/UCA reports). */
if (!var->last_data)
var->last_data = chk_calloc (1, mvl_type_ctrl[var->type_id].data_size);
/*renxiaobao 日志
if (!var->last_log_data)
var->last_log_data = chk_calloc (1, mvl_type_ctrl[var->type_id].data_size);*/
#endif
}
}
return (nvl);
}
/************************************************************************/
/* mvl_vmd_nvl_remove */
/* Remove a Named Variable List. Delete it from table and "destroy" it. */
/************************************************************************/
ST_RET mvl_vmd_nvl_remove (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info)
{
MVL_NVLIST_CTRL *nvl;
/* First find it & make sure it is deletable. */
nvl = mvl_vmd_find_nvl (vmd_ctrl, obj, net_info);
if (nvl == NULL || mvl_nvl_deletable (vmd_ctrl, nvl) == SD_FALSE)
{
MVL_LOG_ERR1 ("Error deleting NVL='%s': not found or not deletable.",
obj->obj_name.vmd_spec);
return (SD_FAILURE);
}
/* Delete it from table. */
if ((nvl = mvl_vmd_nvl_delete (vmd_ctrl, obj, net_info)) == NULL)
return (SD_FAILURE); /* nvl not found */
/* Destroy it. */
mvl_nvl_destroy (nvl);
return (SD_SUCCESS);
}
/************************************************************************/
/* mvl_nvl_destroy */
/************************************************************************/
/* Free a MVL Named Variable List created by 'mvl_nvl_create' */
ST_VOID mvl_nvl_destroy (MVL_NVLIST_CTRL *nvl)
{
MVL_VAR_ASSOC *va;
ST_INT i;
if (u_mvl_nvl_destroy != NULL)
(*u_mvl_nvl_destroy)(nvl);
/* Free up any manufactured variables */
for (i = 0; i < nvl->num_of_entries; ++i)
{
va = nvl->entries[i];
#if defined(MVL_UCA) || defined(USE_MANUFACTURED_OBJS)
/* NOTE: "va" may be NULL if mvl_nvl_create failed while adding entries.*/
if (va && va->va_to_free == va)
{
//u_mvl_free_va (MMSOP_INFO_RPT, va, NULL);//lnk编译删除原前置程序未使用
}
#endif
}
M_FREE (MSMEM_GEN, nvl->entries);
M_FREE (MSMEM_GEN, nvl->va_scope);
M_FREE (MSMEM_GEN, nvl);
}
/************************************************************************/
/**** JOURNALS */
/************************************************************************/
/* mvl_vmd_jou_add */
/* Add a Journal. Allocate, fill in, and insert into table. */
/************************************************************************/
MVL_JOURNAL_CTRL *mvl_vmd_jou_add (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info,
ST_BOOLEAN copy_name)
{
MVL_JOURNAL_CTRL *jou;
jou = mvl_jou_create (obj, net_info, copy_name);
if (mvl_vmd_jou_insert (vmd_ctrl, jou, obj, net_info))
{ /* Failed. */
M_FREE (MSMEM_GEN, jou);
return (NULL);
}
return (jou);
}
/************************************************************************/
/* mvl_jou_create */
/************************************************************************/
MVL_JOURNAL_CTRL *mvl_jou_create (OBJECT_NAME *obj, MVL_NET_INFO *net_info,
ST_BOOLEAN copy_name)
{
MVL_JOURNAL_CTRL *jou;
/* Allocate object and fill in "name". */
if (copy_name)
{
jou = (MVL_JOURNAL_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_JOURNAL_CTRL)
+ strlen (obj->obj_name.vmd_spec) + 1);
jou->name = (ST_CHAR *) (jou+1);
strcpy (jou->name, obj->obj_name.vmd_spec); /* copy name */
}
else
{
jou = (MVL_JOURNAL_CTRL *) M_CALLOC (MSMEM_GEN, 1, sizeof (MVL_JOURNAL_CTRL));
jou->name = obj->obj_name.vmd_spec; /* point to user buffer */
}
return (jou);
}
/************************************************************************/
/* mvl_vmd_jou_remove */
/************************************************************************/
ST_RET mvl_vmd_jou_remove (MVL_VMD_CTRL *vmd_ctrl, OBJECT_NAME *obj, MVL_NET_INFO *net_info)
{
MVL_JOURNAL_CTRL *jou;
jou = mvl_vmd_jou_delete (vmd_ctrl, obj, net_info);
if (jou == NULL)
return (SD_FAILURE);
mvl_jou_destroy (jou);
return (SD_SUCCESS);
}
/************************************************************************/
/* mvl_jou_destroy */
/************************************************************************/
ST_VOID mvl_jou_destroy (MVL_JOURNAL_CTRL *jou)
{
if (u_mvl_jou_destroy != NULL)
(*u_mvl_jou_destroy)(jou);
M_FREE (MSMEM_GEN, jou);
}
/************************************************************************/
/* mvl_vmd_create */
/* Create a new VMD with empty object arrays. */
/* Use "mvl_vmd_destroy" to destroy the VMD. */
/************************************************************************/
MVL_VMD_CTRL *mvl_vmd_create (ST_INT max_num_dom,
ST_INT max_num_var,
ST_INT max_num_nvl,
ST_INT max_num_journal)
{
MVL_VMD_CTRL *vmd_ctrl = chk_calloc (1, sizeof (MVL_VMD_CTRL));
vmd_ctrl->max_num_var_assoc = max_num_var;
if (vmd_ctrl->max_num_var_assoc)
vmd_ctrl->var_assoc_tbl = (MVL_VAR_ASSOC **) chk_calloc (
vmd_ctrl->max_num_var_assoc, sizeof (MVL_VAR_ASSOC *));
vmd_ctrl->max_num_nvlist = max_num_nvl;
if (vmd_ctrl->max_num_nvlist)
vmd_ctrl->nvlist_tbl = (MVL_NVLIST_CTRL **) chk_calloc (
vmd_ctrl->max_num_nvlist, sizeof (MVL_NVLIST_CTRL *));
vmd_ctrl->max_num_dom = max_num_dom;
if (vmd_ctrl->max_num_dom)
vmd_ctrl->dom_tbl = (MVL_DOM_CTRL **) chk_calloc (
vmd_ctrl->max_num_dom, sizeof (MVL_DOM_CTRL *));
vmd_ctrl->max_num_jou = max_num_journal;
if (vmd_ctrl->max_num_jou)
vmd_ctrl->jou_tbl = (MVL_JOURNAL_CTRL **) chk_calloc (
vmd_ctrl->max_num_jou, sizeof (MVL_JOURNAL_CTRL *));
return (vmd_ctrl);
};
/************************************************************************/
/* mvl_vmd_destroy */
/* Destroy all objects in this VMD. */
/* RETURNS: SD_SUCCESS or error code */
/************************************************************************/
ST_RET mvl_vmd_destroy (MVL_VMD_CTRL *vmd_ctrl)
{
ST_RET ret;
ST_INT j;
MVL_DOM_CTRL *dom;
ret = SD_SUCCESS; /* default ret val: returned if LD linked list empty.*/
/* Remove all NVL from this VMD and from all Domains before deleting */
/* Domains. NVLs might reference vars in other domains. */
/* CRITICAL: Must be done first, or vars can't be destroyed later. */
ret = mvl_nvl_remove_all (vmd_ctrl);
if (ret)
{
MVL_LOG_ERR0 ("Error destroying VMD: failed removing all NVL.");
return (ret);
}
/* Delete VMD-Specific Variables. */
for (j = 0; j < vmd_ctrl->num_var_assoc; ++j)
mvl_var_destroy (vmd_ctrl->var_assoc_tbl[j]);
vmd_ctrl->num_var_assoc = 0;
/* Delete Domains (always VMD-Specific). */
while ((dom = mvl_vmd_dom_find_last (vmd_ctrl)) != NULL)
{
ret = mvl_vmd_dom_remove (vmd_ctrl, dom->name);
if (ret != SD_SUCCESS)
break;
}
/* Destroy all types for this VMD. */
if (ret == SD_SUCCESS)
ret = mvl_vmd_type_id_destroy_all (vmd_ctrl);
/* Finally, free the tables and the VMD itself (allocated by mvl_vmd_create).*/
/* NOTE: can't do this for "mvl_vmd" because it was created by Foundry.*/
if (vmd_ctrl != &mvl_vmd)
{
if (vmd_ctrl->var_assoc_tbl)
chk_free (vmd_ctrl->var_assoc_tbl);
if (vmd_ctrl->nvlist_tbl)
chk_free (vmd_ctrl->nvlist_tbl);
if (vmd_ctrl->dom_tbl)
chk_free (vmd_ctrl->dom_tbl);
if (vmd_ctrl->jou_tbl)
chk_free (vmd_ctrl->jou_tbl);
chk_free (vmd_ctrl);
}
return (ret);
}