//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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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); }
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); }