2020-06-09 09:19:11 +00:00
|
|
|
/*
|
|
|
|
* Odyssey.
|
|
|
|
*
|
|
|
|
* Scalable PostgreSQL connection pooler.
|
|
|
|
*/
|
|
|
|
|
2020-11-27 18:03:42 +00:00
|
|
|
#include <machinarium.h>
|
|
|
|
#include <odyssey.h>
|
2020-06-09 09:19:11 +00:00
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
void od_modules_init(od_module_t *module)
|
2020-06-09 09:19:11 +00:00
|
|
|
{
|
|
|
|
od_list_init(&module->link);
|
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
int od_target_module_add(od_logger_t *logger, od_module_t *modules,
|
|
|
|
char *target_module_path)
|
2020-06-09 09:19:11 +00:00
|
|
|
{
|
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&modules->link, i)
|
|
|
|
{
|
|
|
|
od_module_t *m;
|
|
|
|
m = od_container_of(i, od_module_t, link);
|
|
|
|
if (strcmp(m->path, target_module_path) == 0) {
|
|
|
|
goto module_exists;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void *handle;
|
|
|
|
od_module_t *module_ptr;
|
|
|
|
char *err;
|
|
|
|
|
|
|
|
handle = od_dlopen(target_module_path);
|
|
|
|
if (!handle) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
module_ptr = od_load_module(handle);
|
2020-06-15 08:26:58 +00:00
|
|
|
if ((err = dlerror()) != NULL) {
|
2020-06-14 07:29:16 +00:00
|
|
|
goto error_close_handle;
|
2020-06-09 09:19:11 +00:00
|
|
|
}
|
|
|
|
|
2020-06-14 13:28:43 +00:00
|
|
|
if (strlen(module_ptr->path) + strlen(target_module_path) + 1 >
|
|
|
|
sizeof(module_ptr->path))
|
|
|
|
goto error_close_handle;
|
|
|
|
|
2020-06-09 09:19:11 +00:00
|
|
|
module_ptr->handle = handle;
|
|
|
|
od_list_init(&module_ptr->link);
|
|
|
|
od_list_append(&modules->link, &module_ptr->link);
|
|
|
|
strcat(module_ptr->path, target_module_path);
|
|
|
|
|
2020-11-23 09:13:28 +00:00
|
|
|
if (module_ptr->module_init_cb) {
|
2020-06-15 08:26:58 +00:00
|
|
|
return module_ptr->module_init_cb();
|
2020-11-23 09:13:28 +00:00
|
|
|
}
|
|
|
|
|
2020-06-09 09:19:11 +00:00
|
|
|
return OD_MODULE_CB_OK_RETCODE;
|
|
|
|
|
|
|
|
module_exists:
|
|
|
|
if (logger == NULL) {
|
2021-04-07 17:47:28 +00:00
|
|
|
/* most probably its logger is not ready yet */
|
2020-06-09 09:19:11 +00:00
|
|
|
} else {
|
2020-12-28 10:43:31 +00:00
|
|
|
od_log(logger, "od_load_module", NULL, NULL,
|
2021-03-18 16:47:51 +00:00
|
|
|
"od_load_module: skip load module %s: was already loaded!",
|
2020-06-09 09:19:11 +00:00
|
|
|
target_module_path);
|
|
|
|
}
|
|
|
|
return OD_MODULE_CB_FAIL_RETCODE;
|
2020-06-14 07:29:16 +00:00
|
|
|
|
|
|
|
error_close_handle:
|
|
|
|
od_dlclose(handle);
|
2020-06-09 09:19:11 +00:00
|
|
|
error:
|
|
|
|
err = od_dlerror();
|
2021-03-18 17:29:54 +00:00
|
|
|
if (logger) {
|
2020-12-28 10:43:31 +00:00
|
|
|
od_log(logger, "od_load_module", NULL, NULL,
|
|
|
|
"od_load_module: failed to load module %s", err);
|
2020-06-09 09:19:11 +00:00
|
|
|
}
|
|
|
|
return OD_MODULE_CB_FAIL_RETCODE;
|
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
static inline void od_module_free(od_module_t *module)
|
2020-06-09 09:19:11 +00:00
|
|
|
{
|
|
|
|
od_list_unlink(&module->link);
|
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
int od_target_module_unload(od_logger_t *logger, od_module_t *modules,
|
|
|
|
char *target_module)
|
2020-06-09 09:19:11 +00:00
|
|
|
{
|
|
|
|
char *err;
|
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&modules->link, i)
|
|
|
|
{
|
|
|
|
od_module_t *m;
|
|
|
|
m = od_container_of(i, od_module_t, link);
|
|
|
|
if (strcmp(m->path, target_module) == 0) {
|
|
|
|
int rc;
|
|
|
|
rc = m->unload_cb();
|
|
|
|
if (rc != OD_MODULE_CB_OK_RETCODE)
|
|
|
|
return -1;
|
2020-12-28 10:43:31 +00:00
|
|
|
void *h = m->handle;
|
2020-06-09 09:19:11 +00:00
|
|
|
m->handle = NULL;
|
|
|
|
od_module_free(m);
|
|
|
|
// because we cannot access handle after calling dlclose
|
|
|
|
if (od_dlclose(h)) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
return OD_MODULE_CB_OK_RETCODE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
od_log(logger, "od target module unload failed", NULL, NULL,
|
2020-06-09 09:19:11 +00:00
|
|
|
"od_module_unload: failed to find specified module to unload %s",
|
|
|
|
target_module);
|
|
|
|
|
|
|
|
return OD_MODULE_CB_FAIL_RETCODE;
|
|
|
|
error:
|
|
|
|
err = od_dlerror();
|
2020-12-28 10:43:31 +00:00
|
|
|
od_log(logger, "od unload module error", NULL, NULL,
|
|
|
|
"od_module_unload: %s", err);
|
2020-06-09 09:19:11 +00:00
|
|
|
|
|
|
|
return OD_MODULE_CB_FAIL_RETCODE;
|
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
int od_modules_unload(od_logger_t *logger, od_module_t *modules)
|
2020-06-09 09:19:11 +00:00
|
|
|
{
|
|
|
|
char *err;
|
|
|
|
od_list_t *i, *n;
|
|
|
|
od_list_foreach_safe(&modules->link, i, n)
|
|
|
|
{
|
|
|
|
od_module_t *m;
|
|
|
|
m = od_container_of(i, od_module_t, link);
|
|
|
|
int rc;
|
|
|
|
rc = m->unload_cb();
|
|
|
|
if (rc != OD_MODULE_CB_OK_RETCODE)
|
|
|
|
return -1;
|
2020-12-28 10:43:31 +00:00
|
|
|
void *h = m->handle;
|
2020-06-09 09:19:11 +00:00
|
|
|
m->handle = NULL;
|
|
|
|
od_module_free(m);
|
|
|
|
// because we cannot access handle after calling dlclose
|
|
|
|
if (od_dlclose(h)) {
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
}
|
2020-11-23 09:13:28 +00:00
|
|
|
|
2020-06-09 09:19:11 +00:00
|
|
|
return OD_MODULE_CB_OK_RETCODE;
|
|
|
|
error:
|
|
|
|
err = od_dlerror();
|
2020-12-28 10:43:31 +00:00
|
|
|
od_log(logger, "od unload module error", NULL, NULL,
|
|
|
|
"od_module_unload: %s", err);
|
2020-06-09 09:19:11 +00:00
|
|
|
|
|
|
|
return OD_MODULE_CB_FAIL_RETCODE;
|
|
|
|
}
|
|
|
|
|
2020-12-28 10:43:31 +00:00
|
|
|
int od_modules_unload_fast(od_module_t *modules)
|
2020-06-09 09:19:11 +00:00
|
|
|
{
|
|
|
|
od_list_t *i;
|
|
|
|
od_list_foreach(&modules->link, i)
|
|
|
|
{
|
|
|
|
od_module_t *m;
|
2020-12-28 10:43:31 +00:00
|
|
|
m = od_container_of(i, od_module_t, link);
|
|
|
|
void *h = m->handle;
|
2020-06-09 09:19:11 +00:00
|
|
|
m->handle = NULL;
|
|
|
|
od_module_free(m);
|
|
|
|
// because we cannot access handle after calling dlclose
|
|
|
|
if (od_dlclose(h)) {
|
|
|
|
return OD_MODULE_CB_FAIL_RETCODE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return OD_MODULE_CB_OK_RETCODE;
|
|
|
|
}
|