Пример #1
0
//shared memory
shmem_t *shm_create(ngx_str_t *name, ngx_conf_t *cf, size_t shm_size, ngx_int_t (*init)(ngx_shm_zone_t *, void *), void *privdata) {

  ngx_shm_zone_t    *zone;
  shmem_t           *shm;

  shm_size = ngx_align(shm_size, ngx_pagesize);
  if (shm_size < 8 * ngx_pagesize) {
    ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The push_max_reserved_memory value must be at least %udKiB", (8 * ngx_pagesize) >> 10);
    shm_size = 8 * ngx_pagesize;
  }
static ngx_int_t
ngx_http_vod_init_hash(
	ngx_conf_t *cf, 
	ngx_http_vod_uri_param_def_t* elements,
	ngx_http_vod_loc_conf_t* conf, 
	char* hash_name, 
	ngx_hash_t* output)
{
	ngx_http_vod_uri_param_def_t *element;
	ngx_array_t elements_arr;
	ngx_hash_key_t *hash_key;
	ngx_hash_init_t hash;
	ngx_str_t* cur_key;

	if (ngx_array_init(&elements_arr, cf->temp_pool, 32, sizeof(ngx_hash_key_t)) != NGX_OK)
	{
		return NGX_ERROR;
	}

	for (element = elements; element->name_conf_offset >= 0; element++)
	{
		cur_key = (ngx_str_t*)((u_char*)conf + element->name_conf_offset);
		if (cur_key->len == 0)
		{
			break;
		}

		hash_key = ngx_array_push(&elements_arr);
		if (hash_key == NULL)
		{
			return NGX_ERROR;
		}

		hash_key->key = *cur_key;
		hash_key->key_hash = ngx_hash_key_lc(cur_key->data, cur_key->len);
		hash_key->value = element;
	}

	hash.hash = output;
	hash.key = ngx_hash_key_lc;
	hash.max_size = 512;
	hash.bucket_size = ngx_align(64, ngx_cacheline_size);
	hash.name = hash_name;
	hash.pool = cf->pool;
	hash.temp_pool = NULL;

	if (ngx_hash_init(&hash, elements_arr.elts, elements_arr.nelts) != NGX_OK)
	{
		return NGX_ERROR;
	}

	return NGX_OK;
}
ngx_int_t
ngx_child_request_init(ngx_conf_t *cf)
{
	ngx_child_request_hide_header_t *h;
	ngx_array_t hide_headers_arr;
	ngx_hash_key_t  *hk;
	ngx_hash_init_t hash;

	// Note: need to install a header filter in order to support dumping requests -
	//	the headers of the parent request need to be sent before any body data is written
	ngx_http_next_header_filter = ngx_http_top_header_filter;
	ngx_http_top_header_filter = ngx_child_request_header_filter;

	// initialize hide_headers_hash
	if (ngx_array_init(
		&hide_headers_arr,
		cf->temp_pool, 
		sizeof(hide_headers) / sizeof(hide_headers[0]), 
		sizeof(ngx_hash_key_t)) != NGX_OK)
	{
		return NGX_ERROR;
	}

	for (h = hide_headers; h->name.len; h++)
	{
		hk = ngx_array_push(&hide_headers_arr);
		if (hk == NULL) 
		{
			return NGX_ERROR;
		}

		hk->key = h->name;
		hk->key_hash = ngx_hash_key_lc(h->name.data, h->name.len);
		hk->value = h;
	}

	hash.max_size = 512;
	hash.bucket_size = ngx_align(64, ngx_cacheline_size);
	hash.name = "vod_hide_headers_hash";

	hash.hash = &hide_headers_hash;
	hash.key = ngx_hash_key_lc;
	hash.pool = cf->pool;
	hash.temp_pool = NULL;

	if (ngx_hash_init(&hash, hide_headers_arr.elts, hide_headers_arr.nelts) != NGX_OK)
	{
		return NGX_ERROR;
	}

	return NGX_OK;
}
static ngx_int_t	ngx_http_push_postconfig(ngx_conf_t *cf) {
	ngx_http_push_main_conf_t	*conf = ngx_http_conf_get_module_main_conf(cf, ngx_http_push_module);

	//initialize shared memory
	size_t                       shm_size;
	if(conf->shm_size==NGX_CONF_UNSET_SIZE) {
		conf->shm_size=NGX_HTTP_PUSH_DEFAULT_SHM_SIZE;
	}
	shm_size = ngx_align(conf->shm_size, ngx_pagesize);
	if (shm_size < 8 * ngx_pagesize) {
        ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The push_max_reserved_memory value must be at least %udKiB", (8 * ngx_pagesize) >> 10);
        shm_size = 8 * ngx_pagesize;
    }
Пример #5
0
static char * ngx_http_cwinux_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_cwinux_loc_conf_t *prev = parent;
    ngx_http_cwinux_loc_conf_t *conf = child;
    ngx_hash_init_t               hash;
    ngx_str_t                    *h;


    ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
        prev->upstream.connect_timeout, 100);

    ngx_conf_merge_msec_value(conf->upstream.send_timeout,
        prev->upstream.send_timeout, 100);

    ngx_conf_merge_msec_value(conf->upstream.read_timeout,
        prev->upstream.read_timeout, 1000);

    ngx_conf_merge_size_value(conf->upstream.buffer_size,
        prev->upstream.buffer_size,
        (size_t) ngx_pagesize);

    ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
        prev->upstream.next_upstream,
        (NGX_CONF_BITMASK_SET
        |NGX_HTTP_UPSTREAM_FT_ERROR
        |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

    if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
            |NGX_HTTP_UPSTREAM_FT_OFF;
    }
    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "cwinux_hide_headers_hash";
    h = ngx_http_cwinux_hide_headers;

    if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
        &prev->upstream, h, &hash)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    if (conf->upstream.upstream == NULL) {
        conf->upstream.upstream = prev->upstream.upstream;
    }


    return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_push_stream_preconfig(ngx_conf_t *cf)
{
    size_t size = ngx_align(2 * sizeof(ngx_http_push_stream_global_shm_data_t), ngx_pagesize);
    ngx_shm_zone_t     *shm_zone = ngx_shared_memory_add(cf, &ngx_http_push_stream_global_shm_name, size, &ngx_http_push_stream_module);

    if (shm_zone == NULL) {
        return NGX_ERROR;
    }

    shm_zone->init = ngx_http_push_stream_init_global_shm_zone;
    shm_zone->data = (void *) 1;

    return NGX_OK;
}
Пример #7
0
static char *
ngx_stream_core_init_main_conf(ngx_conf_t *cf, void *conf)
{
    ngx_stream_core_main_conf_t *cmcf = conf;

    ngx_conf_init_uint_value(cmcf->variables_hash_max_size, 1024);
    ngx_conf_init_uint_value(cmcf->variables_hash_bucket_size, 64);

    cmcf->variables_hash_bucket_size =
               ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size);

    if (cmcf->ncaptures) {
        cmcf->ncaptures = (cmcf->ncaptures + 1) * 3;
    }

    return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_push_stream_postconfig(ngx_conf_t *cf)
{
    ngx_http_push_stream_main_conf_t   *conf = ngx_http_conf_get_module_main_conf(cf, ngx_http_push_stream_module);
    size_t                              shm_size;
    size_t                              shm_size_limit = 32 * ngx_pagesize;

    if (!conf->enabled) {
        return NGX_OK;
    }

    // initialize shared memory
    shm_size = ngx_align(conf->shm_size, ngx_pagesize);
    if (shm_size < shm_size_limit) {
        ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The push_stream_shared_memory_size value must be at least %udKiB", shm_size_limit >> 10);
        shm_size = shm_size_limit;
    }
Пример #9
0
static char *
ngx_http_themis_init_main_conf(ngx_conf_t *cf, void *conf)
{
    ngx_http_themis_main_conf_t *tmcf = conf;

    if (tmcf->configs_hash_max_size == NGX_CONF_UNSET_UINT) {
        tmcf->configs_hash_max_size = 512;
    }

    if (tmcf->configs_hash_bucket_size == NGX_CONF_UNSET_UINT) {
        tmcf->configs_hash_bucket_size = ngx_cacheline_size;
    }

    tmcf->configs_hash_bucket_size =
              ngx_align(tmcf->configs_hash_bucket_size, ngx_cacheline_size);

    return NGX_CONF_OK;
}
static char *
ngx_http_srcache_init_main_conf(ngx_conf_t *cf, void *conf)
{
    ngx_http_srcache_main_conf_t *smcf = conf;

    ngx_array_t                     headers_in;
    ngx_hash_key_t                 *hk;
    ngx_hash_init_t                 hash;
    ngx_http_srcache_header_t      *header;

    /* srcache_headers_in_hash */

    if (ngx_array_init(&headers_in, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    for (header = ngx_http_srcache_headers_in; header->name.len; header++) {
        hk = ngx_array_push(&headers_in);
        if (hk == NULL) {
            return NGX_CONF_ERROR;
        }

        hk->key = header->name;
        hk->key_hash = ngx_hash_key_lc(header->name.data, header->name.len);
        hk->value = header;
    }

    hash.hash = &smcf->headers_in_hash;
    hash.key = ngx_hash_key_lc;
    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "srcache_headers_in_hash";
    hash.pool = cf->pool;
    hash.temp_pool = NULL;

    if (ngx_hash_init(&hash, headers_in.elts, headers_in.nelts) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}
Пример #11
0
static void *ngx_http_lua_mqtt_create_main_conf(ngx_conf_t *cf){
	ngx_http_lua_mqtt_main_conf_t *mconf = ngx_pcalloc(cf->pool, sizeof(ngx_http_lua_mqtt_main_conf_t));
	if (mconf == NULL) {
		return NULL;
	}
	ngx_log_error(NGX_LOG_DEBUG, cf->log, 0, "ngx_http_lua_mqtt_main_conf_t will be created.");
	//mconf->upstream_names=NGX_CONF_UNSET_PTR;
	mcf = mconf;

	// initialize global shm   ngx_http_lua_mqtt_global_shm_zone
	size_t size = ngx_align(2 * sizeof(ngx_http_lua_mqtt_global_shm_data_t), ngx_pagesize);
    ngx_shm_zone_t     *shm_zone = ngx_shared_memory_add(cf, &ngx_http_lua_mqtt_global_shm_name, size, &ngx_http_lua_mqtt_module);
    if (shm_zone == NULL) {
        return NULL;
    }
    shm_zone->init = ngx_http_lua_mqtt_init_global_shm_zone;
    shm_zone->data = (void *) 1;

	return mconf;
}
Пример #12
0
static char *
ngx_http_upstream_fair_set_shm_size(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ssize_t                         new_shm_size;
    ngx_str_t                      *value;

    value = cf->args->elts;

    new_shm_size = ngx_parse_size(&value[1]);
    if (new_shm_size == NGX_ERROR) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "Invalid memory area size `%V'", &value[1]);
        return NGX_CONF_ERROR;
    }

    new_shm_size = ngx_align(new_shm_size, ngx_pagesize);

    if (new_shm_size < 8 * (ssize_t) ngx_pagesize) {
        ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The upstream_fair_shm_size value must be at least %udKiB", (8 * ngx_pagesize) >> 10);
        new_shm_size = 8 * ngx_pagesize;
    }
// shared memory
char *
ngx_http_lua_mqtt_set_shm_size_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_lua_mqtt_main_conf_t    *mcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_lua_mqtt_module);
    size_t                               shm_size;
    size_t                               shm_size_limit = 32 * ngx_pagesize;
    ngx_str_t                           *value;
    ngx_str_t                           *name;

	if (mcf == NULL) {
		return NULL;
	}

    value = cf->args->elts;

    shm_size = ngx_align(ngx_parse_size(&value[1]), ngx_pagesize);
    if (shm_size < shm_size_limit) {
        ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "The lua_mqtt_shared_memory_size value must be at least %ulKiB", shm_size_limit >> 10);
        return NGX_CONF_ERROR;
    }
ngx_int_t
ngx_http_yy_sec_waf_init_tfns_in_hash(ngx_conf_t *cf,
    ngx_hash_t *tfns_in_hash)
{
    ngx_array_t         tfns;
    ngx_hash_key_t     *hk;
    ngx_hash_init_t     hash;
    re_tfns_metadata     *metadata;

    if (ngx_array_init(&tfns, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    for (metadata = tfns_metadata; metadata->name.len; metadata++) {
        hk = ngx_array_push(&tfns);
        if (hk == NULL) {
            return NGX_ERROR;
        }

        hk->key = metadata->name;
        hk->key_hash = ngx_hash_key_lc(metadata->name.data, metadata->name.len);
        hk->value = metadata;
    }

    hash.hash = tfns_in_hash;
    hash.key = ngx_hash_key_lc;
    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "tfns_in_hash";
    hash.pool = cf->pool;
    hash.temp_pool = NULL;

    if (ngx_hash_init(&hash, tfns.elts, tfns.nelts) != NGX_OK) {
        return NGX_ERROR;
    }

    return NGX_OK;
}
static ngx_int_t ngx_http_redis_init_handle(ngx_conf_t *cf, 
        ngx_http_redis_loc_conf_t *mlcf) 
{
    ngx_array_t commands;
    ngx_http_redis_command_process_t *command;
    ngx_hash_key_t                 *hk;
    ngx_hash_init_t                 hash;

    if (ngx_array_init(&commands, cf->temp_pool, 32, sizeof(ngx_hash_key_t))
        != NGX_OK)
    {
        return NGX_ERROR;
    }

    for (command = ngx_http_redis_command_proc; command->name.len; command++) {
        hk = ngx_array_push(&commands);
        if (hk == NULL) {
            return NGX_ERROR;
        }

        hk->key = command->name;
        hk->key_hash = ngx_hash_key_lc(command->name.data, command->name.len);
        hk->value = command;
    }

    hash.hash = &mlcf->command_hash;
    hash.key = ngx_hash_key_lc;
    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "ngx_http_redis_command_proc_hash";
    hash.pool = cf->pool;
    hash.temp_pool = NULL;

    if (ngx_hash_init(&hash, commands.elts, commands.nelts) != NGX_OK) {
        return NGX_ERROR;
    }

    return NGX_OK;
}
static char *
ngx_http_srcache_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_srcache_loc_conf_t     *prev = parent;
    ngx_http_srcache_loc_conf_t     *conf = child;
    ngx_hash_init_t                  hash;

    ngx_conf_merge_ptr_value(conf->fetch, prev->fetch, NULL);
    ngx_conf_merge_ptr_value(conf->store, prev->store, NULL);

    ngx_conf_merge_size_value(conf->buf_size, prev->buf_size,
            (size_t) ngx_pagesize);

    ngx_conf_merge_size_value(conf->store_max_size, prev->store_max_size, 0);

    ngx_conf_merge_size_value(conf->header_buf_size, prev->header_buf_size,
            (size_t) ngx_pagesize);

    if (conf->fetch_skip == NULL) {
        conf->fetch_skip = prev->fetch_skip;
    }

    if (conf->store_skip == NULL) {
        conf->store_skip = prev->store_skip;
    }

    if (conf->store_statuses == NULL) {
        conf->store_statuses = prev->store_statuses;
    }

    if (conf->cache_methods == 0) {
        conf->cache_methods = prev->cache_methods;
    }

    conf->cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;

    ngx_conf_merge_value(conf->req_cache_control, prev->req_cache_control, 0);
    ngx_conf_merge_value(conf->resp_cache_control, prev->resp_cache_control, 1);

    ngx_conf_merge_value(conf->store_private, prev->store_private, 0);
    ngx_conf_merge_value(conf->store_no_store, prev->store_no_store, 0);
    ngx_conf_merge_value(conf->store_no_cache, prev->store_no_cache, 0);

    ngx_conf_merge_value(conf->max_expire, prev->max_expire, 0);
    ngx_conf_merge_value(conf->default_expire, prev->default_expire, 60);

    ngx_conf_merge_value(conf->ignore_content_encoding,
            prev->ignore_content_encoding, 0);

    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "srcache_store_hide_headers_hash";

    if (ngx_http_srcache_hide_headers_hash(cf, conf,
             prev, ngx_http_srcache_hide_headers, &hash)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}
Пример #17
0
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 (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 && nelts && 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_WARN, hinit->pool->log, 0,
                  "could not build optimal %s, you should increase "
                  "either %s_max_size: %i or %s_bucket_size: %i; "
                  "ignoring %s_bucket_size",
                  hinit->name, hinit->name, hinit->max_size,
                  hinit->name, hinit->bucket_size, hinit->name);

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_short) 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;
}
Пример #18
0
static ngx_int_t
ngx_wd_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 (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 && nelts && 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 (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_short) names[n].key.len;

        strncpy((char *)elt->name, (char *)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;

    return NGX_OK;
}
Пример #19
0
void *ngx_palloc(ngx_pool_t *pool, size_t size)
{
  char              *m;
  ngx_pool_t        *p, *n;
  ngx_pool_large_t  *large, *last;

  if (size <= (size_t) NGX_MAX_ALLOC_FROM_POOL
    && size <= (size_t) (pool->end - (char *) pool) - sizeof(ngx_pool_t))
  {
    for (p = pool, n = pool->next; /* void */; p = n, n = n->next) {
      m = ngx_align(p->last);

      if ((size_t) (p->end - m) >= size) {
        p->last = m + size ;

        return m;
      }

      if (n == NULL) {
        break;
      }
    }

    /* allocate a new pool block */

    if (!(n = ngx_create_pool((size_t) (p->end - (char *) p), p->log))) {
      return NULL;
    }

    p->next = n;
    m = n->last;
    n->last += size;

    return m;
  }

  /* allocate a large block */

  large = NULL;
  last = NULL;

  if (pool->large) {
    for (last = pool->large; /* void */ ; last = last->next) {
      if (last->alloc == NULL) {
        large = last;
        last = NULL;
        break;
      }

      if (last->next == NULL) {
        break;
      }
    }
  }

  if (large == NULL) {
    if (!(large = ngx_palloc(pool, sizeof(ngx_pool_large_t)))) {
      return NULL;
    }

    large->next = NULL;
  }

#if 0
  if (!(p = ngx_memalign(ngx_pagesize, size, pool->log))) {
    return NULL;
  }
#else
  if (!(p = ngx_alloc(size, pool->log))) {
    return NULL;
  }
#endif

  if (pool->large == NULL) {
    pool->large = large;

  } else if (last) {
    last->next = large;
  }

  large->alloc = p;

  return p;
}
Пример #20
0
static char *
ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_referer_conf_t *prev = parent;
    ngx_http_referer_conf_t *conf = child;

    ngx_hash_init_t  hash;

    if (conf->keys == NULL) {
        conf->hash = prev->hash;

#if (NGX_PCRE)
        ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
#endif
        ngx_conf_merge_value(conf->no_referer, prev->no_referer, 0);
        ngx_conf_merge_value(conf->blocked_referer, prev->blocked_referer, 0);
        ngx_conf_merge_uint_value(conf->referer_hash_max_size,
                                  prev->referer_hash_max_size, 2048);
        ngx_conf_merge_uint_value(conf->referer_hash_bucket_size,
                                  prev->referer_hash_bucket_size, 64);

        return NGX_CONF_OK;
    }

    if ((conf->no_referer == 1 || conf->blocked_referer == 1)
            && conf->keys->keys.nelts == 0
            && conf->keys->dns_wc_head.nelts == 0
            && conf->keys->dns_wc_tail.nelts == 0)
    {
        ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
                      "the \"none\" or \"blocked\" referers are specified "
                      "in the \"valid_referers\" directive "
                      "without any valid referer");
        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_uint_value(conf->referer_hash_max_size,
                              prev->referer_hash_max_size, 2048);
    ngx_conf_merge_uint_value(conf->referer_hash_bucket_size,
                              prev->referer_hash_bucket_size, 64);
    conf->referer_hash_bucket_size = ngx_align(conf->referer_hash_bucket_size,
                                     ngx_cacheline_size);

    hash.key = ngx_hash_key_lc;
    hash.max_size = conf->referer_hash_max_size;
    hash.bucket_size = conf->referer_hash_bucket_size;
    hash.name = "referer_hash";
    hash.pool = cf->pool;

    if (conf->keys->keys.nelts) {
        hash.hash = &conf->hash.hash;
        hash.temp_pool = NULL;

        if (ngx_hash_init(&hash, conf->keys->keys.elts, conf->keys->keys.nelts)
                != NGX_OK)
        {
            return NGX_CONF_ERROR;
        }
    }

    if (conf->keys->dns_wc_head.nelts) {

        ngx_qsort(conf->keys->dns_wc_head.elts,
                  (size_t) conf->keys->dns_wc_head.nelts,
                  sizeof(ngx_hash_key_t),
                  ngx_http_cmp_referer_wildcards);

        hash.hash = NULL;
        hash.temp_pool = cf->temp_pool;

        if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_head.elts,
                                   conf->keys->dns_wc_head.nelts)
                != NGX_OK)
        {
            return NGX_CONF_ERROR;
        }

        conf->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
    }

    if (conf->keys->dns_wc_tail.nelts) {

        ngx_qsort(conf->keys->dns_wc_tail.elts,
                  (size_t) conf->keys->dns_wc_tail.nelts,
                  sizeof(ngx_hash_key_t),
                  ngx_http_cmp_referer_wildcards);

        hash.hash = NULL;
        hash.temp_pool = cf->temp_pool;

        if (ngx_hash_wildcard_init(&hash, conf->keys->dns_wc_tail.elts,
                                   conf->keys->dns_wc_tail.nelts)
                != NGX_OK)
        {
            return NGX_CONF_ERROR;
        }

        conf->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
    }

