Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4532358

Browse files
committed
speed up big config parsing by 2x using gperf
1 parent caeab31 commit 4532358

File tree

6 files changed

+157
-31
lines changed

6 files changed

+157
-31
lines changed

src/Makefile.am

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ tinyproxy_SOURCES = \
2929
buffer.c buffer.h \
3030
child.c child.h \
3131
common.h \
32+
conf-tokens.c conf-tokens.h \
3233
conf.c conf.h \
3334
conns.c conns.h \
3435
daemon.c daemon.h \
@@ -58,3 +59,6 @@ EXTRA_tinyproxy_SOURCES = filter.c filter.h \
5859
transparent-proxy.c transparent-proxy.h
5960
tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@
6061
tinyproxy_LDADD = @ADDITIONAL_OBJECTS@ -lpthread
62+
63+
conf-tokens.c: conf-tokens.gperf
64+
gperf $< > $@

src/conf-tokens.gperf

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
%{
2+
#include <string.h>
3+
#include <stdlib.h>
4+
#include "conf-tokens.h"
5+
%}
6+
7+
struct config_directive_entry { const char* name; enum config_directive value; };
8+
9+
%struct-type
10+
%define slot-name name
11+
%define initializer-suffix ,CD_NIL
12+
%define lookup-function-name config_directive_find
13+
%ignore-case
14+
%7bit
15+
%compare-lengths
16+
%readonly-tables
17+
%define constants-prefix CDS_
18+
%omit-struct-type
19+
20+
%%
21+
logfile, CD_logfile
22+
pidfile, CD_pidfile
23+
anonymous, CD_anonymous
24+
viaproxyname, CD_viaproxyname
25+
defaulterrorfile, CD_defaulterrorfile
26+
statfile, CD_statfile
27+
stathost, CD_stathost
28+
xtinyproxy, CD_xtinyproxy
29+
syslog, CD_syslog
30+
bindsame, CD_bindsame
31+
disableviaheader, CD_disableviaheader
32+
port, CD_port
33+
maxclients, CD_maxclients
34+
maxspareservers, CD_maxspareservers
35+
minspareservers, CD_minspareservers
36+
startservers, CD_startservers
37+
maxrequestsperchild, CD_maxrequestsperchild
38+
timeout, CD_timeout
39+
connectport, CD_connectport
40+
user, CD_user
41+
group, CD_group
42+
listen, CD_listen
43+
allow, CD_allow
44+
deny, CD_deny
45+
bind, CD_bind
46+
basicauth, CD_basicauth
47+
errorfile, CD_errorfile
48+
addheader, CD_addheader
49+
filter, CD_filter
50+
filterurls, CD_filterurls
51+
filterextended, CD_filterextended
52+
filterdefaultdeny, CD_filterdefaultdeny
53+
filtercasesensitive, CD_filtercasesensitive
54+
reversebaseurl, CD_reversebaseurl
55+
reverseonly, CD_reverseonly
56+
reversemagic, CD_reversemagic
57+
reversepath, CD_reversepath
58+
upstream, CD_upstream
59+
loglevel, CD_loglevel
60+
%%
61+

src/conf-tokens.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#ifndef CONF_TOKENS_H
2+
#define CONF_TOKENS_H
3+
4+
enum config_directive {
5+
CD_NIL = 0,
6+
CD_logfile,
7+
CD_pidfile,
8+
CD_anonymous,
9+
CD_viaproxyname,
10+
CD_defaulterrorfile,
11+
CD_statfile,
12+
CD_stathost,
13+
CD_xtinyproxy,
14+
CD_syslog,
15+
CD_bindsame,
16+
CD_disableviaheader,
17+
CD_port,
18+
CD_maxclients,
19+
CD_maxspareservers,
20+
CD_minspareservers,
21+
CD_startservers,
22+
CD_maxrequestsperchild,
23+
CD_timeout,
24+
CD_connectport,
25+
CD_user,
26+
CD_group,
27+
CD_listen,
28+
CD_allow,
29+
CD_deny,
30+
CD_bind,
31+
CD_basicauth,
32+
CD_errorfile,
33+
CD_addheader,
34+
CD_filter,
35+
CD_filterurls,
36+
CD_filterextended,
37+
CD_filterdefaultdeny,
38+
CD_filtercasesensitive,
39+
CD_reversebaseurl,
40+
CD_reverseonly,
41+
CD_reversemagic,
42+
CD_reversepath,
43+
CD_upstream,
44+
CD_loglevel,
45+
};
46+
47+
struct config_directive_entry { const char* name; enum config_directive value; };
48+
49+
const struct config_directive_entry *
50+
config_directive_find (register const char *str, register size_t len);
51+
52+
#endif
53+

src/conf.c

Lines changed: 37 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "upstream.h"
3838
#include "connect-ports.h"
3939
#include "basicauth.h"
40+
#include "conf-tokens.h"
4041

4142
/*
4243
* The configuration directives are defined in the structure below. Each
@@ -98,10 +99,13 @@ typedef int (*CONFFILE_HANDLER) (struct config_s *, const char *,
9899
* List all the handling functions. These are defined later, but they need
99100
* to be in-scope before the big structure below.
100101
*/
101-
static HANDLE_FUNC (handle_nop)
102+
static HANDLE_FUNC (handle_disabled_feature)
102103
{
103-
return 0;
104-
} /* do nothing function */
104+
fprintf (stderr, "ERROR: accessing feature that was disabled at compiletime on line %lu\n",
105+
lineno);
106+
107+
return -1;
108+
}
105109

