components/net-snmp-57/sun/agent/modules/entityMib/entPhysicalContainsTable.c
changeset 5867 445e2cf1c845
parent 252 ee0fb1eabcbf
equal deleted inserted replaced
5866:683c5c035a79 5867:445e2cf1c845
       
     1 /*
       
     2  * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
       
     3  *
       
     4  * U.S. Government Rights - Commercial software. Government users are subject
       
     5  * to the Sun Microsystems, Inc. standard license agreement and applicable
       
     6  * provisions of the FAR and its supplements.
       
     7  *
       
     8  *
       
     9  * This distribution may include materials developed by third parties. Sun,
       
    10  * Sun Microsystems, the Sun logo and Solaris are trademarks or registered
       
    11  * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.
       
    12  *
       
    13  */
       
    14 /*
       
    15  * Note: this file originally auto-generated by mib2c using
       
    16  *        : mib2c.iterate.conf,v 5.5 2002/12/16 22:50:18 hardaker Exp $
       
    17  */
       
    18 
       
    19 #include <net-snmp/net-snmp-config.h>
       
    20 #include <net-snmp/net-snmp-includes.h>
       
    21 #include <net-snmp/agent/net-snmp-agent-includes.h>
       
    22 #include "stdhdr.h"
       
    23 #include "entPhysicalContainsTable.h"
       
    24 #include "entPhysicalTable.h"
       
    25 #include "entLastChangeTime.h"
       
    26 
       
    27 static int FreePhyContainsTableEntry(physIndexAndChildIndex_t *);
       
    28 static int isRecursiveChild(int, int);
       
    29 
       
    30 physIndexAndChildIndex_t *gPhyContainsTableHead;
       
    31 int gPhyContainsTableSize;
       
    32 /* Fix for 4910641 */
       
    33 int_l *zChildIndexesTracker;
       
    34 /* End of Fix for 4910641 */
       
    35 
       
    36 /** Initialize the entPhysicalContainsTable table by defining its contents and how it's structured */
       
    37 void
       
    38 initialize_table_entPhysicalContainsTable(void)
       
    39 {
       
    40     static oid entPhysicalContainsTable_oid[] = {1,3,6,1,2,1,47,1,3,3};
       
    41     netsnmp_table_registration_info *table_info;
       
    42     netsnmp_handler_registration *my_handler;
       
    43     netsnmp_iterator_info *iinfo;
       
    44 
       
    45     /* create the table structure itself */
       
    46     table_info = SNMP_MALLOC_TYPEDEF(netsnmp_table_registration_info);
       
    47     iinfo = SNMP_MALLOC_TYPEDEF(netsnmp_iterator_info);
       
    48 
       
    49     /* if your table is read only, it's easiest to change the
       
    50        HANDLER_CAN_RWRITE definition below to HANDLER_CAN_RONLY */
       
    51     /* Fix for 4910624 - changing HANDLER_CAN_RWRITE to HANDLER_CAN_RONLY */
       
    52     my_handler = netsnmp_create_handler_registration("entPhysicalContainsTable",
       
    53                                                      entPhysicalContainsTable_handler,
       
    54                                                      entPhysicalContainsTable_oid,
       
    55                                                      OID_LENGTH(entPhysicalContainsTable_oid),
       
    56                                                      HANDLER_CAN_RONLY);
       
    57     /* End of Fix for 4910624 */
       
    58             
       
    59     if (!my_handler || !table_info || !iinfo)
       
    60         return; /* mallocs failed */
       
    61 
       
    62     /***************************************************
       
    63      * Setting up the table's definition
       
    64      */
       
    65     netsnmp_table_helper_add_indexes(table_info,
       
    66                                      ASN_INTEGER, /* index: entPhysicalIndex */
       
    67                                      ASN_INTEGER, /* index: entPhysicalChildIndex */
       
    68                                      0);
       
    69 
       
    70     table_info->min_column = 1;
       
    71     table_info->max_column = 1;
       
    72 
       
    73     /* iterator access routines */
       
    74     iinfo->get_first_data_point = entPhysicalContainsTable_get_first_data_point;
       
    75     iinfo->get_next_data_point = entPhysicalContainsTable_get_next_data_point;
       
    76 
       
    77     iinfo->table_reginfo = table_info;
       
    78 
       
    79     /***************************************************
       
    80      * registering the table with the master agent
       
    81      */
       
    82     DEBUGMSGTL(("initialize_table_entPhysicalContainsTable",
       
    83                 "Registering table entPhysicalContainsTable as a table iterator\n"));		 
       
    84     netsnmp_register_table_iterator(my_handler, iinfo);
       
    85 }
       
    86 
       
    87 /** Initializes the entPhysicalContainsTable module */
       
    88 void
       
    89 init_entPhysicalContainsTable(void)
       
    90 {
       
    91 
       
    92     /* here we initialize all the tables we're planning on supporting */
       
    93     initialize_table_entPhysicalContainsTable();
       
    94     gPhyContainsTableHead = NULL;
       
    95     gPhyContainsTableSize = 0;
       
    96 }
       
    97 
       
    98 /** returns the first data point within the entPhysicalContainsTable table data.
       
    99 
       
   100     Set the my_loop_context variable to the first data point structure
       
   101     of your choice (from which you can find the next one).  This could
       
   102     be anything from the first node in a linked list, to an integer
       
   103     pointer containing the beginning of an array variable.
       
   104 
       
   105     Set the my_data_context variable to something to be returned to
       
   106     you later that will provide you with the data to return in a given
       
   107     row.  This could be the same pointer as what my_loop_context is
       
   108     set to, or something different.
       
   109 
       
   110     The put_index_data variable contains a list of snmp variable
       
   111     bindings, one for each index in your table.  Set the values of
       
   112     each appropriately according to the data matching the first row
       
   113     and return the put_index_data variable at the end of the function.
       
   114 */
       
   115 netsnmp_variable_list *
       
   116 entPhysicalContainsTable_get_first_data_point(void **my_loop_context, void **my_data_context,
       
   117                                               netsnmp_variable_list *put_index_data,
       
   118                                               netsnmp_iterator_info *mydata)
       
   119 {
       
   120 
       
   121     netsnmp_variable_list *vptr;
       
   122     physIndexAndChildIndex_t *zRunner, *zpValidEntry;
       
   123     int_l *zChildIndexes, zValidChildIdx=0, *zpValidChildIdx;
       
   124 
       
   125     zRunner = gPhyContainsTableHead;
       
   126     while (zRunner) {
       
   127         if (zRunner->entPhysicalIndex > 0) {
       
   128             zChildIndexes = zRunner->childIndexes;
       
   129             while ((zChildIndexes != NULL) && (*zChildIndexes != 0)){
       
   130                 if (*zChildIndexes > 0) {
       
   131                     zValidChildIdx = *zChildIndexes;
       
   132                     break;
       
   133                 }
       
   134                 zChildIndexes++;
       
   135             }
       
   136             if (zValidChildIdx) {
       
   137                 zpValidEntry = zRunner;
       
   138                 zpValidChildIdx = zChildIndexes;
       
   139                 break;
       
   140             }
       
   141         }
       
   142         zRunner = zRunner->pNextEntry;
       
   143     }
       
   144     if (zRunner == NULL) return NULL;
       
   145 
       
   146     /* Fix for 4910641: No idea why it worked in Sparc with the original */
       
   147     /*                  version.  *my_loop_context was pointing to */
       
   148     /*                  temporary address, and maybe Intel and Sparc handles */
       
   149     /*                  memory differently - that is probably why it worked */
       
   150     /*                  on Sparc but not on Intel.  This version is */
       
   151     /*                  valid, and easier to trace and understand. */
       
   152     *my_loop_context = (void *) zpValidEntry;
       
   153     *my_data_context = (void *) zpValidChildIdx;
       
   154     zChildIndexesTracker = zpValidChildIdx;
       
   155     /* End of Fix for 4910641 */
       
   156 
       
   157     vptr = put_index_data;
       
   158     
       
   159     snmp_set_var_value(vptr, (u_char *) &zpValidEntry->entPhysicalIndex, sizeof(zpValidEntry->entPhysicalIndex));
       
   160     vptr = vptr->next_variable;
       
   161     snmp_set_var_value(vptr, (u_char *) zpValidChildIdx, sizeof(int_l));
       
   162     vptr = vptr->next_variable;
       
   163 
       
   164     return put_index_data;
       
   165 }
       
   166 
       
   167 /** functionally the same as entPhysicalContainsTable_get_first_data_point, but
       
   168    my_loop_context has already been set to a previous value and should
       
   169    be updated to the next in the list.  For example, if it was a
       
   170    linked list, you might want to cast it and the return
       
   171    my_loop_context->next.  The my_data_context pointer should be set
       
   172    to something you need later and the indexes in put_index_data
       
   173    updated again. */
       
   174 
       
   175 netsnmp_variable_list *
       
   176 entPhysicalContainsTable_get_next_data_point(void **my_loop_context, void **my_data_context,
       
   177                                              netsnmp_variable_list *put_index_data,
       
   178                                              netsnmp_iterator_info *mydata)
       
   179 {
       
   180 
       
   181     netsnmp_variable_list *vptr;
       
   182     physIndexAndChildIndex_t *zRunner, *zpValidEntry;
       
   183     int_l *zChildIndexes, zValidChildIdx=0, *zpValidChildIdx;
       
   184 
       
   185     /* Fix for 4910641: We need to dereference the pointers, and cast */
       
   186     /*                  them back to the appropriate data structure */
       
   187     zRunner = (physIndexAndChildIndex_t *)*my_loop_context;
       
   188     zChildIndexes = zChildIndexesTracker;
       
   189     /* End of Fix for 4910641 */
       
   190 
       
   191     if (zChildIndexes) 
       
   192 	zChildIndexes++;
       
   193     while (zRunner) {
       
   194         if (zRunner->entPhysicalIndex > 0) {
       
   195             while ((zChildIndexes != NULL) && (*zChildIndexes != 0)){
       
   196                 if (*zChildIndexes > 0) {
       
   197                     zValidChildIdx = *zChildIndexes;
       
   198                     break;
       
   199                 }
       
   200                 zChildIndexes++;
       
   201             }
       
   202             if (zValidChildIdx) {
       
   203                 zpValidEntry = zRunner;
       
   204                 zpValidChildIdx = zChildIndexes;
       
   205                 break;
       
   206             }
       
   207         }
       
   208         zRunner = zRunner->pNextEntry;
       
   209         if (zRunner)
       
   210             zChildIndexes = zRunner->childIndexes;
       
   211     }
       
   212     if (zRunner == NULL) return NULL;
       
   213 
       
   214     /* Fix for 4910641: We are making sure that *my_loop_context and */
       
   215     /*                  *my_data_context are pointing to valid entries. */
       
   216     *my_loop_context = (void *) zpValidEntry;
       
   217     *my_data_context = (void *) zpValidChildIdx;
       
   218     zChildIndexesTracker = zpValidChildIdx;
       
   219     /* End Fix for 4910641 */
       
   220     
       
   221     vptr = put_index_data;
       
   222     
       
   223     snmp_set_var_value(vptr, (u_char *) &zpValidEntry->entPhysicalIndex, sizeof(zpValidEntry->entPhysicalIndex));
       
   224     vptr = vptr->next_variable;
       
   225     snmp_set_var_value(vptr, (u_char *) zpValidChildIdx, sizeof(int_l));
       
   226     vptr = vptr->next_variable;
       
   227 
       
   228     return put_index_data;
       
   229 }
       
   230 
       
   231 /** handles requests for the entPhysicalContainsTable table, if anything else needs to be done */
       
   232 int
       
   233 entPhysicalContainsTable_handler(
       
   234     netsnmp_mib_handler               *handler,
       
   235     netsnmp_handler_registration      *reginfo,
       
   236     netsnmp_agent_request_info        *reqinfo,
       
   237     netsnmp_request_info              *requests) {
       
   238 
       
   239     netsnmp_request_info *request;
       
   240     netsnmp_table_request_info *table_info;
       
   241     netsnmp_variable_list *var;
       
   242     int_l *idx;
       
   243     
       
   244     for(request = requests; request; request = request->next) {
       
   245         var = request->requestvb;
       
   246         if (request->processed != 0)
       
   247             continue;
       
   248 
       
   249         /* perform anything here that you need to do before each
       
   250            request is processed. */
       
   251 
       
   252         /* the following extracts the my_data_context pointer set in
       
   253            the loop functions above.  You can then use the results to
       
   254            help return data for the columns of the entPhysicalContainsTable table in question */
       
   255         idx = (int_l *) netsnmp_extract_iterator_context(request);
       
   256         if (idx == NULL) {
       
   257             if (reqinfo->mode == MODE_GET) {
       
   258                 netsnmp_set_request_error(reqinfo, request, SNMP_NOSUCHINSTANCE);
       
   259                 continue;
       
   260             }
       
   261             /* XXX: no row existed, if you support creation and this is a
       
   262                set, start dealing with it here, else continue */
       
   263         }
       
   264 
       
   265         /* extracts the information about the table from the request */
       
   266         table_info = netsnmp_extract_table_info(request);
       
   267         /* table_info->colnum contains the column number requested */
       
   268         /* table_info->indexes contains a linked list of snmp variable
       
   269            bindings for the indexes of the table.  Values in the list
       
   270            have been set corresponding to the indexes of the
       
   271            request */
       
   272         if (table_info==NULL) {
       
   273             continue;
       
   274         }
       
   275 
       
   276         switch(reqinfo->mode) {
       
   277             /* the table_iterator helper should change all GETNEXTs
       
   278                into GETs for you automatically, so you don't have to
       
   279                worry about the GETNEXT case.  Only GETs and SETs need
       
   280                to be dealt with here */
       
   281         case MODE_GET:
       
   282             switch(table_info->colnum) {
       
   283             case COLUMN_ENTPHYSICALCHILDINDEX:
       
   284                 snmp_set_var_typed_value(var, ASN_INTEGER, (u_char *) idx, sizeof(idx));
       
   285                 break;
       
   286 
       
   287             default:
       
   288                 /* We shouldn't get here */
       
   289                 snmp_log(LOG_ERR, "problem encountered in entPhysicalContainsTable_handler: unknown column\n");
       
   290             }
       
   291             break;
       
   292 
       
   293         case MODE_SET_RESERVE1:
       
   294             /* set handling... */
       
   295 
       
   296         default:
       
   297             snmp_log(LOG_ERR, "problem encountered in entPhysicalContainsTable_handler: unsupported mode\n");
       
   298         }
       
   299     }
       
   300     return SNMP_ERR_NOERROR;
       
   301 }
       
   302 
       
   303 /* Returns 0 for success
       
   304    1 if the entry already exists
       
   305    -1 for failure
       
   306    -2 for stale index */
       
   307 /* Fix for 4915033 */
       
   308 int addPhysicalContainsTableEntry(int xentPhysicalIndex, int xentChildIndex)
       
   309 /* End of Fix for 4915033 */
       
   310 {
       
   311     entPhysicalEntry_t *physentry, *childentry;
       
   312     physIndexAndChildIndex_t *zContainsTableEntry, *zRunner, *zlastEntry;
       
   313     int_l *zChildIndexes;
       
   314  
       
   315     /* Fix for 4890316: Check that adding itself as a child is not allowed */
       
   316     if (xentPhysicalIndex == xentChildIndex) {
       
   317         return (-1);
       
   318     }
       
   319     /* End of Fix for 4890316 */
       
   320 
       
   321     /* Fix for 48888088: -1 for invalid index, -2 for stale entries */
       
   322     if (xentPhysicalIndex <= 0 || xentPhysicalIndex > MAX_ENTITY_INDEX || xentChildIndex <= 0 || xentChildIndex > MAX_ENTITY_INDEX)
       
   323         return -1;
       
   324     physentry = getPhysicalTableStaleEntry(xentPhysicalIndex);
       
   325     if (physentry != NULL)
       
   326         return -2;
       
   327     childentry = getPhysicalTableStaleEntry(xentChildIndex);
       
   328     if (childentry != NULL)
       
   329         return -2;
       
   330     /* End of Fix for 4888088 */
       
   331 
       
   332     physentry = getPhysicalTableEntry(xentPhysicalIndex);
       
   333     childentry = getPhysicalTableEntry(xentChildIndex);
       
   334 
       
   335     if (physentry == NULL || childentry == NULL) {
       
   336 /*
       
   337   Handle error here. Send it to log files
       
   338 */
       
   339         return (-1);
       
   340     }
       
   341 
       
   342     /* Fix for 4915080 */
       
   343     if (isRecursiveChild(xentChildIndex, xentPhysicalIndex))
       
   344         return (-1);
       
   345     /* End of Fix for 4915080 */
       
   346 
       
   347     zlastEntry = NULL;
       
   348     zRunner = gPhyContainsTableHead;
       
   349     while (zRunner != NULL) {
       
   350         if (zRunner->entPhysicalIndex == xentPhysicalIndex) {
       
   351             break;
       
   352         }
       
   353         zlastEntry = zRunner;
       
   354         zRunner = zRunner->pNextEntry;
       
   355     }
       
   356     if (zRunner != NULL ) {/* Found a entry with log index */
       
   357         int_l *p;
       
   358         p = zRunner->childIndexes;
       
   359         if (p == NULL) {
       
   360             zChildIndexes = (int_l *) malloc(2 * sizeof (int_l));
       
   361             if (!zChildIndexes) return -1;
       
   362             zChildIndexes[0] = xentChildIndex;
       
   363             zChildIndexes[1] = 0;
       
   364             zRunner->childIndexes = zChildIndexes;
       
   365         } else {/* Add phy index to last entry in the array */
       
   366             int i=0;
       
   367             int_l *empty = NULL;
       
   368             while (p != NULL && *p != 0) {
       
   369                 if (*p == xentChildIndex) {
       
   370                     /* Already in the array, return a 1 */
       
   371 		    return (1);
       
   372 	        }
       
   373                 if (*p == -1) /* Empty Slot */
       
   374                     empty = p;
       
   375                 p++;
       
   376                 i++;
       
   377             }
       
   378 	    if (empty) { /* Reuse a empty spot */
       
   379 		*empty = xentChildIndex;
       
   380 	    } else {
       
   381                 zRunner->childIndexes =
       
   382                     (int_l *)realloc(zRunner->childIndexes, (i + 2)*sizeof(int_l));
       
   383 		if (!zRunner->childIndexes) return -1;
       
   384                 zRunner->childIndexes[i] = xentChildIndex;
       
   385                 zRunner->childIndexes[i+1] = 0;
       
   386 	    }
       
   387         }
       
   388         /* Fix for 4891869: We replace entPhysicalContainedIn with this */
       
   389         /*                  entry only when this index is lower */
       
   390         if (childentry->entPhysicalContainedIn == 0 || childentry->entPhysicalContainedIn > xentPhysicalIndex)
       
   391             childentry->entPhysicalContainedIn = xentPhysicalIndex;
       
   392         /* End of Fix for 4891869 */
       
   393         configChanged();
       
   394         return (0);
       
   395     }
       
   396 
       
   397     /* New entry*/
       
   398     zContainsTableEntry = (physIndexAndChildIndex_t *)malloc(sizeof(physIndexAndChildIndex_t));
       
   399     if (!zContainsTableEntry) return -1;
       
   400     zContainsTableEntry->entPhysicalIndex = xentPhysicalIndex;
       
   401     zChildIndexes = (int_l *) malloc(2 * sizeof (int_l));
       
   402     if (!zChildIndexes) return -1;
       
   403     zChildIndexes[0] = xentChildIndex;
       
   404     zChildIndexes[1] = 0;
       
   405     zContainsTableEntry->childIndexes = zChildIndexes;
       
   406     zContainsTableEntry->pNextEntry = NULL;
       
   407     if (zlastEntry){
       
   408         zlastEntry->pNextEntry = zContainsTableEntry;
       
   409     } else {
       
   410         gPhyContainsTableHead = zContainsTableEntry;
       
   411     }
       
   412     /* Fix for 4891869: We replace entPhysicalContainedIn with this entry */
       
   413     /*                  only when this index is lower */
       
   414     if (childentry->entPhysicalContainedIn == 0 || childentry->entPhysicalContainedIn > xentPhysicalIndex)
       
   415         childentry->entPhysicalContainedIn = xentPhysicalIndex;
       
   416     /* End of Fix for 4891869 */
       
   417     gPhyContainsTableSize++;
       
   418     configChanged();
       
   419     return (0);
       
   420 }
       
   421 
       
   422 /*
       
   423  * Returns NULL if children, else returns int array with null termination
       
   424  * The array is not a copy and SHOULD NOT be written to unless the
       
   425  * intent is to update the master information
       
   426  */
       
   427 /* Fix for 4915033 */
       
   428 int *getPhysicalContainsChildren(int parentIndex)
       
   429 /* End of Fix for 4915033 */
       
   430 {
       
   431     entPhysicalEntry_t *physentry;
       
   432     int_l *childIndexes=NULL;
       
   433     /* Fix for 4914153 */
       
   434     int *resultIndexes=NULL, i = 0;
       
   435     /* End of Fix for 4914153 */
       
   436     physIndexAndChildIndex_t *zRunner;
       
   437 
       
   438     /*
       
   439      * Find parent
       
   440      */
       
   441     physentry = getPhysicalTableEntry(parentIndex);
       
   442     if (physentry == NULL) {
       
   443         return (NULL);  /* assume no children */
       
   444     }
       
   445 
       
   446     zRunner = gPhyContainsTableHead;
       
   447     while (zRunner != NULL) {
       
   448         if ((zRunner->entPhysicalIndex == parentIndex)) {
       
   449             childIndexes = zRunner->childIndexes;
       
   450             /* Fix for 4914153: From this childIndexes array, we only */
       
   451             /* returns the true children array, excluding those "-1" entries */
       
   452             if (childIndexes != NULL) {
       
   453                 while (*childIndexes != 0) {
       
   454                     /* We only need to count this entry if it is a valid */
       
   455                     /* (> -1) entry.  Else we move on until the end of the */
       
   456                     /* list */
       
   457                     if (*childIndexes > 0) {
       
   458                         resultIndexes = realloc(resultIndexes, (i + 1)*sizeof(int));
       
   459                         if (resultIndexes == NULL)
       
   460                             return NULL; /* Not enough memory, just return NULL */
       
   461                         resultIndexes[i] = *childIndexes;
       
   462                         i++;
       
   463 
       
   464                     }
       
   465                     childIndexes++;
       
   466                 }
       
   467             }
       
   468             /* We can break here because this condition: */
       
   469             /* zRunner->entPhysicalIndex == parentIndex condition */
       
   470             /* can only happen once in the entPhysicalContains linked list */
       
   471             break;
       
   472             /* End of Fix for 4914153 */
       
   473         }
       
   474         zRunner = zRunner->pNextEntry;
       
   475     }
       
   476     /* Fix for 4914153: returns a NULL terminated list */
       
   477     if (i > 0) /* at least one child is found */
       
   478         resultIndexes = realloc(resultIndexes, (i + 1)*sizeof(int));
       
   479     if (resultIndexes == NULL) /* Not enough memory or no child found -> NULL */
       
   480         return NULL;
       
   481     resultIndexes[i] = 0;
       
   482     return (resultIndexes);
       
   483     /* End of Fix for 4914153 */
       
   484 }
       
   485 
       
   486 /* Fix for 4915033 */
       
   487 /* This function will delete all the entries which has the parent index = */
       
   488 /* xParentIndex. */
       
   489 /* Returns number of entries deleted for success, */
       
   490 /* -1 if entry not found */
       
   491 /* -2 if stale */
       
   492 int deletePhysicalContainsParentIndex(int xParentIndex)
       
   493 {
       
   494     /* We go through the ContainsTable, and remove the parent */
       
   495     physIndexAndChildIndex_t *zRunner, *prevEntry, *temp=NULL;
       
   496     int num=0;
       
   497     /* Fix for 4926042*/
       
   498     int *childIndexes, *zchildIndexes;
       
   499     /* End of Fix for 4926042 */
       
   500     int_l *childIndexes2;
       
   501     int lowest_index = 0;
       
   502     entPhysicalEntry_t *physentry;
       
   503     int num_child=0;
       
   504 
       
   505     /* Fix for 4888088 */
       
   506     if (xParentIndex <= 0 || xParentIndex > MAX_ENTITY_INDEX)
       
   507         return -1;
       
   508     physentry = getPhysicalTableStaleEntry(xParentIndex);
       
   509     if (physentry != NULL)
       
   510         return -2;
       
   511     /* End of Fix for 4888088 */
       
   512 
       
   513     zRunner = gPhyContainsTableHead;
       
   514     prevEntry = NULL;
       
   515 
       
   516     while (zRunner != NULL) {
       
   517         if (zRunner->entPhysicalIndex == xParentIndex) {
       
   518             temp =  zRunner->pNextEntry;
       
   519             zRunner->pNextEntry = NULL;
       
   520 
       
   521             /* Fix for 4891869: we need to figure out the list of children */
       
   522             /*                  belonging to this parent, before actually */
       
   523             /*                  deleting the parent */
       
   524             childIndexes = getPhysicalContainsChildren(xParentIndex);
       
   525             /* Fix for 4926042 */
       
   526             zchildIndexes = childIndexes;
       
   527             /* End of Fix for 4926042 */
       
   528             /* End of Fix for 4891869 */
       
   529 
       
   530             if (prevEntry)
       
   531                 prevEntry->pNextEntry = temp;
       
   532             else
       
   533                 gPhyContainsTableHead = temp;
       
   534             FreePhyContainsTableEntry(zRunner);
       
   535             num++;
       
   536             gPhyContainsTableSize--;
       
   537             break;
       
   538         }
       
   539         prevEntry = zRunner;
       
   540         zRunner = zRunner->pNextEntry;
       
   541     }
       
   542     if (num) {
       
   543         /* Fix for 4891869: We need to sync the entPhysicalContainedIn */
       
   544         /* 1. Find all the children that has this as a parent */
       
   545         /* 2. If the parent is the last one for this child, reset the */
       
   546         /*    entPhysicalContainedIn to 0 */
       
   547         /* 3. If more than one parent, and if this is the lowest index, */
       
   548         /*    then reset this to the next lowest */
       
   549         /* 4. Otherwise do nothing */
       
   550         num_child = 0;
       
   551         while (childIndexes != NULL && *childIndexes != 0) {
       
   552             physentry = getPhysicalTableEntry(*childIndexes);
       
   553             if (physentry != NULL) {
       
   554                 /* Need to reset entPhysicalContainedIn only if the */
       
   555                 /* xParentIndex is already the lowest index.  In this case, */
       
   556                 /* we will go through the ContainsTable and search for */
       
   557                 /* all the parents for this particular child, and set it */
       
   558                 /* to the second lowest index */
       
   559                 if (physentry->entPhysicalContainedIn == xParentIndex) {
       
   560                     zRunner = gPhyContainsTableHead;
       
   561                     lowest_index = 0; /* First reset to zero */
       
   562 
       
   563                     while (zRunner != NULL) {
       
   564                         childIndexes2 = zRunner->childIndexes;
       
   565                         while (childIndexes2 != NULL && *childIndexes2 != 0) {
       
   566                             if (*childIndexes2 == *childIndexes) {
       
   567                                 if (lowest_index == 0)
       
   568                                     lowest_index = zRunner->entPhysicalIndex;
       
   569                                 else if (lowest_index > zRunner->entPhysicalIndex)
       
   570                                     lowest_index = zRunner->entPhysicalIndex;
       
   571                                 break;
       
   572                             }
       
   573                             childIndexes2++;
       
   574                         }
       
   575                         zRunner = zRunner->pNextEntry;
       
   576                     }
       
   577                     physentry->entPhysicalContainedIn = lowest_index;
       
   578                 }
       
   579             }
       
   580             /* Fix for 4888088: count the number of children */
       
   581             if (*childIndexes > 0)
       
   582                 num_child++;
       
   583             /* End of Fix for 4888088 */
       
   584             childIndexes++;
       
   585         }
       
   586         /* End of Fix for 4891869 */
       
   587         configChanged();
       
   588         /* Fix for 4926042 */
       
   589         free (zchildIndexes);
       
   590         /* End of Fix for 4926042 */
       
   591         return (num_child);
       
   592     } else {
       
   593         return (-1);
       
   594     }
       
   595 }
       
   596 
       
   597 /* This function will delete all the entries which has the child index = */
       
   598 /* xChildIndex */
       
   599 /* Returns number of entries deleted for success, */
       
   600 /* -1 if entry not found */
       
   601 /* -2 if entry is stale */
       
   602 int deletePhysicalContainsChildIndex(int xChildIndex)
       
   603 {
       
   604     physIndexAndChildIndex_t *zRunner;
       
   605     int_l *childIndexes=NULL;
       
   606     int num=0;
       
   607 
       
   608     /* Fix for 4888088 */
       
   609     entPhysicalEntry_t *physentry;
       
   610     if (xChildIndex <= 0 || xChildIndex > MAX_ENTITY_INDEX)
       
   611         return -1;
       
   612     physentry = getPhysicalTableStaleEntry(xChildIndex);
       
   613     if (physentry != NULL)
       
   614         return -2;
       
   615     /* End of Fix for 4888088 */
       
   616 
       
   617     zRunner = gPhyContainsTableHead;
       
   618     while (zRunner != NULL) {
       
   619         childIndexes = zRunner->childIndexes;
       
   620         while (childIndexes != NULL && *childIndexes != 0) {
       
   621             if (*childIndexes == xChildIndex) {
       
   622                 deletePhysicalContainsTableEntry((int)zRunner->entPhysicalIndex, xChildIndex);
       
   623                 num++;
       
   624             }
       
   625             childIndexes++;
       
   626         }
       
   627         zRunner = zRunner->pNextEntry;
       
   628     }
       
   629     if (num) {
       
   630         configChanged();
       
   631         return (num);
       
   632     } else {
       
   633         return (-1);
       
   634     }
       
   635 }
       
   636 
       
   637 /* Delete the entry specified by the xParentIndex and xChildIndex */
       
   638 /* returns 0 if successful */
       
   639 /* -1 if entry not found */
       
   640 /* -2 if entry is stale */
       
   641 int deletePhysicalContainsTableEntry(int xParentIndex, int xChildIndex)
       
   642 {
       
   643     physIndexAndChildIndex_t *zRunner;
       
   644     entPhysicalEntry_t *physentry;
       
   645     int zparentIdx;
       
   646     int num=0;
       
   647     int_l *childIndexes=NULL;
       
   648     int lowest_index = 0;
       
   649 
       
   650     /* Fix for 4888088 */
       
   651     if (xParentIndex <= 0 || xParentIndex > MAX_ENTITY_INDEX || xChildIndex <= 0 || xChildIndex > MAX_ENTITY_INDEX)
       
   652         return -1;
       
   653     physentry = getPhysicalTableStaleEntry(xParentIndex);
       
   654     if (physentry != NULL)
       
   655         return -2;
       
   656     physentry = getPhysicalTableStaleEntry(xChildIndex);
       
   657     if (physentry != NULL)
       
   658         return -2;
       
   659     /* End of Fix for 4888088 */
       
   660     
       
   661     zRunner = gPhyContainsTableHead;
       
   662 
       
   663     while (zRunner != NULL) {
       
   664         zparentIdx = zRunner->entPhysicalIndex;
       
   665         if (zparentIdx == xParentIndex) {
       
   666             childIndexes = zRunner->childIndexes;
       
   667             while (childIndexes != NULL && *childIndexes != 0) {
       
   668                 if (*childIndexes == xChildIndex) {
       
   669                     *childIndexes = -1;
       
   670                     num++;
       
   671                 }
       
   672                 childIndexes++;
       
   673             }
       
   674             break;
       
   675         }
       
   676         zRunner = zRunner->pNextEntry;
       
   677     }
       
   678     if (num) {
       
   679         /* Fix for 4891869: we need to make sure that we reset the */
       
   680         /* entPhysicalContainedIn when necessary */
       
   681         physentry = getPhysicalTableEntry(xChildIndex);
       
   682         if (physentry != NULL) {
       
   683             if (physentry->entPhysicalContainedIn == xParentIndex) {
       
   684                 /* we want to set entPhysicalContainedIn to the lowest value */
       
   685                 /* or to zero if necessary */
       
   686                 zRunner = gPhyContainsTableHead;
       
   687                 while (zRunner != NULL) {
       
   688                     childIndexes = zRunner->childIndexes;
       
   689                     while (childIndexes != NULL && *childIndexes != 0) {
       
   690                         if (*childIndexes == xChildIndex) {
       
   691                             if (lowest_index == 0)
       
   692                                 lowest_index = zRunner->entPhysicalIndex;
       
   693                             else if (lowest_index > zRunner->entPhysicalIndex)
       
   694                                 lowest_index = zRunner->entPhysicalIndex;
       
   695                             break;
       
   696                         }
       
   697                         childIndexes++;
       
   698                     }
       
   699                     zRunner = zRunner->pNextEntry;
       
   700                 }
       
   701                 physentry->entPhysicalContainedIn = lowest_index;
       
   702             }
       
   703         }
       
   704         /* End of Fix for 4891869 */
       
   705         configChanged();
       
   706         return (0);
       
   707     } else {
       
   708         return (-1);
       
   709     }
       
   710 }
       
   711 /* End of Fix for 4915033 */
       
   712 
       
   713 static int 
       
   714 FreePhyContainsTableEntry(physIndexAndChildIndex_t *xEntry)
       
   715 {
       
   716     if (xEntry == NULL) return (-1);
       
   717     free(xEntry->childIndexes);
       
   718     free(xEntry);
       
   719     xEntry = NULL;
       
   720     return 0;
       
   721 }
       
   722 
       
   723 /* Fix for 4915080 */
       
   724 /* Check to see if childIndex is really related to the parentIndex, in */
       
   725 /* a directed graph way.  Return 1 if it is related, 0 if not. */
       
   726 static int isRecursiveChild(int parentIndex, int childIndex)
       
   727 {
       
   728     int i, ret;
       
   729     int *childlist;
       
   730     int *childlist2;
       
   731 
       
   732     i = 0;
       
   733     ret = 0;
       
   734 
       
   735     if (parentIndex == childIndex)
       
   736         return 1;
       
   737 
       
   738     /* Check for the entPhysicalContainedIn */
       
   739     childlist = getAllChildrenFromPhysicalContainedIn(parentIndex);
       
   740     if (childlist != NULL) {
       
   741         while (childlist[i] != NULL) {
       
   742             ret = isRecursiveChild(childlist[i], childIndex);
       
   743             if (ret == 1) {
       
   744                 free(childlist);
       
   745                 return 1;
       
   746             }
       
   747             i++;
       
   748         }
       
   749         free(childlist);
       
   750     }
       
   751 
       
   752     /* Now we deal with the entPhysicalContainsTable */
       
   753     childlist2 = getPhysicalContainsChildren(parentIndex);
       
   754     i = 0;
       
   755     if (childlist2 != NULL) {
       
   756         while (childlist2[i] != NULL) {
       
   757             ret = isRecursiveChild(childlist2[i], childIndex);
       
   758             if (ret == 1) {
       
   759                 free(childlist2);
       
   760                 return 1;
       
   761             }
       
   762             i++;
       
   763         }
       
   764         free(childlist2);
       
   765     }
       
   766 
       
   767     return 0;
       
   768 }
       
   769 /* End of Fix for 4915080 */