#if (NGX_PCRE)
    ngx_conf_merge_ptr_value(conf->regex, prev->regex, NULL);
#endif

    if (conf->no_referer == NGX_CONF_UNSET) {
        conf->no_referer = 0;
    }

    if (conf->blocked_referer == NGX_CONF_UNSET) {
        conf->blocked_referer = 0;
    }

    conf->keys = NULL;

    return NGX_CONF_OK;
}
ngx_chain_t *
ngx_transmitpackets_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit)
{
    int                        rc;
    u_char                    *prev;
    off_t                      size, send, aligned, sent, fprev;
    ngx_fd_t                   fd;
    ngx_err_t                  err;
    ngx_array_t                vec;
    ngx_event_t               *wev;
    ngx_chain_t               *cl;
    WSAOVERLAPPED             *ovlp;
    TRANSMIT_PACKETS_ELEMENT  *tpe, tpes[NGX_IOVS];

    if (!c->sendfile || !(ngx_event_flags & NGX_USE_IOCP_EVENT)) {
        return ngx_writev_chain(c, in, limit);
    }

    wev = c->write;

    if (wev->closed) {
        return NULL;
    }

    if (wev->error) {
        return NGX_CHAIN_ERROR;
    }

    sent = wev->available;

    if (wev->ready && sent > 0) {

        wev->available = 0;
        c->sent += sent;

        for (cl = in; cl; cl = cl->next) {

            if (ngx_buf_special(cl->buf)) {
                continue;
            }

            if (sent == 0) {
                break;
            }

            size = ngx_buf_size(cl->buf);

            if (sent >= size) {
                sent -= size;

                if (ngx_buf_in_memory(cl->buf)) {
                    cl->buf->pos = cl->buf->last;
                }

                if (cl->buf->in_file) {
                    cl->buf->file_pos = cl->buf->file_last;
                }

                continue;
            }

            if (ngx_buf_in_memory(cl->buf)) {
                cl->buf->pos += sent;
            }

            if (cl->buf->in_file) {
                cl->buf->file_pos += sent;
            }

            break;
        }

        return cl;
    }

    /* the maximum limit size is the maximum size_t value - the page size */

    if (limit == 0 || limit > (off_t) (NGX_MAX_SIZE_T_VALUE - ngx_pagesize)) {
        limit = NGX_MAX_SIZE_T_VALUE - (off_t) ngx_pagesize;
    }

    send = 0;

    vec.nelts = 0;
    vec.elts = tpes;
    vec.size = sizeof(TRANSMIT_PACKETS_ELEMENT);
    vec.nalloc = NGX_IOVS;
    vec.pool = c->pool;

    /*
     * create the TRANSMIT_PACKETS_ELEMENT and
     * coalesce the neighbouring bufs
     */

    fd = INVALID_HANDLE_VALUE;
    prev = NULL;
    fprev = 0;

    for (cl = in; cl && vec.nelts < NGX_IOVS && send < limit;
         cl = cl->next)
    {
        if (ngx_buf_special(cl->buf)) {
            continue;
        }

        if (ngx_buf_in_memory_only(cl->buf)) {

            fd = INVALID_HANDLE_VALUE;
            fprev = 0;

            size = (off_t) (cl->buf->last - cl->buf->pos);

            if (send + size > limit) {
                size = limit - send;
            }

            if (prev == cl->buf->pos) {
                tpe->cLength += (ULONG) size;

            } else {
                tpe = ngx_array_push(&vec);
                if (tpe == NULL) {
                    return NGX_CHAIN_ERROR;
                }

                tpe->dwElFlags = TP_ELEMENT_MEMORY;
                tpe->pBuffer = cl->buf->pos;
                tpe->cLength = (ULONG) size;
            }

            prev = cl->buf->pos + size;

        } else {

            prev = NULL;

            size = cl->buf->file_last - cl->buf->file_pos;

            if (send + size > limit) {
                size = limit - send;

                aligned = ngx_align(cl->buf->file_pos + size,
                                    (off_t) ngx_pagesize);

                if (aligned <= cl->buf->file_last) {
                    size = aligned - cl->buf->file_pos;
                }
            }

            if (fd == cl->buf->file->fd && fprev == cl->buf->file_pos) {
                tpe->cLength += (ULONG) size;

            } else {
                tpe = ngx_array_push(&vec);
                if (tpe == NULL) {
                    return NGX_CHAIN_ERROR;
                }

                /*
                 * caching performance is improved by opening this handle
                 * with FILE_FLAG_SEQUENTIAL_SCAN
                 */

                fd = cl->buf->file->fd;

                tpe->dwElFlags = TP_ELEMENT_FILE;
                tpe->hFile = fd;
                tpe->nFileOffset.QuadPart = cl->buf->file_pos;
                tpe->cLength = (ULONG) size;
            }

            fprev = cl->buf->file_pos + size;
        }

        send += size;
    }

    wev->ovlp.event = wev;
    ovlp = (WSAOVERLAPPED *) &wev->ovlp;

    ngx_memzero(ovlp, sizeof(WSAOVERLAPPED));

    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, c->log, 0,
                   "TransmitPackets: %O", send);

    /*
     * nSendSize and dwFlags parameter of TransmitPackets
     *
     * Set nSendSize to zero to let the sockets layer select a default
     * send size. But when using the TP_ELEMENT_EOP flag in the
     * TRANSMIT_PACKETS_ELEMENT, You should setting nSendSize to 0xFFFFFFF.
     *
     * dwFlags:
     * TP_DISCONNECT、TP_REUSE_SOCKET、TP_USE_DEFAULT_WORKER、
     * TP_USE_SYSTEM_THREAD、TP_USE_KERNEL_APC.
     */

    rc = ngx_transmit_packets(c->fd, vec.elts, (DWORD) vec.nelts, 0, ovlp, 0);

    err = ngx_socket_errno;

    if (rc != 0) {
        wev->ready = 0;
        return in;
    }

    if (err == ERROR_IO_PENDING) {
        ngx_log_debug0(NGX_LOG_DEBUG_EVENT, c->log, err,
                       "TransmitPackets() not ready");
        wev->ready = 0;
        return in;
    }

    ngx_connection_error(c, err, "TransmitPackets() failed");

    wev->error = 1;

    return NGX_CHAIN_ERROR;
}
Пример #22
0
char *
passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    passenger_loc_conf_t         *prev = parent;
    passenger_loc_conf_t         *conf = child;

    u_char                       *p;
    size_t                        size;
    uintptr_t                    *code;
    ngx_str_t                    *header;
    ngx_uint_t                    i, j;
    ngx_array_t                   hide_headers;
    ngx_str_t                    *prev_base_uris, *base_uri;
    ngx_keyval_t                 *src;
    ngx_hash_key_t               *hk;
    ngx_hash_init_t               hash;
    ngx_http_script_compile_t     sc;
    ngx_http_script_copy_code_t  *copy;
