From 2019c6419e247877615cae680df59bb519cc0a8e Mon Sep 17 00:00:00 2001 From: reshke Date: Fri, 7 May 2021 00:58:11 +0500 Subject: [PATCH] odyssey configuration from CLI --- odyssey-dev.conf | 2 +- sources/CMakeLists.txt | 3 +- sources/instance.c | 79 ++++++++++++++++++++++++++++++++---------- sources/instance.h | 1 + sources/odyssey.h | 1 + sources/option.c | 43 +++++++++++++++++++++++ sources/option.h | 77 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 185 insertions(+), 21 deletions(-) create mode 100644 sources/option.c create mode 100644 sources/option.h diff --git a/odyssey-dev.conf b/odyssey-dev.conf index f239de4c..2364b2fb 100644 --- a/odyssey-dev.conf +++ b/odyssey-dev.conf @@ -1,5 +1,5 @@ pid_file "/tmp/odyssey.pid" -daemonize no +daemonize yes unix_socket_dir "/tmp" unix_socket_mode "0644" diff --git a/sources/CMakeLists.txt b/sources/CMakeLists.txt index d364bcd5..ca3b8bff 100644 --- a/sources/CMakeLists.txt +++ b/sources/CMakeLists.txt @@ -39,7 +39,8 @@ set(od_src watchdog.c ejection.c thread_global.c - compression.c) + compression.c + option.c) if (PAM_FOUND) list(APPEND od_src pam.c) diff --git a/sources/instance.c b/sources/instance.c index 23538fe3..300e2c43 100644 --- a/sources/instance.c +++ b/sources/instance.c @@ -37,12 +37,31 @@ void od_instance_free(od_instance_t *instance) od_config_free(&instance->config); // as mallocd on start free(instance->config_file); + free(instance->exec_path); od_log(&instance->logger, "shutdown", NULL, NULL, "Stopping Odyssey"); od_logger_close(&instance->logger); machinarium_free(); } -static inline void od_usage(od_instance_t *instance, char *path) +static inline void od_bind_args(struct argp *argp) +{ + /* Program documentation. */ + static char doc[] = "Odyssey - scalable postgresql connection pooler"; + + /* A description of the arguments we accept. */ + static char args_doc[] = "odyssey.conf [ --opt1 ...]"; + + memset(argp, 0, sizeof(struct argp)); + argp->options = options; + argp->parser = parse_opt; + argp->args_doc = args_doc; + argp->doc = doc; +} + +const char *argp_program_version; +const char *argp_program_bug_address = ""; + +void od_usage(od_instance_t *instance, char *path) { od_log(&instance->logger, "init", NULL, NULL, "odyssey (git: %s %s)", OD_VERSION_GIT, OD_VERSION_BUILD); @@ -50,8 +69,42 @@ static inline void od_usage(od_instance_t *instance, char *path) path); } +static inline void od_bind_version() +{ + od_asprintf(&argp_program_version, "odyssey (git: %s %s %s)", + OD_VERSION_NUMBER, OD_VERSION_GIT, OD_VERSION_BUILD); +} + +static inline od_retcode_t od_args_init(od_arguments_t *args, + od_instance_t *instance) +{ + args->silent = 0; + args->verbose = 0; + args->console = 0; + args->instance = instance; + return OK_RESPONSE; +} + int od_instance_main(od_instance_t *instance, int argc, char **argv) { + od_arguments_t args; + struct argp argp; + od_bind_args(&argp); + od_bind_version(); + + // odyssey accept only ONE positional arg - to path config + if (od_args_init(&args, instance) != OK_RESPONSE) { + goto error; + } + instance->exec_path = strdup(argv[0]); + /* validate command line options */ + int argindx; // index of fisrt unparsed indx + if (argp_parse(&argp, argc, argv, 0, &argindx, &args) != OK_RESPONSE) { + goto error; + } + + od_log(&instance->logger, "startup", NULL, NULL, "Starting Odyssey"); + /* prepare system services */ od_system_t system; od_router_t router; @@ -60,32 +113,14 @@ int od_instance_main(od_instance_t *instance, int argc, char **argv) od_extention_t extentions; od_global_t global; - od_log(&instance->logger, "startup", NULL, NULL, "Starting Odyssey"); - od_system_init(&system); od_router_init(&router, &global); od_cron_init(&cron); od_worker_pool_init(&worker_pool); - //od_modules_init(&modules); od_extentions_init(&extentions); od_global_init(&global, instance, &system, &router, &cron, &worker_pool, &extentions); - /* validate command line options */ - if (argc != 2) { - od_usage(instance, argv[0]); - goto error; - } - if (strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { - od_usage(instance, argv[0]); - od_router_free(&router); - return 0; - } - - // do not use argv point as it may contain invalid data atfer setproctitle() - instance->config_file = malloc(sizeof(char) * (1 + strlen(argv[1]))); - strcpy(instance->config_file, argv[1]); - /* read config file */ od_error_t error; od_error_init(&error); @@ -111,6 +146,12 @@ int od_instance_main(od_instance_t *instance, int argc, char **argv) goto error; } + rc = od_apply_validate_cli_args(&instance->logger, &instance->config, + &args); + if (rc != OK_RESPONSE) { + goto error; + } + /* configure logger */ od_logger_set_format(&instance->logger, instance->config.log_format); od_logger_set_debug(&instance->logger, instance->config.log_debug); diff --git a/sources/instance.h b/sources/instance.h index 08240f10..c9b3922d 100644 --- a/sources/instance.h +++ b/sources/instance.h @@ -14,6 +14,7 @@ struct od_instance { od_pid_t pid; od_logger_t logger; char *config_file; + char *exec_path; od_config_t config; char *orig_argv_ptr; int64_t shutdown_worker_id; diff --git a/sources/odyssey.h b/sources/odyssey.h index c61c36b9..2a9f7741 100644 --- a/sources/odyssey.h +++ b/sources/odyssey.h @@ -100,6 +100,7 @@ #include "sources/router_cancel.h" #include "sources/router.h" #include "sources/instance.h" +#include "sources/option.h" #include "sources/cron.h" #include "sources/system.h" #include "sources/sighandler.h" diff --git a/sources/option.c b/sources/option.c new file mode 100644 index 00000000..f9cbe5e6 --- /dev/null +++ b/sources/option.c @@ -0,0 +1,43 @@ + + +/* + * Odyssey. + * + * Scalable PostgreSQL connection pooler. + */ + +#include +#include + +od_retcode_t od_apply_validate_cli_args(od_logger_t *logger, od_config_t *conf, + od_arguments_t *args) +{ + if (conf->daemonize && !args->console) { + od_dbg_printf_on_dvl_lvl( + 1, + "daemonize config opt is %d and console flag is %d, so daemonizing process\n", + conf->daemonize, args->console); + conf->daemonize |= args->console; + } else { + conf->daemonize = 0; + } + + if (args->silent && args->verbose) { + od_log(logger, "startup", NULL, NULL, + "silent and verbose option both specified"); + return NOT_OK_RESPONSE; + } + + if (args->silent) { + conf->log_debug = 0; + conf->log_session = 0; + conf->log_query = 0; + } + if (args->verbose) { + conf->log_debug = 1; + conf->log_session = 1; + conf->log_query = 1; + } + + return OK_RESPONSE; +} diff --git a/sources/option.h b/sources/option.h new file mode 100644 index 00000000..a2ca259e --- /dev/null +++ b/sources/option.h @@ -0,0 +1,77 @@ +#ifndef OD_OPTION_H +#define OD_OPTION_H + +#include +#include + +extern void od_usage(od_instance_t *instance, char *path); + +typedef struct { + od_instance_t *instance; + int silent; + int verbose; + int console; +} od_arguments_t; + +enum { OD_OPT_CONSOLE = 10001, // >= than any utf symbol like -q -l etc + OD_OPT_SILENT = 10002, + OD_OPT_VERBOSE = 10003, +} od_cli_options; + +static struct argp_option options[] = { + { "verbose", OD_OPT_VERBOSE, 0, 0, "do log everything" }, + { "silent", OD_OPT_SILENT, 0, 0, "do not log anything" }, + { "console", OD_OPT_CONSOLE, 0, 0, "do not fork on startup" }, + { 0 } +}; + +static inline error_t parse_opt(int key, char *arg, struct argp_state *state) +{ + /* Get the input argument from argp_parse, which we + know is a pointer to our arguments structure. */ + od_arguments_t *arguments = state->input; + od_instance_t *instance = arguments->instance; + + switch (key) { + case 'q': + case 's': + case OD_OPT_SILENT: + arguments->silent = 1; + break; + case 'v': + case OD_OPT_VERBOSE: + arguments->verbose = 1; + break; + case 'h': { + od_usage(instance, instance->exec_path); + } break; + case OD_OPT_CONSOLE: { + arguments->console = 1; + } break; + case ARGP_KEY_ARG: { + if (state->arg_num >= 1) { + /* Too many arguments. */ + od_usage(instance, instance->exec_path); + return ARGP_KEY_ERROR; + } + + instance->config_file = strdup(arg); + } break; + case ARGP_KEY_END: + if (state->arg_num < 1) { + /* Not enough arguments. */ + od_usage(instance, instance->exec_path); + return ARGP_KEY_ERROR; + } + break; + + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +extern od_retcode_t od_apply_validate_cli_args(od_logger_t *logger, + od_config_t *conf, + od_arguments_t *args); +#endif // OD_OPTION_H