You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
proxysql/lib/ProxySQL_PluginManager.cpp

132 lines
2.8 KiB

#include "ProxySQL_PluginManager.h"
#include <dlfcn.h>
#include <cstring>
namespace {
std::string format_dl_error(const char *prefix) {
const char *dl_err = dlerror();
if (dl_err == nullptr) {
return prefix;
}
return std::string(prefix) + dl_err;
}
} // namespace
ProxySQL_PluginManager::ProxySQL_PluginManager() : services_{} {}
ProxySQL_PluginManager::~ProxySQL_PluginManager() {
stop_all();
for (auto it = plugins_.rbegin(); it != plugins_.rend(); ++it) {
if (it->handle != nullptr) {
dlclose(it->handle);
it->handle = nullptr;
}
}
}
bool ProxySQL_PluginManager::load(const std::string &path, std::string &err) {
err.clear();
void *handle = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
if (handle == nullptr) {
err = format_dl_error("dlopen failed: ");
return false;
}
dlerror();
auto descriptor_fn = reinterpret_cast<proxysql_plugin_descriptor_v1_t>(
dlsym(handle, "proxysql_plugin_descriptor_v1"));
const char *dlsym_err = dlerror();
if (dlsym_err != nullptr || descriptor_fn == nullptr) {
err = dlsym_err != nullptr ? dlsym_err : "missing proxysql_plugin_descriptor_v1";
dlclose(handle);
return false;
}
const ProxySQL_PluginDescriptor *descriptor = descriptor_fn();
if (descriptor == nullptr) {
err = "proxysql_plugin_descriptor_v1 returned null";
dlclose(handle);
return false;
}
if (descriptor->abi_version != 1) {
err = "unsupported plugin ABI version";
dlclose(handle);
return false;
}
plugin_handle_t plugin;
plugin.handle = handle;
plugin.descriptor = descriptor;
plugins_.push_back(plugin);
return true;
}
bool ProxySQL_PluginManager::init_all(std::string &err) {
err.clear();
for (auto &plugin : plugins_) {
if (plugin.initialized || plugin.stopped) {
continue;
}
if (plugin.descriptor == nullptr || plugin.descriptor->init == nullptr) {
plugin.initialized = true;
continue;
}
if (!plugin.descriptor->init(&services_, err)) {
return false;
}
plugin.initialized = true;
}
return true;
}
bool ProxySQL_PluginManager::start_all(std::string &err) {
err.clear();
for (auto &plugin : plugins_) {
if (plugin.started || plugin.stopped) {
continue;
}
if (plugin.descriptor == nullptr || plugin.descriptor->start == nullptr) {
plugin.started = true;
continue;
}
if (!plugin.descriptor->start(err)) {
return false;
}
plugin.started = true;
}
return true;
}
bool ProxySQL_PluginManager::stop_all() {
bool ok = true;
for (auto it = plugins_.rbegin(); it != plugins_.rend(); ++it) {
if (!it->initialized && !it->started) {
continue;
}
if (it->stopped) {
continue;
}
if (it->descriptor != nullptr && it->descriptor->stop != nullptr) {
ok = it->descriptor->stop() && ok;
}
it->stopped = true;
}
return ok;
}
size_t ProxySQL_PluginManager::size() const {
return plugins_.size();
}