ngx_int_t
ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
{
    u_char          *elts;
    size_t           len;
    u_short         *test;
    ngx_uint_t       i, n, key, size, start, bucket_size;
    ngx_hash_elt_t  *elt, **buckets;
    for (n = 0; n < nelts; n++) {
        if (names[n].key.len >= 255) {
            ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
                          "the \"%V\" value to hash is to long: %uz bytes, "
                          "the maximum length can be 255 bytes only",
                          &names[n].key, names[n].key.len);
            return NGX_ERROR;
        }
        if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))
        {
            ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
                          "could not build the %s, you should "
                          "increase %s_bucket_size: %i",
                          hinit->name, hinit->name, hinit->bucket_size);
            return NGX_ERROR;
        }
    }
    test = ngx_alloc(hinit->max_size * sizeof(u_short), hinit->pool->log);
    if (test == NULL) {
        return NGX_ERROR;
    }
    bucket_size = hinit->bucket_size - sizeof(void *);
    start = nelts / (bucket_size / (2 * sizeof(void *)));
    start = start ? start : 1;
    if (hinit->max_size > 10000 && hinit->max_size / nelts < 100) {
        start = hinit->max_size - 1000;
    }
    for (size = start; size < hinit->max_size; size++) {
        ngx_memzero(test, size * sizeof(u_short));
        for (n = 0; n < nelts; n++) {
            if (names[n].key.data == NULL) {
                continue;
            }
            key = names[n].key_hash % size;
            test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
#if 0
            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                          "%ui: %ui %ui \"%V\"",
                          size, key, test[key], &names[n].key);
#endif
            if (test[key] > (u_short) bucket_size) {
                goto next;
            }
        }
        goto found;
    next:
        continue;
    }
    ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,
                  "could not build the %s, you should increase "
                  "either %s_max_size: %i or %s_bucket_size: %i",
                  hinit->name, hinit->name, hinit->max_size,
                  hinit->name, hinit->bucket_size);
    ngx_free(test);
    return NGX_ERROR;
found:
    for (i = 0; i < size; i++) {
        test[i] = sizeof(void *);
    }
    for (n = 0; n < nelts; n++) {
        if (names[n].key.data == NULL) {
            continue;
        }
        key = names[n].key_hash % size;
        test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
    }
    len = 0;
    for (i = 0; i < size; i++) {
        if (test[i] == sizeof(void *)) {
            continue;
        }
        test[i] = (u_short) (ngx_align(test[i], ngx_cacheline_size));
        len += test[i];
    }
    if (hinit->hash == NULL) {
        hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t)
                                             + size * sizeof(ngx_hash_elt_t *));
        if (hinit->hash == NULL) {
            ngx_free(test);
            return NGX_ERROR;
        }
        buckets = (ngx_hash_elt_t **)
                      ((u_char *) hinit->hash + sizeof(ngx_hash_wildcard_t));
    } else {
        buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *));
        if (buckets == NULL) {
            ngx_free(test);
            return NGX_ERROR;
        }
    }
    elts = ngx_palloc(hinit->pool, len + ngx_cacheline_size);
    if (elts == NULL) {
        ngx_free(test);
        return NGX_ERROR;
    }
    elts = ngx_align_ptr(elts, ngx_cacheline_size);
    for (i = 0; i < size; i++) {
        if (test[i] == sizeof(void *)) {
            continue;
        }
        buckets[i] = (ngx_hash_elt_t *) elts;
        elts += test[i];
    }
    for (i = 0; i < size; i++) {
        test[i] = 0;
    }
    for (n = 0; n < nelts; n++) {
        if (names[n].key.data == NULL) {
            continue;
        }
        key = names[n].key_hash % size;
        elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]);
        elt->value = names[n].value;
        elt->len = (u_char) names[n].key.len;
        ngx_strlow(elt->name, names[n].key.data, names[n].key.len);
        test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));
    }
    for (i = 0; i < size; i++) {
        if (buckets[i] == NULL) {
            continue;
        }
        elt = (ngx_hash_elt_t *) ((u_char *) buckets[i] + test[i]);
        elt->value = NULL;
    }
    ngx_free(test);
    hinit->hash->buckets = buckets;
    hinit->hash->size = size;
