## 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] */