Annotation of embedaddon/nginx/src/core/ngx_radix_tree.c, revision 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>