Annotation of embedaddon/nginx/src/core/ngx_radix_tree.c, revision 1.1.1.1
1.1 misho 1:
2: /*
3: * Copyright (C) Igor Sysoev
4: * Copyright (C) Nginx, Inc.
5: */
6:
7:
8: #include <ngx_config.h>
9: #include <ngx_core.h>
10:
11:
12: static ngx_radix_node_t *ngx_radix_alloc(ngx_radix_tree_t *tree);
13:
14:
15: ngx_radix_tree_t *
16: ngx_radix_tree_create(ngx_pool_t *pool, ngx_int_t preallocate)
17: {
18: uint32_t key, mask, inc;
19: ngx_radix_tree_t *tree;
20:
21: tree = ngx_palloc(pool, sizeof(ngx_radix_tree_t));
22: if (tree == NULL) {
23: return NULL;
24: }
25:
26: tree->pool = pool;
27: tree->free = NULL;
28: tree->start = NULL;
29: tree->size = 0;
30:
31: tree->root = ngx_radix_alloc(tree);
32: if (tree->root == NULL) {
33: return NULL;
34: }
35:
36: tree->root->right = NULL;
37: tree->root->left = NULL;
38: tree->root->parent = NULL;
39: tree->root->value = NGX_RADIX_NO_VALUE;
40:
41: if (preallocate == 0) {
42: return tree;
43: }
44:
45: /*
46: * Preallocation of first nodes : 0, 1, 00, 01, 10, 11, 000, 001, etc.
47: * increases TLB hits even if for first lookup iterations.
48: * On 32-bit platforms the 7 preallocated bits takes continuous 4K,
49: * 8 - 8K, 9 - 16K, etc. On 64-bit platforms the 6 preallocated bits
50: * takes continuous 4K, 7 - 8K, 8 - 16K, etc. There is no sense to
51: * to preallocate more than one page, because further preallocation
52: * distributes the only bit per page. Instead, a random insertion
53: * may distribute several bits per page.
54: *
55: * Thus, by default we preallocate maximum
56: * 6 bits on amd64 (64-bit platform and 4K pages)
57: * 7 bits on i386 (32-bit platform and 4K pages)
58: * 7 bits on sparc64 in 64-bit mode (8K pages)
59: * 8 bits on sparc64 in 32-bit mode (8K pages)
60: */
61:
62: if (preallocate == -1) {
63: switch (ngx_pagesize / sizeof(ngx_radix_node_t)) {
64:
65: /* amd64 */
66: case 128:
67: preallocate = 6;
68: break;
69:
70: /* i386, sparc64 */
71: case 256:
72: preallocate = 7;
73: break;
74:
75: /* sparc64 in 32-bit mode */
76: default:
77: preallocate = 8;
78: }
79: }
80:
81: mask = 0;
82: inc = 0x80000000;
83:
84: while (preallocate--) {
85:
86: key = 0;
87: mask >>= 1;
88: mask |= 0x80000000;
89:
90: do {
91: if (ngx_radix32tree_insert(tree, key, mask, NGX_RADIX_NO_VALUE)
92: != NGX_OK)
93: {
94: return NULL;
95: }
96:
97: key += inc;
98:
99: } while (key);
100:
101: inc >>= 1;
102: }
103:
104: return tree;
105: }
106:
107:
108: ngx_int_t
109: ngx_radix32tree_insert(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask,
110: uintptr_t value)
111: {
112: uint32_t bit;
113: ngx_radix_node_t *node, *next;
114:
115: bit = 0x80000000;
116:
117: node = tree->root;
118: next = tree->root;
119:
120: while (bit & mask) {
121: if (key & bit) {
122: next = node->right;
123:
124: } else {
125: next = node->left;
126: }
127:
128: if (next == NULL) {
129: break;
130: }
131:
132: bit >>= 1;
133: node = next;
134: }
135:
136: if (next) {
137: if (node->value != NGX_RADIX_NO_VALUE) {
138: return NGX_BUSY;
139: }
140:
141: node->value = value;
142: return NGX_OK;
143: }
144:
145: while (bit & mask) {
146: next = ngx_radix_alloc(tree);
147: if (next == NULL) {
148: return NGX_ERROR;
149: }
150:
151: next->right = NULL;
152: next->left = NULL;
153: next->parent = node;
154: next->value = NGX_RADIX_NO_VALUE;
155:
156: if (key & bit) {
157: node->right = next;
158:
159: } else {
160: node->left = next;
161: }
162:
163: bit >>= 1;
164: node = next;
165: }
166:
167: node->value = value;
168:
169: return NGX_OK;
170: }
171:
172:
173: ngx_int_t
174: ngx_radix32tree_delete(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask)
175: {
176: uint32_t bit;
177: ngx_radix_node_t *node;
178:
179: bit = 0x80000000;
180: node = tree->root;
181:
182: while (node && (bit & mask)) {
183: if (key & bit) {
184: node = node->right;
185:
186: } else {
187: node = node->left;
188: }
189:
190: bit >>= 1;
191: }
192:
193: if (node == NULL) {
194: return NGX_ERROR;
195: }
196:
197: if (node->right || node->left) {
198: if (node->value != NGX_RADIX_NO_VALUE) {
199: node->value = NGX_RADIX_NO_VALUE;
200: return NGX_OK;
201: }
202:
203: return NGX_ERROR;
204: }
205:
206: for ( ;; ) {
207: if (node->parent->right == node) {
208: node->parent->right = NULL;
209:
210: } else {
211: node->parent->left = NULL;
212: }
213:
214: node->right = tree->free;
215: tree->free = node;
216:
217: node = node->parent;
218:
219: if (node->right || node->left) {
220: break;
221: }
222:
223: if (node->value != NGX_RADIX_NO_VALUE) {
224: break;
225: }
226:
227: if (node->parent == NULL) {
228: break;
229: }
230: }
231:
232: return NGX_OK;
233: }
234:
235:
236: uintptr_t
237: ngx_radix32tree_find(ngx_radix_tree_t *tree, uint32_t key)
238: {
239: uint32_t bit;
240: uintptr_t value;
241: ngx_radix_node_t *node;
242:
243: bit = 0x80000000;
244: value = NGX_RADIX_NO_VALUE;
245: node = tree->root;
246:
247: while (node) {
248: if (node->value != NGX_RADIX_NO_VALUE) {
249: value = node->value;
250: }
251:
252: if (key & bit) {
253: node = node->right;
254:
255: } else {
256: node = node->left;
257: }
258:
259: bit >>= 1;
260: }
261:
262: return value;
263: }
264:
265:
266: #if (NGX_HAVE_INET6)
267:
268: ngx_int_t
269: ngx_radix128tree_insert(ngx_radix_tree_t *tree, u_char *key, u_char *mask,
270: uintptr_t value)
271: {
272: u_char bit;
273: ngx_uint_t i;
274: ngx_radix_node_t *node, *next;
275:
276: i = 0;
277: bit = 0x80;
278:
279: node = tree->root;
280: next = tree->root;
281:
282: while (bit & mask[i]) {
283: if (key[i] & bit) {
284: next = node->right;
285:
286: } else {
287: next = node->left;
288: }
289:
290: if (next == NULL) {
291: break;
292: }
293:
294: bit >>= 1;
295: node = next;
296:
297: if (bit == 0) {
298: if (++i == 16) {
299: break;
300: }
301:
302: bit = 0x80;
303: }
304: }
305:
306: if (next) {
307: if (node->value != NGX_RADIX_NO_VALUE) {
308: return NGX_BUSY;
309: }
310:
311: node->value = value;
312: return NGX_OK;
313: }
314:
315: while (bit & mask[i]) {
316: next = ngx_radix_alloc(tree);
317: if (next == NULL) {
318: return NGX_ERROR;
319: }
320:
321: next->right = NULL;
322: next->left = NULL;
323: next->parent = node;
324: next->value = NGX_RADIX_NO_VALUE;
325:
326: if (key[i] & bit) {
327: node->right = next;
328:
329: } else {
330: node->left = next;
331: }
332:
333: bit >>= 1;
334: node = next;
335:
336: if (bit == 0) {
337: if (++i == 16) {
338: break;
339: }
340:
341: bit = 0x80;
342: }
343: }
344:
345: node->value = value;
346:
347: return NGX_OK;
348: }
349:
350:
351: ngx_int_t
352: ngx_radix128tree_delete(ngx_radix_tree_t *tree, u_char *key, u_char *mask)
353: {
354: u_char bit;
355: ngx_uint_t i;
356: ngx_radix_node_t *node;
357:
358: i = 0;
359: bit = 0x80;
360: node = tree->root;
361:
362: while (node && (bit & mask[i])) {
363: if (key[i] & bit) {
364: node = node->right;
365:
366: } else {
367: node = node->left;
368: }
369:
370: bit >>= 1;
371:
372: if (bit == 0) {
373: if (++i == 16) {
374: break;
375: }
376:
377: bit = 0x80;
378: }
379: }
380:
381: if (node == NULL) {
382: return NGX_ERROR;
383: }
384:
385: if (node->right || node->left) {
386: if (node->value != NGX_RADIX_NO_VALUE) {
387: node->value = NGX_RADIX_NO_VALUE;
388: return NGX_OK;
389: }
390:
391: return NGX_ERROR;
392: }
393:
394: for ( ;; ) {
395: if (node->parent->right == node) {
396: node->parent->right = NULL;
397:
398: } else {
399: node->parent->left = NULL;
400: }
401:
402: node->right = tree->free;
403: tree->free = node;
404:
405: node = node->parent;
406:
407: if (node->right || node->left) {
408: break;
409: }
410:
411: if (node->value != NGX_RADIX_NO_VALUE) {
412: break;
413: }
414:
415: if (node->parent == NULL) {
416: break;
417: }
418: }
419:
420: return NGX_OK;
421: }
422:
423:
424: uintptr_t
425: ngx_radix128tree_find(ngx_radix_tree_t *tree, u_char *key)
426: {
427: u_char bit;
428: uintptr_t value;
429: ngx_uint_t i;
430: ngx_radix_node_t *node;
431:
432: i = 0;
433: bit = 0x80;
434: value = NGX_RADIX_NO_VALUE;
435: node = tree->root;
436:
437: while (node) {
438: if (node->value != NGX_RADIX_NO_VALUE) {
439: value = node->value;
440: }
441:
442: if (key[i] & bit) {
443: node = node->right;
444:
445: } else {
446: node = node->left;
447: }
448:
449: bit >>= 1;
450:
451: if (bit == 0) {
452: i++;
453: bit = 0x80;
454: }
455: }
456:
457: return value;
458: }
459:
460: #endif
461:
462:
463: static ngx_radix_node_t *
464: ngx_radix_alloc(ngx_radix_tree_t *tree)
465: {
466: ngx_radix_node_t *p;
467:
468: if (tree->free) {
469: p = tree->free;
470: tree->free = tree->free->right;
471: return p;
472: }
473:
474: if (tree->size < sizeof(ngx_radix_node_t)) {
475: tree->start = ngx_pmemalign(tree->pool, ngx_pagesize, ngx_pagesize);
476: if (tree->start == NULL) {
477: return NULL;
478: }
479:
480: tree->size = ngx_pagesize;
481: }
482:
483: p = (ngx_radix_node_t *) tree->start;
484: tree->start += sizeof(ngx_radix_node_t);
485: tree->size -= sizeof(ngx_radix_node_t);
486:
487: return p;
488: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>