#if NGINX_VERSION_NUM < 7000
    u_char                       *temp_path;
#endif

    ngx_conf_merge_value(conf->enabled, prev->enabled, 0);
    ngx_conf_merge_value(conf->use_global_queue, prev->use_global_queue, 0);
    ngx_conf_merge_str_value(conf->environment, prev->environment, "production");
    ngx_conf_merge_str_value(conf->spawn_method, prev->spawn_method, "smart-lv2");
    if (conf->framework_spawner_idle_time == -1 && prev->framework_spawner_idle_time != -1) {
        conf->framework_spawner_idle_time = prev->framework_spawner_idle_time;
    }
    if (conf->app_spawner_idle_time == -1 && prev->app_spawner_idle_time != -1) {
        conf->app_spawner_idle_time = prev->app_spawner_idle_time;
    }

    if (prev->base_uris != NGX_CONF_UNSET_PTR) {
        if (conf->base_uris == NGX_CONF_UNSET_PTR) {
            conf->base_uris = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
            if (conf->base_uris == NULL) {
                return NGX_CONF_ERROR;
            }
        }

        prev_base_uris = (ngx_str_t *) prev->base_uris->elts;
        for (i = 0; i < prev->base_uris->nelts; i++) {
            base_uri = (ngx_str_t *) ngx_array_push(conf->base_uris);
            if (base_uri == NULL) {
                return NGX_CONF_ERROR;
            }
            *base_uri = prev_base_uris[i];
        }
    }


    if (conf->upstream.store != 0) {
        ngx_conf_merge_value(conf->upstream.store,
                             prev->upstream.store, 0);

        if (conf->upstream.store_lengths == NULL) {
            conf->upstream.store_lengths = prev->upstream.store_lengths;
            conf->upstream.store_values = prev->upstream.store_values;
        }
    }

    ngx_conf_merge_uint_value(conf->upstream.store_access,
                              prev->upstream.store_access, 0600);

    ngx_conf_merge_value(conf->upstream.buffering,
                         prev->upstream.buffering, 1);

    ngx_conf_merge_value(conf->upstream.ignore_client_abort,
                         prev->upstream.ignore_client_abort, 0);

    ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
                              prev->upstream.connect_timeout, 60000);

    ngx_conf_merge_msec_value(conf->upstream.send_timeout,
                              prev->upstream.send_timeout, 60000);

    ngx_conf_merge_msec_value(conf->upstream.read_timeout,
                              prev->upstream.read_timeout, 60000);

    ngx_conf_merge_size_value(conf->upstream.send_lowat,
                              prev->upstream.send_lowat, 0);

    ngx_conf_merge_size_value(conf->upstream.buffer_size,
                              prev->upstream.buffer_size,
                              (size_t) ngx_pagesize);


    ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
                              8, ngx_pagesize);

    if (conf->upstream.bufs.num < 2) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "there must be at least 2 \"scgi_buffers\"");
        return NGX_CONF_ERROR;
    }


    size = conf->upstream.buffer_size;
    if (size < conf->upstream.bufs.size) {
        size = conf->upstream.bufs.size;
    }


    ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
                              prev->upstream.busy_buffers_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream.busy_buffers_size = 2 * size;
    } else {
        conf->upstream.busy_buffers_size =
            conf->upstream.busy_buffers_size_conf;
    }

    if (conf->upstream.busy_buffers_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "\"scgi_busy_buffers_size\" must be equal or bigger than "
                           "maximum of the value of \"scgi_buffer_size\" and "
                           "one of the \"scgi_buffers\"");

        return NGX_CONF_ERROR;
    }

    if (conf->upstream.busy_buffers_size
            > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "\"scgi_busy_buffers_size\" must be less than "
                           "the size of all \"scgi_buffers\" minus one buffer");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
                              prev->upstream.temp_file_write_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream.temp_file_write_size = 2 * size;
    } else {
        conf->upstream.temp_file_write_size =
            conf->upstream.temp_file_write_size_conf;
    }

    if (conf->upstream.temp_file_write_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "\"scgi_temp_file_write_size\" must be equal or bigger than "
                           "maximum of the value of \"scgi_buffer_size\" and "
                           "one of the \"scgi_buffers\"");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
                              prev->upstream.max_temp_file_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
    } else {
        conf->upstream.max_temp_file_size =
            conf->upstream.max_temp_file_size_conf;
    }

    if (conf->upstream.max_temp_file_size != 0
            && conf->upstream.max_temp_file_size < size)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "\"scgi_max_temp_file_size\" must be equal to zero to disable "
                           "the temporary files usage or must be equal or bigger than "
                           "maximum of the value of \"scgi_buffer_size\" and "
                           "one of the \"scgi_buffers\"");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
                                 prev->upstream.next_upstream,
                                 (NGX_CONF_BITMASK_SET
                                  |NGX_HTTP_UPSTREAM_FT_ERROR
                                  |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

    if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
                                       |NGX_HTTP_UPSTREAM_FT_OFF;
    }

#if NGINX_VERSION_NUM < 7000
    temp_path = ngx_palloc(cf->pool, NGX_MAX_PATH);
    ngx_memzero(temp_path, NGX_MAX_PATH);
    ngx_snprintf(temp_path, NGX_MAX_PATH, "%s/webserver_private", passenger_temp_dir);
    ngx_conf_merge_path_value(conf->upstream.temp_path,
                              prev->upstream.temp_path,
                              temp_path, 1, 2, 0,
                              ngx_garbage_collector_temp_handler, cf);
    conf->upstream.temp_path->name.len = ngx_strlen(conf->upstream.temp_path->name.data);
#else
    ngx_conf_merge_path_value(cf,
                              &conf->upstream.temp_path,
                              prev->upstream.temp_path,
                              &ngx_http_proxy_temp_path);
