comparison src/http/modules/ngx_http_geo_module.c @ 3645:9f22c780d574

eliminate a number of ranges: about 18,000 /16 networks are empty, this change saves about 70K/140K on 32/64-bit platforms
author Igor Sysoev <igor@sysoev.ru>
date Thu, 24 Jun 2010 15:26:05 +0000
parents 762712d69672
children c12b0dd5bd1c
comparison
equal deleted inserted replaced
3644:5d3282cfc43c 3645:9f22c780d574
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_http_variable_value_t *value;
13 u_short start; 14 u_short start;
14 u_short end; 15 u_short end;
15 ngx_http_variable_value_t *value;
16 } ngx_http_geo_range_t; 16 } ngx_http_geo_range_t;
17 17
18 18
19 typedef struct { 19 typedef struct {
20 ngx_http_geo_range_t *ranges; 20 ngx_http_geo_range_t *low[0x10000];
21 ngx_uint_t n;
22 } ngx_http_geo_low_ranges_t;
23
24
25 typedef struct {
26 ngx_http_geo_low_ranges_t low[0x10000];
27 ngx_http_variable_value_t *default_value; 21 ngx_http_variable_value_t *default_value;
28 } ngx_http_geo_high_ranges_t; 22 } ngx_http_geo_high_ranges_t;
29 23
30 24
31 typedef struct { 25 typedef struct {
152 uintptr_t data) 146 uintptr_t data)
153 { 147 {
154 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data; 148 ngx_http_geo_ctx_t *ctx = (ngx_http_geo_ctx_t *) data;
155 149
156 in_addr_t addr; 150 in_addr_t addr;
157 ngx_uint_t i, n; 151 ngx_uint_t n;
158 ngx_http_geo_range_t *range; 152 ngx_http_geo_range_t *range;
159 153
160 *v = *ctx->u.high->default_value; 154 *v = *ctx->u.high->default_value;
161 155
162 addr = ngx_http_geo_addr(r, ctx); 156 addr = ngx_http_geo_addr(r, ctx);
163 157
164 range = ctx->u.high->low[addr >> 16].ranges; 158 range = ctx->u.high->low[addr >> 16];
165 159
166 n = addr & 0xffff; 160 if (range) {
167 161 n = addr & 0xffff;
168 for (i = 0; i < ctx->u.high->low[addr >> 16].n; i++) { 162 do {
169 if (n >= (ngx_uint_t) range[i].start && n <= (ngx_uint_t) range[i].end) 163 if (n >= (ngx_uint_t) range->start && n <= (ngx_uint_t) range->end)
170 { 164 {
171 *v = *range[i].value; 165 *v = *range->value;
172 break; 166 break;
173 } 167 }
168 } while ((++range)->value);
174 } 169 }
175 170
176 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, 171 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
177 "http geo: %v", v); 172 "http geo: %v", v);
178 173
260 255
261 static char * 256 static char *
262 ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 257 ngx_http_geo_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
263 { 258 {
264 char *rv; 259 char *rv;
260 void **p;
265 size_t len; 261 size_t len;
266 ngx_str_t *value, name; 262 ngx_str_t *value, name;
267 ngx_uint_t i; 263 ngx_uint_t i;
268 ngx_conf_t save; 264 ngx_conf_t save;
269 ngx_pool_t *pool; 265 ngx_pool_t *pool;
333 geo->proxies = ctx.proxies; 329 geo->proxies = ctx.proxies;
334 330
335 if (ctx.high) { 331 if (ctx.high) {
336 332
337 for (i = 0; i < 0x10000; i++) { 333 for (i = 0; i < 0x10000; i++) {
338 a = (ngx_array_t *) ctx.high->low[i].ranges; 334 a = (ngx_array_t *) ctx.high->low[i];
339 335
340 if (a == NULL || a->nelts == 0) { 336 if (a == NULL || a->nelts == 0) {
341 continue; 337 continue;
342 } 338 }
343 339
344 ctx.high->low[i].n = a->nelts;
345
346 len = a->nelts * sizeof(ngx_http_geo_range_t); 340 len = a->nelts * sizeof(ngx_http_geo_range_t);
347 341
348 ctx.high->low[i].ranges = ngx_palloc(cf->pool, len); 342 ctx.high->low[i] = ngx_palloc(cf->pool, len + sizeof(void *));
349 if (ctx.high->low[i].ranges == NULL) { 343 if (ctx.high->low[i] == NULL) {
350 return NGX_CONF_ERROR; 344 return NGX_CONF_ERROR;
351 } 345 }
352 346
353 ngx_memcpy(ctx.high->low[i].ranges, a->elts, len); 347 p = (void **) ngx_cpymem(ctx.high->low[i], a->elts, len);
348 *p = NULL;
354 } 349 }
355 350
356 geo->u.high = ctx.high; 351 geo->u.high = ctx.high;
357 352
358 var->get_handler = ngx_http_geo_range_variable; 353 var->get_handler = ngx_http_geo_range_variable;
609 604
610 } else { 605 } else {
611 e = 0xffff; 606 e = 0xffff;
612 } 607 }
613 608
614 a = (ngx_array_t *) ctx->high->low[h].ranges; 609 a = (ngx_array_t *) ctx->high->low[h];
615 610
616 if (a == NULL) { 611 if (a == NULL) {
617 a = ngx_array_create(ctx->temp_pool, 64, 612 a = ngx_array_create(ctx->temp_pool, 64,
618 sizeof(ngx_http_geo_range_t)); 613 sizeof(ngx_http_geo_range_t));
619 if (a == NULL) { 614 if (a == NULL) {
620 return NGX_CONF_ERROR; 615 return NGX_CONF_ERROR;
621 } 616 }
622 617
623 ctx->high->low[h].ranges = (ngx_http_geo_range_t *) a; 618 ctx->high->low[h] = (ngx_http_geo_range_t *) a;
624 } 619 }
625 620
626 i = a->nelts; 621 i = a->nelts;
627 range = a->elts; 622 range = a->elts;
628 623
806 801
807 } else { 802 } else {
808 e = 0xffff; 803 e = 0xffff;
809 } 804 }
810 805
811 a = (ngx_array_t *) ctx->high->low[h].ranges; 806 a = (ngx_array_t *) ctx->high->low[h];
812 807
813 if (a == NULL) { 808 if (a == NULL) {
814 warn = 1; 809 warn = 1;
815 continue; 810 continue;
816 } 811 }