106110
static HANDLE_FUNC (handle_allow);
107111
static HANDLE_FUNC (handle_basicauth);
@@ -161,7 +165,7 @@ static void config_free_regex (void);
161165
* do not follow the pattern above. This macro is for convenience
162166
* only.
163167
*/
164-
#define STDCONF(d, re, func) { BEGIN "(" #d ")" WS re END, func, NULL }
168+
#define STDCONF(d, re, func) [CD_ ## d] = { BEGIN "()" WS re END, func, NULL }
165169

166170
/*
167171
* Holds the regular expression used to match the configuration directive,
@@ -174,14 +178,6 @@ struct {
174178
CONFFILE_HANDLER handler;
175179
regex_t *cre;
176180
} directives[] = {
177-
/* comments */
178-
{
179-
BEGIN "#", handle_nop, NULL
180-
},
181-
/* blank lines */
182-
{
183-
"^[[:space:]]+$", handle_nop, NULL
184-
},
185181
/* string arguments */
186182
STDCONF (logfile, STR, handle_logfile),
187183
STDCONF (pidfile, STR, handle_pidfile),
@@ -326,20 +322,25 @@ void free_config (struct config_s *conf)
326322
}
327323

328324
/*
325+
* Initializes Config parser. Currently this means:
329326
* Compiles the regular expressions used by the configuration file. This
330327
* routine MUST be called before trying to parse the configuration file.
331328
*
332329
* Returns 0 on success; negative upon failure.
333330
*/
334331
int
335-
config_compile_regex (void)
332+
config_init (void)
336333
{
337334
unsigned int i, r;
338335

339336
for (i = 0; i != ndirectives; ++i) {
340-
assert (directives[i].handler);
341337
assert (!directives[i].cre);
342338

339+
if (!directives[i].handler) {
340+
directives[i].handler = handle_disabled_feature;
341+
continue;
342+
}
343+
343344
directives[i].cre = (regex_t *) safemalloc (sizeof (regex_t));
344345
if (!directives[i].cre)
345346
return -1;
@@ -383,20 +384,17 @@ config_free_regex (void)
383384
* a negative number is returned.
384385
*/
385386
static int check_match (struct config_s *conf, const char *line,
386-
unsigned long lineno)
387+
unsigned long lineno, enum config_directive cd)
387388
{
388389
regmatch_t match[RE_MAX_MATCHES];
389-
unsigned int i;
390-
391-
assert (ndirectives > 0);
390+
unsigned int i = cd;
392391

393-
for (i = 0; i != ndirectives; ++i) {
394-
assert (directives[i].cre);
395-
if (!regexec
396-
(directives[i].cre, line, RE_MAX_MATCHES, match, 0))
397-
return (*directives[i].handler) (conf, line, lineno, match);
398-
}
392+
if (!directives[i].cre)
393+
return (*directives[i].handler) (conf, line, lineno, match);
399394

395+
if (!regexec
396+
(directives[i].cre, line, RE_MAX_MATCHES, match, 0))
397+
return (*directives[i].handler) (conf, line, lineno, match);
400398
return -1;
401399
}
402400

@@ -405,15 +403,25 @@ static int check_match (struct config_s *conf, const char *line,
405403
*/
406404
static int config_parse (struct config_s *conf, FILE * f)
407405
{
408-
char buffer[LINE_MAX];
406+
char buffer[LINE_MAX], *p, *q, c;
407+
const struct config_directive_entry *e;
409408
unsigned long lineno = 1;
410409

411-
while (fgets (buffer, sizeof (buffer), f)) {
412-
if (check_match (conf, buffer, lineno)) {
413-
printf ("Syntax error on line %ld\n", lineno);
410+
for (;fgets (buffer, sizeof (buffer), f);++lineno) {
411+
if(buffer[0] == '#') continue;
412+
p = buffer;
413+
while(isspace(*p))p++;
414+
if(!*p) continue;
415+
q = p;
416+
while(!isspace(*q))q++;
417+
c = *q;
418+
*q = 0;
419+
e = config_directive_find(p, strlen(p));
420+
*q = c;
421+
if (!e || e->value == CD_NIL || check_match (conf, q, lineno, e->value)) {
422+
fprintf (stderr, "ERROR: Syntax error on line %lu\n", lineno);
414423
return 1;
415424
}
416-
++lineno;
417425
}
418426
return 0;
419427
}

src/conf.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ struct config_s {
115115

116116
extern int reload_config_file (const char *config_fname, struct config_s *conf);
117117

118-
int config_compile_regex (void);
118+
int config_init (void);
119119
void free_config (struct config_s *conf);
120120

121121
#endif

src/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ main (int argc, char **argv)
300300

301301
log_message (LOG_NOTICE, "Initializing " PACKAGE " ...");
302302

303-
if (config_compile_regex()) {
303+
if (config_init()) {
304304
exit (EX_SOFTWARE);
305305
}
306306

0 commit comments

Comments
 (0)