#endif

    ngx_conf_merge_value(conf->upstream.pass_request_headers,
                         prev->upstream.pass_request_headers, 1);
    ngx_conf_merge_value(conf->upstream.pass_request_body,
                         prev->upstream.pass_request_body, 1);

    ngx_conf_merge_value(conf->upstream.intercept_errors,
                         prev->upstream.intercept_errors, 0);



    ngx_conf_merge_str_value(conf->index, prev->index, "");

    if (conf->upstream.hide_headers == NULL
            && conf->upstream.pass_headers == NULL)
    {
        conf->upstream.hide_headers = prev->upstream.hide_headers;
        conf->upstream.pass_headers = prev->upstream.pass_headers;
        conf->upstream.hide_headers_hash = prev->upstream.hide_headers_hash;

        if (conf->upstream.hide_headers_hash.buckets) {
            goto peers;
        }

    } else {
        if (conf->upstream.hide_headers == NULL) {
            conf->upstream.hide_headers = prev->upstream.hide_headers;
        }

        if (conf->upstream.pass_headers == NULL) {
            conf->upstream.pass_headers = prev->upstream.pass_headers;
        }
    }

    if (ngx_array_init(&hide_headers, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
            != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    for (header = headers_to_hide; header->len; header++) {
        hk = ngx_array_push(&hide_headers);
        if (hk == NULL) {
            return NGX_CONF_ERROR;
        }

        hk->key = *header;
        hk->key_hash = ngx_hash_key_lc(header->data, header->len);
        hk->value = (void *) 1;
    }

    if (conf->upstream.hide_headers) {

        header = conf->upstream.hide_headers->elts;

        for (i = 0; i < conf->upstream.hide_headers->nelts; i++) {

            hk = hide_headers.elts;

            for (j = 0; j < hide_headers.nelts; j++) {
                if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
                    goto exist;
                }
            }

            hk = ngx_array_push(&hide_headers);
            if (hk == NULL) {
                return NGX_CONF_ERROR;
            }

            hk->key = header[i];
            hk->key_hash = ngx_hash_key_lc(header[i].data, header[i].len);
            hk->value = (void *) 1;

exist:

            continue;
        }
    }

    if (conf->upstream.pass_headers) {

        hk = hide_headers.elts;
        header = conf->upstream.pass_headers->elts;

        for (i = 0; i < conf->upstream.pass_headers->nelts; i++) {

            for (j = 0; j < hide_headers.nelts; j++) {

                if (hk[j].key.data == NULL) {
                    continue;
                }

                if (ngx_strcasecmp(header[i].data, hk[j].key.data) == 0) {
                    hk[j].key.data = NULL;
                    break;
                }
            }
        }
    }

    hash.hash = &conf->upstream.hide_headers_hash;
    hash.key = ngx_hash_key_lc;
    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "passenger_hide_headers_hash";
    hash.pool = cf->pool;
    hash.temp_pool = NULL;

    if (ngx_hash_init(&hash, hide_headers.elts, hide_headers.nelts) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

peers:

    if (conf->upstream.upstream == NULL) {
        conf->upstream.upstream = prev->upstream.upstream;
#if NGINX_VERSION_NUM < 7000
        conf->upstream.schema = prev->upstream.schema;
#endif
    }

    if (conf->vars_source == NULL) {
        conf->flushes = prev->flushes;
        conf->vars_len = prev->vars_len;
        conf->vars = prev->vars;
        conf->vars_source = prev->vars_source;

        if (conf->vars_source == NULL) {
            return NGX_CONF_OK;
        }
    }

    conf->vars_len = ngx_array_create(cf->pool, 64, 1);
    if (conf->vars_len == NULL) {
        return NGX_CONF_ERROR;
    }

    conf->vars = ngx_array_create(cf->pool, 512, 1);
    if (conf->vars == NULL) {
        return NGX_CONF_ERROR;
    }

    src = conf->vars_source->elts;
    for (i = 0; i < conf->vars_source->nelts; i++) {

        if (ngx_http_script_variables_count(&src[i].value) == 0) {
            copy = ngx_array_push_n(conf->vars_len,
                                    sizeof(ngx_http_script_copy_code_t));
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = (ngx_http_script_code_pt)
                         ngx_http_script_copy_len_code;
            copy->len = src[i].key.len;


            copy = ngx_array_push_n(conf->vars_len,
                                    sizeof(ngx_http_script_copy_code_t));
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = (ngx_http_script_code_pt)
                         ngx_http_script_copy_len_code;
            copy->len = src[i].value.len;


            size = (sizeof(ngx_http_script_copy_code_t)
                    + src[i].key.len + src[i].value.len
                    + sizeof(uintptr_t) - 1)
                   & ~(sizeof(uintptr_t) - 1);

            copy = ngx_array_push_n(conf->vars, size);
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = ngx_http_script_copy_code;
            copy->len = src[i].key.len + src[i].value.len;

            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);

            p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
            ngx_memcpy(p, src[i].value.data, src[i].value.len);

        } else {
            copy = ngx_array_push_n(conf->vars_len,
                                    sizeof(ngx_http_script_copy_code_t));
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = (ngx_http_script_code_pt)
                         ngx_http_script_copy_len_code;
            copy->len = src[i].key.len;


            size = (sizeof(ngx_http_script_copy_code_t)
                    + src[i].key.len + sizeof(uintptr_t) - 1)
                   & ~(sizeof(uintptr_t) - 1);

            copy = ngx_array_push_n(conf->vars, size);
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = ngx_http_script_copy_code;
            copy->len = src[i].key.len;

            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
            ngx_memcpy(p, src[i].key.data, src[i].key.len);


            ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

            sc.cf = cf;
            sc.source = &src[i].value;
            sc.flushes = &conf->flushes;
            sc.lengths = &conf->vars_len;
            sc.values = &conf->vars;

            if (ngx_http_script_compile(&sc) != NGX_OK) {
                return NGX_CONF_ERROR;
            }
        }

        code = ngx_array_push_n(conf->vars_len, sizeof(uintptr_t));
        if (code == NULL) {
            return NGX_CONF_ERROR;
        }

        *code = (uintptr_t) NULL;


        code = ngx_array_push_n(conf->vars, sizeof(uintptr_t));
        if (code == NULL) {
            return NGX_CONF_ERROR;
        }

        *code = (uintptr_t) NULL;
    }

    code = ngx_array_push_n(conf->vars_len, sizeof(uintptr_t));
    if (code == NULL) {
        return NGX_CONF_ERROR;
    }

    *code = (uintptr_t) NULL;

    return NGX_CONF_OK;
}
static char *
ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_scgi_loc_conf_t *prev = parent;
    ngx_http_scgi_loc_conf_t *conf = child;

    u_char                       *p;
    size_t                        size;
    uintptr_t                    *code;
    ngx_uint_t                    i;
    ngx_array_t                   headers_names;
    ngx_keyval_t                 *src;
    ngx_hash_key_t               *hk;
    ngx_hash_init_t               hash;
    ngx_http_core_loc_conf_t     *clcf;
    ngx_http_script_compile_t     sc;
    ngx_http_script_copy_code_t  *copy;

    if (conf->upstream.store != 0) {
        ngx_conf_merge_value(conf->upstream.store, prev->upstream.store, 0);

        if (conf->upstream.store_lengths == NULL) {
            conf->upstream.store_lengths = prev->upstream.store_lengths;
            conf->upstream.store_values = prev->upstream.store_values;
        }
    }

    ngx_conf_merge_uint_value(conf->upstream.store_access,
                              prev->upstream.store_access, 0600);

    ngx_conf_merge_value(conf->upstream.buffering,
                              prev->upstream.buffering, 1);

    ngx_conf_merge_value(conf->upstream.ignore_client_abort,
                              prev->upstream.ignore_client_abort, 0);

    ngx_conf_merge_msec_value(conf->upstream.connect_timeout,
                              prev->upstream.connect_timeout, 60000);

    ngx_conf_merge_msec_value(conf->upstream.send_timeout,
                              prev->upstream.send_timeout, 60000);

    ngx_conf_merge_msec_value(conf->upstream.read_timeout,
                              prev->upstream.read_timeout, 60000);

    ngx_conf_merge_size_value(conf->upstream.send_lowat,
                              prev->upstream.send_lowat, 0);

    ngx_conf_merge_size_value(conf->upstream.buffer_size,
                              prev->upstream.buffer_size,
                              (size_t) ngx_pagesize);


    ngx_conf_merge_bufs_value(conf->upstream.bufs, prev->upstream.bufs,
                              8, ngx_pagesize);

    if (conf->upstream.bufs.num < 2) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "there must be at least 2 \"scgi_buffers\"");
        return NGX_CONF_ERROR;
    }


    size = conf->upstream.buffer_size;
    if (size < conf->upstream.bufs.size) {
        size = conf->upstream.bufs.size;
    }


    ngx_conf_merge_size_value(conf->upstream.busy_buffers_size_conf,
                              prev->upstream.busy_buffers_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream.busy_buffers_size = 2 * size;
    } else {
        conf->upstream.busy_buffers_size =
            conf->upstream.busy_buffers_size_conf;
    }

    if (conf->upstream.busy_buffers_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
            "\"scgi_busy_buffers_size\" must be equal or bigger "
            "than maximum of the value of \"scgi_buffer_size\" and "
            "one of the \"scgi_buffers\"");

        return NGX_CONF_ERROR;
    }

    if (conf->upstream.busy_buffers_size
        > (conf->upstream.bufs.num - 1) * conf->upstream.bufs.size)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
            "\"scgi_busy_buffers_size\" must be less than "
            "the size of all \"scgi_buffers\" minus one buffer");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_size_value(conf->upstream.temp_file_write_size_conf,
                              prev->upstream.temp_file_write_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream.temp_file_write_size = 2 * size;
    } else {
        conf->upstream.temp_file_write_size =
            conf->upstream.temp_file_write_size_conf;
    }

    if (conf->upstream.temp_file_write_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
            "\"scgi_temp_file_write_size\" must be equal or bigger than "
            "maximum of the value of \"scgi_buffer_size\" and "
            "one of the \"scgi_buffers\"");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_size_value(conf->upstream.max_temp_file_size_conf,
                              prev->upstream.max_temp_file_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream.max_temp_file_size = 1024 * 1024 * 1024;
    } else {
        conf->upstream.max_temp_file_size =
            conf->upstream.max_temp_file_size_conf;
    }

    if (conf->upstream.max_temp_file_size != 0
        && conf->upstream.max_temp_file_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
            "\"scgi_max_temp_file_size\" must be equal to zero to disable "
            "the temporary files usage or must be equal or bigger than "
            "maximum of the value of \"scgi_buffer_size\" and "
            "one of the \"scgi_buffers\"");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_bitmask_value(conf->upstream.ignore_headers,
                                 prev->upstream.ignore_headers,
                                 NGX_CONF_BITMASK_SET);


    ngx_conf_merge_bitmask_value(conf->upstream.next_upstream,
                                 prev->upstream.next_upstream,
                                 (NGX_CONF_BITMASK_SET
                                  |NGX_HTTP_UPSTREAM_FT_ERROR
                                  |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

    if (conf->upstream.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream.next_upstream = NGX_CONF_BITMASK_SET
                                       |NGX_HTTP_UPSTREAM_FT_OFF;
    }

    if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
                                  prev->upstream.temp_path,
                                  &ngx_http_scgi_temp_path)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

#if (NGX_HTTP_CACHE)

    ngx_conf_merge_ptr_value(conf->upstream.cache,
                              prev->upstream.cache, NULL);

    if (conf->upstream.cache && conf->upstream.cache->data == NULL) {
        ngx_shm_zone_t  *shm_zone;

        shm_zone = conf->upstream.cache;

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "\"scgi_cache\" zone \"%V\" is unknown",
                           &shm_zone->shm.name);

        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
                              prev->upstream.cache_min_uses, 1);

    ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
                              prev->upstream.cache_use_stale,
                              (NGX_CONF_BITMASK_SET
                               |NGX_HTTP_UPSTREAM_FT_OFF));

    if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
                                         |NGX_HTTP_UPSTREAM_FT_OFF;
    }

    if (conf->upstream.cache_methods == 0) {
        conf->upstream.cache_methods = prev->upstream.cache_methods;
    }

    conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;

    ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
                             prev->upstream.cache_bypass, NULL);

    ngx_conf_merge_ptr_value(conf->upstream.no_cache,
                             prev->upstream.no_cache, NULL);

    ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
                             prev->upstream.cache_valid, NULL);

    if (conf->cache_key.value.data == NULL) {
        conf->cache_key = prev->cache_key;
    }

