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 |