speed up big config parsing by 2x using gperf
This commit is contained in:
parent
caeab31fca
commit
45323584a0
@ -29,6 +29,7 @@ tinyproxy_SOURCES = \
|
||||
buffer.c buffer.h \
|
||||
child.c child.h \
|
||||
common.h \
|
||||
conf-tokens.c conf-tokens.h \
|
||||
conf.c conf.h \
|
||||
conns.c conns.h \
|
||||
daemon.c daemon.h \
|
||||
@ -58,3 +59,6 @@ EXTRA_tinyproxy_SOURCES = filter.c filter.h \
|
||||
transparent-proxy.c transparent-proxy.h
|
||||
tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@
|
||||
tinyproxy_LDADD = @ADDITIONAL_OBJECTS@ -lpthread
|
||||
|
||||
conf-tokens.c: conf-tokens.gperf
|
||||
gperf $< > $@
|
||||
|
61
src/conf-tokens.gperf
Normal file
61
src/conf-tokens.gperf
Normal file
@ -0,0 +1,61 @@
|
||||
%{
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "conf-tokens.h"
|
||||
%}
|
||||
|
||||
struct config_directive_entry { const char* name; enum config_directive value; };
|
||||
|
||||
%struct-type
|
||||
%define slot-name name
|
||||
%define initializer-suffix ,CD_NIL
|
||||
%define lookup-function-name config_directive_find
|
||||
%ignore-case
|
||||
%7bit
|
||||
%compare-lengths
|
||||
%readonly-tables
|
||||
%define constants-prefix CDS_
|
||||
%omit-struct-type
|
||||
|
||||
%%
|
||||
logfile, CD_logfile
|
||||
pidfile, CD_pidfile
|
||||
anonymous, CD_anonymous
|
||||
viaproxyname, CD_viaproxyname
|
||||
defaulterrorfile, CD_defaulterrorfile
|
||||
statfile, CD_statfile
|
||||
stathost, CD_stathost
|
||||
xtinyproxy, CD_xtinyproxy
|
||||
syslog, CD_syslog
|
||||
bindsame, CD_bindsame
|
||||
disableviaheader, CD_disableviaheader
|
||||
port, CD_port
|
||||
maxclients, CD_maxclients
|
||||
maxspareservers, CD_maxspareservers
|
||||
minspareservers, CD_minspareservers
|
||||
startservers, CD_startservers
|
||||
maxrequestsperchild, CD_maxrequestsperchild
|
||||
timeout, CD_timeout
|
||||
connectport, CD_connectport
|
||||
user, CD_user
|
||||
group, CD_group
|
||||
listen, CD_listen
|
||||
allow, CD_allow
|
||||
deny, CD_deny
|
||||
bind, CD_bind
|
||||
basicauth, CD_basicauth
|
||||
errorfile, CD_errorfile
|
||||
addheader, CD_addheader
|
||||
filter, CD_filter
|
||||
filterurls, CD_filterurls
|
||||
filterextended, CD_filterextended
|
||||
filterdefaultdeny, CD_filterdefaultdeny
|
||||
filtercasesensitive, CD_filtercasesensitive
|
||||
reversebaseurl, CD_reversebaseurl
|
||||
reverseonly, CD_reverseonly
|
||||
reversemagic, CD_reversemagic
|
||||
reversepath, CD_reversepath
|
||||
upstream, CD_upstream
|
||||
loglevel, CD_loglevel
|
||||
%%
|
||||
|
53
src/conf-tokens.h
Normal file
53
src/conf-tokens.h
Normal file
@ -0,0 +1,53 @@
|
||||
#ifndef CONF_TOKENS_H
|
||||
#define CONF_TOKENS_H
|
||||
|
||||
enum config_directive {
|
||||
CD_NIL = 0,
|
||||
CD_logfile,
|
||||
CD_pidfile,
|
||||
CD_anonymous,
|
||||
CD_viaproxyname,
|
||||
CD_defaulterrorfile,
|
||||
CD_statfile,
|
||||
CD_stathost,
|
||||
CD_xtinyproxy,
|
||||
CD_syslog,
|
||||
CD_bindsame,
|
||||
CD_disableviaheader,
|
||||
CD_port,
|
||||
CD_maxclients,
|
||||
CD_maxspareservers,
|
||||
CD_minspareservers,
|
||||
CD_startservers,
|
||||
CD_maxrequestsperchild,
|
||||
CD_timeout,
|
||||
CD_connectport,
|
||||
CD_user,
|
||||
CD_group,
|
||||
CD_listen,
|
||||
CD_allow,
|
||||
CD_deny,
|
||||
CD_bind,
|
||||
CD_basicauth,
|
||||
CD_errorfile,
|
||||
CD_addheader,
|
||||
CD_filter,
|
||||
CD_filterurls,
|
||||
CD_filterextended,
|
||||
CD_filterdefaultdeny,
|
||||
CD_filtercasesensitive,
|
||||
CD_reversebaseurl,
|
||||
CD_reverseonly,
|
||||
CD_reversemagic,
|
||||
CD_reversepath,
|
||||
CD_upstream,
|
||||
CD_loglevel,
|
||||
};
|
||||
|
||||
struct config_directive_entry { const char* name; enum config_directive value; };
|
||||
|
||||
const struct config_directive_entry *
|
||||
config_directive_find (register const char *str, register size_t len);
|
||||
|
||||
#endif
|
||||
|
66
src/conf.c
66
src/conf.c
@ -37,6 +37,7 @@
|
||||
#include "upstream.h"
|
||||
#include "connect-ports.h"
|
||||
#include "basicauth.h"
|
||||
#include "conf-tokens.h"
|
||||
|
||||
/*
|
||||
* The configuration directives are defined in the structure below. Each
|
||||
@ -98,10 +99,13 @@ typedef int (*CONFFILE_HANDLER) (struct config_s *, const char *,
|
||||
* List all the handling functions. These are defined later, but they need
|
||||
* to be in-scope before the big structure below.
|
||||
*/
|
||||
static HANDLE_FUNC (handle_nop)
|
||||
static HANDLE_FUNC (handle_disabled_feature)
|
||||
{
|
||||
return 0;
|
||||
} /* do nothing function */
|
||||
fprintf (stderr, "ERROR: accessing feature that was disabled at compiletime on line %lu\n",
|
||||
lineno);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static HANDLE_FUNC (handle_allow);
|
||||
static HANDLE_FUNC (handle_basicauth);
|
||||
@ -161,7 +165,7 @@ static void config_free_regex (void);
|
||||
* do not follow the pattern above. This macro is for convenience
|
||||
* only.
|
||||
*/
|
||||
#define STDCONF(d, re, func) { BEGIN "(" #d ")" WS re END, func, NULL }
|
||||
#define STDCONF(d, re, func) [CD_ ## d] = { BEGIN "()" WS re END, func, NULL }
|
||||
|
||||
/*
|
||||
* Holds the regular expression used to match the configuration directive,
|
||||
@ -174,14 +178,6 @@ struct {
|
||||
CONFFILE_HANDLER handler;
|
||||
regex_t *cre;
|
||||
} directives[] = {
|
||||
/* comments */
|
||||
{
|
||||
BEGIN "#", handle_nop, NULL
|
||||
},
|
||||
/* blank lines */
|
||||
{
|
||||
"^[[:space:]]+$", handle_nop, NULL
|
||||
},
|
||||
/* string arguments */
|
||||
STDCONF (logfile, STR, handle_logfile),
|
||||
STDCONF (pidfile, STR, handle_pidfile),
|
||||
@ -326,20 +322,25 @@ void free_config (struct config_s *conf)
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes Config parser. Currently this means:
|
||||
* Compiles the regular expressions used by the configuration file. This
|
||||
* routine MUST be called before trying to parse the configuration file.
|
||||
*
|
||||
* Returns 0 on success; negative upon failure.
|
||||
*/
|
||||
int
|
||||
config_compile_regex (void)
|
||||
config_init (void)
|
||||
{
|
||||
unsigned int i, r;
|
||||
|
||||
for (i = 0; i != ndirectives; ++i) {
|
||||
assert (directives[i].handler);
|
||||
assert (!directives[i].cre);
|
||||
|
||||
if (!directives[i].handler) {
|
||||
directives[i].handler = handle_disabled_feature;
|
||||
continue;
|
||||
}
|
||||
|
||||
directives[i].cre = (regex_t *) safemalloc (sizeof (regex_t));
|
||||
if (!directives[i].cre)
|
||||
return -1;
|
||||
@ -383,20 +384,17 @@ config_free_regex (void)
|
||||
* a negative number is returned.
|
||||
*/
|
||||
static int check_match (struct config_s *conf, const char *line,
|
||||
unsigned long lineno)
|
||||
unsigned long lineno, enum config_directive cd)
|
||||
{
|
||||
regmatch_t match[RE_MAX_MATCHES];
|
||||
unsigned int i;
|
||||
unsigned int i = cd;
|
||||
|
||||
assert (ndirectives > 0);
|
||||
|
||||
for (i = 0; i != ndirectives; ++i) {
|
||||
assert (directives[i].cre);
|
||||
if (!regexec
|
||||
(directives[i].cre, line, RE_MAX_MATCHES, match, 0))
|
||||
return (*directives[i].handler) (conf, line, lineno, match);
|
||||
}
|
||||
if (!directives[i].cre)
|
||||
return (*directives[i].handler) (conf, line, lineno, match);
|
||||
|
||||
if (!regexec
|
||||
(directives[i].cre, line, RE_MAX_MATCHES, match, 0))
|
||||
return (*directives[i].handler) (conf, line, lineno, match);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -405,15 +403,25 @@ static int check_match (struct config_s *conf, const char *line,
|
||||
*/
|
||||
static int config_parse (struct config_s *conf, FILE * f)
|
||||
{
|
||||
char buffer[LINE_MAX];
|
||||
char buffer[LINE_MAX], *p, *q, c;
|
||||
const struct config_directive_entry *e;
|
||||
unsigned long lineno = 1;
|
||||
|
||||
while (fgets (buffer, sizeof (buffer), f)) {
|
||||
if (check_match (conf, buffer, lineno)) {
|
||||
printf ("Syntax error on line %ld\n", lineno);
|
||||
for (;fgets (buffer, sizeof (buffer), f);++lineno) {
|
||||
if(buffer[0] == '#') continue;
|
||||
p = buffer;
|
||||
while(isspace(*p))p++;
|
||||
if(!*p) continue;
|
||||
q = p;
|
||||
while(!isspace(*q))q++;
|
||||
c = *q;
|
||||
*q = 0;
|
||||
e = config_directive_find(p, strlen(p));
|
||||
*q = c;
|
||||
if (!e || e->value == CD_NIL || check_match (conf, q, lineno, e->value)) {
|
||||
fprintf (stderr, "ERROR: Syntax error on line %lu\n", lineno);
|
||||
return 1;
|
||||
}
|
||||
++lineno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -115,7 +115,7 @@ struct config_s {
|
||||
|
||||
extern int reload_config_file (const char *config_fname, struct config_s *conf);
|
||||
|
||||
int config_compile_regex (void);
|
||||
int config_init (void);
|
||||
void free_config (struct config_s *conf);
|
||||
|
||||
#endif
|
||||
|
@ -300,7 +300,7 @@ main (int argc, char **argv)
|
||||
|
||||
log_message (LOG_NOTICE, "Initializing " PACKAGE " ...");
|
||||
|
||||
if (config_compile_regex()) {
|
||||
if (config_init()) {
|
||||
exit (EX_SOFTWARE);
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user