#endif

    ngx_conf_merge_value(conf->upstream.pass_request_headers,
                         prev->upstream.pass_request_headers, 1);
    ngx_conf_merge_value(conf->upstream.pass_request_body,
                         prev->upstream.pass_request_body, 1);

    ngx_conf_merge_value(conf->upstream.intercept_errors,
                         prev->upstream.intercept_errors, 0);

    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "scgi_hide_headers_hash";

    if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream,
            &prev->upstream, ngx_http_scgi_hide_headers, &hash)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    if (conf->upstream.upstream == NULL) {
        conf->upstream.upstream = prev->upstream.upstream;
    }

    if (conf->scgi_lengths == NULL) {
        conf->scgi_lengths = prev->scgi_lengths;
        conf->scgi_values = prev->scgi_values;
    }

    if (conf->upstream.upstream || conf->scgi_lengths) {
        clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);
        if (clcf->handler == NULL && clcf->lmt_excpt) {
            clcf->handler = ngx_http_scgi_handler;
        }
    }

    if (conf->params_source == NULL) {
        conf->flushes = prev->flushes;
        conf->params_len = prev->params_len;
        conf->params = prev->params;
        conf->params_source = prev->params_source;
        conf->headers_hash = prev->headers_hash;

#if (NGX_HTTP_CACHE)

        if (conf->params_source == NULL) {

            if ((conf->upstream.cache == NULL)
                == (prev->upstream.cache == NULL))
            {
                return NGX_CONF_OK;
            }

            /* 6 is a number of ngx_http_scgi_cache_headers entries */
            conf->params_source = ngx_array_create(cf->pool, 6,
                                                   sizeof(ngx_keyval_t));
            if (conf->params_source == NULL) {
                return NGX_CONF_ERROR;
            }
        }
#else

        if (conf->params_source == NULL) {
            return NGX_CONF_OK;
        }

#endif
    }

    conf->params_len = ngx_array_create(cf->pool, 64, 1);
    if (conf->params_len == NULL) {
        return NGX_CONF_ERROR;
    }

    conf->params = ngx_array_create(cf->pool, 512, 1);
    if (conf->params == NULL) {
        return NGX_CONF_ERROR;
    }

    if (ngx_array_init(&headers_names, cf->temp_pool, 4, sizeof(ngx_hash_key_t))
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    src = conf->params_source->elts;

#if (NGX_HTTP_CACHE)

    if (conf->upstream.cache) {
        ngx_keyval_t  *h, *s;

        for (h = ngx_http_scgi_cache_headers; h->key.len; h++) {

            for (i = 0; i < conf->params_source->nelts; i++) {
                if (ngx_strcasecmp(h->key.data, src[i].key.data) == 0) {
                    goto next;
                }
            }

            s = ngx_array_push(conf->params_source);
            if (s == NULL) {
                return NGX_CONF_ERROR;
            }

            *s = *h;

            src = conf->params_source->elts;

        next:

            h++;
        }
    }

#endif

    for (i = 0; i < conf->params_source->nelts; i++) {

        if (src[i].key.len > sizeof("HTTP_") - 1
            && ngx_strncmp(src[i].key.data, "HTTP_", sizeof("HTTP_") - 1) == 0)
        {
            hk = ngx_array_push(&headers_names);
            if (hk == NULL) {
                return NGX_CONF_ERROR;
            }

            hk->key.len = src[i].key.len - 5;
            hk->key.data = src[i].key.data + 5;
            hk->key_hash = ngx_hash_key_lc(hk->key.data, hk->key.len);
            hk->value = (void *) 1;

            if (src[i].value.len == 0) {
                continue;
            }
        }

        copy = ngx_array_push_n(conf->params_len,
                                sizeof(ngx_http_script_copy_code_t));
        if (copy == NULL) {
            return NGX_CONF_ERROR;
        }

        copy->code = (ngx_http_script_code_pt) ngx_http_script_copy_len_code;
        copy->len = src[i].key.len + 1;


        size = (sizeof(ngx_http_script_copy_code_t)
                + src[i].key.len + 1 + sizeof(uintptr_t) - 1)
               & ~(sizeof(uintptr_t) - 1);

        copy = ngx_array_push_n(conf->params, size);
        if (copy == NULL) {
            return NGX_CONF_ERROR;
        }

        copy->code = ngx_http_script_copy_code;
        copy->len = src[i].key.len + 1;

        p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
        (void) ngx_cpystrn(p, src[i].key.data, src[i].key.len + 1);


        ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

        sc.cf = cf;
        sc.source = &src[i].value;
        sc.flushes = &conf->flushes;
        sc.lengths = &conf->params_len;
        sc.values = &conf->params;

        if (ngx_http_script_compile(&sc) != NGX_OK) {
            return NGX_CONF_ERROR;
        }

        code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
        if (code == NULL) {
            return NGX_CONF_ERROR;
        }

        *code = (uintptr_t) NULL;


        code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
        if (code == NULL) {
            return NGX_CONF_ERROR;
        }

        *code = (uintptr_t) NULL;
    }

    code = ngx_array_push_n(conf->params_len, sizeof(uintptr_t));
    if (code == NULL) {
        return NGX_CONF_ERROR;
    }

    *code = (uintptr_t) NULL;

    code = ngx_array_push_n(conf->params, sizeof(uintptr_t));
    if (code == NULL) {
        return NGX_CONF_ERROR;
    }

    *code = (uintptr_t) NULL;

    conf->header_params = headers_names.nelts;

    hash.hash = &conf->headers_hash;
    hash.key = ngx_hash_key_lc;
    hash.max_size = 512;
    hash.bucket_size = 64;
    hash.name = "scgi_params_hash";
    hash.pool = cf->pool;
    hash.temp_pool = NULL;

    if (ngx_hash_init(&hash, headers_names.elts, headers_names.nelts) != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}
static char *
ngx_http_filter_cache_merge_conf(ngx_conf_t *cf, void *parent, void *child)
{
    ngx_http_filter_cache_conf_t *prev = parent;
    ngx_http_filter_cache_conf_t *conf = child;
    /* ngx_hash_init_t             hash; */

    ngx_conf_merge_uint_value(conf->headers_hash_max_size,
                              prev->headers_hash_max_size, 512);

    ngx_conf_merge_uint_value(conf->headers_hash_bucket_size,
                              prev->headers_hash_bucket_size, 64);

    conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
                                               ngx_cacheline_size);

    if (ngx_http_filter_cache_hide_headers_merge(cf, conf, prev, ngx_http_filter_cache_hide_headers)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_ptr_value(conf->upstream.cache,
                             prev->upstream.cache, NULL);

    if (conf->upstream.cache && conf->upstream.cache->data == NULL) {
        ngx_shm_zone_t  *shm_zone = NULL;

        shm_zone = conf->upstream.cache;

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "\"filter_cache\" zone \"%V\" is unknown",
                           &shm_zone->shm.name);

        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_uint_value(conf->upstream.cache_min_uses,
                              prev->upstream.cache_min_uses, 1);

    ngx_conf_merge_bitmask_value(conf->upstream.cache_use_stale,
                              prev->upstream.cache_use_stale,
                              (NGX_CONF_BITMASK_SET
                               |NGX_HTTP_UPSTREAM_FT_OFF));

    if (conf->upstream.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream.cache_use_stale = NGX_CONF_BITMASK_SET
                                         |NGX_HTTP_UPSTREAM_FT_OFF;
    }

    if (conf->upstream.cache_methods == 0) {
        conf->upstream.cache_methods = prev->upstream.cache_methods;
    }

    conf->upstream.cache_methods |= NGX_HTTP_GET|NGX_HTTP_HEAD;

    ngx_conf_merge_ptr_value(conf->upstream.cache_bypass,
                             prev->upstream.cache_bypass, NULL);

    ngx_conf_merge_ptr_value(conf->upstream.no_cache,
                             prev->upstream.no_cache, NULL);

    if (conf->upstream.no_cache && conf->upstream.cache_bypass == NULL) {
        ngx_log_error(NGX_LOG_WARN, cf->log, 0,
                      "\"filter_cache_disable\" should generally be used together with \"filter_cache_bypass\"");
    }

    ngx_conf_merge_ptr_value(conf->upstream.cache_valid,
                             prev->upstream.cache_valid, NULL);

    if (conf->cache_key.value.data == NULL) {
        conf->cache_key = prev->cache_key;
    }

    if (ngx_conf_merge_path_value(cf, &conf->upstream.temp_path,
                                  prev->upstream.temp_path,
                                  &ngx_http_filter_cache_temp_path)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_size_value(conf->upstream.buffer_size,
                              prev->upstream.buffer_size,
                              (size_t) ngx_pagesize);


    /* hash.max_size = conf->headers_hash_max_size; */
    /* hash.bucket_size = conf->headers_hash_bucket_size; */
    /* hash.name = "filter_cache_headers_hash"; */

    /* if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream, */
    /*         &prev->upstream, ngx_http_filter_cache_hide_headers, &hash) */
    /*     != NGX_OK) */
    /* { */
    /*     return NGX_CONF_ERROR; */
    /* } */

    ngx_conf_merge_value(conf->grace,
                         prev->grace, 0);

    ngx_conf_merge_value(conf->handler,
                         prev->handler, 1);

    return NGX_CONF_OK;
}
Пример #25
0
dvt_cache_t *dvt_cache_init(ngx_pool_t *pool)
{
  dvt_cache_t *cache = ngx_palloc(pool, sizeof(dvt_cache_t));

  cache->label_and_value_summary_json = NGX_CONF_UNSET_PTR;
  cache->label_names = NGX_CONF_UNSET_PTR;
  cache->label_ids = NGX_CONF_UNSET_PTR;
  cache->label_value_names = NGX_CONF_UNSET_PTR;
  cache->label_value_ids = NGX_CONF_UNSET_PTR;

  uint64_t i, j;
  ngx_str_t *jsn = NGX_CONF_UNSET_PTR;
  ngx_array_t* series_collection;
  ngx_array_t* lavs; // labels and values
  ngx_str_t *current_str;
  ngx_array_t *hash_elts;
  ngx_hash_key_t *el;
  ngx_array_t **ael;
  ngx_hash_init_t hash_spec;

  // ### json summary.
  series_collection = load_test_exposition(pool);
  if (series_collection)
  {
    lavs = lavs_from_series_set(series_collection, pool);
    jsn = lavs_to_json(lavs, pool, pool);
  }
  cache->label_and_value_summary_json = jsn;

  // ### label_id -> label_names array
  cache->label_names = ngx_array_create(pool, 32, sizeof(ngx_str_t));
  for (i=0; i<lavs->nelts; ++i)
  {
    current_str = ngx_array_push(cache->label_names);
    *current_str = ((dvt_label_summary_info_t *)lavs->elts)[i].label_name;
  }

  // ### label_name -> label_id hash
  hash_elts = ngx_array_create(pool, 32, sizeof(ngx_hash_key_t));
  for (i=0; i<cache->label_names->nelts; ++i)
  {
    el = ngx_array_push(hash_elts);
    el->key = ((ngx_str_t *)cache->label_names->elts)[i];
    el->key_hash = ngx_hash_key(el->key.data, el->key.len);
    el->value = (void *)(i + ARBITRARY_OFFSET_TO_AVOID_PTR_EQ_NULL);
  }
  cache->label_ids = ngx_palloc(pool, sizeof(ngx_hash_t));
  hash_spec.hash = cache->label_ids;
  hash_spec.key = ngx_hash_key;
  hash_spec.max_size = 1024;
  hash_spec.bucket_size = ngx_align(64, ngx_cacheline_size);
  hash_spec.name = "label_ids";
  hash_spec.pool = pool;
  if (ngx_hash_init(&hash_spec, hash_elts->elts, hash_elts->nelts) != NGX_OK) {
    return NGX_CONF_ERROR;
  }

  // ### label_value_names
  cache->label_value_names = ngx_array_create(
    pool, cache->label_names->nelts, sizeof(ngx_array_t *));
  for (i=0; i<cache->label_names->nelts; ++i)
  {
    dvt_label_summary_info_t *labsum =
        &(((dvt_label_summary_info_t *)lavs->elts)[i]);
    ael = ngx_array_push(cache->label_value_names);
    *ael = ngx_array_create(
      pool, labsum->label_values->nelts, sizeof(ngx_str_t *));
    for (j=0; j<labsum->label_values->nelts; ++j)
    {
      dvt_label_value_summary_info_t* labval_info
        = &((dvt_label_value_summary_info_t *)labsum->label_values->elts)[j];
      ngx_str_t *lval
        = &labval_info->label_value_name;
      ngx_str_t **p = ngx_array_push(*ael);
      *p = lval;
    }
  }

  // ### label_value_ids
  cache->label_value_ids = ngx_array_create(
    pool, cache->label_names->nelts, sizeof(ngx_hash_t));
  for (i=0; i<cache->label_names->nelts; ++i)
  {
    hash_elts = ngx_array_create(pool, 32, sizeof(ngx_hash_key_t));
    ngx_array_t *value_names
      = ((ngx_array_t **)cache->label_value_names->elts)[i];
    for (j=0; j<value_names->nelts; ++j)
    {
      el = ngx_array_push(hash_elts);
      el->key = *((ngx_str_t **)value_names->elts)[j];
      el->key_hash = ngx_hash_key(el->key.data, el->key.len);
      el->value = (void *)(j + ARBITRARY_OFFSET_TO_AVOID_PTR_EQ_NULL);
    }

    ngx_hash_t *hel = ngx_array_push(cache->label_value_ids);
    hash_spec.hash = hel;
    hash_spec.key = ngx_hash_key;
    hash_spec.max_size = 1024;
    hash_spec.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash_spec.name = "label_value_ids";
    hash_spec.pool = pool;
    if (ngx_hash_init(&hash_spec, hash_elts->elts, hash_elts->nelts) != NGX_OK) {
      return NGX_CONF_ERROR;
    }
  }

  // TODO: some sort of partitioning.
  // Probably binary.
  // Goal is to keep as balanced as possible.
  // ### all series
  ngx_array_init(&cache->all_series, pool, 128, sizeof(uint32_t *));
  for (i=0; i<series_collection->nelts; ++i)
  {
    ngx_array_t *series_kvps = ((ngx_array_t **)series_collection->elts)[i];
    uint32_t **loc = ngx_array_push(&cache->all_series);
    *loc = dvt_series_spec_from_kv_array(cache, series_kvps, pool);
    dbg_ngx(dvt_series_spec_to_text(cache, *loc, pool), pool);
  }

  return cache;
}
Пример #26
0
char *
passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    passenger_loc_conf_t         *prev = parent;
    passenger_loc_conf_t         *conf = child;
    ngx_http_core_loc_conf_t     *clcf;

    size_t                        size;
    ngx_hash_init_t               hash;

    clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module);

    if (generated_merge_part(conf, prev, cf) == 0) {
    	return NGX_CONF_ERROR;
    }

    if (prev->options_cache.data == NULL) {
        if (cache_loc_conf_options(cf, prev) != NGX_OK) {
            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "cannot create " PROGRAM_NAME " configuration cache");
            return NGX_CONF_ERROR;
        }
    }

    /******************************/
    /******************************/

    #if (NGX_HTTP_CACHE) && NGINX_VERSION_NUM >= 1007009
        if (conf->upstream_config.store > 0) {
            conf->upstream_config.cache = 0;
        }
        if (conf->upstream_config.cache > 0) {
            conf->upstream_config.store = 0;
        }
    #endif

    #if NGINX_VERSION_NUM >= 1007009
        if (conf->upstream_config.store == NGX_CONF_UNSET) {
            ngx_conf_merge_value(conf->upstream_config.store,
                                      prev->upstream_config.store, 0);

            conf->upstream_config.store_lengths = prev->upstream_config.store_lengths;
            conf->upstream_config.store_values = prev->upstream_config.store_values;
        }
    #else
        if (conf->upstream_config.store != 0) {
            ngx_conf_merge_value(conf->upstream_config.store,
                                      prev->upstream_config.store, 0);

            if (conf->upstream_config.store_lengths == NULL) {
                conf->upstream_config.store_lengths = prev->upstream_config.store_lengths;
                conf->upstream_config.store_values = prev->upstream_config.store_values;
            }
        }
    #endif

    ngx_conf_merge_uint_value(conf->upstream_config.store_access,
                              prev->upstream_config.store_access, 0600);

    #if NGINX_VERSION_NUM >= 1007005
        ngx_conf_merge_uint_value(conf->upstream_config.next_upstream_tries,
                                  prev->upstream_config.next_upstream_tries, 0);
    #endif

    ngx_conf_merge_value(conf->upstream_config.buffering,
                         prev->upstream_config.buffering, 0);

    ngx_conf_merge_value(conf->upstream_config.ignore_client_abort,
                         prev->upstream_config.ignore_client_abort, 0);

    #if NGINX_VERSION_NUM >= 1007007
        ngx_conf_merge_value(conf->upstream_config.force_ranges,
                             prev->upstream_config.force_ranges, 0);
    #endif

    ngx_conf_merge_ptr_value(conf->upstream_config.local,
                             prev->upstream_config.local, NULL);

    ngx_conf_merge_msec_value(conf->upstream_config.connect_timeout,
                              prev->upstream_config.connect_timeout, 12000000);

    ngx_conf_merge_msec_value(conf->upstream_config.send_timeout,
                              prev->upstream_config.send_timeout, 12000000);

    ngx_conf_merge_msec_value(conf->upstream_config.read_timeout,
                              prev->upstream_config.read_timeout, 12000000);

    #if NGINX_VERSION_NUM >= 1007005
        ngx_conf_merge_msec_value(conf->upstream_config.next_upstream_timeout,
                                  prev->upstream_config.next_upstream_timeout, 0);
    #endif

    ngx_conf_merge_size_value(conf->upstream_config.send_lowat,
                              prev->upstream_config.send_lowat, 0);

    ngx_conf_merge_size_value(conf->upstream_config.buffer_size,
                              prev->upstream_config.buffer_size,
                              16 * 1024);

    #if NGINX_VERSION_NUM >= 1007007
        ngx_conf_merge_size_value(conf->upstream_config.limit_rate,
                                  prev->upstream_config.limit_rate, 0);
    #endif


    ngx_conf_merge_bufs_value(conf->upstream_config.bufs, prev->upstream_config.bufs,
                              8, 16 * 1024);

    if (conf->upstream_config.bufs.num < 2) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "there must be at least 2 \"passenger_buffers\"");
        return NGX_CONF_ERROR;
    }


    size = conf->upstream_config.buffer_size;
    if (size < conf->upstream_config.bufs.size) {
        size = conf->upstream_config.bufs.size;
    }


    ngx_conf_merge_size_value(conf->upstream_config.busy_buffers_size_conf,
                              prev->upstream_config.busy_buffers_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream_config.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream_config.busy_buffers_size = 2 * size;
    } else {
        conf->upstream_config.busy_buffers_size =
                                         conf->upstream_config.busy_buffers_size_conf;
    }

    if (conf->upstream_config.busy_buffers_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
             "\"passenger_busy_buffers_size\" must be equal to or greater "
             "than the maximum of the value of \"passenger_buffer_size\" and "
             "one of the \"passenger_buffers\"");

        return NGX_CONF_ERROR;
    }

    if (conf->upstream_config.busy_buffers_size
        > (conf->upstream_config.bufs.num - 1) * conf->upstream_config.bufs.size)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
             "\"passenger_busy_buffers_size\" must be less than "
             "the size of all \"passenger_buffers\" minus one buffer");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_size_value(conf->upstream_config.temp_file_write_size_conf,
                              prev->upstream_config.temp_file_write_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream_config.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream_config.temp_file_write_size = 2 * size;
    } else {
        conf->upstream_config.temp_file_write_size =
                                      conf->upstream_config.temp_file_write_size_conf;
    }

    if (conf->upstream_config.temp_file_write_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
             "\"passenger_temp_file_write_size\" must be equal to or greater than "
             "the maximum of the value of \"passenger_buffer_size\" and "
             "one of the \"passenger_buffers\"");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_size_value(conf->upstream_config.max_temp_file_size_conf,
                              prev->upstream_config.max_temp_file_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream_config.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream_config.max_temp_file_size = 1024 * 1024 * 1024;
    } else {
        conf->upstream_config.max_temp_file_size =
                                        conf->upstream_config.max_temp_file_size_conf;
    }

    if (conf->upstream_config.max_temp_file_size != 0
        && conf->upstream_config.max_temp_file_size < size)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
             "\"passenger_max_temp_file_size\" must be equal to zero to disable "
             "temporary files usage or must be equal to or greater than "
             "the maximum of the value of \"passenger_buffer_size\" and "
             "one of the \"passenger_buffers\"");

        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_bitmask_value(conf->upstream_config.ignore_headers,
                                 prev->upstream_config.ignore_headers,
                                 NGX_CONF_BITMASK_SET);

    ngx_conf_merge_bitmask_value(conf->upstream_config.next_upstream,
                              prev->upstream_config.next_upstream,
                              (NGX_CONF_BITMASK_SET
                               |NGX_HTTP_UPSTREAM_FT_ERROR
                               |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

    if (conf->upstream_config.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream_config.next_upstream = NGX_CONF_BITMASK_SET
                                       |NGX_HTTP_UPSTREAM_FT_OFF;
    }

    ngx_conf_merge_path_value(cf,
                              &conf->upstream_config.temp_path,
                              prev->upstream_config.temp_path,
                              &ngx_http_proxy_temp_path);

#if (NGX_HTTP_CACHE)

    #if NGINX_VERSION_NUM >= 1007009
        if (conf->upstream_config.cache == NGX_CONF_UNSET) {
           ngx_conf_merge_value(conf->upstream_config.cache,
                                prev->upstream_config.cache, 0);

           conf->upstream_config.cache_zone = prev->upstream_config.cache_zone;
           conf->upstream_config.cache_value = prev->upstream_config.cache_value;
        }

        if (conf->upstream_config.cache_zone && conf->upstream_config.cache_zone->data == NULL) {
            ngx_shm_zone_t  *shm_zone;

            shm_zone = conf->upstream_config.cache_zone;

            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "\"scgi_cache\" zone \"%V\" is unknown",
                               &shm_zone->shm.name);

            return NGX_CONF_ERROR;
        }
    #else
        ngx_conf_merge_ptr_value(conf->upstream_config.cache,
                                 prev->upstream_config.cache, NULL);

        if (conf->upstream_config.cache && conf->upstream_config.cache->data == NULL) {
            ngx_shm_zone_t  *shm_zone;

            shm_zone = conf->upstream_config.cache;

            ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                               "\"scgi_cache\" zone \"%V\" is unknown",
                               &shm_zone->shm.name);

            return NGX_CONF_ERROR;
        }
    #endif

    ngx_conf_merge_uint_value(conf->upstream_config.cache_min_uses,
                              prev->upstream_config.cache_min_uses, 1);

    ngx_conf_merge_bitmask_value(conf->upstream_config.cache_use_stale,
                              prev->upstream_config.cache_use_stale,
                              (NGX_CONF_BITMASK_SET
                               | NGX_HTTP_UPSTREAM_FT_OFF));

    if (conf->upstream_config.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream_config.cache_use_stale = NGX_CONF_BITMASK_SET
                                                | NGX_HTTP_UPSTREAM_FT_OFF;
    }

    if (conf->upstream_config.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
        conf->upstream_config.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
    }

    if (conf->upstream_config.cache_methods == 0) {
        conf->upstream_config.cache_methods = prev->upstream_config.cache_methods;
    }

    conf->upstream_config.cache_methods |= NGX_HTTP_GET | NGX_HTTP_HEAD;

    ngx_conf_merge_ptr_value(conf->upstream_config.cache_bypass,
                             prev->upstream_config.cache_bypass, NULL);

    ngx_conf_merge_ptr_value(conf->upstream_config.no_cache,
                             prev->upstream_config.no_cache, NULL);

    ngx_conf_merge_ptr_value(conf->upstream_config.cache_valid,
                             prev->upstream_config.cache_valid, NULL);

    if (conf->cache_key.value.data == NULL) {
        conf->cache_key = prev->cache_key;
    }

    ngx_conf_merge_value(conf->upstream_config.cache_lock,
                         prev->upstream_config.cache_lock, 0);

    ngx_conf_merge_msec_value(conf->upstream_config.cache_lock_timeout,
                              prev->upstream_config.cache_lock_timeout, 5000);

    ngx_conf_merge_value(conf->upstream_config.cache_revalidate,
                         prev->upstream_config.cache_revalidate, 0);

    #if NGINX_VERSION_NUM >= 1007008
        ngx_conf_merge_msec_value(conf->upstream_config.cache_lock_age,
                                  prev->upstream_config.cache_lock_age, 5000);
    #endif

    #if NGINX_VERSION_NUM >= 1006000
        ngx_conf_merge_value(conf->upstream_config.cache_revalidate,
                             prev->upstream_config.cache_revalidate, 0);
    #endif

