## modules/rx/rx_tree.c

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

## FUNCTIONS

This source file includes following functions.

1. rx_walk_tree
2. RX_tree_cre
3. rx_check_walk_tree
4. RX_treecheck

       1 /***************************************
       2   $Revision: 1.17 $
       3
       4   Radix tree (rx).  rx_tree.c - functions to operate on trees
       5   (creation/deletion/finding).
       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 <iproutines.h>
      34 #include <memwrap.h>
      35 #include <stubs.h>
      36
      37 /***************************************************************************/
      38
      39 #define RX_IMPL
      40
      41 #include <rxroutines.h>
      42 /***************************************************************************/
      43
      44
      45 /*+++++++++
      46   go down the tree calling func on every node.
      47   (func takes the node pointer and the current level)
      48
      49   the function is called recursively with level increased
      50   it stops recursing when no child nodes are found or maxlevel is reached.
      51
      52   therefore the initial call must set level to 0.
      53
      54   the nodecounter increments at every node, and is the return value
      55   of the function. So start with 0 to get the number of nodes traversed.
      56
      57   ERROR HANDLING IS DIFFERENT HERE!
      58   Unlike other functions it is not the return value:
      59   The error code from the func function IF DEFINED (== not NULL ) goes
      60   to the variable pointed to by the last parameter.
      61 ++++++++++++*/
      62 int
      63 rx_walk_tree(rx_node_t *node,
         /* [<][>][^][v][top][bottom][index][help] */
      64              er_ret_t (*func)(rx_node_t *node, int level, int nodecounter,
      65                           void *userptr),
      66              rx_walk_mt walk_mode,
      67                              /* controls if glue nodes are counted*/
      68                              /* and if levels or prefix lenghts are checked*/
      69              int maxlevel,
      70              int level,
      71              int nodecounter,
      72              void *userptr,
      73              er_ret_t *err)
      74 {
      75 int i, link, skpglue=0;
      76
      77  if( node == NULL ) die; /* program error. we expect a valid, checked, node.*/
      78
      79  /* count the node appropriately:*/
      80  /* if (not glue) or (it doesn't matter)*/
      81
      82  if( node->glue == 0 || (walk_mode & RX_WALK_SKPGLU) == 0 ) {
      83    level++;
      84  } else { /* nodeglue = 1 && walkmode&skpglue = 1 */
      85    skpglue = 1;
      86  }
      87
      88  /* check the limits and maybe quit here: prefix length for RX_WALK_PRFLEN, */
      89  /* level otherwise */
      90
      91  if(walk_mode & RX_WALK_PRFLEN) {
      92    if(node->prefix.bits > maxlevel) {
      93      return nodecounter;
      94    }
      95  }
      96  else if( level > maxlevel ) {
      97    return nodecounter;
      98  }
      99
     100  /* didn't quit ?? OK, count it too...*/
     101  if( skpglue == 0 ) {
     102    nodecounter++;
     103  }
     104
     105  if( func != NULL && skpglue == 0 ) {
     106    *err = func(node, level, nodecounter, userptr);
     107
     108    /* abort the walk on error*/
     109    if( *err != RX_OK ) {
     110      ER_dbg_va(FAC_RX, ASP_RX_TREE_WALK,
     111                "walk_tree: func returned error %d, aborting", *err);
     112      return nodecounter;
     113    }
     114  }
     115
     116
     117  for(i=0; i<=1; i++) {
     118
     119    /* reverse the sense of the walk*/
     120    link = ( walk_mode & RX_WALK_REVERS ) ? ! i : i;
     121
     122    if( node->child_ptr[link] != NULL ) {
     123      nodecounter += rx_walk_tree(node->child_ptr[link], func, walk_mode,
     124                                  maxlevel, level, 0, userptr, err);
     125      /* abort the walk on error*/
     126      if( func != NULL && *err != RX_OK ) {
     127        break;
     128      }
     129    }
     130  }
     131
     132  return nodecounter;
     133 }
     134
     135
     136
     137 /***************************************************************************/
     138 /*++++++
     139   creates a (top) tree for the space, fills out sql table of trees
     140   generates a tablename for a tree (if NONE)
     141   updates LL of trees
     142
     143   MT-note: locks/unlocks the forest (still to be done)
     144
     145 ++++++++*/
     146 er_ret_t
     147 RX_tree_cre (
         /* [<][>][^][v][top][bottom][index][help] */
     148               char      *prefixstr, /*+ prefix the tree will cover (string) +*/
     149               rx_fam_t   fam_id,
     150               rx_mem_mt   mem_mode, /* memory only, memory+sql, sql only +*/
     151               rx_subtree_mt subtrees,   /*+ one of NONE, AUTO, HAND +*/
     152               rx_tree_t **treestore /* store the tree pointer here */
     153              )
     154
     155 {
     156   er_ret_t     err;
     157   rx_tree_t    *newtree;
     158   ip_prefix_t  newpref;
     159   ip_space_t   spc_id;
     160
     161   if( IP_pref_e2b(&newpref, prefixstr) != IP_OK ) {
     162     die;
     163   }
     164
     165   spc_id = IP_pref_b2_space( &newpref );
     166
     167   if ( (err=wr_malloc( (void **) & newtree, sizeof(rx_tree_t))) != UT_OK ) {
     168     return err;  /* die*/
     169   }
     170
     171   ER_dbg_va(FAC_RX, ASP_RX_TREE_GEN, "creating a tree at %08x", newtree);
     172
     173   /* copy tree settings */
     174   newtree -> space  = spc_id;
     175   newtree -> family = fam_id;
     176
     177   newtree -> subtrees = subtrees;
     178   newtree -> mem_mode = mem_mode;
     179
     180   /* set other tree values */
     181
     182   /* parent set to NULL because it's not a subtree */
     183   newtree -> parent_tree = NULL;
     184   /* PR_zeroprefix(& newtree -> prefix);*/
     185   newtree -> maxbits = IP_sizebits(spc_id);
     186
     187   strcpy(newtree->data_table.val,"");
     188   strcpy(newtree->radix_table.val,"");
     189   strcpy(newtree->leaves_table.val,"");
     190
     191   newtree->num_nodes = 0;
     192
     193   newtree->top_ptr = NULL;
     194   newtree->top_key = SQ_NOKEY;
     195
     196   newtree->prefix = newpref;
     197
     198   TH_init_read_write_lock( &(newtree->rwlock));
     199
     200   *treestore = newtree;
     201
     202   return RX_OK;
     203 }
     204
     205
     206 /* ************************************
     207    special walk function for use in consistency checks - it checks the parent
     208    pointer too.
     209 ************************************/
     210 int rx_check_walk_tree( rx_node_t *node,
         /* [<][>][^][v][top][bottom][index][help] */
     211                         rx_node_t *parent_node,
     212                         int nodecounter,
     213                         rx_treecheck_t *checkstruct )
     214 {
     215 int i;
     216
     217  /* checks*/
     218  if( node == NULL ) {
     219    checkstruct->code |= 1;
     220  }
     221  if( node->parent_ptr != parent_node ) {
     222    checkstruct->code |= 2;
     223  }
     224  if( node->glue && node->leaves_ptr ) {
     225    checkstruct->code |= 4;
     226  }
     227  if( node->glue && (node->child_ptr[0] == NULL || node->child_ptr[1] == NULL ) ) {
     228    checkstruct->code |= 8;
     229  }
     230
     231
     232  if( node->leaves_ptr && checkstruct->datatoo ) {
     233    switch( checkstruct->tree->family ) {
     234    case  RX_FAM_IP:
     235      /* the simplest (?) case: only one leaf attached to any node
     236         (except for glues) */
     237      if( g_list_length(node->leaves_ptr) != 1 ) {
     238        checkstruct->code |= 16;
     239      }
     240      break;
     241    case RX_FAM_RT:
     242      /* many dataleaves attached to nodes. */
     243      break;
     244    case RX_FAM_IN:
     245      /* many dataleaves attached to nodes.
     246         Some leaves pointed to from many nodes => from as many as the number
     247         of composing prefixes
     248      */
     249      break;
     250    default:
     251      /* ignore */
     252      break;
     253    }
     254  }
     255
     256
     257  if( checkstruct->code != 0 ) {
     258    checkstruct->node = node;
     259
     260    return nodecounter;          /* abort the walk on error*/
     261  }
     262
     263
     264   nodecounter++;
     265
     266   for(i=0; i<=1; i++) {
     267     if( node->child_ptr[i] != NULL ) {
     268       nodecounter += rx_check_walk_tree( node->child_ptr[i],
     269                                          node,
     270                                          0, checkstruct );
     271       /* abort the walk on error*/
     272       if ( checkstruct->code != 0 ) {
     273         die; break;
     274       }
     275     }
     276   }
     277   return nodecounter;
     278 }
     279
     280 /* **************************************************************************
     281 tree consistency check.
     282
     283 if datatoo = 0, then only parent/child links are checked.
     284
     285 if datatoo = 1, then a check on the contents of the nodes is done too.
     286
     287 **************************************************************************/
     288
     289 er_ret_t
     290 RX_treecheck( rx_tree_t *tree, int datatoo, rx_treecheck_t *errorfound)
         /* [<][>][^][v][top][bottom][index][help] */
     291 {
     292   er_ret_t err = RX_OK;
     293   int nodnum;
     294
     295   errorfound->tree = tree;
     296   errorfound->datatoo = datatoo;
     297
     298   /* errorfound.node will be set by hook if it finds an error*/
     299   errorfound->code = 0;
     300
     301   nodnum = rx_check_walk_tree( tree->top_ptr,
     302                                NULL,
     303                                0,
     304                                errorfound );
     305
     306   if( nodnum != tree->num_nodes ) {
     307     errorfound->code |= 1024;
     308   }
     309   if( tree->num_nodes == 0 && tree->top_ptr != NULL ) {
     310     errorfound->code |= 2048;
     311   }
     312   if( tree->num_nodes != 0 && tree->top_ptr == NULL ) {
     313     errorfound->code |= 4096;
     314   }
     315
     316   if( errorfound->code != 0) {
     317     err = RX_DATNOF;
     318   }
     319   return err;
     320 }

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