modules/rx/rx_node.c

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. rx_creat_node
  2. rx_delete_node
  3. rx_bin_node
  4. RX_rt_node
  5. RX_in_node

   1 /***************************************
   2   $Revision: 1.27 $
   3 
   4   Radix tree (rx).  rx_node.c - functions to operate on nodes of the tree
   5   (creation/deletion).
   6 
   7   Status: NOT REVUED, TESTED, INCOMPLETE
   8 
   9   Design and implementation by: Marek Bukowy
  10 
  11   ******************/ /******************
  12   Copyright (c) 1999                              RIPE NCC
  13  
  14   All Rights Reserved
  15   
  16   Permission to use, copy, modify, and distribute this software and its
  17   documentation for any purpose and without fee is hereby granted,
  18   provided that the above copyright notice appear in all copies and that
  19   both that copyright notice and this permission notice appear in
  20   supporting documentation, and that the name of the author not be
  21   used in advertising or publicity pertaining to distribution of the
  22   software without specific, written prior permission.
  23   
  24   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  25   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
  26   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
  27   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
  28   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  29   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  30   ***************************************/
  31 
  32 #include <erroutines.h>
  33 #include <rxroutines.h>
  34 #include <memwrap.h>
  35 #include <stubs.h>
  36 #include <glib.h>
  37 
  38 #include <comparisons.h> 
  39 
  40 /***************************************************************************/
  41 /*++++++++++++++++
  42   rx_creat_node = create a new data node 
  43   (empty{glue} nodes get created automatically).
  44 
  45   Takes a pointer to the (already allocated) data leaf to be included 
  46   in the list of data nodes (presumably empty as the node is only now being
  47   created).
  48   
  49   Requires a stack of nodes created in CREAT mode (with glue nodes, 
  50   until deep enough and the last node being non-glue).
  51   
  52   MT notes: requires the tree to be locked.
  53   
  54   Returns: RX_OK or error code.
  55 
  56   +++++++++++++++++*/
  57 static
  58 er_ret_t
  59 rx_creat_node (
     /* [<][>][^][v][top][bottom][index][help] */
  60                ip_prefix_t   *newpref,  /*+ prefix of the node to be added +*/
  61                rx_tree_t     *tree,     /*+ tree the new node goes to +*/
  62                rx_dataleaf_t *dataleaf, /*+ dataleaf to attach at this node+*/
  63                rx_nodcpy_t   stack[],   /*+ stack==array of node_copies +*/
  64                int           stackdepth /*+ length of the stack +*/
  65              )
  66 {
  67   rx_node_t *newnode, *curnode, *memnode, *gluenode;
  68   int chk_bit, dif_bit, link, curpos;
  69   char buf[1024];
  70   er_ret_t err;
  71 
  72   /* assume no such node yet. Will die if there is one.*/
  73    
  74   /* calloc, because parent/child keys and child ptrs are not always set.*/
  75 
  76   if( (err=wr_calloc( (void **) & newnode, 1, sizeof(rx_node_t))) != UT_OK) {
  77     return err; 
  78   }
  79   
  80   /* increment the number of nodes in the tree*/
  81   tree -> num_nodes ++;
  82   
  83   newnode -> prefix = *newpref;
  84   
  85   /* attach the leaf to a (presumably empty?! hence NULL) list...*/
  86   newnode->leaves_ptr = g_list_prepend(NULL, dataleaf);
  87   newnode->glue = 0;
  88   
  89   /* OK, so take a look at the tree*/
  90 
  91   if ( tree -> num_nodes == 1 ) { 
  92     /* The tree was empty. Create a new top node.*/
  93     
  94     tree -> top_ptr = newnode;
  95     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "Created as the top node");
  96     return RX_OK;
  97   }
  98 
  99   /* OK, there is at least one node in the tree. Take a look at the stack.*/
 100 
 101   /*    we've got a real node there (not a glue), but we may be too deep.*/
 102   /*   (it's not a glue, because glues have always two children.*/
 103   /*    we had to go that deep because from a glue alone one doesn't know */
 104   /*    what it glues)*/
 105   /* GO UP.*/
 106   /* take the first differing bit from comparing */
 107   /* the new and the found nodes' prefixes. */
 108   /* (not deeper than the shorter of the two)*/
 109   
 110   curpos =   stackdepth-1;
 111   curnode =  & stack[curpos].cpy;
 112 
 113   chk_bit = smaller(curnode->prefix.bits, newpref->bits );
 114   
 115   for(dif_bit = 0; dif_bit < chk_bit; dif_bit++) {
 116     /* break the loop when the first different bit is found*/
 117 
 118     if( IP_addr_bit_get( & curnode->prefix.ip, dif_bit) 
 119         !=  IP_addr_bit_get( & newpref->ip, dif_bit) ) {
 120       break;
 121     }
 122   }
 123  
 124   ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 
 125             "cur = %d, new = %d, chk_bit = %d, dif_bit = %d", 
 126             curnode->prefix.bits, newpref->bits, chk_bit, dif_bit );
 127   
 128   if(dif_bit == IP_sizebits(newpref->ip.space)) die; /* it mustn't happen!!!*/
 129  
 130   /* go up to that level (watch the head of the tree!)*/
 131   
 132   while( curpos > 0 && stack[curpos-1].cpy.prefix.bits >= dif_bit) {
 133     curpos--;
 134     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 
 135               "up to level %d", curpos );
 136   }
 137   
 138   /*
 139     if the bit lenghts of the node, new prefix and the diffbit are equal
 140     {
 141     YOU'VE GOT THE NODE where the new one will be attached.
 142     Either it has data (and will be moved accordingly), 
 143     or is a glue (and will be turned into a regular node).
 144     }
 145   */
 146   
 147   curnode =  & stack[curpos].cpy;
 148   
 149   /* RAM: set a pointer to the real node in memory*/
 150   memnode = stack[curpos].srcptr;
 151         
 152   if(    dif_bit == newpref->bits 
 153          && dif_bit == curnode->prefix.bits ) {
 154 
 155     /* such node already exists, nothing to change in the tree!!!*/
 156     /* this should be checked before calling this function, so..*/
 157       
 158     die;
 159   }
 160   /*
 161     else  ** the branch ends here; we must create a new node... **
 162     {
 163     OK, how is the new node's prefix length w.r.t the dif_bit ? 
 164     longer  -> make it a child of the node found
 165     shorter -> make it the parent of the node found and take its place
 166     equal   -> make a glue node the parent of both 
 167     }
 168     
 169     WHEN ATTACHING THE NODE, VALUES FROM THE STACK ARE USED,
 170     TO PREVENT EXCESSIVE LOOKUPS AGAIN.
 171     
 172   */
 173   else {
 174     
 175     /* **** attach it.*/
 176     if( ER_is_traced(FAC_RX, ASP_RX_NODCRE_DET) ) {
 177       rx_nod_print(curnode, buf, 1024);
 178       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "Looking at node %s", buf);
 179     }
 180     
 181     if( curnode -> prefix.bits == dif_bit ) {
 182       
 183       /* attach here as a child of the node found      */
 184       link = IP_addr_bit_get( &newpref->ip, dif_bit );
 185       
 186       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "attaching as child %d", link);
 187       
 188       if( memnode -> child_ptr[link] != NULL ) {
 189         die;
 190       }
 191       
 192       memnode -> child_ptr[link] = newnode;
 193       newnode -> parent_ptr = memnode;
 194     }
 195     else if ( newpref->bits == dif_bit ) {
 196       /* make it the parent of the node found and take its place,*/
 197       /* moving it down.*/
 198 
 199       /* set the link from the NEW node to the OLD one (different than before)*/
 200 
 201       link = IP_addr_bit_get( &curnode->prefix.ip, dif_bit );
 202       
 203       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "shifting down as child %d", link);
 204 
 205       /* PARENT<->NEW LINKS*/
 206       /* see if the node was the top_node*/
 207       if (curnode -> parent_ptr == NULL) {
 208         /*  update tree struct */
 209         tree -> top_ptr = newnode;
 210       } else {    
 211         /* no - fix the child link at the parent.*/
 212         /* at the link where it was attached*/
 213         int link = (curnode->parent_ptr->child_ptr[1] == memnode);
 214         memnode -> parent_ptr -> child_ptr[link] = newnode;
 215       }
 216       memnode -> parent_ptr = newnode;
 217 
 218       /* NEW<->CHILD LINKS*/
 219       newnode -> parent_ptr = curnode->parent_ptr;
 220       newnode -> child_ptr[link] = memnode;
 221     }
 222     else {
 223       /* create a glue and shift the curnode below the glue,*/
 224       /* then attach the new node at the glue*/
 225       
 226       /* calloc, because parent/child keys are not set.*/
 227 
 228       if( (err=wr_calloc( (void **)& gluenode, 1, sizeof(rx_node_t))) != UT_OK) {
 229         return err; /* die;*/
 230       }
 231       tree -> num_nodes ++;
 232 
 233       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "created glue node at %p", gluenode);
 234 
 235       gluenode -> prefix.bits = dif_bit;
 236 
 237       /* fill in the address. The glue node should get the prefix*/
 238       /* shorter by one than the shorter of the two prefixes that are glued*/
 239       /* (difbit)*/
 240       /**/
 241       
 242       gluenode -> prefix.ip = newpref->ip;
 243       gluenode -> prefix.bits = dif_bit;
 244       
 245       /* the ip in this prefix is probably incorrect. Fix it.*/
 246       IP_pref_bit_fix(  & gluenode -> prefix );
 247       
 248       gluenode -> leaves_ptr = NULL;
 249       gluenode -> glue = 1;
 250 
 251       /* 1. Fix the link to and from the parent to the gluenode.*/
 252 
 253       gluenode -> parent_ptr = curnode->parent_ptr;
 254       if (gluenode->parent_ptr == NULL) {
 255         tree -> top_ptr = gluenode;
 256       } 
 257       else {
 258         /* fix the child link in the parent. */
 259         /* if it was at 1, then let fix the link 1, 0 otherwise*/
 260         
 261         link = (curnode->parent_ptr->child_ptr[1] == memnode);
 262       
 263         memnode->parent_ptr->child_ptr[link] = gluenode;
 264       }
 265 
 266       /* 2. Fix the links between gluenode and the OLD node*/
 267 
 268       link = IP_addr_bit_get( &newpref->ip, dif_bit );
 269 
 270       gluenode -> child_ptr[ ! link ] = memnode;
 271       memnode->parent_ptr = gluenode;
 272 
 273       /* 3. Fix the links between gluenode and the NEW node*/
 274       
 275       gluenode -> child_ptr[ link ] = newnode;
 276       newnode -> parent_ptr = gluenode;
 277     }
 278     return RX_OK;
 279   }
 280   die;
 281   return -1; /*this is just to calm down the compiler*/
 282 }
 283 
 284 
 285 /******************************************************************
 286  an auxiliary function to delete data from a node 
 287  (and delete the node or turn it into a glue afterwards)
 288 
 289  takes 
 290 
 291  tree              tree
 292  curnode           pointer to the node 
 293  dataleaf          pointer to a dataleaf with ObjectID (dataleaf->data_key) 
 294                    set; which is used to choose the right dataleaf
 295                    when browsing data leaves. It is never assumed to be 
 296                    allocated via malloc, can be a local variable as well.
 297 
 298     If the composed flag of the dataleaf in the tree 
 299     (being the reference count at the same time) 
 300     is non zero, decrements the count.
 301     Deletes the dataleaf when it reaches zero.
 302 
 303  suceeds always or dies when dataleaf with such data cannot be found 
 304  in the node
 305 */
 306 
 307 void
 308 rx_delete_node (rx_tree_t *tree, rx_node_t *curnode, rx_dataleaf_t *dataleaf)
     /* [<][>][^][v][top][bottom][index][help] */
 309 {
 310   rx_dataleaf_t *leaffound = NULL;
 311   GList *qitem;
 312   int leavesum=0;
 313   
 314   /* go through leaves, comparing the objectID (data_key) */
 315   for( qitem = g_list_first(curnode->leaves_ptr);
 316        qitem != NULL;
 317        qitem = g_list_next(qitem)) {
 318     rx_dataleaf_t *leafptr = qitem->data;
 319     
 320     if( leafptr->data_key == dataleaf->data_key ) {
 321       leaffound = leafptr;
 322       /* no break - we're counting leaves..*/
 323     }
 324     leavesum++;
 325   }
 326   
 327   ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "%d dataleaves at the node", leavesum);
 328 
 329   /* return error if none of the dataleaves matched */
 330   if( leaffound == NULL ) die;
 331   
 332   /* NO error? good. Remove the leaf from the list */
 333   curnode->leaves_ptr = g_list_remove ( curnode->leaves_ptr, leaffound );
 334   
 335   /* if not >composed< then delete dataleaf */
 336   if( leaffound->composed == 0 ) {
 337       if( leaffound->data_ptr != NULL        /* allow dataleafs without attached */
 338           && leaffound->data_len > 0 ) {     /* data */
 339           wr_free(leaffound->data_ptr);
 340       }
 341       wr_free(leaffound);
 342 
 343       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "dataleaf refcount = 0, removed");
 344        
 345   }
 346   /* else decrement the reference number ( == number of prefixes 
 347      composing the range minus 1 == the >composed< flag */
 348   else {
 349     leaffound->composed--;
 350     
 351     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "dataleaf refcount -- to %d ",
 352               leaffound->composed );
 353   }  
 354   
 355   /* if that was the last leave at this node, then delete node. */
 356   if( leavesum == 1 ) {
 357     rx_node_t *parent = curnode->parent_ptr;
 358 
 359     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "last dataleaf, removing node");
 360 
 361     assert(curnode->leaves_ptr == NULL);
 362     /* To do this, check the number of children: */
 363     
 364     /*  0 - just delete this node and the link to it */
 365     if( curnode->child_ptr[0] == NULL && curnode->child_ptr[1] == NULL ) {
 366 
 367       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "no children, just removing");
 368 
 369       if( parent != NULL ) { /* watch the head! */
 370         int plink = (parent->child_ptr[1] == curnode);
 371         parent->child_ptr[plink] = NULL;
 372       }
 373       else {
 374         assert(tree->top_ptr == curnode);
 375         tree->top_ptr = NULL;
 376       }
 377       tree->num_nodes--;
 378       wr_free(curnode);
 379 
 380 
 381     /* now, if we deleted curnode, let's see if the parent node is a glue.
 382        If it is, then hook the remaining child up the grandparent,
 383        and delete the parent */
 384       if( parent != NULL && parent->glue ) {
 385         int slink = (parent->child_ptr[1] != NULL );
 386         rx_node_t *schild = parent->child_ptr[slink]; 
 387         rx_node_t *gparent = parent->parent_ptr;
 388         
 389         assert( schild != NULL && parent->child_ptr[ ! slink] == NULL);
 390         
 391         /* upd parent */
 392         if( gparent != NULL ) { /* watch the head! */
 393           int plink = (gparent->child_ptr[1] == parent);
 394           gparent->child_ptr[plink] = parent->child_ptr[slink];
 395         } else {
 396           assert(tree->top_ptr == parent);
 397           tree->top_ptr = parent->child_ptr[slink];
 398         }
 399         
 400         /* update the child's parent link too */
 401         parent->child_ptr[slink]->parent_ptr = gparent;
 402         
 403         /* del */
 404         tree->num_nodes--;
 405         wr_free(parent);
 406         
 407       } /* if parent glue */
 408     }
 409     /*  2 - turn into a glue  */
 410     else if(    curnode->child_ptr[0] != NULL 
 411              && curnode->child_ptr[1] != NULL ) {
 412 
 413       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "two children, turning into a glue");
 414       
 415       curnode->glue = 1;
 416 
 417     } 
 418     /*  1 - copy the child's link to parent. then delete */
 419     else {
 420       int clink = (curnode->child_ptr[1] != NULL );
 421 
 422       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "one child at %d, shifting it up",
 423                 clink);
 424 
 425       /* upd parent */
 426       if( parent != NULL ) { /* watch the head! */
 427         int plink = (parent->child_ptr[1] == curnode);
 428         parent->child_ptr[plink] = curnode->child_ptr[clink];
 429       } else {
 430         /* no parent; the child becomes the top node now */
 431         tree->top_ptr = curnode->child_ptr[clink];
 432       }
 433       
 434       /* update the child's parent link too */
 435       curnode->child_ptr[clink]->parent_ptr = parent;
 436       
 437       /* del */
 438       tree->num_nodes--;
 439       wr_free(curnode);
 440     }
 441     
 442     
 443   } /* leavesum == 1 <=> that was the last data leaf */  
 444 } /* rx_delete_node */
 445 
 446 /*+++++++++++++++++++
 447 
 448   General function to operate on dataleaves attached to a single node
 449   (create / modify / delete).
 450   
 451   searches tree, finds and creates/deletes a node,
 452   copies modified nodes to disk using rx_sql_node_set (not yet implemented).
 453   Updates memory rollback info.
 454   
 455   
 456 
 457   
 458   creation: 
 459     Add a dataleaf at the node defined by prefix. 
 460     Create a new node if it doesn't exist yet.
 461 
 462  
 463   MT notes: requires the tree to be locked.
 464   
 465   Returns: RX_OK or error code.
 466 
 467   Errors from:
 468   rx_bin_search,
 469   memory alloc routines.
 470   
 471   - no such node (if not in create mode)
 472   
 473   - too many nodes found (strange).
 474   
 475   +++++++++++++++++*/
 476 
 477 /*static*/
 478 er_ret_t
 479 rx_bin_node (
     /* [<][>][^][v][top][bottom][index][help] */
 480              rx_oper_mt   mode,       /*+ MODE={cre|mod|del} +*/
 481              ip_prefix_t *newpref,    /*+ prefix of the node +*/
 482              rx_tree_t  *tree,        /*+ pointer to the tree structure +*/
 483              rx_dataleaf_t *dataleaf  /*+ dataleaf to attach at the node +*/
 484              )
 485      
 486 {
 487   GList *nodlist = NULL;
 488   int nodesfound, stackdepth;
 489   int glue;
 490   rx_nodcpy_t *curcpy;
 491   rx_node_t *curnode;
 492   /* rx_nodcpy_t *stack;*/
 493   rx_nodcpy_t stack[128];
 494   er_ret_t err;
 495   char bbf[IP_PREFSTR_MAX];
 496   
 497 
 498   if( ER_is_traced( FAC_RX, ASP_RX_NODCRE_DET)) {
 499     IP_pref_b2a( newpref , bbf, IP_PREFSTR_MAX);
 500     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_GEN,
 501               "rx_bin_node: %s in spc %d /fam %d operation %d", 
 502               bbf, tree->space, tree->family, mode);
 503   }
 504 
 505   /* first check: are we using the correct tree ???*/
 506   if( tree->space != newpref->ip.space ) {
 507     /* trying to insert a prefix of space %d into a tree of space %d\n",
 508            tree->space,
 509            newpref->ip.space);
 510     */
 511     die;
 512   }
 513 
 514   assert( dataleaf );
 515   assert( newpref->bits <= IP_sizebits(tree->space) );
 516 
 517   /* fix the prefix, to make sure all insignificant bits are 0*/
 518   IP_pref_bit_fix( newpref );
 519 
 520   if( (err=rx_build_stack(stack, &stackdepth, tree, newpref, RX_STK_CREAT))
 521        != RX_OK ) {
 522     return err; /*die*/
 523   }
 524   
 525   /*   rx_stk_print(stack, stackdepth);*/
 526   
 527   /* perform a search on the stack. The result is a list, and it must*/
 528   /* be properly deleted after use!!*/
 529 
 530   if( rx_nod_search(RX_SRCH_CREAT, 0, 0, 
 531                     tree, newpref, stack, stackdepth, 
 532                     &nodlist, RX_ANS_ALL) != RX_OK ) {
 533     return err; /* die;*/
 534   }
 535 
 536   
 537   /* count number of nodes in the answer */
 538   nodesfound = g_list_length (nodlist);
 539   
 540   switch( nodesfound ) {
 541   case 0:
 542     /* no such node (yet). See what we're up to.
 543        if( mode==cre )  create, else - program error, die */
 544  
 545     /*  C R E A T I O N */
 546     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 
 547               "rx_bin_node: Creating a new node %s in spc %d /fam %d ", 
 548               bbf, tree->space, tree->family);
 549     if( mode != RX_OPER_CRE) {
 550       die;
 551     }
 552    
 553     rx_creat_node(  newpref, tree, dataleaf, stack, stackdepth );
 554     break;
 555   case 1: /* found */
 556     /* set the curnode pointer   */
 557     curcpy = g_list_nth_data(nodlist, 0);
 558     curnode = curcpy->srcptr;
 559 
 560     switch( mode ) {
 561     case RX_OPER_CRE:
 562       /*  attach the data at the node that was found;*/
 563       
 564       /* was it glue ?*/
 565       glue = curnode->glue;
 566             
 567       curnode->leaves_ptr = g_list_prepend(curnode->leaves_ptr, dataleaf);
 568       /* now it's not a glue anymore */
 569       curnode->glue = 0;
 570 
 571       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "Appended data to a %s node",
 572                 glue ? "glue" : "data");
 573       
 574       break;
 575     case RX_OPER_DEL: 
 576 
 577       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 
 578                 "rx_bin_node: Deleting node %s in spc %d /fam %d ", 
 579                 bbf, tree->space, tree->family);
 580       rx_delete_node( tree, curnode, dataleaf);
 581       break;
 582     }
 583     break;
 584   default:
 585     /* too many nodes found! from an exact/exact-less-1 search.
 586        this cannot happen. Call Ghostbusters now.
 587      */
 588     die;
 589   }
 590 
 591   wr_clear_list( &nodlist );
 592   
 593   return RX_OK;
 594 }
 595 
 596 
 597 
 598 /***************************************************************************/
 599 /* ++++++++++++++++
 600    A wrapper around RX_bin_node.
 601 
 602    It's there only to control the freeing of dataleaf copies passed 
 603    for comparison during deletion.
 604 
 605    +++++++++++++++++*/
 606 er_ret_t
 607 RX_rt_node (
     /* [<][>][^][v][top][bottom][index][help] */
 608              rx_oper_mt   mode,       /*+ MODE={cre|mod|del} +*/
 609              ip_prefix_t *newpref,    /*+ prefix of the node +*/
 610              rx_tree_t  *tree,        /*+ pointer to the tree structure +*/
 611              rx_dataleaf_t *leafptr  /*+ dataleaf to attach at the node +*/
 612              )
 613 {
 614   er_ret_t reterr;
 615 
 616   IP_pref_2_rang( & leafptr->iprange, newpref);
 617   leafptr->preflen = IP_pref_b2_len(newpref);
 618 
 619   /* store the object's range, used in rp.search */
 620   
 621   reterr = rx_bin_node(mode, newpref, tree, leafptr);
 622   
 623   return reterr;
 624 }
 625      
 626 /***************************************************************************/
 627 /*+++++++++++++++
 628   performs the actual update for inetnums (possibly composed of many prefixes).
 629   Decomposes the ranges into prefixes and then falls back to rx_bin_node
 630   to perform changes at the nodes.
 631   
 632   Requires/returns - practically the same as rx_bin_node.
 633 ++++++++++++++++*/
 634 
 635 er_ret_t
 636 RX_in_node(   rx_oper_mt mode,       /*+ MODE={cre|mod|del} +*/
     /* [<][>][^][v][top][bottom][index][help] */
 637               ip_range_t *rang,      /*+ range of IP addresses +*/
 638               rx_tree_t *tree,       /*+ pointer to the tree structure +*/
 639               rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/
 640               )     
 641 {
 642   int i, prefcount;
 643   GList *preflist = NULL;
 644   char buf[IP_RANGSTR_MAX];
 645 
 646   if( ER_is_traced( FAC_RX, ASP_RX_NODCRE_GEN)) {
 647     IP_rang_b2a(rang, buf, IP_RANGSTR_MAX );
 648     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_GEN, 
 649               "rx_inum_node: adding %s", buf);
 650   }
 651 
 652   /* decompose, put links to the data leaf into every prefix*/
 653   /* that makes up this range.*/
 654   IP_rang_decomp(rang, &preflist);
 655   
 656   /* see if there is more than 1 prefix, set the composed flag*/
 657   prefcount = g_list_length(preflist);
 658   leafptr->composed = (prefcount - 1) ;
 659   
 660   leafptr->iprange = *rang;
 661   
 662   for(i=0; i < prefcount; i++) {
 663     ip_prefix_t *mypref = g_list_nth_data(preflist, i);
 664     
 665     rx_bin_node(mode, mypref, tree, leafptr);
 666   }
 667     
 668   /* free the storage from decomposition*/
 669   wr_clear_list( &preflist );
 670 
 671   return RX_OK;
 672 }

/* [<][>][^][v][top][bottom][index][help] */