#endif

    ngx_conf_merge_value(conf->upstream_config.pass_request_headers,
                         prev->upstream_config.pass_request_headers, 1);
    ngx_conf_merge_value(conf->upstream_config.pass_request_body,
                         prev->upstream_config.pass_request_body, 1);

    ngx_conf_merge_value(conf->upstream_config.intercept_errors,
                         prev->upstream_config.intercept_errors, 0);


    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "passenger_hide_headers_hash";

    if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream_config,
            &prev->upstream_config, headers_to_hide, &hash)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    if (conf->upstream_config.upstream == NULL) {
        conf->upstream_config.upstream = prev->upstream_config.upstream;
    }

    if (conf->enabled == 1 /* and not NGX_CONF_UNSET */
     && passenger_main_conf.root_dir.len != 0
     && clcf->handler == NULL /* no handler set by other modules */)
    {
        clcf->handler = passenger_content_handler;
    }

    conf->headers_hash_bucket_size = ngx_align(conf->headers_hash_bucket_size,
                                               ngx_cacheline_size);
    hash.max_size = conf->headers_hash_max_size;
    hash.bucket_size = conf->headers_hash_bucket_size;
    hash.name = "passenger_headers_hash";

    if (merge_headers(cf, conf, prev) != NGX_OK) {
        return NGX_CONF_ERROR;
    }

    if (cache_loc_conf_options(cf, conf) != NGX_OK) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "cannot create " PROGRAM_NAME " configuration cache");
        return NGX_CONF_ERROR;
    }

    return NGX_CONF_OK;
}
Пример #27
0
char *
passenger_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
{
    passenger_loc_conf_t         *prev = parent;
    passenger_loc_conf_t         *conf = child;

    u_char                       *p;
    size_t                        size;
    uintptr_t                    *code;
    ngx_uint_t                    i;
    ngx_str_t                    *prev_base_uris, *base_uri;
    ngx_str_t                    *prev_union_station_filters, *union_station_filter;
    ngx_keyval_t                 *src;
    ngx_hash_init_t               hash;
    ngx_http_script_compile_t     sc;
    ngx_http_script_copy_code_t  *copy;

    #include "MergeLocationConfig.c"
    if (prev->options_cache.data == NULL) {
        cache_loc_conf_options(cf, prev);
    }
    cache_loc_conf_options(cf, conf);
    
    if (prev->base_uris != NGX_CONF_UNSET_PTR) {
        if (conf->base_uris == NGX_CONF_UNSET_PTR) {
            conf->base_uris = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
            if (conf->base_uris == NULL) {
                return NGX_CONF_ERROR;
            }
        }
        
        prev_base_uris = (ngx_str_t *) prev->base_uris->elts;
        for (i = 0; i < prev->base_uris->nelts; i++) {
            base_uri = (ngx_str_t *) ngx_array_push(conf->base_uris);
            if (base_uri == NULL) {
                return NGX_CONF_ERROR;
            }
            *base_uri = prev_base_uris[i];
        }
    }
    
    if (prev->union_station_filters != NGX_CONF_UNSET_PTR) {
        if (conf->union_station_filters == NGX_CONF_UNSET_PTR) {
            conf->union_station_filters = ngx_array_create(cf->pool, 4, sizeof(ngx_str_t));
            if (conf->union_station_filters == NULL) {
                return NGX_CONF_ERROR;
            }
        }
        
        prev_union_station_filters = (ngx_str_t *) prev->union_station_filters->elts;
        for (i = 0; i < prev->union_station_filters->nelts; i++) {
            union_station_filter = (ngx_str_t *) ngx_array_push(conf->union_station_filters);
            if (union_station_filter == NULL) {
                return NGX_CONF_ERROR;
            }
            *union_station_filter = prev_union_station_filters[i];
        }
    }

    /******************************/
    /******************************/

    if (conf->upstream_config.store != 0) {
        ngx_conf_merge_value(conf->upstream_config.store,
                                  prev->upstream_config.store, 0);

        if (conf->upstream_config.store_lengths == NULL) {
            conf->upstream_config.store_lengths = prev->upstream_config.store_lengths;
            conf->upstream_config.store_values = prev->upstream_config.store_values;
        }
    }

    ngx_conf_merge_uint_value(conf->upstream_config.store_access,
                              prev->upstream_config.store_access, 0600);

    ngx_conf_merge_value(conf->upstream_config.buffering,
                         prev->upstream_config.buffering, 0);

    ngx_conf_merge_value(conf->upstream_config.ignore_client_abort,
                         prev->upstream_config.ignore_client_abort, 0);

    ngx_conf_merge_ptr_value(conf->upstream_config.local,
                             prev->upstream_config.local, NULL);

    ngx_conf_merge_msec_value(conf->upstream_config.connect_timeout,
                              prev->upstream_config.connect_timeout, 12000000);

    ngx_conf_merge_msec_value(conf->upstream_config.send_timeout,
                              prev->upstream_config.send_timeout, 12000000);

    ngx_conf_merge_msec_value(conf->upstream_config.read_timeout,
                              prev->upstream_config.read_timeout, 12000000);

    ngx_conf_merge_size_value(conf->upstream_config.send_lowat,
                              prev->upstream_config.send_lowat, 0);

    ngx_conf_merge_size_value(conf->upstream_config.buffer_size,
                              prev->upstream_config.buffer_size,
                              16 * 1024);


    ngx_conf_merge_bufs_value(conf->upstream_config.bufs, prev->upstream_config.bufs,
                              8, 16 * 1024);

    if (conf->upstream_config.bufs.num < 2) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "there must be at least 2 \"passenger_buffers\"");
        return NGX_CONF_ERROR;
    }


    size = conf->upstream_config.buffer_size;
    if (size < conf->upstream_config.bufs.size) {
        size = conf->upstream_config.bufs.size;
    }


    ngx_conf_merge_size_value(conf->upstream_config.busy_buffers_size_conf,
                              prev->upstream_config.busy_buffers_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream_config.busy_buffers_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream_config.busy_buffers_size = 2 * size;
    } else {
        conf->upstream_config.busy_buffers_size =
                                         conf->upstream_config.busy_buffers_size_conf;
    }

    if (conf->upstream_config.busy_buffers_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
             "\"passenger_busy_buffers_size\" must be equal to or greater "
             "than the maximum of the value of \"passenger_buffer_size\" and "
             "one of the \"passenger_buffers\"");

        return NGX_CONF_ERROR;
    }

    if (conf->upstream_config.busy_buffers_size
        > (conf->upstream_config.bufs.num - 1) * conf->upstream_config.bufs.size)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
             "\"passenger_busy_buffers_size\" must be less than "
             "the size of all \"passenger_buffers\" minus one buffer");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_size_value(conf->upstream_config.temp_file_write_size_conf,
                              prev->upstream_config.temp_file_write_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream_config.temp_file_write_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream_config.temp_file_write_size = 2 * size;
    } else {
        conf->upstream_config.temp_file_write_size =
                                      conf->upstream_config.temp_file_write_size_conf;
    }

    if (conf->upstream_config.temp_file_write_size < size) {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
             "\"passenger_temp_file_write_size\" must be equal to or greater than "
             "the maximum of the value of \"passenger_buffer_size\" and "
             "one of the \"passenger_buffers\"");

        return NGX_CONF_ERROR;
    }


    ngx_conf_merge_size_value(conf->upstream_config.max_temp_file_size_conf,
                              prev->upstream_config.max_temp_file_size_conf,
                              NGX_CONF_UNSET_SIZE);

    if (conf->upstream_config.max_temp_file_size_conf == NGX_CONF_UNSET_SIZE) {
        conf->upstream_config.max_temp_file_size = 1024 * 1024 * 1024;
    } else {
        conf->upstream_config.max_temp_file_size =
                                        conf->upstream_config.max_temp_file_size_conf;
    }

    if (conf->upstream_config.max_temp_file_size != 0
        && conf->upstream_config.max_temp_file_size < size)
    {
        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
             "\"passenger_max_temp_file_size\" must be equal to zero to disable "
             "temporary files usage or must be equal to or greater than "
             "the maximum of the value of \"passenger_buffer_size\" and "
             "one of the \"passenger_buffers\"");

        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_bitmask_value(conf->upstream_config.ignore_headers,
                                 prev->upstream_config.ignore_headers,
                                 NGX_CONF_BITMASK_SET);

    ngx_conf_merge_bitmask_value(conf->upstream_config.next_upstream,
                              prev->upstream_config.next_upstream,
                              (NGX_CONF_BITMASK_SET
                               |NGX_HTTP_UPSTREAM_FT_ERROR
                               |NGX_HTTP_UPSTREAM_FT_TIMEOUT));

    if (conf->upstream_config.next_upstream & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream_config.next_upstream = NGX_CONF_BITMASK_SET
                                       |NGX_HTTP_UPSTREAM_FT_OFF;
    }

    ngx_conf_merge_path_value(cf,
                              &conf->upstream_config.temp_path,
                              prev->upstream_config.temp_path,
                              &ngx_http_proxy_temp_path);

