diff --git a/odissey.conf b/odissey.conf index 743fded8..18e66083 100644 --- a/odissey.conf +++ b/odissey.conf @@ -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 = - 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 = - 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 } } diff --git a/src/od_config.c b/src/od_config.c index b49be92a..91add7c6 100644 --- a/src/od_config.c +++ b/src/od_config.c @@ -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; } diff --git a/src/od_scheme.c b/src/od_scheme.c index 1b993792..fca9057d 100644 --- a/src/od_scheme.c +++ b/src/od_scheme.c @@ -6,6 +6,7 @@ #include #include +#include #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; +} diff --git a/src/od_scheme.h b/src/od_scheme.h index dbd2ce61..36e3a573 100644 --- a/src/od_scheme.h +++ b/src/od_scheme.h @@ -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