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

602 lines
22 KiB
C

/************************************************************************/
/* SISCO SOFTWARE MODULE HEADER *****************************************/
/************************************************************************/
/* (c) Copyright Systems Integration Specialists Company, Inc., */
/* 1998 All Rights Reserved */
/* */
/* MODULE NAME : mvl_ijou.c */
/* PRODUCT(S) : Lean-T Stack */
/* */
/* MODULE DESCRIPTION : */
/* Functions to automatically build a ReadJournal response, */
/* assuming the Journal is modeled as a linked list of journal */
/* entries. */
/* */
/* GLOBAL FUNCTIONS DEFINED IN THIS MODULE : */
/* u_mvl_start_jread */
/* u_mvl_get_next_jread_entry */
/* u_mvl_free_jread_entry */
/* u_mvl_end_jread */
/* */
/* MODIFICATION LOG : */
/* Date Who Rev Comments */
/* -------- --- ------ ------------------------------------------- */
/* 03/11/04 GLB 07 Remove "thisFileName" */
/* 04/14/00 JRB 06 Lint cleanup. */
/* 01/21/00 MDE 05 Now use MEM_SMEM for dynamic memory */
/* 09/13/99 MDE 04 Added SD_CONST modifiers */
/* 11/16/98 MDE 03 Renamed internal functions (prefix '_') */
/* 10/29/98 JRB 02 Delete unnecessary includes. */
/* 10/09/98 JRB 01 Created */
/************************************************************************/
#include "glbtypes.h"
#include "sysincs.h"
#include "mmsdefs.h"
#include "mvl_defs.h"
/************************************************************************/
/* All the functions below, used for building the ReadJournal response, */
/* assume the Journal is modeled as a linked list of journal entries. */
/* They use SISCO functions to search the linked list. The user code */
/* must use the same linked list functions to add journal entries to */
/* the linked list (or remove them from the linked list). */
/************************************************************************/
/************************************************************************/
/* Static functions for building the JREAD response. */
/************************************************************************/
static MVL_JOURNAL_ENTRY *find_je_start_time_forward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo);
static MVL_JOURNAL_ENTRY *find_je_start_time_backward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo);
static MVL_JOURNAL_ENTRY *find_je_start_entry (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo);
static MVL_JOURNAL_ENTRY *find_je_stop_forward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *start_je);
static MVL_JOURNAL_ENTRY *find_je_stop_backward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *start_je);
static MVL_JOURNAL_ENTRY *find_je_start_after_forward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *start_je,
MVL_JOURNAL_ENTRY *stop_je);
static MVL_JOURNAL_ENTRY *find_je_start_after_backward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *start_je,
MVL_JOURNAL_ENTRY *stop_je);
ST_BOOLEAN check_je_list_of_var (JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *je);
/************************************************************************/
/* Global variables for building the JREAD response. */
/************************************************************************/
MVL_JOURNAL_ENTRY *je_array [MAX_JREAD_RESP_ENTRIES]; /* array or pointers*/
ST_INT je_array_index; /* index into "je_array" */
ST_INT je_array_num_entries; /* # of entries in "je_array" */
ST_BOOLEAN jread_more_follows;
MVL_JOURNAL_ENTRY *stop_je; /* journal entry to stop with. */
/* NOT INCLUDED in response. */
/************************************************************************/
/************************************************************************/
ST_RET u_mvl_start_jread (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JREAD_BUF_CTRL *bufCtrl,
ST_VOID **usrHandleOut)
{
MVL_JOURNAL_ENTRY *je;
MVL_JOURNAL_ENTRY *start_je =jCtrl->entries; /* First entry that passes*/
/* "Range Start Spec." */
ST_BOOLEAN backwards = SD_FALSE;
ST_INT k;
/* Init global variables. */
je_array_index = 0;
je_array_num_entries = 0;
jread_more_follows = SD_TRUE; /* Assume "more_follows". */
if (reqInfo->range_start_pres
&& reqInfo->start_tag == 0 /* Use Starting time */
&& reqInfo->start_time.form != MMS_BTOD6)
{
printf ("\nERROR: ReadJournal request Starting Time illegal. Must be Btime6.");
return (SD_FAILURE);
}
if (reqInfo->range_stop_pres
&& reqInfo->stop_tag == 0 /* Use Stop time */
&& reqInfo->end_time.form != MMS_BTOD6)
{
printf ("\nERROR: ReadJournal request End Time illegal. Must be Btime6.");
return (SD_FAILURE);
}
if (reqInfo->sa_entry_pres
&& reqInfo->time_spec.form != MMS_BTOD6)
{
printf ("\nERROR: ReadJournal request Time Specification illegal. Must be Btime6.");
return (SD_FAILURE);
}
/* If "Number of Entries" is used and is negative, do reverse order. */
if (reqInfo->range_stop_pres
&& reqInfo->stop_tag != 0 /* Use "Number of Entries" */
&& reqInfo->num_of_entries < 0) /* Negative */
backwards = SD_TRUE; /* return entries in reverse order */
/* Process "Range Start Specification" */
if (reqInfo->range_start_pres)
{
if (reqInfo->start_tag == 0) /* Use Starting time */
{
if (reqInfo->range_stop_pres && reqInfo->stop_tag == 0)
{ /* Use "Ending Time" */
if (reqInfo->start_time.day > reqInfo->end_time.day ||
(reqInfo->start_time.day == reqInfo->end_time.day &&
reqInfo->start_time.ms > reqInfo->end_time.ms) )
{ /* Start time > End time */
backwards = SD_TRUE; /* return entries in reverse order */
}
}
if (backwards)
{
/* Set "start_je" to the first entry with time <= start time. */
/* Could be NULL if no entry found. */
start_je = find_je_start_time_backward (jCtrl, reqInfo);
}
else
{
/* Set "start_je" to the first entry with time >= start time. */
/* Could be NULL if no entry found. */
start_je = find_je_start_time_forward (jCtrl, reqInfo);
}
if (start_je == NULL)
return (SD_SUCCESS); /* None found. Return 0 entries */
}
else /* Use "Starting Entry" */
{
start_je = find_je_start_entry (jCtrl, reqInfo);
if (start_je == NULL)
return (SD_FAILURE); /* If no match, must send Negative resp.*/
if (reqInfo->range_stop_pres && reqInfo->stop_tag == 0)
{ /* Use "Ending Time" */
if (start_je->occur_time.day > reqInfo->end_time.day ||
(start_je->occur_time.day == reqInfo->end_time.day &&
start_je->occur_time.ms > reqInfo->end_time.ms) )
{ /* Entry time > End time */
backwards = SD_TRUE; /* return entries in reverse order */
}
}
}
} /* End processing "Range Start Specification". */
else
start_je = jCtrl->entries;
/* Process "Range Stop Specification" */
/* Set "stop_je" pointing to first entry past the "stop spec". */
if (backwards)
{ /* Search BACKWARD thru linked list */
stop_je = find_je_stop_backward (jCtrl, reqInfo, start_je);
}
else
{ /* Search FORWARD thru linked list */
stop_je = find_je_stop_forward (jCtrl, reqInfo, start_je);
}
/* Process "Entry to Start After" */
if (reqInfo->sa_entry_pres)
{ /* "Entry to Start After" specified. */
/* Scan linked list for "Start After Entry" and "Start After Time", */
/* up to "Range Stop", if specified. */
/* Adjust "start_entry" accordingly. */
if (backwards)
{ /* Search BACKWARD thru linked list */
start_je = find_je_start_after_backward (jCtrl, reqInfo, start_je, stop_je);
}
else
{ /* Search FORWARD thru linked list */
start_je = find_je_start_after_forward (jCtrl, reqInfo, start_je, stop_je);
} /* End "Search FORWARD thru linked list" */
}
else
; /* "Entry to Start After" NOT specified. Do nothing. */
/* End processing of "Entry to Start After" */
/* Now find all entries that pass the "List of Variables" filter */
/* and add them to an array of Journal entries to send in response. */
if (backwards)
{
for (je = start_je;
je != stop_je;
je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, (DBL_LNK *) je))
{
if (je_array_num_entries >= MAX_JREAD_RESP_ENTRIES)
break; /* Assume still more entries. */
/* If "List of Variables" specified, check if this entry matches.*/
if (check_je_list_of_var (reqInfo, je))
je_array[je_array_num_entries++] = je; /* Matched. */
} /* end "for" */
}
else
{ /* "!backwards" */
for (je = start_je;
je != stop_je;
je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je))
{
if (je_array_num_entries >= MAX_JREAD_RESP_ENTRIES)
break; /* Assume still more entries. */
/* If "List of Variables" specified, check if this entry matches.*/
if (check_je_list_of_var (reqInfo, je))
je_array[je_array_num_entries++] = je; /* Matched. */
} /* end "for" */
} /* End "!backwards" */
if (je == stop_je) /* End of linked list. */
jread_more_follows = SD_FALSE; /* No more entries */
/* We need to tell MVL how many entries and variables we have */
bufCtrl->numVarInfo = 0;
bufCtrl->numUsrEntries = je_array_num_entries;
for (k = 0; k < je_array_num_entries; k++)
{
je = je_array [k];
if (je->entry_form_tag == JE_FORM_DATA && je->ef.data.list_of_var_pres)
{ /* entry form is 'data' */
bufCtrl->numVarInfo += je->ef.data.num_of_var;
}
}
/* By default, MVL assumes "u_mvl_get_next_jread_entry" returns a */
/* pointer (*mvlJeDest) to persistent data. */
/* This is a valid assumption for the linked list implementation */
/* in this sample code. If you cannot point to persistent data, */
/* you must compile the MVL library and this code with */
/* MVL_JREAD_*_DYNAMIC defined and adjust the allocation to allow */
/* MVL enough space to copy the data. */
#if defined (MVL_JREAD_ENTRYID_DYNAMIC)
bufCtrl->entryIdBuf = M_MALLOC (MSMEM_GEN, 1000);
#endif
#if defined (MVL_JREAD_VARTAG_DYNAMIC)
bufCtrl->varTagBuf = M_MALLOC (MSMEM_GEN, 1000);
#endif
#if defined (MVL_JREAD_ANNOTATION_DYNAMIC)
bufCtrl->annotationBuf = M_MALLOC (MSMEM_GEN, 1000);
#endif
return (SD_SUCCESS);
}
/************************************************************************/
/************************************************************************/
ST_RET u_mvl_get_next_jread_entry (MVL_JOURNAL_CTRL *jCtrl,
ST_VOID *usrHandle,
ST_BOOLEAN *moreFollowsOut,
MVL_JOURNAL_ENTRY **mvlJeDest)
{
if (je_array_index >= je_array_num_entries)
return (SD_FAILURE); /* Should never happen. */
/* If last in "je_array", use "real more_follows value". */
if (je_array_index + 1 == je_array_num_entries)
*moreFollowsOut = jread_more_follows;
else
*moreFollowsOut = SD_TRUE; /* Not last in array, so always more. */
*mvlJeDest = je_array[je_array_index];
je_array_index++; /* Increment array index to next entry. */
return (SD_SUCCESS);
}
/************************************************************************/
ST_VOID u_mvl_free_jread_entry (MVL_JOURNAL_CTRL *jCtrl,
ST_VOID *usrHandle,
MVL_JOURNAL_ENTRY *mvlJe)
{
}
/************************************************************************/
ST_VOID u_mvl_end_jread (MVL_JOURNAL_CTRL *jCtrl,
ST_VOID *usrHandle,
MVL_JREAD_BUF_CTRL *bufCtrl,
JREAD_REQ_INFO *reqInfo)
{
/* Free up buffers allocated in "u_mvl_start_jread". */
#if defined (MVL_JREAD_ENTRYID_DYNAMIC)
M_FREE (MSMEM_GEN, bufCtrl->entryIdBuf);
#endif
#if defined (MVL_JREAD_VARTAG_DYNAMIC)
M_FREE (MSMEM_GEN, bufCtrl->varTagBuf);
#endif
#if defined (MVL_JREAD_ANNOTATION_DYNAMIC)
M_FREE (MSMEM_GEN, bufCtrl->annotationBuf);
#endif
}
/************************************************************************/
/************************************************************************/
static MVL_JOURNAL_ENTRY *find_je_start_time_forward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo)
{
MVL_JOURNAL_ENTRY *je;
for (je = jCtrl->entries;
je != NULL;
je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je))
{ /* Search entire linked list */
if (je->occur_time.day > reqInfo->start_time.day ||
(je->occur_time.day == reqInfo->start_time.day &&
je->occur_time.ms >= reqInfo->start_time.ms) )
break; /* entry time >= start time. Start here. */
} /* End "for" loop for time spec */
return (je); /* May be NULL if not found. */
}
/************************************************************************/
/************************************************************************/
static MVL_JOURNAL_ENTRY *find_je_start_time_backward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo)
{
MVL_JOURNAL_ENTRY *je;
for (je = (MVL_JOURNAL_ENTRY *) list_find_last ((DBL_LNK *) jCtrl->entries);
je != NULL;
je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, (DBL_LNK *) je))
{ /* Search entire linked list */
if (je->occur_time.day < reqInfo->start_time.day ||
(je->occur_time.day == reqInfo->start_time.day &&
je->occur_time.ms <= reqInfo->start_time.ms) )
break; /* entry time <= start time. Start here. */
} /* End "for" loop for time spec */
return (je); /* May be NULL if not found. */
}
/************************************************************************/
/************************************************************************/
static MVL_JOURNAL_ENTRY *find_je_start_entry (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo)
{
MVL_JOURNAL_ENTRY *je;
for (je = jCtrl->entries;
je != NULL;
je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je))
{
if (je->entry_id_len == reqInfo->start_entry_len &&
!memcmp (je->entry_id, reqInfo->start_entry, je->entry_id_len))
return (je); /* entry id == Starting Entry. Start here. */
} /* End "for" loop for "Starting Entry" */
return (NULL);
}
/************************************************************************/
/************************************************************************/
static MVL_JOURNAL_ENTRY *find_je_stop_forward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *start_je)
{
MVL_JOURNAL_ENTRY *je;
MVL_JOURNAL_ENTRY *stop_je;
ST_INT num_entries;
if (reqInfo->range_stop_pres)
{
for (je = start_je, num_entries = 0;
je != NULL;
je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je),
num_entries++)
{
if (reqInfo->stop_tag == 0)
{ /* Use "Ending Time" */
if (je->occur_time.day > reqInfo->end_time.day ||
(je->occur_time.day == reqInfo->end_time.day &&
je->occur_time.ms > reqInfo->end_time.ms) )
{ /* Entry time > End time */
break; /* Found it. Done. */
}
}
else
{ /* Use "Number of entries" */
if (num_entries >= reqInfo->num_of_entries)
break; /* Found it. Done. */
}
} /* end "for" */
stop_je = je; /* May be NULL if not found. */
}
else
stop_je = NULL; /* No stop spec. Set to NULL (i.e. end of list) */
return (stop_je);
}
/************************************************************************/
/************************************************************************/
static MVL_JOURNAL_ENTRY *find_je_stop_backward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *start_je)
{
MVL_JOURNAL_ENTRY *je;
MVL_JOURNAL_ENTRY *stop_je;
ST_INT num_entries;
if (reqInfo->range_stop_pres)
{
for (je = start_je, num_entries = 0;
je != NULL;
je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, (DBL_LNK *) je),
num_entries++)
{
if (reqInfo->stop_tag == 0)
{ /* Use "Ending Time" */
if (je->occur_time.day < reqInfo->end_time.day ||
(je->occur_time.day == reqInfo->end_time.day &&
je->occur_time.ms < reqInfo->end_time.ms) )
{ /* Entry time < End time */
break; /* Found it. Done. */
}
}
else
{ /* Use "Number of entries" ("0 -" converts neg to pos) */
if (num_entries >= (0 - reqInfo->num_of_entries) )
break; /* Found it. Done. */
}
} /* end "for" */
stop_je = je; /* May be NULL if not found. */
}
else
stop_je = NULL; /* No stop spec. Set to NULL (i.e. end of list) */
return (stop_je);
}
/************************************************************************/
/************************************************************************/
static MVL_JOURNAL_ENTRY *find_je_start_after_forward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *start_je,
MVL_JOURNAL_ENTRY *stop_je)
{
MVL_JOURNAL_ENTRY *je;
MVL_JOURNAL_ENTRY *start_after_entry_je=NULL; /* First entry that passes*/
/* "Start After Entry Spec."*/
MVL_JOURNAL_ENTRY *start_after_time_je=NULL; /* First entry that passes*/
/* "Start After Time Spec."*/
/* The variables "start_after_entry_je" and/or "start_after_time_je"*/
/* will be set to non-NULL values if they are found. */
/* If one of them is found, adjust "start_entry" accordingly. */
for (je = start_je;
je != stop_je;
je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries, je))
{
/* Check for matching "entry_spec" */
if (je->entry_id_len == reqInfo->entry_spec_len &&
!memcmp (je->entry_id, reqInfo->entry_spec, je->entry_id_len))
{ /* entry spec matches */
start_after_entry_je = je;
break; /* Done checking. */
}
/* If haven't found matching "entry_spec" yet, check "time_spec". */
if (start_after_time_je == NULL)
{ /* "time_spec" match not found yet. */
if (je->occur_time.day > reqInfo->time_spec.day ||
(je->occur_time.day == reqInfo->time_spec.day &&
je->occur_time.ms > reqInfo->time_spec.ms) )
{ /* entry time > time spec. */
/* Save this but keep checking for matching "entry_spec". */
start_after_time_je = je; /* DO NOT "break" */
}
}
} /* end "for" */
/* If found match on Start After Entry, start with NEXT entry. */
/* If only found match on Start After Time, start with THAT entry.*/
if (start_after_entry_je)
start_je = (MVL_JOURNAL_ENTRY *) list_get_next (jCtrl->entries,
start_after_entry_je);
else if (start_after_time_je)
start_je = start_after_time_je;
else
start_je = NULL; /* Didn't find either. Return 0 entries.*/
return (start_je);
}
/************************************************************************/
/************************************************************************/
static MVL_JOURNAL_ENTRY *find_je_start_after_backward (MVL_JOURNAL_CTRL *jCtrl,
JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *start_je,
MVL_JOURNAL_ENTRY *stop_je)
{
MVL_JOURNAL_ENTRY *je;
MVL_JOURNAL_ENTRY *start_after_entry_je=NULL; /* First entry that passes*/
/* "Start After Entry Spec."*/
MVL_JOURNAL_ENTRY *start_after_time_je=NULL; /* First entry that passes*/
/* "Start After Time Spec."*/
/* The variables "start_after_entry_je" and/or "start_after_time_je" */
/* will be set to non-NULL values if they are found. */
/* If one of them is found, adjust "start_entry" accordingly. */
for (je = start_je;
je != stop_je;
je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries, (DBL_LNK *) je))
{
/* Check for matching "entry_spec" */
if (je->entry_id_len == reqInfo->entry_spec_len &&
!memcmp (je->entry_id, reqInfo->entry_spec, je->entry_id_len))
{ /* entry spec matches */
start_after_entry_je = je;
break; /* Done checking. */
}
/* If haven't found matching "entry_spec" yet, check "time_spec". */
if (start_after_time_je == NULL)
{ /* "time_spec" match not found yet. */
if (je->occur_time.day < reqInfo->time_spec.day ||
(je->occur_time.day == reqInfo->time_spec.day &&
je->occur_time.ms < reqInfo->time_spec.ms) )
{ /* entry time < time spec. */
/* Save this but keep checking for matching "entry_spec". */
start_after_time_je = je; /* DO NOT "break" */
}
}
} /* end "for" */
/* If found match on Start After Entry, start with NEXT entry. */
/* If only found match on Start After Time, start with THAT entry.*/
if (start_after_entry_je)
start_je = (MVL_JOURNAL_ENTRY *) list_find_prev ((DBL_LNK *) jCtrl->entries,
(DBL_LNK *) start_after_entry_je);
else if (start_after_time_je)
start_je = start_after_time_je;
else
start_je = NULL; /* Didn't find either. Return 0 entries.*/
return (start_je);
}
/************************************************************************/
/************************************************************************/
ST_BOOLEAN check_je_list_of_var (JREAD_REQ_INFO *reqInfo,
MVL_JOURNAL_ENTRY *je)
{
ST_BOOLEAN retcode = SD_FALSE; /* No match. */
ST_INT j, k;
ST_CHAR **list_of_var;
if (reqInfo->list_of_var_pres)
{
list_of_var = (ST_CHAR **) (reqInfo + 1);
if (je->entry_form_tag == JE_FORM_DATA
&& je->ef.data.list_of_var_pres)
{
for (j = 0; j < reqInfo->num_of_var; j++)
{
for (k = 0; k < je->ef.data.num_of_var; k++)
{
if (!strcmp (je->ef.data.list_of_var[k].var_tag, list_of_var [j]))
retcode = SD_TRUE; /* Matched. */
} /* end "for" loop */
} /* end "for" loop */
}
} /* End "if (reqInfo->list_of_var_pres)" */
else
{ /* No "List of Variables" to check. This one must be OK.*/
retcode = SD_TRUE; /* Just as good as a match. */
}
return (retcode);
}