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.32 $
   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   unsigned 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   /*+ RX_FAM_IP implies there's no dataleaf!!!
 315     The structure in place of a dataleaf is payload
 316     +*/
 317   
 318   /* go through leaves, comparing the objectID (data_key) */
 319   for( qitem = g_list_first(curnode->leaves_ptr);
 320        qitem != NULL;
 321        qitem = g_list_next(qitem)) {
 322     rx_dataleaf_t *leafptr = qitem->data;
 323     
 324     if( tree->family == RX_FAM_IP    /* do not look at the pointers */
 325         || leafptr->data_key == dataleaf->data_key ) { /* if RX_FAM_IP */
 326       leaffound = leafptr;
 327       /* no break - we're counting leaves..*/
 328     }
 329     leavesum++;
 330   }
 331   
 332 
 333   ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "%d dataleaves at the node", leavesum);
 334   
 335   /* return error if none of the dataleaves matched */
 336   if( leaffound == NULL ) die;
 337   
 338   /* NO error? good. Remove the leaf from the list */
 339   curnode->leaves_ptr = g_list_remove ( curnode->leaves_ptr, leaffound );
 340   
 341   
 342   if(tree->family == RX_FAM_IP ) {
 343     /* again: do not look at the leaf if  RX_FAM_IP */
 344     /* Just free the payload, there must be one and just one. */
 345     wr_free(leaffound);
 346   }  
 347   else { /* other families */
 348     /* if not >composed< then delete dataleaf */
 349     if( leaffound->composed == 0 ) {
 350       if( leaffound->data_ptr != NULL        /* allow dataleafs without attached */
 351           && leaffound->data_len > 0 ) {     /* data */
 352         wr_free(leaffound->data_ptr);
 353       }
 354       wr_free(leaffound);
 355       
 356       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "dataleaf refcount = 0, removed");
 357       
 358     }
 359   /* else decrement the reference number ( == number of prefixes 
 360      composing the range minus 1 == the >composed< flag */
 361     else {
 362       leaffound->composed--;
 363       
 364       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "dataleaf refcount -- to %d ",
 365                 leaffound->composed );
 366     }  
 367   } /* if family != RX_FAM_IP */
 368   
 369   /* if that was the last leave at this node, then delete node. */
 370   if( leavesum == 1 ) {
 371     rx_node_t *parent = curnode->parent_ptr;
 372     
 373     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "last dataleaf, removing node");
 374     
 375     assert(curnode->leaves_ptr == NULL);
 376     /* To do this, check the number of children: */
 377     
 378     /*  0 - just delete this node and the link to it */
 379     if( curnode->child_ptr[0] == NULL && curnode->child_ptr[1] == NULL ) {
 380       
 381       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "no children, just removing");
 382       
 383       if( parent != NULL ) { /* watch the head! */
 384         int plink = (parent->child_ptr[1] == curnode);
 385         parent->child_ptr[plink] = NULL;
 386       }
 387       else {
 388         assert(tree->top_ptr == curnode);
 389         tree->top_ptr = NULL;
 390       }
 391       tree->num_nodes--;
 392       wr_free(curnode);
 393 
 394 
 395     /* now, if we deleted curnode, let's see if the parent node is a glue.
 396        If it is, then hook the remaining child up the grandparent,
 397        and delete the parent */
 398       if( parent != NULL && parent->glue ) {
 399         int slink = (parent->child_ptr[1] != NULL );
 400         rx_node_t *schild = parent->child_ptr[slink]; 
 401         rx_node_t *gparent = parent->parent_ptr;
 402         
 403         assert( schild != NULL && parent->child_ptr[ ! slink] == NULL);
 404         
 405         /* upd parent */
 406         if( gparent != NULL ) { /* watch the head! */
 407           int plink = (gparent->child_ptr[1] == parent);
 408           gparent->child_ptr[plink] = parent->child_ptr[slink];
 409         } else {
 410           assert(tree->top_ptr == parent);
 411           tree->top_ptr = parent->child_ptr[slink];
 412         }
 413         
 414         /* update the child's parent link too */
 415         parent->child_ptr[slink]->parent_ptr = gparent;
 416         
 417         /* del */
 418         tree->num_nodes--;
 419         wr_free(parent);
 420         
 421       } /* if parent glue */
 422     }
 423     /*  2 - turn into a glue  */
 424     else if(    curnode->child_ptr[0] != NULL 
 425              && curnode->child_ptr[1] != NULL ) {
 426 
 427       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "two children, turning into a glue");
 428       
 429       curnode->glue = 1;
 430 
 431     } 
 432     /*  1 - copy the child's link to parent. then delete */
 433     else {
 434       int clink = (curnode->child_ptr[1] != NULL );
 435 
 436       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "one child at %d, shifting it up",
 437                 clink);
 438 
 439       /* upd parent */
 440       if( parent != NULL ) { /* watch the head! */
 441         int plink = (parent->child_ptr[1] == curnode);
 442         parent->child_ptr[plink] = curnode->child_ptr[clink];
 443       } else {
 444         /* no parent; the child becomes the top node now */
 445         tree->top_ptr = curnode->child_ptr[clink];
 446       }
 447       
 448       /* update the child's parent link too */
 449       curnode->child_ptr[clink]->parent_ptr = parent;
 450       
 451       /* del */
 452       tree->num_nodes--;
 453       wr_free(curnode);
 454     }
 455     
 456     
 457   } /* leavesum == 1 <=> that was the last data leaf */  
 458 } /* rx_delete_node */
 459 
 460 /*+++++++++++++++++++
 461 
 462   General function to operate on dataleaves attached to a single node
 463   (create / modify / delete).
 464   
 465   searches tree, finds and creates/deletes a node,
 466   copies modified nodes to disk using rx_sql_node_set (not yet implemented).
 467   Updates memory rollback info.
 468   
 469   
 470 
 471   
 472   creation: 
 473     Add a dataleaf at the node defined by prefix. 
 474     Create a new node if it doesn't exist yet.
 475 
 476  
 477   MT notes: requires the tree to be locked.
 478   
 479   Returns: RX_OK or error code.
 480 
 481   Errors from:
 482   rx_bin_search,
 483   memory alloc routines.
 484   
 485   - no such node (if not in create mode)
 486   
 487   - too many nodes found (strange).
 488   
 489   +++++++++++++++++*/
 490 
 491 /*static*/
 492 er_ret_t
 493 rx_bin_node (
     /* [<][>][^][v][top][bottom][index][help] */
 494              rx_oper_mt   mode,       /*+ MODE={cre|mod|del} +*/
 495              ip_prefix_t *newpref,    /*+ prefix of the node +*/
 496              rx_tree_t  *tree,        /*+ pointer to the tree structure +*/
 497              rx_dataleaf_t *dataleaf  /*+ dataleaf to attach at the node +*/
 498              )
 499      
 500 {
 501   GList *nodlist = NULL;
 502   int nodesfound, stackdepth;
 503   int glue;
 504   rx_nodcpy_t *curcpy;
 505   rx_node_t *curnode;
 506   /* rx_nodcpy_t *stack;*/
 507   rx_nodcpy_t stack[128];
 508   er_ret_t err;
 509   char bbf[IP_PREFSTR_MAX];
 510   
 511 
 512   if( ER_is_traced( FAC_RX, ASP_RX_NODCRE_DET)) {
 513     IP_pref_b2a( newpref , bbf, IP_PREFSTR_MAX);
 514     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_GEN,
 515               "rx_bin_node: %s in spc %d /fam %d operation %d", 
 516               bbf, tree->space, tree->family, mode);
 517   }
 518 
 519   /* first check: are we using the correct tree ???*/
 520   if( tree->space != newpref->ip.space ) {
 521     /* trying to insert a prefix of space %d into a tree of space %d\n",
 522            tree->space,
 523            newpref->ip.space);
 524     */
 525     die;
 526   }
 527 
 528   assert( dataleaf );
 529   assert( newpref->bits <= IP_sizebits(tree->space) );
 530 
 531   /* fix the prefix, to make sure all insignificant bits are 0*/
 532   IP_pref_bit_fix( newpref );
 533 
 534   if( (err=rx_build_stack(stack, &stackdepth, tree, newpref, RX_STK_CREAT))
 535        != RX_OK ) {
 536     return err; /*die*/
 537   }
 538   
 539   /*   rx_stk_print(stack, stackdepth);*/
 540   
 541   /* perform a search on the stack. The result is a list, and it must*/
 542   /* be properly deleted after use!!*/
 543 
 544   if( (err=rx_nod_search(RX_SRCH_CREAT, 0, 0, 
 545                          tree, newpref, stack, stackdepth, 
 546                          &nodlist, RX_ANS_ALL)) != RX_OK ) {
 547     return err; /* die;*/
 548   }
 549 
 550   
 551   /* count number of nodes in the answer */
 552   nodesfound = g_list_length (nodlist);
 553   
 554   switch( nodesfound ) {
 555   case 0:
 556     /* no such node (yet). See what we're up to.
 557        if( mode==cre )  create, else - program error, die */
 558  
 559     /*  C R E A T I O N */
 560     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 
 561               "rx_bin_node: Creating a new node %s in spc %d /fam %d ", 
 562               bbf, tree->space, tree->family);
 563     if( mode != RX_OPER_CRE) {
 564       die;
 565     }
 566    
 567     rx_creat_node(  newpref, tree, dataleaf, stack, stackdepth );
 568     break;
 569   case 1: /* found */
 570     /* set the curnode pointer   */
 571     curcpy = g_list_nth_data(nodlist, 0);
 572     curnode = curcpy->srcptr;
 573 
 574     switch( mode ) {
 575     case RX_OPER_CRE:
 576       /*  attach the data at the node that was found;*/
 577       
 578       /* was it glue ?*/
 579       glue = curnode->glue;
 580             
 581       curnode->leaves_ptr = g_list_prepend(curnode->leaves_ptr, dataleaf);
 582       /* now it's not a glue anymore */
 583       curnode->glue = 0;
 584 
 585       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, "Appended data to a %s node",
 586                 glue ? "glue" : "data");
 587       
 588       break;
 589     case RX_OPER_DEL: 
 590 
 591       ER_dbg_va(FAC_RX, ASP_RX_NODCRE_DET, 
 592                 "rx_bin_node: Deleting node %s in spc %d /fam %d ", 
 593                 bbf, tree->space, tree->family);
 594       rx_delete_node( tree, curnode, dataleaf);
 595       break;
 596     }
 597     break;
 598   default:
 599     /* too many nodes found! from an exact/exact-less-1 search.
 600        this cannot happen. Call Ghostbusters now.
 601      */
 602     die;
 603   }
 604 
 605   wr_clear_list( &nodlist );
 606   
 607   return RX_OK;
 608 }
 609 
 610 
 611 
 612 /***************************************************************************/
 613 /* ++++++++++++++++
 614    A wrapper around RX_bin_node.
 615 
 616    It's there only to control the freeing of dataleaf copies passed 
 617    for comparison during deletion.
 618 
 619    +++++++++++++++++*/
 620 er_ret_t
 621 RX_rt_node (
     /* [<][>][^][v][top][bottom][index][help] */
 622              rx_oper_mt   mode,       /*+ MODE={cre|mod|del} +*/
 623              ip_prefix_t *newpref,    /*+ prefix of the node +*/
 624              rx_tree_t  *tree,        /*+ pointer to the tree structure +*/
 625              rx_dataleaf_t *leafptr  /*+ dataleaf to attach at the node +*/
 626              )
 627 {
 628   er_ret_t reterr;
 629 
 630   IP_pref_2_rang( & leafptr->iprange, newpref);
 631   leafptr->preflen = IP_pref_b2_len(newpref);
 632 
 633   /* store the object's range, used in rp.search */
 634   
 635   reterr = rx_bin_node(mode, newpref, tree, leafptr);
 636   
 637   return reterr;
 638 }
 639      
 640 /***************************************************************************/
 641 /*+++++++++++++++
 642   performs the actual update for inetnums (possibly composed of many prefixes).
 643   Decomposes the ranges into prefixes and then falls back to rx_bin_node
 644   to perform changes at the nodes.
 645   
 646   Requires/returns - practically the same as rx_bin_node.
 647 ++++++++++++++++*/
 648 
 649 er_ret_t
 650 RX_in_node(   rx_oper_mt mode,       /*+ MODE={cre|mod|del} +*/
     /* [<][>][^][v][top][bottom][index][help] */
 651               ip_range_t *rang,      /*+ range of IP addresses +*/
 652               rx_tree_t *tree,       /*+ pointer to the tree structure +*/
 653               rx_dataleaf_t *leafptr /*+ dataleaf to attach at the node +*/
 654               )     
 655 {
 656   unsigned i, prefcount;
 657   GList *preflist = NULL;
 658   char buf[IP_RANGSTR_MAX];
 659 
 660   if( ER_is_traced( FAC_RX, ASP_RX_NODCRE_GEN)) {
 661     IP_rang_b2a(rang, buf, IP_RANGSTR_MAX );
 662     ER_dbg_va(FAC_RX, ASP_RX_NODCRE_GEN, 
 663               "rx_inum_node: adding %s", buf);
 664   }
 665 
 666   /* decompose, put links to the data leaf into every prefix*/
 667   /* that makes up this range.*/
 668   IP_rang_decomp(rang, &preflist);
 669   
 670   /* see if there is more than 1 prefix, set the composed flag*/
 671   prefcount = g_list_length(preflist);
 672   leafptr->composed = (prefcount - 1) ;
 673   
 674   leafptr->iprange = *rang;
 675   
 676 /* XXX */  
 677 if(prefcount==0) {
 678         fprintf(stderr, "**** prefcount=0 range: [%s][%u-%u]\n", buf, (rang->begin).words[0], (rang->end).words[0]);
 679 }
 680   
 681   for(i=0; i < prefcount; i++) {
 682     ip_prefix_t *mypref = g_list_nth_data(preflist, i);
 683     
 684     rx_bin_node(mode, mypref, tree, leafptr);
 685   }
 686     
 687   /* free the storage from decomposition*/
 688   wr_clear_list( &preflist );
 689 
 690   return RX_OK;
 691 }

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