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

View File

@ -104,9 +104,361 @@ od_configclose(odconfig_t *config)
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
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;
}

View File

@ -6,6 +6,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "od_macro.h"
#include "od_list.h"
@ -20,3 +21,29 @@ void od_schemefree(odscheme_t *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,18 +11,21 @@ typedef struct odscheme_route_t odscheme_route_t;
typedef struct odscheme_t odscheme_t;
struct odscheme_server_t {
char *host;
int port;
int is_default;
char *name;
char *host;
int port;
int is_default;
odlist_t link;
};
struct odscheme_route_t {
char *database;
char *user;
char *password;
int client_max;
int pool_min;
int pool_max;
char *database;
char *user;
char *password;
int client_max;
int pool_min;
int pool_max;
odlist_t link;
};
struct odscheme_t {
@ -47,4 +50,10 @@ struct odscheme_t {
void od_schemeinit(odscheme_t*);
void od_schemefree(odscheme_t*);
odscheme_server_t*
od_scheme_addserver(odscheme_t*);
odscheme_route_t*
od_scheme_addroute(odscheme_t*);
#endif