mirror of https://github.com/yandex/odyssey.git
208 lines
5.0 KiB
C
208 lines
5.0 KiB
C
|
|
/*
|
|
* odissey.
|
|
*
|
|
* PostgreSQL connection pooler and request router.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "od_macro.h"
|
|
#include "od_list.h"
|
|
#include "od_log.h"
|
|
#include "od_scheme.h"
|
|
|
|
void od_schemeinit(odscheme_t *scheme)
|
|
{
|
|
scheme->config_file = NULL;
|
|
scheme->daemonize = 0;
|
|
scheme->log_file = NULL;
|
|
scheme->pid_file = NULL;
|
|
scheme->host = NULL;
|
|
scheme->port = 6432;
|
|
scheme->workers = 1;
|
|
scheme->client_max = 100;
|
|
scheme->pooling = NULL;
|
|
scheme->pooling_mode = OD_PUNDEF;
|
|
scheme->routing = NULL;
|
|
scheme->routing_mode = OD_RUNDEF;
|
|
scheme->server_id = 0;
|
|
od_listinit(&scheme->servers);
|
|
od_listinit(&scheme->routing_table);
|
|
}
|
|
|
|
void od_schemefree(odscheme_t *scheme)
|
|
{
|
|
odlist_t *i, *n;
|
|
od_listforeach_safe(&scheme->servers, i, n) {
|
|
odscheme_server_t *server;
|
|
server = od_container_of(i, odscheme_server_t, link);
|
|
free(server);
|
|
}
|
|
od_listforeach_safe(&scheme->routing_table, i, n) {
|
|
odscheme_route_t *route;
|
|
route = od_container_of(i, odscheme_route_t, link);
|
|
free(route);
|
|
}
|
|
}
|
|
|
|
odscheme_server_t*
|
|
od_schemeserver_add(odscheme_t *scheme)
|
|
{
|
|
odscheme_server_t *s =
|
|
(odscheme_server_t*)malloc(sizeof(*s));
|
|
if (s == NULL)
|
|
return NULL;
|
|
memset(s, 0, sizeof(*s));
|
|
s->id = scheme->server_id++;
|
|
od_listinit(&s->link);
|
|
od_listappend(&scheme->servers, &s->link);
|
|
return s;
|
|
}
|
|
|
|
odscheme_server_t*
|
|
od_schemeserver_match(odscheme_t *scheme, char *name)
|
|
{
|
|
odlist_t *i;
|
|
od_listforeach(&scheme->servers, i) {
|
|
odscheme_server_t *server;
|
|
server = od_container_of(i, odscheme_server_t, link);
|
|
if (strcmp(server->name, name) == 0)
|
|
return server;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
odscheme_route_t*
|
|
od_schemeroute_add(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;
|
|
}
|
|
|
|
int od_schemevalidate(odscheme_t *scheme, odlog_t *log)
|
|
{
|
|
/* pooling mode */
|
|
if (scheme->pooling == NULL) {
|
|
od_error(log, "pooling mode is not set");
|
|
return -1;
|
|
}
|
|
if (strcmp(scheme->pooling, "session") == 0)
|
|
scheme->pooling_mode = OD_PSESSION;
|
|
else
|
|
if (strcmp(scheme->pooling, "statement") == 0)
|
|
scheme->pooling_mode = OD_PSTATEMENT;
|
|
else
|
|
if (strcmp(scheme->pooling, "transaction") == 0)
|
|
scheme->pooling_mode = OD_PTRANSACTION;
|
|
|
|
if (scheme->pooling_mode == OD_PUNDEF) {
|
|
od_error(log, "unknown pooling mode");
|
|
return -1;
|
|
}
|
|
|
|
/* routing mode */
|
|
if (scheme->routing == NULL) {
|
|
od_error(log, "routing mode is not set");
|
|
return -1;
|
|
}
|
|
if (strcmp(scheme->routing, "forward") == 0)
|
|
scheme->routing_mode = OD_RFORWARD;
|
|
else
|
|
if (strcmp(scheme->routing, "round-robin") == 0)
|
|
scheme->routing_mode = OD_RROUND_ROBIN;
|
|
|
|
if (scheme->routing_mode == OD_RUNDEF) {
|
|
od_error(log, "unknown routing mode");
|
|
return -1;
|
|
}
|
|
|
|
/* listen */
|
|
if (scheme->host == NULL)
|
|
scheme->host = "127.0.0.1";
|
|
|
|
/* servers */
|
|
if (od_listempty(&scheme->servers)) {
|
|
od_error(log, "no servers are defined");
|
|
return -1;
|
|
}
|
|
odlist_t *i;
|
|
od_listforeach(&scheme->servers, i) {
|
|
odscheme_server_t *server;
|
|
server = od_container_of(i, odscheme_server_t, link);
|
|
if (server->host == NULL) {
|
|
od_error(log, "server '%s': no host is specified",
|
|
server->name);
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
/* routing table */
|
|
od_listforeach(&scheme->routing_table, i) {
|
|
odscheme_route_t *route;
|
|
route = od_container_of(i, odscheme_route_t, link);
|
|
if (route->route == NULL) {
|
|
od_error(log, "route '%s': no route server is specified",
|
|
route->database);
|
|
return -1;
|
|
}
|
|
route->server = od_schemeserver_match(scheme, route->route);
|
|
if (route->server == NULL) {
|
|
od_error(log, "route '%s': no route server '%s' found",
|
|
route->route);
|
|
return -1;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void od_schemeprint(odscheme_t *scheme, odlog_t *log)
|
|
{
|
|
od_log(log, "using configuration file '%s'",
|
|
scheme->config_file);
|
|
if (scheme->log_file)
|
|
od_log(log, "log_file '%s'", scheme->log_file);
|
|
if (scheme->pid_file)
|
|
od_log(log, "pid_file '%s'", scheme->pid_file);
|
|
if (scheme->daemonize)
|
|
od_log(log, "daemonize %s",
|
|
scheme->daemonize ? "yes" : "no");
|
|
od_log(log, "pooling '%s'", scheme->pooling);
|
|
od_log(log, "");
|
|
od_log(log, "servers");
|
|
odlist_t *i;
|
|
od_listforeach(&scheme->servers, i) {
|
|
odscheme_server_t *server;
|
|
server = od_container_of(i, odscheme_server_t, link);
|
|
od_log(log, " <%s> %s",
|
|
server->name ? server->name : "",
|
|
server->is_default ? "default" : "");
|
|
od_log(log, " host '%s'", server->host);
|
|
od_log(log, " port %d", server->port);
|
|
|
|
}
|
|
od_log(log, "");
|
|
od_log(log, "routing");
|
|
od_log(log, " mode '%s'", scheme->routing);
|
|
od_listforeach(&scheme->routing_table, i) {
|
|
odscheme_route_t *route;
|
|
route = od_container_of(i, odscheme_route_t, link);
|
|
od_log(log, " <%s>", route->database);
|
|
od_log(log, " route '%s'", route->route);
|
|
if (route->user)
|
|
od_log(log, " user '%s'", route->user);
|
|
if (route->password)
|
|
od_log(log, " password '****'");
|
|
od_log(log, " pool_min %d", route->pool_min);
|
|
od_log(log, " pool_max %d", route->pool_max);
|
|
}
|
|
}
|