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>