#if (NGX_HTTP_CACHE)

    ngx_conf_merge_ptr_value(conf->upstream_config.cache,
                             prev->upstream_config.cache, NULL);

    if (conf->upstream_config.cache && conf->upstream_config.cache->data == NULL) {
        ngx_shm_zone_t  *shm_zone;

        shm_zone = conf->upstream_config.cache;

        ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
                           "\"scgi_cache\" zone \"%V\" is unknown",
                           &shm_zone->shm.name);

        return NGX_CONF_ERROR;
    }

    ngx_conf_merge_uint_value(conf->upstream_config.cache_min_uses,
                              prev->upstream_config.cache_min_uses, 1);

    ngx_conf_merge_bitmask_value(conf->upstream_config.cache_use_stale,
                              prev->upstream_config.cache_use_stale,
                              (NGX_CONF_BITMASK_SET
                               | NGX_HTTP_UPSTREAM_FT_OFF));

    if (conf->upstream_config.cache_use_stale & NGX_HTTP_UPSTREAM_FT_OFF) {
        conf->upstream_config.cache_use_stale = NGX_CONF_BITMASK_SET
                                                | NGX_HTTP_UPSTREAM_FT_OFF;
    }

    if (conf->upstream_config.cache_use_stale & NGX_HTTP_UPSTREAM_FT_ERROR) {
        conf->upstream_config.cache_use_stale |= NGX_HTTP_UPSTREAM_FT_NOLIVE;
    }

    if (conf->upstream_config.cache_methods == 0) {
        conf->upstream_config.cache_methods = prev->upstream_config.cache_methods;
    }

    conf->upstream_config.cache_methods |= NGX_HTTP_GET | NGX_HTTP_HEAD;

    ngx_conf_merge_ptr_value(conf->upstream_config.cache_bypass,
                             prev->upstream_config.cache_bypass, NULL);

    ngx_conf_merge_ptr_value(conf->upstream_config.no_cache,
                             prev->upstream_config.no_cache, NULL);

    ngx_conf_merge_ptr_value(conf->upstream_config.cache_valid,
                             prev->upstream_config.cache_valid, NULL);

    if (conf->cache_key.value.data == NULL) {
        conf->cache_key = prev->cache_key;
    }

    #if NGINX_VERSION_NUM >= 1002000
    ngx_conf_merge_value(conf->upstream_config.cache_lock,
                         prev->upstream_config.cache_lock, 0);

    ngx_conf_merge_msec_value(conf->upstream_config.cache_lock_timeout,
                              prev->upstream_config.cache_lock_timeout, 5000);
    #endif