#if 0
    for (i = 0; i < size; i++) {
        ngx_str_t   val;
        ngx_uint_t  key;
        elt = buckets[i];
        if (elt == NULL) {
            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                          "%ui: NULL", i);
            continue;
        }
        while (elt->value) {
            val.len = elt->len;
            val.data = &elt->name[0];
            key = hinit->key(val.data, val.len);
            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,
                          "%ui: %p \"%V\" %ui", i, elt, &val, key);
            elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len,
                                                   sizeof(void *));
        }
    }
#endif
    return NGX_OK;
}
['static char *\nngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf)\n{\n    ngx_http_upstream_main_conf_t  *umcf = conf;\n    ngx_uint_t                      i;\n    ngx_array_t                     headers_in;\n    ngx_hash_key_t                 *hk;\n    ngx_hash_init_t                 hash;\n    ngx_http_upstream_init_pt       init;\n    ngx_http_upstream_header_t     *header;\n    ngx_http_upstream_srv_conf_t  **uscfp;\n    uscfp = umcf->upstreams.elts;\n    for (i = 0; i < umcf->upstreams.nelts; i++) {\n        init = uscfp[i]->peer.init_upstream ? uscfp[i]->peer.init_upstream:\n                                            ngx_http_upstream_init_round_robin;\n        if (init(cf, uscfp[i]) != NGX_OK) {\n            return NGX_CONF_ERROR;\n        }\n    }\n    if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))\n        != NGX_OK)\n    {\n        return NGX_CONF_ERROR;\n    }\n    for (header = ngx_http_upstream_headers_in; header->name.len; header++) {\n        hk = ngx_array_push(&headers_in);\n        if (hk == NULL) {\n            return NGX_CONF_ERROR;\n        }\n        hk->key = header->name;\n        hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);\n        hk->value = header;\n    }\n    hash.hash = &umcf->headers_in_hash;\n    hash.key = ngx_hash_key_lc;\n    hash.max_size = 512;\n    hash.bucket_size = ngx_align(64, ngx_cacheline_size);\n    hash.name = "upstream_headers_in_hash";\n    hash.pool = cf->pool;\n    hash.temp_pool = NULL;\n    if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {\n        return NGX_CONF_ERROR;\n    }\n    return NGX_CONF_OK;\n}', 'ngx_int_t\nngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)\n{\n    u_char          *elts;\n    size_t           len;\n    u_short         *test;\n    ngx_uint_t       i, n, key, size, start, bucket_size;\n    ngx_hash_elt_t  *elt, **buckets;\n    for (n = 0; n < nelts; n++) {\n        if (names[n].key.len >= 255) {\n            ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,\n                          "the \\"%V\\" value to hash is to long: %uz bytes, "\n                          "the maximum length can be 255 bytes only",\n                          &names[n].key, names[n].key.len);\n            return NGX_ERROR;\n        }\n        if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *))\n        {\n            ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,\n                          "could not build the %s, you should "\n                          "increase %s_bucket_size: %i",\n                          hinit->name, hinit->name, hinit->bucket_size);\n            return NGX_ERROR;\n        }\n    }\n    test = ngx_alloc(hinit->max_size * sizeof(u_short), hinit->pool->log);\n    if (test == NULL) {\n        return NGX_ERROR;\n    }\n    bucket_size = hinit->bucket_size - sizeof(void *);\n    start = nelts / (bucket_size / (2 * sizeof(void *)));\n    start = start ? start : 1;\n    if (hinit->max_size > 10000 && hinit->max_size / nelts < 100) {\n        start = hinit->max_size - 1000;\n    }\n    for (size = start; size < hinit->max_size; size++) {\n        ngx_memzero(test, size * sizeof(u_short));\n        for (n = 0; n < nelts; n++) {\n            if (names[n].key.data == NULL) {\n                continue;\n            }\n            key = names[n].key_hash % size;\n            test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));\n#if 0\n            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,\n                          "%ui: %ui %ui \\"%V\\"",\n                          size, key, test[key], &names[n].key);\n#endif\n            if (test[key] > (u_short) bucket_size) {\n                goto next;\n            }\n        }\n        goto found;\n    next:\n        continue;\n    }\n    ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0,\n                  "could not build the %s, you should increase "\n                  "either %s_max_size: %i or %s_bucket_size: %i",\n                  hinit->name, hinit->name, hinit->max_size,\n                  hinit->name, hinit->bucket_size);\n    ngx_free(test);\n    return NGX_ERROR;\nfound:\n    for (i = 0; i < size; i++) {\n        test[i] = sizeof(void *);\n    }\n    for (n = 0; n < nelts; n++) {\n        if (names[n].key.data == NULL) {\n            continue;\n        }\n        key = names[n].key_hash % size;\n        test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));\n    }\n    len = 0;\n    for (i = 0; i < size; i++) {\n        if (test[i] == sizeof(void *)) {\n            continue;\n        }\n        test[i] = (u_short) (ngx_align(test[i], ngx_cacheline_size));\n        len += test[i];\n    }\n    if (hinit->hash == NULL) {\n        hinit->hash = ngx_pcalloc(hinit->pool, sizeof(ngx_hash_wildcard_t)\n                                             + size * sizeof(ngx_hash_elt_t *));\n        if (hinit->hash == NULL) {\n            ngx_free(test);\n            return NGX_ERROR;\n        }\n        buckets = (ngx_hash_elt_t **)\n                      ((u_char *) hinit->hash + sizeof(ngx_hash_wildcard_t));\n    } else {\n        buckets = ngx_pcalloc(hinit->pool, size * sizeof(ngx_hash_elt_t *));\n        if (buckets == NULL) {\n            ngx_free(test);\n            return NGX_ERROR;\n        }\n    }\n    elts = ngx_palloc(hinit->pool, len + ngx_cacheline_size);\n    if (elts == NULL) {\n        ngx_free(test);\n        return NGX_ERROR;\n    }\n    elts = ngx_align_ptr(elts, ngx_cacheline_size);\n    for (i = 0; i < size; i++) {\n        if (test[i] == sizeof(void *)) {\n            continue;\n        }\n        buckets[i] = (ngx_hash_elt_t *) elts;\n        elts += test[i];\n    }\n    for (i = 0; i < size; i++) {\n        test[i] = 0;\n    }\n    for (n = 0; n < nelts; n++) {\n        if (names[n].key.data == NULL) {\n            continue;\n        }\n        key = names[n].key_hash % size;\n        elt = (ngx_hash_elt_t *) ((u_char *) buckets[key] + test[key]);\n        elt->value = names[n].value;\n        elt->len = (u_char) names[n].key.len;\n        ngx_strlow(elt->name, names[n].key.data, names[n].key.len);\n        test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n]));\n    }\n    for (i = 0; i < size; i++) {\n        if (buckets[i] == NULL) {\n            continue;\n        }\n        elt = (ngx_hash_elt_t *) ((u_char *) buckets[i] + test[i]);\n        elt->value = NULL;\n    }\n    ngx_free(test);\n    hinit->hash->buckets = buckets;\n    hinit->hash->size = size;\n#if 0\n    for (i = 0; i < size; i++) {\n        ngx_str_t   val;\n        ngx_uint_t  key;\n        elt = buckets[i];\n        if (elt == NULL) {\n            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,\n                          "%ui: NULL", i);\n            continue;\n        }\n        while (elt->value) {\n            val.len = elt->len;\n            val.data = &elt->name[0];\n            key = hinit->key(val.data, val.len);\n            ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0,\n                          "%ui: %p \\"%V\\" %ui", i, elt, &val, key);\n            elt = (ngx_hash_elt_t *) ngx_align_ptr(&elt->name[0] + elt->len,\n                                                   sizeof(void *));\n        }\n    }\n#endif\n    return NGX_OK;\n}', 'void *\nngx_pcalloc(ngx_pool_t *pool, size_t size)\n{\n    void *p;\n    p = ngx_palloc(pool, size);\n    if (p) {\n        ngx_memzero(p, size);\n    }\n    return p;\n}', 'void *\nngx_palloc(ngx_pool_t *pool, size_t size)\n{\n    u_char      *m;\n    ngx_pool_t  *p;\n    if (size <= pool->max) {\n        p = pool->current;\n        do {\n            m = ngx_align_ptr(p->d.last, NGX_ALIGNMENT);\n            if ((size_t) (p->d.end - m) >= size) {\n                p->d.last = m + size;\n                return m;\n            }\n            p = p->d.next;\n        } while (p);\n        return ngx_palloc_block(pool, size);\n    }\n    return ngx_palloc_large(pool, size);\n}']