Source File modules/rp/rp_tree.c

    1    | /***************************************
    2    |   $Revision: 1.7 $
    3    |
    4    |   Radix payload (rp) - user level functions for storing data in radix trees
    5    |
    6    |   rp_load = user level tree maintenance (knows about registries and attributes)
    7    |
    8    |   Status: NOT REVIEWED, TESTED
    9    |
    10   |   Design and implementation by: Marek Bukowy
    11   |
    12   |   ******************/ /******************
    13   |   Copyright (c) 1999                              RIPE NCC
    14   |
    15   |   All Rights Reserved
    16   |
    17   |   Permission to use, copy, modify, and distribute this software and its
    18   |   documentation for any purpose and without fee is hereby granted,
    19   |   provided that the above copyright notice appear in all copies and that
    20   |   both that copyright notice and this permission notice appear in
    21   |   supporting documentation, and that the name of the author not be
    22   |   used in advertising or publicity pertaining to distribution of the
    23   |   software without specific, written prior permission.
    24   |
    25   |   THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
    26   |   ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS; IN NO EVENT SHALL
    27   |   AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
    28   |   DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    29   |   AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
    30   |   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    31   |   ***************************************/
    32   |
    33   | #define RP_IMPL
    34   | #include <rp.h>
    35   | #include <rxroutines.h>
    36   | /***************************************************************************/
    37   | /*++++++++++++++
    38   |   finds a tree matching the specified criteria(registry+space+family+tid).
    39   |
    40   |   MT-note: locks/unlocks forest (still to be done)
    41   |
    42   |   Returns: RX_OK or RX_NOTREE if no such tree can be found.
    43   | +++++++++++*/
    44   |
    45   | er_ret_t
    46   | RP_tree_get ( rx_tree_t **treeptr, /*+ answer goes here, please +*/
    47   | 	      rp_regid_t reg_id,   /*+ id of the registry +*/
    48   | 	      ip_space_t spc_id,   /*+ type of space (ipv4/ipv6) +*/
    49   | 	      rp_attr_t  attr    /*+ extra tree id (within the same reg/spc/fam +*/
    50   | 	      )
    51   |
    52   | {
    53   |   GList *elem;
    54   |   rp_tentry_t  *trdef;
    55   |   /* lock the forest */
    56   |   TH_acquire_read_lockw(&rx_forest_rwlock);
    57   |   elem = g_list_first(rx_forest);
    58   |
    59   |   while( elem != NULL ) {
    60   |     trdef = elem->data;
    61   |
    62   |
    63   |     if(    trdef->reg_id == reg_id
    64   | 	&& trdef->attr == attr
    65   | 	&& trdef->tree->space == spc_id ) {
    66   |       /* copy the value to user's data */
    67   |       *treeptr = trdef->tree;
    68   |       ER_dbg_va(FAC_RP, ASP_RP_TREE_DET,
    69   | 		"tree found at %08x -> %08x",trdef, trdef->tree);
    70   |       return RP_OK;
    71   |     }
    72   |     elem = g_list_next(elem);
    73   |   }
    74   |
    75   |   *treeptr = NULL; /* set when NOT FOUND*/
    76   |   TH_release_read_lockw(&rx_forest_rwlock);
    77   | /*  pthread_mutex_unlock(&rx_forest_mx);*/
    78   |   return RP_NOTREE;
    79   | }
    80   |
    81   |
    82   |
    83   | /*++++++++++++++++++++++++++++++++
    84   |        put into LL of trees; handle alloc err ???
    85   |
    86   |        since other threads are supposed to be reading already,
    87   |        must create the tree locked and observe the forest mutex.
    88   |        ++++++++++++++++++++*/
    89   | er_ret_t
    90   | RP_tree_add (
    91   | 	     rp_regid_t reg_id,    /*+ id of the registry +*/
    92   | 	     rp_attr_t  attr,      /*+ extra tree id (within the same registry/space/family +*/
    93   | 	     char      *prefixstr, /*+ prefix the tree will cover (string) +*/
    94   | 	     rx_mem_mt   mem_mode, /* memory only, memory+sql, sql only +*/
    95   | 	     rx_subtree_mt subtrees	/*+ one of NONE, AUTO, HAND +*/
    96   | 	     )
    97   | {
    98   |   er_ret_t     err;
    99   |   rp_tentry_t *treedef;
    100  |   rx_tree_t   *mytree;
    101  |   rx_tree_t   *existree;
    102  |   rx_fam_t   fam_id = RP_attr2fam( attr );
    103  |
    104  |   if( (err = RX_tree_cre(prefixstr, fam_id, mem_mode, subtrees, &mytree)) == RX_OK) {
    105  |
    106  |     /* OK, see if there is a tree for this space already */
    107  |     if( RP_tree_get(&existree, reg_id, mytree->space, attr) == RP_OK ) {
    108  |       /* In this case we need to delete and re-initialize it  */
    109  |       /* lock the tree for writing and leave it in the locked state for loading */
    110  |       TH_acquire_write_lockw(&existree->rwlock);
    111  |
    112  |       if( (err = RP_tree_del(existree)) == RP_OK){
    113  | 	      /* Initialize the tree */
    114  | 	      existree->num_nodes=0;
    115  |       }
    116  |       /* free the newly created tree */
    117  |       UT_free(mytree);
    118  |       return err;
    119  |     }
    120  |
    121  |     dieif(wr_malloc((void **) &treedef, sizeof(rp_tentry_t)) != UT_OK);
    122  |
    123  |     treedef -> reg_id = reg_id;
    124  |     treedef -> attr   = attr;
    125  |     treedef -> tree   = mytree;
    126  |
    127  |     /* add the tree to the forest in locked state */
    128  |     TH_acquire_write_lockw( &(mytree->rwlock) );
    129  |
    130  |     /* Lock the forest */
    131  |     TH_acquire_write_lockw(&rx_forest_rwlock);
    132  |     rx_forest = g_list_append (rx_forest, treedef);
    133  |     TH_release_write_lockw(&rx_forest_rwlock);
    134  |   }
    135  |
    136  |   return err;
    137  | }
    138  |
    139  | /*++++++++++++++
    140  |   finds a tree and deletes its contents
    141  |   the tree itself is not deleted !
    142  |
    143  |   Returns: RX_OK or RX_NOTREE if no such tree can be found.
    144  | +++++++++++*/
    145  |
    146  | er_ret_t
    147  | RP_tree_del ( rx_tree_t *tree )
    148  | {
    149  | int cnt;
    150  |
    151  |   if( tree->top_ptr != NULL ) {
    152  |     cnt = rx_delete_tree(tree, tree->top_ptr, 255, 0, 0, NULL);
    153  |     ER_inf_va(FAC_RP, ASP_RP_LOAD_GEN,
    154  |                "tree at %08x: %d nodes deleted", tree, cnt);
    155  | 	 if (cnt != tree->num_nodes){
    156  | 		 ER_perror(FAC_RP, RP_NOYETI,
    157  | 		"tree at %08x: %d nodes deleted, should be %d", tree, cnt, tree->num_nodes);
    158  | 		 return  RP_NOYETI;
    159  |          }
    160  |   }
    161  |   return RP_OK;
    162  | }
    163  |
    164  |
    165  | er_ret_t
    166  | rp_init_attr_tree( rp_regid_t reg_id, rp_attr_t attr)
    167  | {
    168  |   er_ret_t err;
    169  |
    170  |   /* Some (DN) attributes are related to two trees */
    171  |   if( RP_attr2spc(attr, IP_V4) ) {
    172  |     err=RP_tree_add(reg_id, attr, "0.0.0.0/0",
    173  | 		    RX_MEM_RAMONLY, RX_SUB_NONE);
    174  |   }
    175  |
    176  |   if( RP_attr2spc(attr, IP_V6) ) {
    177  |    err=RP_tree_add(reg_id, attr, "0::/0",
    178  | 		   RX_MEM_RAMONLY, RX_SUB_NONE);
    179  |   }
    180  |
    181  |   return err;
    182  | }
    183  | /***************************************************************************/
    184  |
    185  | er_ret_t
    186  | RP_init_trees( rp_regid_t reg_id )
    187  | {
    188  |   er_ret_t err;
    189  |
    190  |   if(    NOERR(err=rp_init_attr_tree(reg_id, A_IN))
    191  |       && NOERR(err=rp_init_attr_tree(reg_id, A_RT))
    192  |       && NOERR(err=rp_init_attr_tree(reg_id, A_I6))
    193  |       && NOERR(err=rp_init_attr_tree(reg_id, A_DN)) ) {
    194  |     return RP_OK;
    195  |   }
    196  |
    197  |   return err;
    198  | }
    199  |
    200  |
    201  |
    202  |