Mercurial > hg > nginx
comparison src/http/modules/ngx_http_geo_module.c @ 2334:6e30d64f919b
use value rbtree instead of array in geo configuration
author | Igor Sysoev <igor@sysoev.ru> |
---|---|
date | Sat, 22 Nov 2008 20:42:51 +0000 |
parents | 4c43e25d11ea |
children | 22d2b6609853 |
comparison
equal
deleted
inserted
replaced
2333:f267d23868fc | 2334:6e30d64f919b |
---|---|
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 #include <ngx_http.h> | 9 #include <ngx_http.h> |
10 | 10 |
11 | 11 |
12 typedef struct { | 12 typedef struct { |
13 ngx_radix_tree_t *tree; | 13 ngx_radix_tree_t *tree; |
14 ngx_pool_t *pool; | 14 ngx_rbtree_t rbtree; |
15 ngx_array_t values; | 15 ngx_rbtree_node_t sentinel; |
16 ngx_pool_t *pool; | |
16 } ngx_http_geo_conf_ctx_t; | 17 } ngx_http_geo_conf_ctx_t; |
17 | 18 |
18 | 19 |
19 static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); | 20 static char *ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); |
20 static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); | 21 static char *ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf); |
133 pool = ngx_create_pool(16384, cf->log); | 134 pool = ngx_create_pool(16384, cf->log); |
134 if (pool == NULL) { | 135 if (pool == NULL) { |
135 return NGX_CONF_ERROR; | 136 return NGX_CONF_ERROR; |
136 } | 137 } |
137 | 138 |
138 if (ngx_array_init(&ctx.values, pool, 512, | 139 ngx_rbtree_init(&ctx.rbtree, &ctx.sentinel, |
139 sizeof(ngx_http_variable_value_t *)) | 140 ngx_http_variable_value_rbtree_insert); |
140 != NGX_OK) | |
141 { | |
142 ngx_destroy_pool(pool); | |
143 return NGX_CONF_ERROR; | |
144 } | |
145 | 141 |
146 ctx.tree = tree; | 142 ctx.tree = tree; |
147 ctx.pool = cf->pool; | 143 ctx.pool = cf->pool; |
148 | 144 |
149 save = *cf; | 145 save = *cf; |
176 /* AF_INET only */ | 172 /* AF_INET only */ |
177 | 173 |
178 static char * | 174 static char * |
179 ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) | 175 ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf) |
180 { | 176 { |
181 ngx_int_t rc; | 177 uint32_t hash; |
182 ngx_str_t *value, file; | 178 ngx_int_t rc; |
183 ngx_uint_t i; | 179 ngx_str_t *value, file; |
184 ngx_inet_cidr_t cidrin; | 180 ngx_uint_t i; |
185 ngx_http_geo_conf_ctx_t *ctx; | 181 ngx_inet_cidr_t cidrin; |
186 ngx_http_variable_value_t *var, *old, **v; | 182 ngx_http_geo_conf_ctx_t *ctx; |
183 ngx_http_variable_value_t *val, *old; | |
184 ngx_http_variable_value_node_t *vvn; | |
187 | 185 |
188 ctx = cf->ctx; | 186 ctx = cf->ctx; |
189 | 187 |
190 if (cf->args->nelts != 2) { | 188 if (cf->args->nelts != 2) { |
191 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | 189 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, |
228 | 226 |
229 cidrin.addr = ntohl(cidrin.addr); | 227 cidrin.addr = ntohl(cidrin.addr); |
230 cidrin.mask = ntohl(cidrin.mask); | 228 cidrin.mask = ntohl(cidrin.mask); |
231 } | 229 } |
232 | 230 |
233 var = NULL; | 231 hash = ngx_crc32_long(value[1].data, value[1].len); |
234 v = ctx->values.elts; | 232 |
235 | 233 val = ngx_http_variable_value_lookup(&ctx->rbtree, &value[1], hash); |
236 for (i = 0; i < ctx->values.nelts; i++) { | 234 |
237 if ((size_t) v[i]->len != value[1].len) { | 235 if (val == NULL) { |
238 continue; | 236 val = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t)); |
239 } | 237 if (val == NULL) { |
240 | 238 return NGX_CONF_ERROR; |
241 if (ngx_strncmp(value[1].data, v[i]->data, value[1].len) == 0) { | 239 } |
242 var = v[i]; | 240 |
243 break; | 241 val->len = value[1].len; |
244 } | 242 val->data = ngx_pstrdup(ctx->pool, &value[1]); |
245 } | 243 if (val->data == NULL) { |
246 | 244 return NGX_CONF_ERROR; |
247 if (var == NULL) { | 245 } |
248 var = ngx_palloc(ctx->pool, sizeof(ngx_http_variable_value_t)); | 246 |
249 if (var == NULL) { | 247 val->valid = 1; |
250 return NGX_CONF_ERROR; | 248 val->no_cacheable = 0; |
251 } | 249 val->not_found = 0; |
252 | 250 |
253 var->len = value[1].len; | 251 vvn = ngx_palloc(cf->pool, sizeof(ngx_http_variable_value_node_t)); |
254 var->data = ngx_pstrdup(ctx->pool, &value[1]); | 252 if (vvn == NULL) { |
255 if (var->data == NULL) { | 253 return NGX_CONF_ERROR; |
256 return NGX_CONF_ERROR; | 254 } |
257 } | 255 |
258 | 256 vvn->node.key = hash; |
259 var->valid = 1; | 257 vvn->len = val->len; |
260 var->no_cacheable = 0; | 258 vvn->value = val; |
261 var->not_found = 0; | 259 |
262 | 260 ngx_rbtree_insert(&ctx->rbtree, &vvn->node); |
263 v = ngx_array_push(&ctx->values); | |
264 if (v == NULL) { | |
265 return NGX_CONF_ERROR; | |
266 } | |
267 | |
268 *v = var; | |
269 } | 261 } |
270 | 262 |
271 for (i = 2; i; i--) { | 263 for (i = 2; i; i--) { |
272 rc = ngx_radix32tree_insert(ctx->tree, cidrin.addr, cidrin.mask, | 264 rc = ngx_radix32tree_insert(ctx->tree, cidrin.addr, cidrin.mask, |
273 (uintptr_t) var); | 265 (uintptr_t) val); |
274 if (rc == NGX_OK) { | 266 if (rc == NGX_OK) { |
275 return NGX_CONF_OK; | 267 return NGX_CONF_OK; |
276 } | 268 } |
277 | 269 |
278 if (rc == NGX_ERROR) { | 270 if (rc == NGX_ERROR) { |
284 old = (ngx_http_variable_value_t *) | 276 old = (ngx_http_variable_value_t *) |
285 ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask); | 277 ngx_radix32tree_find(ctx->tree, cidrin.addr & cidrin.mask); |
286 | 278 |
287 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | 279 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, |
288 "duplicate parameter \"%V\", value: \"%v\", old value: \"%v\"", | 280 "duplicate parameter \"%V\", value: \"%v\", old value: \"%v\"", |
289 &value[0], var, old); | 281 &value[0], val, old); |
290 | 282 |
291 rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask); | 283 rc = ngx_radix32tree_delete(ctx->tree, cidrin.addr, cidrin.mask); |
292 | 284 |
293 if (rc == NGX_ERROR) { | 285 if (rc == NGX_ERROR) { |
294 return NGX_CONF_ERROR; | 286 return NGX_CONF_ERROR; |