Mercurial > hg > nginx
comparison src/core/ngx_regex.c @ 4388:005fc2d5e84f
Added support for regex study and PCRE JIT (ticket #41) optimizations on
configuration phase.
author | Valentin Bartenev <vbart@nginx.com> |
---|---|
date | Mon, 26 Dec 2011 13:10:36 +0000 |
parents | 7423800ef437 |
children | d620f497c50f |
comparison
equal
deleted
inserted
replaced
4387:e8181eeddaf8 | 4388:005fc2d5e84f |
---|---|
6 | 6 |
7 #include <ngx_config.h> | 7 #include <ngx_config.h> |
8 #include <ngx_core.h> | 8 #include <ngx_core.h> |
9 | 9 |
10 | 10 |
11 typedef struct { | |
12 ngx_flag_t pcre_jit; | |
13 } ngx_regex_conf_t; | |
14 | |
15 | |
11 static void * ngx_libc_cdecl ngx_regex_malloc(size_t size); | 16 static void * ngx_libc_cdecl ngx_regex_malloc(size_t size); |
12 static void ngx_libc_cdecl ngx_regex_free(void *p); | 17 static void ngx_libc_cdecl ngx_regex_free(void *p); |
13 | 18 |
19 static ngx_int_t ngx_regex_module_init(ngx_cycle_t *cycle); | |
20 | |
21 static void *ngx_regex_create_conf(ngx_cycle_t *cycle); | |
22 static char *ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf); | |
23 | |
24 static char *ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data); | |
25 static ngx_conf_post_t ngx_regex_pcre_jit_post = { ngx_regex_pcre_jit }; | |
26 | |
27 | |
28 static ngx_command_t ngx_regex_commands[] = { | |
29 | |
30 { ngx_string("pcre_jit"), | |
31 NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, | |
32 ngx_conf_set_flag_slot, | |
33 0, | |
34 offsetof(ngx_regex_conf_t, pcre_jit), | |
35 &ngx_regex_pcre_jit_post }, | |
36 | |
37 ngx_null_command | |
38 }; | |
39 | |
40 | |
41 static ngx_core_module_t ngx_regex_module_ctx = { | |
42 ngx_string("regex"), | |
43 ngx_regex_create_conf, | |
44 ngx_regex_init_conf | |
45 }; | |
46 | |
47 | |
48 ngx_module_t ngx_regex_module = { | |
49 NGX_MODULE_V1, | |
50 &ngx_regex_module_ctx, /* module context */ | |
51 ngx_regex_commands, /* module directives */ | |
52 NGX_CORE_MODULE, /* module type */ | |
53 NULL, /* init master */ | |
54 ngx_regex_module_init, /* init module */ | |
55 NULL, /* init process */ | |
56 NULL, /* init thread */ | |
57 NULL, /* exit thread */ | |
58 NULL, /* exit process */ | |
59 NULL, /* exit master */ | |
60 NGX_MODULE_V1_PADDING | |
61 }; | |
62 | |
14 | 63 |
15 static ngx_pool_t *ngx_pcre_pool; | 64 static ngx_pool_t *ngx_pcre_pool; |
65 static ngx_list_t *ngx_pcre_studies; | |
16 | 66 |
17 | 67 |
18 void | 68 void |
19 ngx_regex_init(void) | 69 ngx_regex_init(void) |
20 { | 70 { |
60 | 110 |
61 | 111 |
62 ngx_int_t | 112 ngx_int_t |
63 ngx_regex_compile(ngx_regex_compile_t *rc) | 113 ngx_regex_compile(ngx_regex_compile_t *rc) |
64 { | 114 { |
65 int n, erroff; | 115 int n, erroff; |
66 char *p; | 116 char *p; |
67 const char *errstr; | 117 pcre *re; |
68 ngx_regex_t *re; | 118 const char *errstr; |
119 ngx_regex_elt_t *elt; | |
69 | 120 |
70 ngx_regex_malloc_init(rc->pool); | 121 ngx_regex_malloc_init(rc->pool); |
71 | 122 |
72 re = pcre_compile((const char *) rc->pattern.data, (int) rc->options, | 123 re = pcre_compile((const char *) rc->pattern.data, (int) rc->options, |
73 &errstr, &erroff, NULL); | 124 &errstr, &erroff, NULL); |
90 } | 141 } |
91 | 142 |
92 return NGX_ERROR; | 143 return NGX_ERROR; |
93 } | 144 } |
94 | 145 |
95 rc->regex = re; | 146 rc->regex = ngx_pcalloc(rc->pool, sizeof(ngx_regex_t)); |
147 if (rc->regex == NULL) { | |
148 return NGX_ERROR; | |
149 } | |
150 | |
151 rc->regex->pcre = re; | |
152 | |
153 /* do not study at runtime */ | |
154 | |
155 if (ngx_pcre_studies != NULL) { | |
156 elt = ngx_list_push(ngx_pcre_studies); | |
157 if (elt == NULL) { | |
158 return NGX_ERROR; | |
159 } | |
160 | |
161 elt->regex = rc->regex; | |
162 elt->name = rc->pattern.data; | |
163 } | |
96 | 164 |
97 n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures); | 165 n = pcre_fullinfo(re, NULL, PCRE_INFO_CAPTURECOUNT, &rc->captures); |
98 if (n < 0) { | 166 if (n < 0) { |
99 p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d"; | 167 p = "pcre_fullinfo(\"%V\", PCRE_INFO_CAPTURECOUNT) failed: %d"; |
100 goto failed; | 168 goto failed; |
201 static void ngx_libc_cdecl | 269 static void ngx_libc_cdecl |
202 ngx_regex_free(void *p) | 270 ngx_regex_free(void *p) |
203 { | 271 { |
204 return; | 272 return; |
205 } | 273 } |
274 | |
275 | |
276 static ngx_int_t | |
277 ngx_regex_module_init(ngx_cycle_t *cycle) | |
278 { | |
279 int opt; | |
280 const char *errstr; | |
281 ngx_uint_t i; | |
282 ngx_list_part_t *part; | |
283 ngx_regex_elt_t *elts; | |
284 | |
285 opt = 0; | |
286 | |
287 #if (NGX_HAVE_PCRE_JIT) | |
288 { | |
289 ngx_regex_conf_t *rcf; | |
290 | |
291 rcf = (ngx_regex_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_regex_module); | |
292 | |
293 if (rcf->pcre_jit) { | |
294 opt = PCRE_STUDY_JIT_COMPILE; | |
295 } | |
296 } | |
297 #endif | |
298 | |
299 ngx_regex_malloc_init(cycle->pool); | |
300 | |
301 part = &ngx_pcre_studies->part; | |
302 elts = part->elts; | |
303 | |
304 for (i = 0 ; /* void */ ; i++) { | |
305 | |
306 if (i >= part->nelts) { | |
307 if (part->next == NULL) { | |
308 break; | |
309 } | |
310 | |
311 part = part->next; | |
312 elts = part->elts; | |
313 i = 0; | |
314 } | |
315 | |
316 elts[i].regex->extra = pcre_study(elts[i].regex->pcre, opt, &errstr); | |
317 | |
318 if (errstr != NULL) { | |
319 ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, | |
320 "pcre_study() failed: %s in \"%s\"", | |
321 errstr, elts[i].name); | |
322 } | |
323 | |
324 #if (NGX_HAVE_PCRE_JIT) | |
325 if (opt & PCRE_STUDY_JIT_COMPILE) { | |
326 int jit, n; | |
327 | |
328 jit = 0; | |
329 n = pcre_fullinfo(elts[i].regex->pcre, elts[i].regex->extra, | |
330 PCRE_INFO_JIT, &jit); | |
331 | |
332 if (n != 0 || jit != 1) { | |
333 ngx_log_error(NGX_LOG_INFO, cycle->log, 0, | |
334 "JIT compiler does not support pattern: \"%s\"", | |
335 elts[i].name); | |
336 } | |
337 } | |
338 #endif | |
339 } | |
340 | |
341 ngx_regex_malloc_done(); | |
342 | |
343 ngx_pcre_studies = NULL; | |
344 | |
345 return NGX_OK; | |
346 } | |
347 | |
348 | |
349 static void * | |
350 ngx_regex_create_conf(ngx_cycle_t *cycle) | |
351 { | |
352 ngx_regex_conf_t *rcf; | |
353 | |
354 rcf = ngx_pcalloc(cycle->pool, sizeof(ngx_regex_conf_t)); | |
355 if (rcf == NULL) { | |
356 return NULL; | |
357 } | |
358 | |
359 rcf->pcre_jit = NGX_CONF_UNSET; | |
360 | |
361 ngx_pcre_studies = ngx_list_create(cycle->pool, 8, sizeof(ngx_regex_elt_t)); | |
362 if (ngx_pcre_studies == NULL) { | |
363 return NULL; | |
364 } | |
365 | |
366 return rcf; | |
367 } | |
368 | |
369 | |
370 static char * | |
371 ngx_regex_init_conf(ngx_cycle_t *cycle, void *conf) | |
372 { | |
373 ngx_regex_conf_t *rcf = conf; | |
374 | |
375 ngx_conf_init_value(rcf->pcre_jit, 0); | |
376 | |
377 return NGX_CONF_OK; | |
378 } | |
379 | |
380 | |
381 static char * | |
382 ngx_regex_pcre_jit(ngx_conf_t *cf, void *post, void *data) | |
383 { | |
384 ngx_flag_t *fp = data; | |
385 | |
386 if (*fp == 0) { | |
387 return NGX_CONF_OK; | |
388 } | |
389 | |
390 #if (NGX_HAVE_PCRE_JIT) | |
391 { | |
392 int jit, r; | |
393 | |
394 jit = 0; | |
395 r = pcre_config(PCRE_CONFIG_JIT, &jit); | |
396 | |
397 if (r != 0 || jit != 1) { | |
398 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
399 "PCRE library does not support JIT"); | |
400 *fp = 0; | |
401 } | |
402 } | |
403 #else | |
404 ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
405 "nginx was build without PCRE JIT support"); | |
406 *fp = 0; | |
407 #endif | |
408 | |
409 return NGX_CONF_OK; | |
410 } |