#ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_set_hashed_upstream.h" ngx_uint_t ngx_http_set_misc_apply_distribution(ngx_log_t *log, ngx_uint_t hash, ndk_upstream_list_t *ul, ngx_http_set_misc_distribution_t type) { switch (type) { case ngx_http_set_misc_distribution_modula: return (uint32_t) hash % (uint32_t) ul->nelts; default: ngx_log_error(NGX_LOG_ERR, log, 0, "apply_distribution: " "unknown distribution: %d", type); return 0; } /* impossible to reach here */ } ngx_int_t ngx_http_set_misc_set_hashed_upstream(ngx_http_request_t *r, ngx_str_t *res, ngx_http_variable_value_t *v, void *data) { ngx_str_t **u; ndk_upstream_list_t *ul = data; ngx_str_t ulname; ngx_uint_t hash, index; ngx_http_variable_value_t *key; if (ul == NULL) { ulname.data = v->data; ulname.len = v->len; dd("ulname: %.*s", (int) ulname.len, ulname.data); ul = ndk_get_upstream_list(ndk_http_get_main_conf(r), ulname.data, ulname.len); if (ul == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "set_hashed_upstream: upstream list \"%V\" " "not defined yet", &ulname); return NGX_ERROR; } key = v + 1; } else { key = v; } if (ul->nelts == 0) { res->data = NULL; res->len = 0; return NGX_OK; } u = ul->elts; dd("upstream list: %d upstreams found", (int) ul->nelts); if (ul->nelts == 1) { dd("only one upstream found in the list"); res->data = u[0]->data; res->len = u[0]->len; return NGX_OK; } dd("key: \"%.*s\"", key->len, key->data); hash = ngx_hash_key_lc(key->data, key->len); index = ngx_http_set_misc_apply_distribution(r->connection->log, hash, ul, ngx_http_set_misc_distribution_modula); res->data = u[index]->data; res->len = u[index]->len; return NGX_OK; } char * ngx_http_set_hashed_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_str_t *value; ndk_set_var_t filter; ngx_uint_t n; ngx_str_t *var; ngx_str_t *ulname; ndk_upstream_list_t *ul; ngx_str_t *v; value = cf->args->elts; var = &value[1]; ulname = &value[2]; n = ngx_http_script_variables_count(ulname); filter.func = (void *) ngx_http_set_misc_set_hashed_upstream; if (n) { /* upstream list name contains variables */ v = &value[2]; filter.size = 2; filter.data = NULL; filter.type = NDK_SET_VAR_MULTI_VALUE_DATA; return ndk_set_var_multi_value_core(cf, var, v, &filter); } ul = ndk_get_upstream_list(ndk_http_conf_get_main_conf(cf), ulname->data, ulname->len); if (ul == NULL) { ngx_log_error(NGX_LOG_ERR, cf->log, 0, "set_hashed_upstream: upstream list \"%V\" " "not defined yet", ulname); return NGX_CONF_ERROR; } v = &value[3]; filter.size = 1; filter.data = ul; filter.type = NDK_SET_VAR_VALUE_DATA; return ndk_set_var_value_core(cf, var, v, &filter); }