Files
microser/mmslib/mvlu/mvl_obj.c
2026-06-15 15:48:16 +08:00

1132 lines
38 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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