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

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