odissey: implement config parser

This commit is contained in:
Dmitry Simonenko 2016-11-07 15:59:29 +03:00
parent 0be7c41987
commit d6b072bcfd
4 changed files with 426 additions and 38 deletions

View File

@ -3,49 +3,49 @@
odissey { odissey {
daemonize on; daemonize on;
log_file = ""; log_file "";
pid_file = ""; pid_file "";
pooling = "session"; # transaction, statement pooling "session"; # transaction, statement
listen { listen {
host = "localhost"; host "localhost";
port = 1234; port 1234;
tls_sslmode = disable tls_sslmode disable
tls_ca_file = <system default> tls_ca_file
tls_key_file = tls_key_file
tls_cert_file = tls_cert_file
tls_protocols = all; tls_protocols all;
tls_ciphers = fast; tls_ciphers fast;
connection_max = 100; client_max 100;
threads = 8; workers 8;
} }
server default { server default {
host = "localhost"; host "localhost";
port = 4322; port 4322;
} }
server "misc" { server "misc" {
host = "localhost"; host "localhost";
port = 4321; port 4321;
tls_sslmode = disable tls_sslmode disable
tls_ca_file = <system default> tls_ca_file
tls_key_file = tls_key_file
tls_cert_file = tls_cert_file
tls_protocols = all; tls_protocol all;
tls_ciphers = fast; tls_ciphers fast;
} }
routing { routing {
mode = "forward"; # round-robin mode "forward"; # round-robin
bardb { bardb {
redirect = "misc"; redirect "misc";
client_max = 100; client_max 100;
pool_size_min = 0; pool_size_min 0;
pool_size_max = 100 pool_size_max 100;
# force user, db, limits # force user, db, limits
} }
} }

View File

@ -104,9 +104,361 @@ od_configclose(odconfig_t *config)
od_lexfree(&config->lex); od_lexfree(&config->lex);
} }
static void
od_configerror(odconfig_t *config, odtoken_t *tk, char *fmt, ...)
{
char msg[256];
va_list args;
va_start(args, fmt);
vsnprintf(msg, sizeof(msg), fmt, args);
va_end(args);
int line = config->lex.line;
if (tk)
line = tk->line;
od_log(config->log, "%s:%d %s\n", config->scheme->config_file,
line, msg);
}
static int
od_confignext(odconfig_t *config, int id, odtoken_t **tk)
{
odtoken_t *tkp = NULL;
int token = od_lexpop(&config->lex, &tkp);
if (token == OD_LERROR) {
od_configerror(config, NULL, "%s", config->lex.error);
return -1;
}
if (tk) {
*tk = tkp;
}
if (token != id) {
if (id < 0xff && ispunct(id)) {
od_configerror(config, tkp, "expected '%c'", id);
return -1;
}
od_configerror(config, tkp, "expected '%s'",
od_lexname_of(&config->lex, id));
return -1;
}
return 0;
}
static int
od_confignext_yes_no(odconfig_t *config, odtoken_t **tk)
{
int rc;
rc = od_lexpop(&config->lex, tk);
if (rc == OD_LYES)
return 1;
if (rc == OD_LNO)
return 0;
od_configerror(config, *tk, "expected yes/no");
return -1;
}
static int
od_configparse_listen(odconfig_t *config)
{
if (od_confignext(config, '{', NULL) == -1)
return -1;
odtoken_t *tk;
int rc;
int eof = 0;
while (! eof)
{
rc = od_lexpop(&config->lex, &tk);
switch (rc) {
/* host */
case OD_LHOST:
if (od_confignext(config, OD_LSTRING, &tk) == -1)
return -1;
config->scheme->host = tk->v.string;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* port */
case OD_LPORT:
if (od_confignext(config, OD_LNUMBER, &tk) == -1)
return -1;
config->scheme->port = tk->v.num;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* client_max */
case OD_LCLIENT_MAX:
if (od_confignext(config, OD_LNUMBER, &tk) == -1)
return -1;
config->scheme->client_max = tk->v.num;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* workers */
case OD_LWORKERS:
if (od_confignext(config, OD_LNUMBER, &tk) == -1)
return -1;
config->scheme->workers = tk->v.num;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
case OD_LEOF:
od_configerror(config, tk, "unexpected end of config file");
return -1;
case '}':
eof = 1;
continue;
default:
od_configerror(config, tk, "unknown option");
return -1;
}
}
return 0;
}
static int
od_configparse_server(odconfig_t *config)
{
odscheme_server_t *server =
od_scheme_addserver(config->scheme);
if (server == NULL)
return -1;
odtoken_t *tk;
int rc;
/* name */
rc = od_lexpop(&config->lex, &tk);
if (rc == OD_LSTRING)
server->name = tk->v.string;
else
od_lexpush(&config->lex, tk);
/* default */
rc = od_lexpop(&config->lex, &tk);
if (rc == OD_LDEFAULT)
server->is_default = 1;
else
od_lexpush(&config->lex, tk);
if (od_confignext(config, '{', NULL) == -1)
return -1;
int eof = 0;
while (! eof)
{
rc = od_lexpop(&config->lex, &tk);
switch (rc) {
/* host */
case OD_LHOST:
if (od_confignext(config, OD_LSTRING, &tk) == -1)
return -1;
server->host = tk->v.string;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* port */
case OD_LPORT:
if (od_confignext(config, OD_LNUMBER, &tk) == -1)
return -1;
server->port = tk->v.num;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
case OD_LEOF:
od_configerror(config, tk, "unexpected end of config file");
return -1;
case '}':
eof = 1;
continue;
default:
od_configerror(config, tk, "unknown option");
return -1;
}
}
return 0;
}
static int
od_configparse_route(odconfig_t *config, odtoken_t *name)
{
odscheme_route_t *route =
od_scheme_addroute(config->scheme);
if (route == NULL)
return -1;
route->database = name->v.string;
if (od_confignext(config, '{', NULL) == -1)
return -1;
odtoken_t *tk;
int rc;
int eof = 0;
while (! eof)
{
rc = od_lexpop(&config->lex, &tk);
switch (rc) {
/* client_max */
case OD_LCLIENT_MAX:
if (od_confignext(config, OD_LNUMBER, &tk) == -1)
return -1;
route->client_max = tk->v.num;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* pool_min */
case OD_LPOOL_MIN:
if (od_confignext(config, OD_LNUMBER, &tk) == -1)
return -1;
route->pool_min = tk->v.num;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* pool_max */
case OD_LPOOL_MAX:
if (od_confignext(config, OD_LNUMBER, &tk) == -1)
return -1;
route->pool_max = tk->v.num;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* user */
case OD_LUSER:
if (od_confignext(config, OD_LSTRING, &tk) == -1)
return -1;
route->user = tk->v.string;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* password */
case OD_LPASSWORD:
if (od_confignext(config, OD_LSTRING, &tk) == -1)
return -1;
route->password = tk->v.string;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
case OD_LEOF:
od_configerror(config, tk, "unexpected end of config file");
return -1;
case '}':
eof = 1;
continue;
default:
od_configerror(config, tk, "unknown option");
return -1;
}
}
return 0;
}
static int
od_configparse_routing(odconfig_t *config)
{
if (od_confignext(config, '{', NULL) == -1)
return -1;
odtoken_t *tk;
int rc;
int eof = 0;
while (! eof)
{
rc = od_lexpop(&config->lex, &tk);
switch (rc) {
/* mode */
case OD_LMODE:
if (od_confignext(config, OD_LSTRING, &tk) == -1)
return -1;
config->scheme->routing = tk->v.string;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* route (database name) */
case OD_LSTRING:
rc = od_configparse_route(config, tk);
if (rc == -1)
return -1;
break;
case OD_LEOF:
od_configerror(config, tk, "unexpected end of config file");
return -1;
case '}':
eof = 1;
continue;
default:
od_configerror(config, tk, "unknown option");
return -1;
}
}
return 0;
}
int int
od_configparse(odconfig_t *config) od_configparse(odconfig_t *config)
{ {
(void)config; odtoken_t *tk;
if (od_confignext(config, OD_LODISSEY, NULL) == -1)
return -1;
if (od_confignext(config, '{', NULL) == -1)
return -1;
int rc;
int eof = 0;
while (! eof)
{
rc = od_lexpop(&config->lex, &tk);
switch (rc) {
/* daemonize */
case OD_LDAEMONIZE:
rc = od_confignext_yes_no(config, &tk);
if (rc == -1)
return -1;
config->scheme->daemonize = rc;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* log_file */
case OD_LLOG_FILE:
if (od_confignext(config, OD_LSTRING, &tk) == -1)
return -1;
config->scheme->log_file = tk->v.string;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* pid_file */
case OD_LPID_FILE:
if (od_confignext(config, OD_LSTRING, &tk) == -1)
return -1;
config->scheme->pid_file = tk->v.string;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* pooling */
case OD_LPOOLING:
if (od_confignext(config, OD_LSTRING, &tk) == -1)
return -1;
config->scheme->pooling = tk->v.string;
if (od_confignext(config, ';', NULL) == -1)
return -1;
continue;
/* listen */
case OD_LLISTEN:
rc = od_configparse_listen(config);
if (rc == -1)
return -1;
continue;
/* server */
case OD_LSERVER:
rc = od_configparse_server(config);
if (rc == -1)
return -1;
continue;
/* routing */
case OD_LROUTING:
rc = od_configparse_routing(config);
if (rc == -1)
return -1;
continue;
case OD_LEOF:
od_configerror(config, tk, "unexpected end of config file");
return -1;
case '}':
eof = 1;
continue;
default:
od_configerror(config, tk, "unknown option");
return -1;
}
}
return 0; return 0;
} }

