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;