2017-05-24 11:57:15 +00:00
|
|
|
|
|
|
|
/*
|
2017-07-05 12:42:49 +00:00
|
|
|
* Odissey.
|
2017-05-24 11:57:15 +00:00
|
|
|
*
|
2017-07-05 12:42:49 +00:00
|
|
|
* Advanced PostgreSQL connection pooler.
|
2017-05-24 11:57:15 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
2017-05-31 15:47:15 +00:00
|
|
|
#include <inttypes.h>
|
2017-07-17 14:05:46 +00:00
|
|
|
#include <assert.h>
|
2017-05-24 11:57:15 +00:00
|
|
|
|
|
|
|
#include <machinarium.h>
|
|
|
|
|
2017-07-05 12:15:17 +00:00
|
|
|
#include "sources/macro.h"
|
2017-11-27 12:54:16 +00:00
|
|
|
#include "sources/util.h"
|
2017-09-15 13:08:42 +00:00
|
|
|
#include "sources/error.h"
|
2017-07-05 12:15:17 +00:00
|
|
|
#include "sources/list.h"
|
|
|
|
#include "sources/pid.h"
|
|
|
|
#include "sources/id.h"
|
2017-07-26 14:05:29 +00:00
|
|
|
#include "sources/logger.h"
|
2017-07-05 12:15:17 +00:00
|
|
|
#include "sources/scheme.h"
|
2017-07-14 13:40:31 +00:00
|
|
|
#include "sources/scheme_mgr.h"
|
2017-05-24 11:57:15 +00:00
|
|
|
|
2017-05-24 12:13:44 +00:00
|
|
|
void od_scheme_init(od_scheme_t *scheme)
|
2017-05-24 11:57:15 +00:00
|
|
|
{
|
|
|
|
scheme->daemonize = 0;
|
2017-06-01 09:38:46 +00:00
|
|
|
scheme->log_debug = 0;
|
2017-07-28 13:23:05 +00:00
|
|
|
scheme->log_to_stdout = 1;
|
2017-06-01 09:45:49 +00:00
|
|
|
scheme->log_config = 0;
|
2017-06-28 10:50:29 +00:00
|
|
|
scheme->log_session = 1;
|
2017-10-26 12:54:32 +00:00
|
|
|
scheme->log_query = 0;
|
2017-05-24 11:57:15 +00:00
|
|
|
scheme->log_file = NULL;
|
2017-08-11 14:11:44 +00:00
|
|
|
scheme->log_stats = 1;
|
|
|
|
scheme->stats_interval = 3;
|
2017-09-21 13:44:19 +00:00
|
|
|
scheme->log_format = NULL;
|
2017-05-24 11:57:15 +00:00
|
|
|
scheme->pid_file = NULL;
|
2017-09-18 13:14:52 +00:00
|
|
|
scheme->log_syslog = 0;
|
|
|
|
scheme->log_syslog_ident = NULL;
|
|
|
|
scheme->log_syslog_facility = NULL;
|
2017-08-29 14:43:41 +00:00
|
|
|
scheme->readahead = 8192;
|
2017-05-24 11:57:15 +00:00
|
|
|
scheme->nodelay = 1;
|
|
|
|
scheme->keepalive = 7200;
|
|
|
|
scheme->workers = 1;
|
2017-06-19 10:55:49 +00:00
|
|
|
scheme->client_max_set = 0;
|
|
|
|
scheme->client_max = 0;
|
2018-02-14 11:55:38 +00:00
|
|
|
scheme->cache = 100;
|
|
|
|
scheme->cache_chunk = 16 * 1024;
|
|
|
|
scheme->cache_chunk_ra = 14 * 1024;
|
2017-06-21 12:18:48 +00:00
|
|
|
od_list_init(&scheme->storages);
|
2017-07-21 14:29:01 +00:00
|
|
|
od_list_init(&scheme->routes);
|
2017-08-28 13:59:41 +00:00
|
|
|
od_list_init(&scheme->listen);
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
|
2017-08-28 13:59:41 +00:00
|
|
|
static void
|
|
|
|
od_schemelisten_free(od_schemelisten_t*);
|
|
|
|
|
2017-05-24 12:13:44 +00:00
|
|
|
void od_scheme_free(od_scheme_t *scheme)
|
2017-05-24 11:57:15 +00:00
|
|
|
{
|
|
|
|
od_list_t *i, *n;
|
2017-07-21 14:29:01 +00:00
|
|
|
od_list_foreach_safe(&scheme->routes, i, n) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
|
|
|
od_schemeroute_free(route);
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
2017-08-28 13:59:41 +00:00
|
|
|
od_list_foreach_safe(&scheme->listen, i, n) {
|
|
|
|
od_schemelisten_t *listen;
|
|
|
|
listen = od_container_of(i, od_schemelisten_t, link);
|
|
|
|
od_schemelisten_free(listen);
|
|
|
|
}
|
2017-07-13 12:58:32 +00:00
|
|
|
if (scheme->log_file)
|
|
|
|
free(scheme->log_file);
|
2017-09-21 13:44:19 +00:00
|
|
|
if (scheme->log_format)
|
|
|
|
free(scheme->log_format);
|
2017-07-13 12:58:32 +00:00
|
|
|
if (scheme->pid_file)
|
|
|
|
free(scheme->pid_file);
|
2017-09-18 13:14:52 +00:00
|
|
|
if (scheme->log_syslog_ident)
|
|
|
|
free(scheme->log_syslog_ident);
|
|
|
|
if (scheme->log_syslog_facility)
|
|
|
|
free(scheme->log_syslog_facility);
|
2017-08-28 13:59:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
od_schemelisten_t*
|
|
|
|
od_schemelisten_add(od_scheme_t *scheme)
|
|
|
|
{
|
|
|
|
od_schemelisten_t *listen;
|
|
|
|
listen = (od_schemelisten_t*)malloc(sizeof(*scheme));
|
|
|
|
if (listen == NULL)
|
|
|
|
return NULL;
|
|
|
|
memset(listen, 0, sizeof(*listen));
|
2017-08-29 14:43:41 +00:00
|
|
|
listen->port = 6432;
|
|
|
|
listen->backlog = 128;
|
2017-08-28 13:59:41 +00:00
|
|
|
od_list_init(&listen->link);
|
2017-08-29 14:43:41 +00:00
|
|
|
od_list_append(&scheme->listen, &listen->link);
|
2017-08-28 13:59:41 +00:00
|
|
|
return listen;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
od_schemelisten_free(od_schemelisten_t *scheme)
|
|
|
|
{
|
2017-07-13 12:58:32 +00:00
|
|
|
if (scheme->host)
|
|
|
|
free(scheme->host);
|
|
|
|
if (scheme->tls)
|
|
|
|
free(scheme->tls);
|
|
|
|
if (scheme->tls_ca_file)
|
|
|
|
free(scheme->tls_ca_file);
|
|
|
|
if (scheme->tls_key_file)
|
|
|
|
free(scheme->tls_key_file);
|
|
|
|
if (scheme->tls_cert_file)
|
|
|
|
free(scheme->tls_cert_file);
|
|
|
|
if (scheme->tls_protocols)
|
|
|
|
free(scheme->tls_protocols);
|
2017-08-28 13:59:41 +00:00
|
|
|
free(scheme);
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
|
2017-07-20 12:39:13 +00:00
|
|
|
static inline od_schemestorage_t*
|
|
|
|
od_schemestorage_allocate(void)
|
2017-05-24 11:57:15 +00:00
|
|
|
{
|
2017-06-21 12:18:48 +00:00
|
|
|
od_schemestorage_t *storage;
|
|
|
|
storage = (od_schemestorage_t*)malloc(sizeof(*storage));
|
|
|
|
if (storage == NULL)
|
2017-05-24 11:57:15 +00:00
|
|
|
return NULL;
|
2017-06-21 12:18:48 +00:00
|
|
|
memset(storage, 0, sizeof(*storage));
|
|
|
|
od_list_init(&storage->link);
|
|
|
|
return storage;
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
|
2018-02-22 13:43:52 +00:00
|
|
|
void
|
2017-07-17 14:05:46 +00:00
|
|
|
od_schemestorage_free(od_schemestorage_t *storage)
|
2017-07-13 12:13:55 +00:00
|
|
|
{
|
2017-07-13 12:32:05 +00:00
|
|
|
if (storage->name)
|
|
|
|
free(storage->name);
|
|
|
|
if (storage->type)
|
|
|
|
free(storage->type);
|
|
|
|
if (storage->host)
|
|
|
|
free(storage->host);
|
|
|
|
if (storage->tls)
|
|
|
|
free(storage->tls);
|
|
|
|
if (storage->tls_ca_file)
|
|
|
|
free(storage->tls_ca_file);
|
|
|
|
if (storage->tls_key_file)
|
|
|
|
free(storage->tls_key_file);
|
|
|
|
if (storage->tls_cert_file)
|
|
|
|
free(storage->tls_cert_file);
|
|
|
|
if (storage->tls_protocols)
|
|
|
|
free(storage->tls_protocols);
|
|
|
|
od_list_unlink(&storage->link);
|
|
|
|
free(storage);
|
2017-07-13 12:13:55 +00:00
|
|
|
}
|
|
|
|
|
2017-07-20 12:39:13 +00:00
|
|
|
od_schemestorage_t*
|
|
|
|
od_schemestorage_add(od_scheme_t *scheme)
|
|
|
|
{
|
|
|
|
od_schemestorage_t *storage;
|
|
|
|
storage = od_schemestorage_allocate();
|
|
|
|
if (storage == NULL)
|
|
|
|
return NULL;
|
|
|
|
od_list_append(&scheme->storages, &storage->link);
|
|
|
|
return storage;
|
|
|
|
}
|
|
|
|
|
|
|
|
od_schemestorage_t*
|
|
|
|
od_schemestorage_match(od_scheme_t *scheme, char *name)
|
|
|
|
{
|
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&scheme->storages, i) {
|
|
|
|
od_schemestorage_t *storage;
|
|
|
|
storage = od_container_of(i, od_schemestorage_t, link);
|
|
|
|
if (strcmp(storage->name, name) == 0)
|
|
|
|
return storage;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-07-24 11:19:56 +00:00
|
|
|
od_schemestorage_t*
|
|
|
|
od_schemestorage_match_latest(od_scheme_t *scheme, char *name)
|
|
|
|
{
|
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&scheme->storages, i) {
|
|
|
|
od_schemestorage_t *storage;
|
|
|
|
storage = od_container_of(i, od_schemestorage_t, link);
|
|
|
|
if (strcmp(storage->name, name) == 0)
|
|
|
|
return storage;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-07-20 12:39:13 +00:00
|
|
|
od_schemestorage_t*
|
|
|
|
od_schemestorage_copy(od_schemestorage_t *storage)
|
|
|
|
{
|
|
|
|
od_schemestorage_t *copy;
|
|
|
|
copy = od_schemestorage_allocate();
|
|
|
|
if (copy == NULL)
|
|
|
|
return NULL;
|
2017-07-21 14:29:01 +00:00
|
|
|
copy->storage_type = storage->storage_type;
|
2017-07-20 12:39:13 +00:00
|
|
|
copy->name = strdup(storage->name);
|
|
|
|
if (copy->name == NULL)
|
|
|
|
goto error;
|
|
|
|
copy->type = strdup(storage->type);
|
|
|
|
if (copy->type == NULL)
|
|
|
|
goto error;
|
|
|
|
if (storage->host) {
|
|
|
|
copy->host = strdup(storage->host);
|
|
|
|
if (copy->host == NULL)
|
|
|
|
goto error;
|
|
|
|
}
|
2017-07-21 14:29:01 +00:00
|
|
|
copy->port = storage->port;
|
2017-07-28 13:19:53 +00:00
|
|
|
copy->tls_mode = storage->tls_mode;
|
2017-07-20 12:39:13 +00:00
|
|
|
if (storage->tls) {
|
|
|
|
copy->tls = strdup(storage->tls);
|
|
|
|
if (copy->tls == NULL)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (storage->tls_ca_file) {
|
|
|
|
copy->tls_ca_file = strdup(storage->tls_ca_file);
|
|
|
|
if (copy->tls_ca_file == NULL)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (storage->tls_key_file) {
|
|
|
|
copy->tls_key_file = strdup(storage->tls_key_file);
|
|
|
|
if (copy->tls_key_file == NULL)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (storage->tls_cert_file) {
|
|
|
|
copy->tls_cert_file = strdup(storage->tls_cert_file);
|
|
|
|
if (copy->tls_cert_file == NULL)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (storage->tls_protocols) {
|
|
|
|
copy->tls_protocols = strdup(storage->tls_protocols);
|
|
|
|
if (copy->tls_protocols == NULL)
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
return copy;
|
|
|
|
error:
|
|
|
|
od_schemestorage_free(copy);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-07-18 12:22:14 +00:00
|
|
|
static inline int
|
|
|
|
od_schemestorage_compare(od_schemestorage_t *a, od_schemestorage_t *b)
|
|
|
|
{
|
|
|
|
/* type */
|
2017-07-19 11:29:23 +00:00
|
|
|
if (a->storage_type != b->storage_type)
|
2017-07-18 12:22:14 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* host */
|
2017-07-19 11:29:23 +00:00
|
|
|
if (a->host && b->host) {
|
|
|
|
if (strcmp(a->host, b->host) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->host || b->host) {
|
2017-07-18 12:22:14 +00:00
|
|
|
return 0;
|
2017-07-19 11:29:23 +00:00
|
|
|
}
|
2017-07-18 12:22:14 +00:00
|
|
|
|
|
|
|
/* port */
|
|
|
|
if (a->port != b->port)
|
|
|
|
return 0;
|
|
|
|
|
2017-07-28 13:19:53 +00:00
|
|
|
/* tls_mode */
|
|
|
|
if (a->tls_mode != b->tls_mode)
|
2017-07-18 12:22:14 +00:00
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* tls_ca_file */
|
|
|
|
if (a->tls_ca_file && b->tls_ca_file) {
|
|
|
|
if (strcmp(a->tls_ca_file, b->tls_ca_file) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->tls_ca_file || b->tls_ca_file) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* tls_key_file */
|
|
|
|
if (a->tls_key_file && b->tls_key_file) {
|
|
|
|
if (strcmp(a->tls_key_file, b->tls_key_file) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->tls_key_file || b->tls_key_file) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* tls_cert_file */
|
|
|
|
if (a->tls_cert_file && b->tls_cert_file) {
|
|
|
|
if (strcmp(a->tls_cert_file, b->tls_cert_file) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->tls_cert_file || b->tls_cert_file) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* tls_protocols */
|
|
|
|
if (a->tls_protocols && b->tls_protocols) {
|
|
|
|
if (strcmp(a->tls_protocols, b->tls_protocols) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->tls_protocols || b->tls_protocols) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
od_schemeroute_t*
|
2017-08-03 14:03:37 +00:00
|
|
|
od_schemeroute_add(od_scheme_t *scheme, uint64_t version)
|
2017-07-18 12:22:14 +00:00
|
|
|
{
|
2017-07-21 14:29:01 +00:00
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = (od_schemeroute_t*)malloc(sizeof(*route));
|
|
|
|
if (route == NULL)
|
|
|
|
return NULL;
|
|
|
|
memset(route, 0, sizeof(*route));
|
|
|
|
route->version = version;
|
2017-11-23 13:27:16 +00:00
|
|
|
route->pool_size = 0;
|
|
|
|
route->pool_timeout = 0;
|
2017-07-21 14:29:01 +00:00
|
|
|
route->pool_cancel = 1;
|
|
|
|
route->pool_rollback = 1;
|
|
|
|
od_list_init(&route->link);
|
|
|
|
od_list_append(&scheme->routes, &route->link);
|
|
|
|
return route;
|
2017-07-18 12:22:14 +00:00
|
|
|
}
|
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
void od_schemeroute_free(od_schemeroute_t *route)
|
2017-05-24 11:57:15 +00:00
|
|
|
{
|
2017-07-21 14:29:01 +00:00
|
|
|
assert(route->refs == 0);
|
|
|
|
if (route->db_name)
|
|
|
|
free(route->db_name);
|
|
|
|
if (route->user_name)
|
|
|
|
free(route->user_name);
|
|
|
|
if (route->password)
|
|
|
|
free(route->password);
|
|
|
|
if (route->auth)
|
|
|
|
free(route->auth);
|
2017-09-25 14:10:44 +00:00
|
|
|
if (route->auth_query)
|
|
|
|
free(route->auth_query);
|
|
|
|
if (route->auth_query_db)
|
|
|
|
free(route->auth_query_db);
|
|
|
|
if (route->auth_query_user)
|
|
|
|
free(route->auth_query_user);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage)
|
|
|
|
od_schemestorage_free(route->storage);
|
|
|
|
if (route->storage_name)
|
|
|
|
free(route->storage_name);
|
|
|
|
if (route->storage_db)
|
|
|
|
free(route->storage_db);
|
|
|
|
if (route->storage_user)
|
|
|
|
free(route->storage_user);
|
|
|
|
if (route->storage_password)
|
|
|
|
free(route->storage_password);
|
|
|
|
if (route->pool_sz)
|
|
|
|
free(route->pool_sz);
|
|
|
|
od_list_unlink(&route->link);
|
|
|
|
free(route);
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
static inline void
|
|
|
|
od_schemeroute_cmpswap(od_schemeroute_t **dest, od_schemeroute_t *next)
|
2017-05-24 11:57:15 +00:00
|
|
|
{
|
2017-07-21 14:29:01 +00:00
|
|
|
/* update dest if (a) it is not set or (b) previous version is lower
|
2017-07-21 14:32:08 +00:00
|
|
|
* then new version */
|
2017-07-21 14:29:01 +00:00
|
|
|
od_schemeroute_t *prev = *dest;
|
|
|
|
if (prev == NULL) {
|
|
|
|
*dest = next;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
assert( prev->version != next->version);
|
|
|
|
if (prev->version < next->version)
|
|
|
|
*dest = next;
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
od_schemeroute_t*
|
|
|
|
od_schemeroute_forward(od_scheme_t *scheme, char *db_name, char *user_name)
|
2017-07-17 14:05:46 +00:00
|
|
|
{
|
2017-07-21 14:29:01 +00:00
|
|
|
od_schemeroute_t *route_db_user = NULL;
|
|
|
|
od_schemeroute_t *route_db_default = NULL;
|
|
|
|
od_schemeroute_t *route_default_user = NULL;
|
|
|
|
od_schemeroute_t *route_default_default = NULL;
|
|
|
|
|
2017-07-18 12:22:14 +00:00
|
|
|
od_list_t *i;
|
2017-07-21 14:29:01 +00:00
|
|
|
od_list_foreach(&scheme->routes, i) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
|
|
|
if (route->db_is_default) {
|
|
|
|
if (route->user_is_default)
|
|
|
|
od_schemeroute_cmpswap(&route_default_default, route);
|
|
|
|
else
|
|
|
|
if (strcmp(route->user_name, user_name) == 0)
|
|
|
|
od_schemeroute_cmpswap(&route_default_user, route);
|
|
|
|
} else
|
|
|
|
if (strcmp(route->db_name, db_name) == 0) {
|
|
|
|
if (route->user_is_default)
|
|
|
|
od_schemeroute_cmpswap(&route_db_default, route);
|
|
|
|
else
|
|
|
|
if (strcmp(route->user_name, user_name) == 0)
|
|
|
|
od_schemeroute_cmpswap(&route_db_user, route);
|
|
|
|
}
|
2017-07-18 12:22:14 +00:00
|
|
|
}
|
2017-07-17 14:05:46 +00:00
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route_db_user)
|
|
|
|
return route_db_user;
|
2017-07-13 12:58:32 +00:00
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route_db_default)
|
|
|
|
return route_db_default;
|
2017-07-13 12:58:32 +00:00
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route_default_user)
|
|
|
|
return route_default_user;
|
|
|
|
|
|
|
|
return route_default_default;
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
od_schemeroute_t*
|
|
|
|
od_schemeroute_match(od_scheme_t *scheme, char *db_name, char *user_name)
|
2017-05-24 11:57:15 +00:00
|
|
|
{
|
|
|
|
od_list_t *i;
|
2017-07-21 14:29:01 +00:00
|
|
|
od_list_foreach(&scheme->routes, i) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
|
|
|
if (strcmp(route->db_name, db_name) == 0 &&
|
|
|
|
strcmp(route->user_name, user_name) == 0)
|
|
|
|
return route;
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2017-07-24 11:19:56 +00:00
|
|
|
od_schemeroute_t*
|
|
|
|
od_schemeroute_match_latest(od_scheme_t *scheme, char *db_name, char *user_name)
|
|
|
|
{
|
|
|
|
/* match latest route scheme version */
|
|
|
|
od_schemeroute_t *match = NULL;
|
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&scheme->routes, i) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
|
|
|
if (strcmp(route->db_name, db_name) != 0 ||
|
|
|
|
strcmp(route->user_name, user_name) != 0)
|
|
|
|
continue;
|
|
|
|
if (match) {
|
|
|
|
if (match->version < route->version)
|
|
|
|
match = route;
|
|
|
|
} else {
|
|
|
|
match = route;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return match;
|
|
|
|
}
|
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
int od_schemeroute_compare(od_schemeroute_t *a, od_schemeroute_t *b)
|
2017-07-13 12:58:32 +00:00
|
|
|
{
|
2017-07-21 14:29:01 +00:00
|
|
|
/* db default */
|
|
|
|
if (a->db_is_default != b->db_is_default)
|
|
|
|
return 0;
|
2017-07-13 12:58:32 +00:00
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
/* user default */
|
|
|
|
if (a->user_is_default != b->user_is_default)
|
|
|
|
return 0;
|
2017-07-18 12:22:14 +00:00
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
/* password */
|
|
|
|
if (a->password && b->password) {
|
|
|
|
if (strcmp(a->password, b->password) != 0)
|
2017-07-18 12:22:14 +00:00
|
|
|
return 0;
|
|
|
|
} else
|
2017-07-21 14:29:01 +00:00
|
|
|
if (a->password || b->password) {
|
2017-07-18 12:22:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* auth */
|
|
|
|
if (a->auth_mode != b->auth_mode)
|
|
|
|
return 0;
|
|
|
|
|
2017-09-25 14:10:44 +00:00
|
|
|
/* auth_query */
|
|
|
|
if (a->auth_query && b->auth_query) {
|
|
|
|
if (strcmp(a->auth_query, b->auth_query) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->auth_query || b->auth_query) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* auth_query_db */
|
|
|
|
if (a->auth_query_db && b->auth_query_db) {
|
|
|
|
if (strcmp(a->auth_query_db, b->auth_query_db) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->auth_query_db || b->auth_query_db) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* auth_query_user */
|
|
|
|
if (a->auth_query_user && b->auth_query_user) {
|
|
|
|
if (strcmp(a->auth_query_user, b->auth_query_user) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->auth_query_user || b->auth_query_user) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-07-18 12:22:14 +00:00
|
|
|
/* storage */
|
|
|
|
if (strcmp(a->storage_name, b->storage_name) != 0)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (! od_schemestorage_compare(a->storage, b->storage))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* storage_db */
|
|
|
|
if (a->storage_db && b->storage_db) {
|
|
|
|
if (strcmp(a->storage_db, b->storage_db) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
2017-07-19 11:29:23 +00:00
|
|
|
if (a->storage_db || b->storage_db) {
|
2017-07-18 12:22:14 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* storage_user */
|
|
|
|
if (a->storage_user && b->storage_user) {
|
|
|
|
if (strcmp(a->storage_user, b->storage_user) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->storage_user || b->storage_user) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* storage_password */
|
|
|
|
if (a->storage_password && b->storage_password) {
|
|
|
|
if (strcmp(a->storage_password, b->storage_password) != 0)
|
|
|
|
return 0;
|
|
|
|
} else
|
|
|
|
if (a->storage_password || b->storage_password) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* pool */
|
|
|
|
if (a->pool != b->pool)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* pool_size */
|
|
|
|
if (a->pool_size != b->pool_size)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* pool_timeout */
|
|
|
|
if (a->pool_timeout != b->pool_timeout)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* pool_ttl */
|
|
|
|
if (a->pool_ttl != b->pool_ttl)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* pool_cancel */
|
|
|
|
if (a->pool_cancel != b->pool_cancel)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* pool_rollback*/
|
|
|
|
if (a->pool_rollback != b->pool_rollback)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
/* client_max */
|
|
|
|
if (a->client_max != b->client_max)
|
|
|
|
return 0;
|
|
|
|
|
2017-09-12 13:45:04 +00:00
|
|
|
/* client_fwd_error */
|
|
|
|
if (a->client_fwd_error != b->client_fwd_error)
|
|
|
|
return 0;
|
|
|
|
|
2017-12-05 12:32:08 +00:00
|
|
|
/* log_debug */
|
|
|
|
if (a->log_debug != b->log_debug)
|
|
|
|
return 0;
|
|
|
|
|
2017-07-18 12:22:14 +00:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2017-07-26 14:05:29 +00:00
|
|
|
int od_scheme_validate(od_scheme_t *scheme, od_logger_t *logger)
|
2017-05-24 11:57:15 +00:00
|
|
|
{
|
2017-08-31 14:14:58 +00:00
|
|
|
/* workers */
|
|
|
|
if (scheme->workers == 0) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL, "bad workers number");
|
2017-08-31 14:14:58 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2018-02-14 11:55:38 +00:00
|
|
|
/* set pipeline cache chunk watermark to 90% */
|
|
|
|
if (scheme->cache_chunk > 0)
|
|
|
|
scheme->cache_chunk_ra = scheme->cache_chunk - (scheme->cache_chunk / 10);
|
|
|
|
else
|
2018-02-14 12:22:36 +00:00
|
|
|
scheme->cache_chunk_ra = scheme->readahead;
|
2018-02-14 11:55:38 +00:00
|
|
|
|
2017-07-27 12:06:59 +00:00
|
|
|
/* log format */
|
2017-09-21 13:44:19 +00:00
|
|
|
if (scheme->log_format == NULL) {
|
|
|
|
od_error(logger, "config", NULL, NULL, "log is not defined");
|
|
|
|
return -1;
|
2017-07-27 12:06:59 +00:00
|
|
|
}
|
|
|
|
|
2017-05-24 11:57:15 +00:00
|
|
|
/* listen */
|
2017-08-29 14:43:41 +00:00
|
|
|
if (od_list_empty(&scheme->listen)) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL, "no listen servers defined");
|
2017-07-13 12:18:46 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-08-29 14:43:41 +00:00
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&scheme->listen, i) {
|
|
|
|
od_schemelisten_t *listen;
|
|
|
|
listen = od_container_of(i, od_schemelisten_t, link);
|
|
|
|
if (listen->host == NULL) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL, "listen host is not defined");
|
2017-05-24 11:57:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-08-29 14:43:41 +00:00
|
|
|
/* tls */
|
|
|
|
if (listen->tls) {
|
|
|
|
if (strcmp(listen->tls, "disable") == 0) {
|
|
|
|
listen->tls_mode = OD_TLS_DISABLE;
|
|
|
|
} else
|
|
|
|
if (strcmp(listen->tls, "allow") == 0) {
|
|
|
|
listen->tls_mode = OD_TLS_ALLOW;
|
|
|
|
} else
|
|
|
|
if (strcmp(listen->tls, "require") == 0) {
|
|
|
|
listen->tls_mode = OD_TLS_REQUIRE;
|
|
|
|
} else
|
|
|
|
if (strcmp(listen->tls, "verify_ca") == 0) {
|
|
|
|
listen->tls_mode = OD_TLS_VERIFY_CA;
|
|
|
|
} else
|
|
|
|
if (strcmp(listen->tls, "verify_full") == 0) {
|
|
|
|
listen->tls_mode = OD_TLS_VERIFY_FULL;
|
|
|
|
} else {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL, "unknown tls mode");
|
2017-08-29 14:43:41 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
|
2017-06-21 12:18:48 +00:00
|
|
|
/* storages */
|
|
|
|
if (od_list_empty(&scheme->storages)) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL, "no storages defined");
|
2017-05-24 11:57:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-06-21 12:18:48 +00:00
|
|
|
od_list_foreach(&scheme->storages, i) {
|
|
|
|
od_schemestorage_t *storage;
|
|
|
|
storage = od_container_of(i, od_schemestorage_t, link);
|
2017-06-22 12:29:39 +00:00
|
|
|
if (storage->type == NULL) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"storage '%s': no type is specified",
|
2017-06-22 12:29:39 +00:00
|
|
|
storage->name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (strcmp(storage->type, "remote") == 0) {
|
2017-07-28 13:11:52 +00:00
|
|
|
storage->storage_type = OD_STORAGETYPE_REMOTE;
|
2017-06-22 12:29:39 +00:00
|
|
|
} else
|
|
|
|
if (strcmp(storage->type, "local") == 0) {
|
2017-07-28 13:11:52 +00:00
|
|
|
storage->storage_type = OD_STORAGETYPE_LOCAL;
|
2017-06-22 12:29:39 +00:00
|
|
|
} else {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL, "unknown storage type");
|
2017-06-22 12:29:39 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-28 13:11:52 +00:00
|
|
|
if (storage->storage_type == OD_STORAGETYPE_REMOTE &&
|
2017-06-24 14:58:38 +00:00
|
|
|
storage->host == NULL) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"storage '%s': no remote host is specified",
|
2017-06-21 12:18:48 +00:00
|
|
|
storage->name);
|
2017-05-24 11:57:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-06-24 13:04:20 +00:00
|
|
|
if (storage->tls) {
|
|
|
|
if (strcmp(storage->tls, "disable") == 0) {
|
2017-07-28 13:19:53 +00:00
|
|
|
storage->tls_mode = OD_TLS_DISABLE;
|
2017-05-24 11:57:15 +00:00
|
|
|
} else
|
2017-06-24 13:04:20 +00:00
|
|
|
if (strcmp(storage->tls, "allow") == 0) {
|
2017-07-28 13:19:53 +00:00
|
|
|
storage->tls_mode = OD_TLS_ALLOW;
|
2017-05-24 11:57:15 +00:00
|
|
|
} else
|
2017-06-24 13:04:20 +00:00
|
|
|
if (strcmp(storage->tls, "require") == 0) {
|
2017-07-28 13:19:53 +00:00
|
|
|
storage->tls_mode = OD_TLS_REQUIRE;
|
2017-05-24 11:57:15 +00:00
|
|
|
} else
|
2017-06-24 13:04:20 +00:00
|
|
|
if (strcmp(storage->tls, "verify_ca") == 0) {
|
2017-07-28 13:19:53 +00:00
|
|
|
storage->tls_mode = OD_TLS_VERIFY_CA;
|
2017-05-24 11:57:15 +00:00
|
|
|
} else
|
2017-06-24 13:04:20 +00:00
|
|
|
if (strcmp(storage->tls, "verify_full") == 0) {
|
2017-07-28 13:19:53 +00:00
|
|
|
storage->tls_mode = OD_TLS_VERIFY_FULL;
|
2017-05-24 11:57:15 +00:00
|
|
|
} else {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL, "unknown storage tls mode");
|
2017-05-24 11:57:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
/* routes */
|
|
|
|
if (od_list_empty(&scheme->routes)) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL, "no routes defined");
|
2017-07-21 14:29:01 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
od_schemeroute_t *route_default_default = NULL;
|
|
|
|
od_list_foreach(&scheme->routes, i) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
|
|
|
|
|
|
|
/* ensure route default.default exists */
|
|
|
|
if (route->db_is_default && route->user_is_default) {
|
|
|
|
assert(! route_default_default);
|
|
|
|
route_default_default = route;
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
/* match storage and make a copy of in the user scheme */
|
|
|
|
if (route->storage_name == NULL) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': no route storage is specified",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->db_name, route->user_name);
|
2017-05-24 11:57:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-21 14:29:01 +00:00
|
|
|
od_schemestorage_t *storage;
|
|
|
|
storage = od_schemestorage_match(scheme, route->storage_name);
|
|
|
|
if (storage == NULL) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': no route storage '%s' found",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->db_name, route->user_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
route->storage = od_schemestorage_copy(storage);
|
|
|
|
if (route->storage == NULL)
|
|
|
|
return -1;
|
2017-07-13 12:32:05 +00:00
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
/* pooling mode */
|
|
|
|
if (! route->pool_sz) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': pooling mode is not set",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->db_name, route->user_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (strcmp(route->pool_sz, "session") == 0) {
|
2017-07-28 13:13:05 +00:00
|
|
|
route->pool = OD_POOLING_SESSION;
|
2017-07-21 14:29:01 +00:00
|
|
|
} else
|
|
|
|
if (strcmp(route->pool_sz, "transaction") == 0) {
|
2017-07-28 13:13:05 +00:00
|
|
|
route->pool = OD_POOLING_TRANSACTION;
|
2017-07-21 14:29:01 +00:00
|
|
|
} else {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': unknown pooling mode",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->db_name, route->user_name);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-07-03 14:32:48 +00:00
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
/* auth */
|
|
|
|
if (! route->auth) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': authentication mode is not defined",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->db_name, route->user_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (strcmp(route->auth, "none") == 0) {
|
2017-07-28 13:14:21 +00:00
|
|
|
route->auth_mode = OD_AUTH_NONE;
|
2017-07-21 14:29:01 +00:00
|
|
|
} else
|
|
|
|
if (strcmp(route->auth, "block") == 0) {
|
2017-07-28 13:14:21 +00:00
|
|
|
route->auth_mode = OD_AUTH_BLOCK;
|
2017-07-21 14:29:01 +00:00
|
|
|
} else
|
|
|
|
if (strcmp(route->auth, "clear_text") == 0) {
|
2017-07-28 13:14:21 +00:00
|
|
|
route->auth_mode = OD_AUTH_CLEAR_TEXT;
|
2017-10-02 13:42:40 +00:00
|
|
|
|
|
|
|
if (route->password == NULL && route->auth_query == NULL) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': password is not set",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->db_name, route->user_name);
|
2017-07-03 14:32:48 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-07-21 14:29:01 +00:00
|
|
|
} else
|
|
|
|
if (strcmp(route->auth, "md5") == 0) {
|
2017-07-28 13:14:21 +00:00
|
|
|
route->auth_mode = OD_AUTH_MD5;
|
2017-10-02 13:42:40 +00:00
|
|
|
if (route->password == NULL && route->auth_query == NULL) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': password is not set",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->db_name, route->user_name);
|
2017-05-24 11:57:15 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2017-09-28 14:21:59 +00:00
|
|
|
} else {
|
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': has unknown authentication mode",
|
|
|
|
route->db_name, route->user_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* auth_query */
|
|
|
|
if (route->auth_query) {
|
2017-09-28 14:11:09 +00:00
|
|
|
if (route->auth_query_user == NULL) {
|
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': auth_query_user is not set",
|
|
|
|
route->db_name, route->user_name);
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (route->auth_query_db == NULL) {
|
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route '%s.%s': auth_query_db is not set",
|
|
|
|
route->db_name, route->user_name);
|
|
|
|
return -1;
|
|
|
|
}
|
2017-07-18 12:41:00 +00:00
|
|
|
}
|
|
|
|
}
|
2017-08-31 14:14:58 +00:00
|
|
|
|
2017-07-21 14:29:01 +00:00
|
|
|
if (! route_default_default) {
|
2017-09-21 13:44:19 +00:00
|
|
|
od_error(logger, "config", NULL, NULL,
|
|
|
|
"route 'default.default': not defined");
|
2017-07-18 12:41:00 +00:00
|
|
|
return -1;
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
2017-07-03 14:32:48 +00:00
|
|
|
|
2017-07-20 12:39:13 +00:00
|
|
|
/* cleanup declarative storages scheme data */
|
|
|
|
od_list_t *n;
|
|
|
|
od_list_foreach_safe(&scheme->storages, i, n) {
|
|
|
|
od_schemestorage_t *storage;
|
|
|
|
storage = od_container_of(i, od_schemestorage_t, link);
|
|
|
|
od_schemestorage_free(storage);
|
|
|
|
}
|
|
|
|
od_list_init(&scheme->storages);
|
2017-05-24 11:57:15 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-06-01 09:45:49 +00:00
|
|
|
static inline char*
|
|
|
|
od_scheme_yes_no(int value) {
|
|
|
|
return value ? "yes" : "no";
|
|
|
|
}
|
|
|
|
|
2017-07-26 14:05:29 +00:00
|
|
|
void od_scheme_print(od_scheme_t *scheme, od_logger_t *logger, int routes_only)
|
2017-05-24 11:57:15 +00:00
|
|
|
{
|
2017-10-30 14:25:17 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"daemonize %s",
|
|
|
|
od_scheme_yes_no(scheme->daemonize));
|
2017-09-18 13:14:52 +00:00
|
|
|
if (scheme->pid_file)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"pid_file %s", scheme->pid_file);
|
2017-07-24 12:06:18 +00:00
|
|
|
if (routes_only)
|
|
|
|
goto log_routes;
|
2017-09-21 13:44:19 +00:00
|
|
|
if (scheme->log_format)
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_format %s", scheme->log_format);
|
2017-09-18 13:14:52 +00:00
|
|
|
if (scheme->log_file)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_file %s", scheme->log_file);
|
2017-10-30 14:25:17 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_to_stdout %s",
|
|
|
|
od_scheme_yes_no(scheme->log_to_stdout));
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_syslog %s",
|
|
|
|
od_scheme_yes_no(scheme->log_syslog));
|
2017-09-18 13:14:52 +00:00
|
|
|
if (scheme->log_syslog_ident)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_syslog_ident %s", scheme->log_syslog_ident);
|
2017-09-18 13:14:52 +00:00
|
|
|
if (scheme->log_syslog_facility)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_syslog_facility %s", scheme->log_syslog_facility);
|
2017-10-30 14:25:17 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_debug %s",
|
|
|
|
od_scheme_yes_no(scheme->log_debug));
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_config %s",
|
|
|
|
od_scheme_yes_no(scheme->log_config));
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_session %s",
|
|
|
|
od_scheme_yes_no(scheme->log_session));
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_query %s",
|
|
|
|
od_scheme_yes_no(scheme->log_query));
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"log_stats %s",
|
|
|
|
od_scheme_yes_no(scheme->log_stats));
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"stats_interval %d", scheme->stats_interval);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"readahead %d", scheme->readahead);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
2017-12-13 18:39:03 +00:00
|
|
|
"nodelay %s",
|
2017-12-12 15:16:35 +00:00
|
|
|
od_scheme_yes_no(scheme->nodelay));
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"keepalive %d", scheme->keepalive);
|
2017-06-19 10:55:49 +00:00
|
|
|
if (scheme->client_max_set)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"client_max %d", scheme->client_max);
|
2018-02-14 11:55:38 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"cache %d", scheme->cache);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"cache_chunk %d", scheme->cache_chunk);
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"workers %d", scheme->workers);
|
|
|
|
od_log(logger, "config", NULL, NULL, "");
|
2017-05-24 11:57:15 +00:00
|
|
|
od_list_t *i;
|
2017-09-21 13:44:19 +00:00
|
|
|
od_list_foreach(&scheme->listen, i)
|
|
|
|
{
|
2017-08-29 14:43:41 +00:00
|
|
|
od_schemelisten_t *listen;
|
|
|
|
listen = od_container_of(i, od_schemelisten_t, link);
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL, "listen");
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" host %s", listen->host);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" port %d", listen->port);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" backlog %d", listen->backlog);
|
2017-08-29 14:43:41 +00:00
|
|
|
if (listen->tls)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls %s", listen->tls);
|
2017-08-29 14:43:41 +00:00
|
|
|
if (listen->tls_ca_file)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls_ca_file %s", listen->tls_ca_file);
|
2017-08-29 14:43:41 +00:00
|
|
|
if (listen->tls_key_file)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls_key_file %s", listen->tls_key_file);
|
2017-08-29 14:43:41 +00:00
|
|
|
if (listen->tls_cert_file)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls_cert_file %s", listen->tls_cert_file);
|
2017-08-29 14:43:41 +00:00
|
|
|
if (listen->tls_protocols)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls_protocols %s", listen->tls_protocols);
|
|
|
|
od_log(logger, "config", NULL, NULL, "");
|
2017-08-29 14:43:41 +00:00
|
|
|
}
|
|
|
|
log_routes:;
|
2017-07-21 14:29:01 +00:00
|
|
|
od_list_foreach(&scheme->routes, i) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL, "route %s.%s.%d %s",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->db_name,
|
2017-07-24 12:06:18 +00:00
|
|
|
route->user_name, route->version,
|
|
|
|
route->is_obsolete ? "(obsolete)" : "");
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" authentication %s", route->auth);
|
2017-09-25 14:10:44 +00:00
|
|
|
if (route->auth_query)
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" auth_query %s", route->auth_query);
|
|
|
|
if (route->auth_query_db)
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" auth_query_db %s", route->auth_query_db);
|
|
|
|
if (route->auth_query_user)
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" auth_query_user %s", route->auth_query_user);
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" pool %s", route->pool_sz);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" pool_size %d", route->pool_size);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" pool_timeout %d", route->pool_timeout);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" pool_ttl %d", route->pool_ttl);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" pool_cancel %s",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->pool_cancel ? "yes" : "no");
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" pool_rollback %s",
|
2017-07-21 14:29:01 +00:00
|
|
|
route->pool_rollback ? "yes" : "no");
|
|
|
|
if (route->client_max_set)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" client_max %d", route->client_max);
|
2017-10-30 14:25:17 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" client_fwd_error %s",
|
|
|
|
od_scheme_yes_no(route->client_fwd_error));
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" storage %s", route->storage_name);
|
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" type %s", route->storage->type);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage->host)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" host %s", route->storage->host);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage->port)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" port %d", route->storage->port);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage->tls)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls %s", route->storage->tls);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage->tls_ca_file)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger,"config", NULL, NULL,
|
|
|
|
" tls_ca_file %s", route->storage->tls_ca_file);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage->tls_key_file)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls_key_file %s", route->storage->tls_key_file);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage->tls_cert_file)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls_cert_file %s", route->storage->tls_cert_file);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage->tls_protocols)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" tls_protocols %s", route->storage->tls_protocols);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage_db)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" storage_db %s", route->storage_db);
|
2017-07-21 14:29:01 +00:00
|
|
|
if (route->storage_user)
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" storage_user %s", route->storage_user);
|
2017-12-05 12:32:08 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
" log_debug %s",
|
|
|
|
od_scheme_yes_no(route->log_debug));
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL, "");
|
2017-05-24 11:57:15 +00:00
|
|
|
}
|
|
|
|
}
|
2017-07-18 12:22:14 +00:00
|
|
|
|
2017-07-26 14:05:29 +00:00
|
|
|
int od_scheme_merge(od_scheme_t *scheme, od_logger_t *logger, od_scheme_t *src)
|
2017-07-18 12:22:14 +00:00
|
|
|
{
|
|
|
|
int count_obsolete = 0;
|
2017-07-19 15:25:44 +00:00
|
|
|
int count_deleted = 0;
|
2017-07-18 12:22:14 +00:00
|
|
|
int count_new = 0;
|
|
|
|
|
2017-07-24 11:19:56 +00:00
|
|
|
/* mark all routes obsolete */
|
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&scheme->routes, i) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
|
|
|
route->is_obsolete = 1;
|
2017-07-18 12:22:14 +00:00
|
|
|
count_obsolete++;
|
|
|
|
}
|
|
|
|
|
2017-07-24 11:19:56 +00:00
|
|
|
/* select new routes */
|
|
|
|
od_list_t *n;
|
|
|
|
od_list_foreach_safe(&src->routes, i, n) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
2017-07-18 12:22:14 +00:00
|
|
|
|
2017-07-24 11:19:56 +00:00
|
|
|
/* find and compare origin route */
|
|
|
|
od_schemeroute_t *origin;
|
|
|
|
origin = od_schemeroute_match_latest(scheme, route->db_name, route->user_name);
|
2017-07-18 12:22:14 +00:00
|
|
|
if (origin) {
|
2017-07-24 11:19:56 +00:00
|
|
|
if (od_schemeroute_compare(origin, route)) {
|
2017-07-18 12:22:14 +00:00
|
|
|
origin->is_obsolete = 0;
|
|
|
|
count_obsolete--;
|
|
|
|
continue;
|
|
|
|
}
|
2017-07-18 12:41:00 +00:00
|
|
|
|
2017-07-18 12:22:14 +00:00
|
|
|
/* add new version, origin version still exists */
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"update route %s.%s.%d -> %s.%s.%d",
|
2017-07-24 12:06:18 +00:00
|
|
|
origin->db_name, origin->user_name,
|
|
|
|
origin->version,
|
|
|
|
route->db_name, route->user_name,
|
|
|
|
route->version);
|
2017-07-18 12:22:14 +00:00
|
|
|
} else {
|
|
|
|
/* add new version */
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"new route %s.%s.%d",
|
2017-07-24 12:06:18 +00:00
|
|
|
route->db_name, route->user_name,
|
|
|
|
route->version);
|
2017-07-18 12:22:14 +00:00
|
|
|
}
|
2017-07-19 15:25:44 +00:00
|
|
|
|
2017-07-24 11:19:56 +00:00
|
|
|
od_list_unlink(&route->link);
|
|
|
|
od_list_init(&route->link);
|
|
|
|
od_list_append(&scheme->routes, &route->link);
|
2017-07-19 15:25:44 +00:00
|
|
|
|
2017-07-18 12:22:14 +00:00
|
|
|
count_new++;
|
|
|
|
}
|
|
|
|
|
2017-07-19 15:25:44 +00:00
|
|
|
/* try to free obsolete schemes, which are unused by any
|
|
|
|
* route at the moment */
|
|
|
|
if (count_obsolete) {
|
2017-07-24 11:19:56 +00:00
|
|
|
od_list_foreach_safe(&scheme->routes, i, n) {
|
|
|
|
od_schemeroute_t *route;
|
|
|
|
route = od_container_of(i, od_schemeroute_t, link);
|
|
|
|
if (route->is_obsolete && route->refs == 0) {
|
|
|
|
od_schemeroute_free(route);
|
2017-07-19 15:25:44 +00:00
|
|
|
count_deleted++;
|
|
|
|
count_obsolete--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-21 13:44:19 +00:00
|
|
|
od_log(logger, "config", NULL, NULL,
|
|
|
|
"%d routes added, %d removed, %d scheduled for removal",
|
2017-07-19 15:25:44 +00:00
|
|
|
count_new, count_deleted,
|
|
|
|
count_obsolete);
|
2017-07-24 12:06:18 +00:00
|
|
|
|
|
|
|
return count_new + count_obsolete + count_deleted;
|
2017-07-18 12:22:14 +00:00
|
|
|
}
|