View File

@ -6,6 +6,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "od_macro.h" #include "od_macro.h"
#include "od_list.h" #include "od_list.h"
@ -20,3 +21,29 @@ void od_schemefree(odscheme_t *scheme)
{ {
(void)scheme; (void)scheme;
} }
odscheme_server_t*
od_scheme_addserver(odscheme_t *scheme)
{
odscheme_server_t *s =
(odscheme_server_t*)malloc(sizeof(*s));
if (s == NULL)
return NULL;
memset(s, 0, sizeof(*s));
od_listinit(&s->link);
od_listappend(&scheme->servers, &s->link);
return s;
}
odscheme_route_t*
od_scheme_addroute(odscheme_t *scheme)
{
odscheme_route_t *r =
(odscheme_route_t*)malloc(sizeof(*r));
if (r == NULL)
return NULL;
memset(r, 0, sizeof(*r));
od_listinit(&r->link);
od_listappend(&scheme->routing_table, &r->link);
return r;
}

View File

@ -11,9 +11,11 @@ typedef struct odscheme_route_t odscheme_route_t;
typedef struct odscheme_t odscheme_t; typedef struct odscheme_t odscheme_t;
struct odscheme_server_t { struct odscheme_server_t {
char *name;
char *host; char *host;
int port; int port;
int is_default; int is_default;
odlist_t link;
}; };
struct odscheme_route_t { struct odscheme_route_t {
@ -23,6 +25,7 @@ struct odscheme_route_t {
int client_max; int client_max;
int pool_min; int pool_min;
int pool_max; int pool_max;
odlist_t link;
}; };
struct odscheme_t { struct odscheme_t {
@ -47,4 +50,10 @@ struct odscheme_t {
void od_schemeinit(odscheme_t*); void od_schemeinit(odscheme_t*);
void od_schemefree(odscheme_t*); void od_schemefree(odscheme_t*);
odscheme_server_t*
od_scheme_addserver(odscheme_t*);
odscheme_route_t*
od_scheme_addroute(odscheme_t*);
#endif #endif