#endif

    ngx_conf_merge_value(conf->upstream_config.pass_request_headers,
                         prev->upstream_config.pass_request_headers, 1);
    ngx_conf_merge_value(conf->upstream_config.pass_request_body,
                         prev->upstream_config.pass_request_body, 1);

    ngx_conf_merge_value(conf->upstream_config.intercept_errors,
                         prev->upstream_config.intercept_errors, 0);


    hash.max_size = 512;
    hash.bucket_size = ngx_align(64, ngx_cacheline_size);
    hash.name = "passenger_hide_headers_hash";

    if (ngx_http_upstream_hide_headers_hash(cf, &conf->upstream_config,
            &prev->upstream_config, headers_to_hide, &hash)
        != NGX_OK)
    {
        return NGX_CONF_ERROR;
    }

    if (conf->upstream_config.upstream == NULL) {
        conf->upstream_config.upstream = prev->upstream_config.upstream;
    }

    if (conf->vars_source == NULL) {
        conf->flushes = prev->flushes;
        conf->vars_len = prev->vars_len;
        conf->vars = prev->vars;
        conf->vars_source = prev->vars_source;

        if (conf->vars_source == NULL) {
            return NGX_CONF_OK;
        }
    }

    conf->vars_len = ngx_array_create(cf->pool, 64, 1);
    if (conf->vars_len == NULL) {
        return NGX_CONF_ERROR;
    }

    conf->vars = ngx_array_create(cf->pool, 512, 1);
    if (conf->vars == NULL) {
        return NGX_CONF_ERROR;
    }

    src = conf->vars_source->elts;
    for (i = 0; i < conf->vars_source->nelts; i++) {

        if (ngx_http_script_variables_count(&src[i].value) == 0) {
            copy = ngx_array_push_n(conf->vars_len,
                                    sizeof(ngx_http_script_copy_code_t));
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = (ngx_http_script_code_pt)
                                                  ngx_http_script_copy_len_code;
            copy->len = src[i].key.len;


            copy = ngx_array_push_n(conf->vars_len,
                                    sizeof(ngx_http_script_copy_code_t));
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = (ngx_http_script_code_pt)
                                                 ngx_http_script_copy_len_code;
            copy->len = src[i].value.len;


            size = (sizeof(ngx_http_script_copy_code_t)
                       + src[i].key.len + src[i].value.len
                       + sizeof(uintptr_t) - 1)
                    & ~(sizeof(uintptr_t) - 1);

            copy = ngx_array_push_n(conf->vars, size);
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = ngx_http_script_copy_code;
            copy->len = src[i].key.len + src[i].value.len;

            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);

            p = ngx_cpymem(p, src[i].key.data, src[i].key.len);
            ngx_memcpy(p, src[i].value.data, src[i].value.len);

        } else {
            copy = ngx_array_push_n(conf->vars_len,
                                    sizeof(ngx_http_script_copy_code_t));
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = (ngx_http_script_code_pt)
                                                 ngx_http_script_copy_len_code;
            copy->len = src[i].key.len;


            size = (sizeof(ngx_http_script_copy_code_t)
                    + src[i].key.len + sizeof(uintptr_t) - 1)
                    & ~(sizeof(uintptr_t) - 1);

            copy = ngx_array_push_n(conf->vars, size);
            if (copy == NULL) {
                return NGX_CONF_ERROR;
            }

            copy->code = ngx_http_script_copy_code;
            copy->len = src[i].key.len;

            p = (u_char *) copy + sizeof(ngx_http_script_copy_code_t);
            ngx_memcpy(p, src[i].key.data, src[i].key.len);


            ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));

            sc.cf = cf;
            sc.source = &src[i].value;
            sc.flushes = &conf->flushes;
            sc.lengths = &conf->vars_len;
            sc.values = &conf->vars;

            if (ngx_http_script_compile(&sc) != NGX_OK) {
                return NGX_CONF_ERROR;
            }
        }

        code = ngx_array_push_n(conf->vars_len, sizeof(uintptr_t));
        if (code == NULL) {
            return NGX_CONF_ERROR;
        }

        *code = (uintptr_t) NULL;


        code = ngx_array_push_n(conf->vars, sizeof(uintptr_t));
        if (code == NULL) {
            return NGX_CONF_ERROR;
        }

        *code = (uintptr_t) NULL;
    }

    code = ngx_array_push_n(conf->vars_len, sizeof(uintptr_t));
    if (code == NULL) {
        return NGX_CONF_ERROR;
    }

    *code = (uintptr_t) NULL;

    return NGX_CONF_OK;
}
static ngx_int_t
ngx_http_replace_header_filter(ngx_http_request_t *r)
{
    size_t                         size;
    ngx_str_t                      skip;
    ngx_pool_cleanup_t            *cln;
    ngx_http_replace_ctx_t        *ctx;
    ngx_http_replace_loc_conf_t  *rlcf;

    rlcf = ngx_http_get_module_loc_conf(r, ngx_http_replace_filter_module);

    dd("replace header filter");

    if (rlcf->regexes.nelts == 0
        || r->headers_out.content_length_n == 0
        || (r->headers_out.content_encoding
            && r->headers_out.content_encoding->value.len)
        || ngx_http_test_content_type(r, &rlcf->types) == NULL)
    {
        return ngx_http_next_header_filter(r);
    }

    dd("skip: %p", rlcf->skip);

    if (rlcf->skip != NULL) {
        if (ngx_http_complex_value(r, rlcf->skip, &skip) != NGX_OK) {
            return NGX_ERROR;
        }

        if (skip.len && (skip.len != 1 || skip.data[0] != '0')) {
            return ngx_http_next_header_filter(r);
        }
    }

    ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_replace_ctx_t));
    if (ctx == NULL) {
        return NGX_ERROR;
    }

    ctx->last_special = &ctx->special;
    ctx->last_pending = &ctx->pending;
    ctx->last_pending2 = &ctx->pending2;
    ctx->last_captured = &ctx->captured;

    ctx->sub = ngx_pcalloc(r->pool,
                           rlcf->multi_replace.nelts * sizeof(ngx_str_t));
    if (ctx->sub == NULL) {
        return NGX_ERROR;
    }

    ctx->ovector = ngx_palloc(r->pool, rlcf->ovecsize);
    if (ctx->ovector == NULL) {
        return NGX_ERROR;
    }

    size = ngx_align(rlcf->regexes.nelts, 8) / 8;
    ctx->disabled = ngx_pcalloc(r->pool, size);
    if (ctx->disabled == NULL) {
        return NGX_ERROR;
    }

    ctx->vm_pool = sre_create_pool(1024);
    if (ctx->vm_pool == NULL) {
        return NGX_ERROR;
    }

    dd("created vm pool %p", ctx->vm_pool);

    cln = ngx_pool_cleanup_add(r->pool, 0);
    if (cln == NULL) {
        sre_destroy_pool(ctx->vm_pool);
        return NGX_ERROR;
    }

    cln->data = ctx->vm_pool;
    cln->handler = ngx_http_replace_cleanup_pool;

    ctx->vm_ctx = sre_vm_pike_create_ctx(ctx->vm_pool, rlcf->program,
                                         ctx->ovector, rlcf->ovecsize);
    if (ctx->vm_ctx == NULL) {
        return NGX_ERROR;
    }

    ngx_http_set_ctx(r, ctx, ngx_http_replace_filter_module);

    ctx->last_out = &ctx->out;

    r->filter_need_in_memory = 1;

    if (r == r->main) {
        ngx_http_clear_content_length(r);

        if (rlcf->last_modified == NGX_HTTP_REPLACE_CLEAR_LAST_MODIFIED) {
            ngx_http_clear_last_modified(r);
        }
    }

    return ngx_http_next_header_filter(r);
}
Пример #29
0
static char *
ngx_http_map_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
    ngx_http_map_conf_t  *mcf = conf;

    char                      *rv;
    ngx_str_t                 *value, name;
    ngx_conf_t                 save;
    ngx_pool_t                *pool;
    ngx_hash_init_t            hash;
    ngx_http_map_ctx_t        *map;
    ngx_http_variable_t       *var;
    ngx_http_map_conf_ctx_t    ctx;

    if (mcf->hash_max_size == NGX_CONF_UNSET_UINT) {
        mcf->hash_max_size = 2048;
    }

    if (mcf->hash_bucket_size == NGX_CONF_UNSET_UINT) {
        mcf->hash_bucket_size = ngx_cacheline_size;

    } else {
        mcf->hash_bucket_size = ngx_align(mcf->hash_bucket_size,
                                          ngx_cacheline_size);
    }

    map = ngx_pcalloc(cf->pool, sizeof(ngx_http_map_ctx_t));
    if (map == NULL) {
        return NGX_CONF_ERROR;
    }

    value = cf->args->elts;

    name = value[1];
    name.len--;
    name.data++;

    map->index = ngx_http_get_variable_index(cf, &name);

    if (map->index == NGX_ERROR) {
        return NGX_CONF_ERROR;
    }

    name = value[2];
    name.len--;
    name.data++;

    var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
    if (var == NULL) {
        return NGX_CONF_ERROR;
    }

    var->get_handler = ngx_http_map_variable;
    var->data = (uintptr_t) map;

    pool = ngx_create_pool(16384, cf->log);
    if (pool == NULL) {
        return NGX_CONF_ERROR;
    }

    ctx.keys.pool = cf->pool;
    ctx.keys.temp_pool = pool;

    if (ngx_hash_keys_array_init(&ctx.keys, NGX_HASH_LARGE) != NGX_OK) {
        ngx_destroy_pool(pool);
        return NGX_CONF_ERROR;
    }

    ctx.values_hash = ngx_pcalloc(pool, sizeof(ngx_array_t) * ctx.keys.hsize);
    if (ctx.values_hash == NULL) {
        ngx_destroy_pool(pool);
        return NGX_CONF_ERROR;
    }

    ctx.default_value = NULL;
    ctx.hostnames = 0;

    save = *cf;
    cf->pool = pool;
    cf->ctx = &ctx;
    cf->handler = ngx_http_map;
    cf->handler_conf = conf;

    rv = ngx_conf_parse(cf, NULL);

    *cf = save;

    if (rv != NGX_CONF_OK) {
        ngx_destroy_pool(pool);
        return rv;
    }

    map->default_value = ctx.default_value ? ctx.default_value:
                                             &ngx_http_variable_null_value;

    hash.key = ngx_hash_key_lc;
    hash.max_size = mcf->hash_max_size;
    hash.bucket_size = mcf->hash_bucket_size;
    hash.name = "map_hash";
    hash.pool = cf->pool;

    if (ctx.keys.keys.nelts) {
        hash.hash = &map->hash.hash;
        hash.temp_pool = NULL;

        if (ngx_hash_init(&hash, ctx.keys.keys.elts, ctx.keys.keys.nelts)
            != NGX_OK)
        {
            ngx_destroy_pool(pool);
            return NGX_CONF_ERROR;
        }
    }

    if (ctx.keys.dns_wc_head.nelts) {

        ngx_qsort(ctx.keys.dns_wc_head.elts,
                  (size_t) ctx.keys.dns_wc_head.nelts,
                  sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);

        hash.hash = NULL;
        hash.temp_pool = pool;

        if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_head.elts,
                                   ctx.keys.dns_wc_head.nelts)
            != NGX_OK)
        {
            ngx_destroy_pool(pool);
            return NGX_CONF_ERROR;
        }

        map->hash.wc_head = (ngx_hash_wildcard_t *) hash.hash;
    }

    if (ctx.keys.dns_wc_tail.nelts) {

        ngx_qsort(ctx.keys.dns_wc_tail.elts,
                  (size_t) ctx.keys.dns_wc_tail.nelts,
                  sizeof(ngx_hash_key_t), ngx_http_map_cmp_dns_wildcards);

        hash.hash = NULL;
        hash.temp_pool = pool;

        if (ngx_hash_wildcard_init(&hash, ctx.keys.dns_wc_tail.elts,
                                   ctx.keys.dns_wc_tail.nelts)
            != NGX_OK)
        {
            ngx_destroy_pool(pool);
            return NGX_CONF_ERROR;
        }

        map->hash.wc_tail = (ngx_hash_wildcard_t *) hash.hash;
    }

    ngx_destroy_pool(pool);

    return rv;
}
ngx_int_t
ngx_http_upstream_check_status_handler(ngx_http_request_t *r)
{
    size_t                          buffer_size;
    ngx_int_t                       rc;
    ngx_buf_t                      *b;
    ngx_uint_t                      i, last;
    ngx_chain_t                     out;
    ngx_http_check_peer_t          *peer;
    ngx_http_check_peers_t         *peers;
    ngx_http_check_peer_shm_t      *peer_shm;
    ngx_http_check_peers_shm_t     *peers_shm;

    if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) {
        return NGX_HTTP_NOT_ALLOWED;
    }

    rc = ngx_http_discard_request_body(r);

    if (rc != NGX_OK) {
        return rc;
    }

    r->headers_out.content_type.len = sizeof("text/javascript") - 1;
    r->headers_out.content_type.data = (u_char *) "text/javascript";

    if (r->method == NGX_HTTP_HEAD) {
        r->headers_out.status = NGX_HTTP_OK;

        rc = ngx_http_send_header(r);

        if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
            return rc;
        }
    }

    peers = check_peers_ctx;
    if (peers == NULL) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "[http upstream check] can not find the check servers, "
                      "have you added the check servers? ");

        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    peers_shm = peers->peers_shm;

    peer = peers->peers.elts;
    peer_shm = peers_shm->peers;

    buffer_size = peers->peers.nelts * ngx_pagesize / 4;
    buffer_size = ngx_align(buffer_size, ngx_pagesize) + ngx_pagesize;

    b = ngx_create_temp_buf(r->pool, buffer_size);
    if (b == NULL) {
        return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }

    out.buf = b;
    out.next = NULL;
    last = peers->peers.nelts - 1;
    
    b->last = ngx_snprintf(b->last, b->end - b->last,
            "{\"servers\": {\n"
            "  \"total\": %ui,\n"
            "  \"generation\": %ui,\n"
            "  \"server\": [\n",
            peers->peers.nelts,
            ngx_http_check_shm_generation);


    for (i = 0; i < peers->peers.nelts; i++) {
        b->last = ngx_snprintf(b->last, b->end - b->last,
                "    {\"index\": %ui, "
                "\"upstream\": \"%V\", "
                "\"name\": \"%V\", "
                "\"status\": \"%s\", "
                "\"rise\": %ui, "
                "\"fall\": %ui, "
                "\"type\": \"%s\" }"
		"%s\n",                
                i,
                peer[i].upstream_name,
                &peer[i].peer_addr->name,
                peer_shm[i].down ? "down" : "up",
                peer_shm[i].rise_count,
                peer_shm[i].fall_count,
                peer[i].conf->check_type_conf->name,
		(i == last) ? "" : ",");
    }

    b->last = ngx_snprintf(b->last, b->end - b->last,
            "  ]\n");

    b->last = ngx_snprintf(b->last, b->end - b->last,
            "}}\n");

    r->headers_out.status = NGX_HTTP_OK;
    r->headers_out.content_length_n = b->last - b->pos;

    b->last_buf = 1;

    rc = ngx_http_send_header(r);

    if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) {
        return rc;
    }

    return ngx_http_output_filter(r, &out);
}