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 \
|
buffer.c buffer.h \
|
||||||
child.c child.h \
|
child.c child.h \
|
||||||
common.h \
|
common.h \
|
||||||
|
conf-tokens.c conf-tokens.h \
|
||||||
conf.c conf.h \
|
conf.c conf.h \
|
||||||
conns.c conns.h \
|
conns.c conns.h \
|
||||||
daemon.c daemon.h \
|
daemon.c daemon.h \
|
||||||
@ -58,3 +59,6 @@ EXTRA_tinyproxy_SOURCES = filter.c filter.h \
|
|||||||
transparent-proxy.c transparent-proxy.h
|
transparent-proxy.c transparent-proxy.h
|
||||||
tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@
|
tinyproxy_DEPENDENCIES = @ADDITIONAL_OBJECTS@
|
||||||
tinyproxy_LDADD = @ADDITIONAL_OBJECTS@ -lpthread
|
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 "upstream.h"
|
||||||
#include "connect-ports.h"
|
#include "connect-ports.h"
|
||||||
#include "basicauth.h"
|
#include "basicauth.h"
|
||||||
|
#include "conf-tokens.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The configuration directives are defined in the structure below. Each
|
* 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
|
* List all the handling functions. These are defined later, but they need
|
||||||
* to be in-scope before the big structure below.
|
* to be in-scope before the big structure below.
|
||||||
*/
|
*/
|
||||||
static HANDLE_FUNC (handle_nop)
|
static HANDLE_FUNC (handle_disabled_feature)
|
||||||
{
|
{
|
||||||
return 0;
|
fprintf (stderr, "ERROR: accessing feature that was disabled at compiletime on line %lu\n",
|
||||||
} /* do nothing function */
|
lineno);
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static HANDLE_FUNC (handle_allow);
|
static HANDLE_FUNC (handle_allow);
|
||||||
static HANDLE_FUNC (handle_basicauth);
|
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
|
* do not follow the pattern above. This macro is for convenience
|
||||||
* only.
|
* 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,
|
* Holds the regular expression used to match the configuration directive,
|
||||||
@ -174,14 +178,6 @@ struct {
|
|||||||
CONFFILE_HANDLER handler;
|
CONFFILE_HANDLER handler;
|
||||||
regex_t *cre;
|
regex_t *cre;
|
||||||
} directives[] = {
|
} directives[] = {
|
||||||
/* comments */
|
|
||||||
{
|
|
||||||
BEGIN "#", handle_nop, NULL
|
|
||||||
},
|
|
||||||
/* blank lines */
|
|
||||||
{
|
|
||||||
"^[[:space:]]+$", handle_nop, NULL
|
|
||||||
},
|
|
||||||
/* string arguments */
|
/* string arguments */
|
||||||
STDCONF (logfile, STR, handle_logfile),
|
STDCONF (logfile, STR, handle_logfile),
|
||||||
STDCONF (pidfile, STR, handle_pidfile),
|
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
|
* Compiles the regular expressions used by the configuration file. This
|
||||||
* routine MUST be called before trying to parse the configuration file.
|
* routine MUST be called before trying to parse the configuration file.
|
||||||
*
|
*
|
||||||
* Returns 0 on success; negative upon failure.
|
* Returns 0 on success; negative upon failure.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
config_compile_regex (void)
|
config_init (void)
|
||||||
{
|
{
|
||||||
unsigned int i, r;
|
unsigned int i, r;
|
||||||
|
|
||||||
for (i = 0; i != ndirectives; ++i) {
|
for (i = 0; i != ndirectives; ++i) {
|
||||||
assert (directives[i].handler);
|
|
||||||
assert (!directives[i].cre);
|
assert (!directives[i].cre);
|
||||||
|
|
||||||
|
if (!directives[i].handler) {
|
||||||
|
directives[i].handler = handle_disabled_feature;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
directives[i].cre = (regex_t *) safemalloc (sizeof (regex_t));
|
directives[i].cre = (regex_t *) safemalloc (sizeof (regex_t));
|
||||||
if (!directives[i].cre)
|
if (!directives[i].cre)
|
||||||
return -1;
|
return -1;
|
||||||
@ -383,20 +384,17 @@ config_free_regex (void)
|
|||||||
* a negative number is returned.
|
* a negative number is returned.
|
||||||
*/
|
*/
|
||||||
static int check_match (struct config_s *conf, const char *line,
|
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];
|
regmatch_t match[RE_MAX_MATCHES];
|
||||||
unsigned int i;
|
unsigned int i = cd;
|
||||||
|
|
||||||
assert (ndirectives > 0);
|
if (!directives[i].cre)
|
||||||
|
return (*directives[i].handler) (conf, line, lineno, match);
|
||||||
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 (!regexec
|
||||||
|
(directives[i].cre, line, RE_MAX_MATCHES, match, 0))
|
||||||
|
return (*directives[i].handler) (conf, line, lineno, match);
|
||||||
return -1;
|
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)
|
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;
|
unsigned long lineno = 1;
|
||||||
|
|
||||||
while (fgets (buffer, sizeof (buffer), f)) {
|
for (;fgets (buffer, sizeof (buffer), f);++lineno) {
|
||||||
if (check_match (conf, buffer, lineno)) {
|
if(buffer[0] == '#') continue;
|
||||||
printf ("Syntax error on line %ld\n", lineno);
|
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;
|
return 1;
|
||||||
}
|
}
|
||||||
++lineno;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ struct config_s {
|
|||||||
|
|
||||||
extern int reload_config_file (const char *config_fname, struct config_s *conf);
|
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);
|
void free_config (struct config_s *conf);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -300,7 +300,7 @@ main (int argc, char **argv)
|
|||||||
|
|
||||||
log_message (LOG_NOTICE, "Initializing " PACKAGE " ...");
|
log_message (LOG_NOTICE, "Initializing " PACKAGE " ...");
|
||||||
|
|
||||||
if (config_compile_regex()) {
|
if (config_init()) {
|
||||||
exit (EX_SOFTWARE);
|
exit (EX_SOFTWARE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user