mirror of
https://github.com/matrix-construct/construct
synced 2024-11-15 14:31:11 +01:00
ircd::mods: Interface modernization; various cleanup; reorg.
This commit is contained in:
parent
8050628748
commit
f36af09789
8 changed files with 265 additions and 250 deletions
|
@ -32,13 +32,13 @@ struct ircd::mods::import_shared
|
||||||
operator T &() { return std::shared_ptr<T>::operator*(); }
|
operator T &() { return std::shared_ptr<T>::operator*(); }
|
||||||
|
|
||||||
import_shared() = default;
|
import_shared() = default;
|
||||||
import_shared(module, const std::string &symname);
|
import_shared(module, const string_view &symname);
|
||||||
import_shared(const std::string &modname, const std::string &symname);
|
import_shared(const string_view &modname, const string_view &symname);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
ircd::mods::import_shared<T>::import_shared(const std::string &modname,
|
ircd::mods::import_shared<T>::import_shared(const string_view &modname,
|
||||||
const std::string &symname)
|
const string_view &symname)
|
||||||
:import_shared
|
:import_shared
|
||||||
{
|
{
|
||||||
module(modname), symname
|
module(modname), symname
|
||||||
|
@ -47,7 +47,7 @@ ircd::mods::import_shared<T>::import_shared(const std::string &modname,
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
ircd::mods::import_shared<T>::import_shared(module module,
|
ircd::mods::import_shared<T>::import_shared(module module,
|
||||||
const std::string &symname)
|
const string_view &symname)
|
||||||
:import<std::shared_ptr<T>>
|
:import<std::shared_ptr<T>>
|
||||||
{
|
{
|
||||||
module, symname
|
module, symname
|
||||||
|
|
|
@ -24,6 +24,14 @@ namespace ircd::mods
|
||||||
|
|
||||||
string_view name(const mod &);
|
string_view name(const mod &);
|
||||||
string_view path(const mod &);
|
string_view path(const mod &);
|
||||||
|
|
||||||
|
bool has(const mod &, const string_view &sym);
|
||||||
|
|
||||||
|
template<class T = uint8_t> const T *ptr(const mod &, const string_view &sym);
|
||||||
|
template<class T = uint8_t> T *ptr(mod &, const string_view &sym);
|
||||||
|
|
||||||
|
template<class T> const T &get(const mod &, const string_view &sym);
|
||||||
|
template<class T> T &get(mod &, const string_view &sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "paths.h"
|
#include "paths.h"
|
||||||
|
@ -36,17 +44,17 @@ namespace ircd::mods
|
||||||
// misc util
|
// misc util
|
||||||
namespace ircd::mods
|
namespace ircd::mods
|
||||||
{
|
{
|
||||||
bool loaded(const std::string &name);
|
bool loaded(const string_view &name);
|
||||||
bool available(const std::string &name);
|
bool available(const string_view &name);
|
||||||
bool is_module(const std::string &fullpath);
|
bool is_module(const string_view &fullpath);
|
||||||
bool is_module(const std::string &fullpath, std::nothrow_t);
|
bool is_module(const string_view &fullpath, std::nothrow_t);
|
||||||
bool is_module(const std::string &fullpath, std::string &why);
|
bool is_module(const string_view &fullpath, std::string &why);
|
||||||
|
|
||||||
// returns dir/name of first dir containing 'name' (and this will be
|
// returns dir/name of first dir containing 'name' (and this will be
|
||||||
// a loadable module). Unlike libltdl, the reason each individual
|
// a loadable module). Unlike libltdl, the reason each individual
|
||||||
// candidate failed is presented in a vector.
|
// candidate failed is presented in a vector.
|
||||||
std::string search(const std::string &name, std::vector<std::string> &why);
|
std::string search(const string_view &name, std::vector<std::string> &why);
|
||||||
std::string search(const std::string &name);
|
std::string search(const string_view &name);
|
||||||
|
|
||||||
// Potential modules available to load
|
// Potential modules available to load
|
||||||
std::forward_list<std::string> available();
|
std::forward_list<std::string> available();
|
||||||
|
@ -59,3 +67,41 @@ namespace ircd
|
||||||
using mods::import;
|
using mods::import;
|
||||||
using mods::import_shared;
|
using mods::import_shared;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ircd::mods
|
||||||
|
{
|
||||||
|
template<> const uint8_t *ptr<const uint8_t>(const mod &, const string_view &sym);
|
||||||
|
template<> uint8_t *ptr<uint8_t>(mod &, const string_view &sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T &
|
||||||
|
ircd::mods::get(mod &mod,
|
||||||
|
const string_view &sym)
|
||||||
|
{
|
||||||
|
return *ptr<T>(mod, sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
const T &
|
||||||
|
ircd::mods::get(const mod &mod,
|
||||||
|
const string_view &sym)
|
||||||
|
{
|
||||||
|
return *ptr<T>(mod, sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
T *
|
||||||
|
ircd::mods::ptr(mod &mod,
|
||||||
|
const string_view &sym)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<T *>(ptr<uint8_t>(mod, sym));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
const T *
|
||||||
|
ircd::mods::ptr(const mod &mod,
|
||||||
|
const string_view &sym)
|
||||||
|
{
|
||||||
|
return reinterpret_cast<const T *>(ptr<const uint8_t>(mod, sym));
|
||||||
|
}
|
||||||
|
|
|
@ -19,58 +19,71 @@ namespace ircd::mods
|
||||||
struct ircd::mods::module
|
struct ircd::mods::module
|
||||||
:std::shared_ptr<mod>
|
:std::shared_ptr<mod>
|
||||||
{
|
{
|
||||||
const std::string &name() const;
|
operator const mod &() const;
|
||||||
const std::string &path() const;
|
operator mod &();
|
||||||
const std::string &mangle(const std::string &) const;
|
|
||||||
|
|
||||||
bool has(const std::string &name) const;
|
string_view name() const;
|
||||||
|
string_view path() const;
|
||||||
|
|
||||||
template<class T = uint8_t> const T *ptr(const std::string &name) const;
|
bool has(const string_view &sym) const;
|
||||||
template<class T = uint8_t> T *ptr(const std::string &name);
|
|
||||||
|
|
||||||
template<class T> const T &get(const std::string &name) const;
|
template<class T = uint8_t> const T *ptr(const string_view &sym) const;
|
||||||
template<class T> T &get(const std::string &name);
|
template<class T = uint8_t> T *ptr(const string_view &sym);
|
||||||
|
|
||||||
module(std::shared_ptr<mod> ptr = {})
|
template<class T> const T &get(const string_view &sym) const;
|
||||||
:std::shared_ptr<mod>{std::move(ptr)}
|
template<class T> T &get(const string_view &sym);
|
||||||
{}
|
|
||||||
|
|
||||||
module(const std::string &name);
|
module(std::shared_ptr<mod> ptr = {});
|
||||||
|
module(const string_view &name);
|
||||||
~module() noexcept;
|
~module() noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace ircd::mods
|
inline
|
||||||
{
|
ircd::mods::module::module(std::shared_ptr<mod> ptr)
|
||||||
template<> const uint8_t *module::ptr<const uint8_t>(const std::string &name) const;
|
:std::shared_ptr<mod>{std::move(ptr)}
|
||||||
template<> uint8_t *module::ptr<uint8_t>(const std::string &name);
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T &
|
T &
|
||||||
ircd::mods::module::get(const std::string &name)
|
ircd::mods::module::get(const string_view &sym)
|
||||||
{
|
{
|
||||||
return *ptr<T>(name);
|
return mods::get<T>(*this, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
const T &
|
const T &
|
||||||
ircd::mods::module::get(const std::string &name)
|
ircd::mods::module::get(const string_view &sym)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
return *ptr<T>(name);
|
return mods::get<T>(*this, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
T *
|
T *
|
||||||
ircd::mods::module::ptr(const std::string &name)
|
ircd::mods::module::ptr(const string_view &sym)
|
||||||
{
|
{
|
||||||
return reinterpret_cast<T *>(ptr<uint8_t>(name));
|
return mods::ptr<T>(*this, sym);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
const T *
|
const T *
|
||||||
ircd::mods::module::ptr(const std::string &name)
|
ircd::mods::module::ptr(const string_view &sym)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
return reinterpret_cast<const T *>(ptr<const uint8_t>(name));
|
return mods::ptr<T>(*this, sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ircd::mods::module::operator
|
||||||
|
mod &()
|
||||||
|
{
|
||||||
|
assert(bool(*this));
|
||||||
|
return std::shared_ptr<mod>::operator*();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ircd::mods::module::operator
|
||||||
|
const mod &()
|
||||||
|
const
|
||||||
|
{
|
||||||
|
assert(bool(*this));
|
||||||
|
return std::shared_ptr<mod>::operator*();
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,18 +16,20 @@ namespace ircd::mods
|
||||||
struct paths extern paths;
|
struct paths extern paths;
|
||||||
|
|
||||||
// Platform (.so|.dll) postfixing
|
// Platform (.so|.dll) postfixing
|
||||||
std::string postfixed(const std::string &name);
|
std::string postfixed(std::string name);
|
||||||
std::string unpostfixed(const std::string &name);
|
std::string postfixed(const string_view &);
|
||||||
|
std::string unpostfixed(std::string name);
|
||||||
|
std::string unpostfixed(const string_view &);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ircd::mods::paths
|
struct ircd::mods::paths
|
||||||
:std::vector<std::string>
|
:std::vector<std::string>
|
||||||
{
|
{
|
||||||
bool added(const std::string &dir) const;
|
bool added(const string_view &dir) const;
|
||||||
|
|
||||||
bool del(const std::string &dir);
|
bool del(const string_view &dir);
|
||||||
bool add(const std::string &dir, std::nothrow_t);
|
bool add(const string_view &dir, std::nothrow_t);
|
||||||
bool add(const std::string &dir);
|
bool add(const string_view &dir);
|
||||||
|
|
||||||
paths();
|
paths();
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,9 +37,8 @@ class ircd::mods::sym_ptr
|
||||||
template<class T> T &operator*();
|
template<class T> T &operator*();
|
||||||
|
|
||||||
sym_ptr() = default;
|
sym_ptr() = default;
|
||||||
sym_ptr(module, const std::string &symname);
|
sym_ptr(module, const string_view &symname);
|
||||||
sym_ptr(const std::string &modname, const std::string &symname);
|
sym_ptr(const string_view &modname, const string_view &symname);
|
||||||
~sym_ptr() noexcept;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
|
|
|
@ -14,16 +14,16 @@
|
||||||
namespace ircd::mods
|
namespace ircd::mods
|
||||||
{
|
{
|
||||||
// Section & Symbol utilites
|
// Section & Symbol utilites
|
||||||
std::vector<std::string> sections(const std::string &fullpath);
|
std::vector<std::string> sections(const string_view &fullpath);
|
||||||
|
|
||||||
std::vector<std::string> symbols(const std::string &fullpath, const std::string §ion);
|
std::vector<std::string> symbols(const string_view &fullpath, const string_view §ion);
|
||||||
std::vector<std::string> symbols(const std::string &fullpath);
|
std::vector<std::string> symbols(const string_view &fullpath);
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string> mangles(const std::vector<std::string> &);
|
std::unordered_map<std::string, std::string> mangles(const std::vector<std::string> &);
|
||||||
std::unordered_map<std::string, std::string> mangles(const std::string &fullpath, const std::string §ion);
|
std::unordered_map<std::string, std::string> mangles(const string_view &fullpath, const string_view §ion);
|
||||||
std::unordered_map<std::string, std::string> mangles(const std::string &fullpath);
|
std::unordered_map<std::string, std::string> mangles(const string_view &fullpath);
|
||||||
|
|
||||||
// Find module names where symbol resides
|
// Find module names where symbol resides
|
||||||
bool has_symbol(const std::string &name, const std::string &symbol);
|
bool has_symbol(const string_view &name, const string_view &symbol);
|
||||||
std::vector<std::string> find_symbol(const std::string &symbol);
|
std::vector<std::string> find_symbol(const string_view &symbol);
|
||||||
}
|
}
|
||||||
|
|
331
ircd/mods.cc
331
ircd/mods.cc
|
@ -30,14 +30,6 @@ ircd::mods::suffix
|
||||||
boost::dll::shared_library::suffix()
|
boost::dll::shared_library::suffix()
|
||||||
};
|
};
|
||||||
|
|
||||||
std::stack<ircd::mods::mod *>
|
|
||||||
ircd::mods::mod::loading
|
|
||||||
{};
|
|
||||||
|
|
||||||
std::map<std::string, ircd::mods::mod *>
|
|
||||||
ircd::mods::mod::loaded
|
|
||||||
{};
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// mods/mods.h (misc util)
|
// mods/mods.h (misc util)
|
||||||
|
@ -58,7 +50,9 @@ ircd::mods::available()
|
||||||
}
|
}
|
||||||
catch(const filesystem::filesystem_error &e)
|
catch(const filesystem::filesystem_error &e)
|
||||||
{
|
{
|
||||||
log.warning("Module path [%s]: %s", dir, e.what());
|
log.warning("Module path [%s]: %s",
|
||||||
|
dir,
|
||||||
|
e.what());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,14 +60,16 @@ ircd::mods::available()
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystem::path
|
filesystem::path
|
||||||
ircd::mods::fullpath(const std::string &name)
|
ircd::mods::fullpath(const string_view &name)
|
||||||
{
|
{
|
||||||
std::vector<std::string> why;
|
std::vector<std::string> why;
|
||||||
const filesystem::path path(search(name, why));
|
const filesystem::path path(search(name, why));
|
||||||
if(path.empty())
|
if(path.empty())
|
||||||
{
|
{
|
||||||
for(const auto &str : why)
|
for(const auto &str : why)
|
||||||
log.error("candidate for module '%s' failed: %s", name, str);
|
log.error("candidate for module '%s' failed: %s",
|
||||||
|
name,
|
||||||
|
str);
|
||||||
|
|
||||||
throw error
|
throw error
|
||||||
{
|
{
|
||||||
|
@ -85,23 +81,29 @@ ircd::mods::fullpath(const std::string &name)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ircd::mods::search(const std::string &name)
|
ircd::mods::search(const string_view &name)
|
||||||
{
|
{
|
||||||
std::vector<std::string> why;
|
std::vector<std::string> why;
|
||||||
return search(name, why);
|
return search(name, why);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ircd::mods::search(const std::string &name,
|
ircd::mods::search(const string_view &name,
|
||||||
std::vector<std::string> &why)
|
std::vector<std::string> &why)
|
||||||
{
|
{
|
||||||
using filesystem::path;
|
using filesystem::path;
|
||||||
|
|
||||||
const path path(postfixed(name));
|
const path path
|
||||||
|
{
|
||||||
|
postfixed(name)
|
||||||
|
};
|
||||||
|
|
||||||
if(!path.is_relative())
|
if(!path.is_relative())
|
||||||
{
|
{
|
||||||
why.resize(why.size() + 1);
|
why.resize(why.size() + 1);
|
||||||
return is_module(path, why.back())? name : std::string{};
|
return is_module(path, why.back())?
|
||||||
|
std::string{name}:
|
||||||
|
std::string{};
|
||||||
}
|
}
|
||||||
else for(const auto &dir : paths)
|
else for(const auto &dir : paths)
|
||||||
{
|
{
|
||||||
|
@ -114,23 +116,23 @@ ircd::mods::search(const std::string &name,
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::is_module(const std::string &fullpath)
|
ircd::mods::is_module(const string_view &fullpath)
|
||||||
{
|
{
|
||||||
return is_module(filesystem::path(fullpath));
|
return is_module(filesystem::path(std::string{fullpath}));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::is_module(const std::string &fullpath,
|
ircd::mods::is_module(const string_view &fullpath,
|
||||||
std::nothrow_t)
|
std::nothrow_t)
|
||||||
{
|
{
|
||||||
return is_module(filesystem::path(fullpath), std::nothrow);
|
return is_module(filesystem::path(std::string{fullpath}), std::nothrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::is_module(const std::string &fullpath,
|
ircd::mods::is_module(const string_view &fullpath,
|
||||||
std::string &why)
|
std::string &why)
|
||||||
{
|
{
|
||||||
return is_module(filesystem::path(fullpath), why);
|
return is_module(filesystem::path(std::string{fullpath}), why);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -174,7 +176,7 @@ ircd::mods::is_module(const filesystem::path &path)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::available(const std::string &name)
|
ircd::mods::available(const string_view &name)
|
||||||
{
|
{
|
||||||
using filesystem::path;
|
using filesystem::path;
|
||||||
|
|
||||||
|
@ -183,7 +185,7 @@ ircd::mods::available(const std::string &name)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::loaded(const std::string &name)
|
ircd::mods::loaded(const string_view &name)
|
||||||
{
|
{
|
||||||
return mod::loaded.count(name);
|
return mod::loaded.count(name);
|
||||||
}
|
}
|
||||||
|
@ -193,8 +195,8 @@ ircd::mods::loaded(const std::string &name)
|
||||||
// mods/sym_ptr.h
|
// mods/sym_ptr.h
|
||||||
//
|
//
|
||||||
|
|
||||||
ircd::mods::sym_ptr::sym_ptr(const std::string &modname,
|
ircd::mods::sym_ptr::sym_ptr(const string_view &modname,
|
||||||
const std::string &symname)
|
const string_view &symname)
|
||||||
:sym_ptr
|
:sym_ptr
|
||||||
{
|
{
|
||||||
module(modname), symname
|
module(modname), symname
|
||||||
|
@ -203,40 +205,33 @@ ircd::mods::sym_ptr::sym_ptr(const std::string &modname,
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::mods::sym_ptr::sym_ptr(module module,
|
ircd::mods::sym_ptr::sym_ptr(module module,
|
||||||
const std::string &symname)
|
const string_view &symname)
|
||||||
:std::weak_ptr<mod>
|
:std::weak_ptr<mod>
|
||||||
{
|
{
|
||||||
module
|
module
|
||||||
}
|
}
|
||||||
,ptr{[this, &symname]
|
,ptr{[this, &module, &symname]
|
||||||
{
|
{
|
||||||
const life_guard<mods::mod> mod{*this};
|
if(unlikely(!module.has(symname)))
|
||||||
const auto &mangled(mod->mangle(symname));
|
|
||||||
if(unlikely(!mod->has(mangled)))
|
|
||||||
throw undefined_symbol
|
throw undefined_symbol
|
||||||
{
|
{
|
||||||
"Could not find symbol '%s' (%s) in module '%s'",
|
"Could not find symbol '%s' (%s) in module '%s'",
|
||||||
|
demangle(symname),
|
||||||
symname,
|
symname,
|
||||||
mangled,
|
module.name()
|
||||||
mod->name()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return mod->ptr(mangled);
|
return module.ptr(symname);
|
||||||
}()}
|
}()}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
ircd::mods::sym_ptr::~sym_ptr()
|
|
||||||
noexcept
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// mods/module.h
|
// mods/module.h
|
||||||
//
|
//
|
||||||
|
|
||||||
ircd::mods::module::module(const std::string &name)
|
ircd::mods::module::module(const string_view &name)
|
||||||
try
|
try
|
||||||
:std::shared_ptr<mod>{[&name]
|
:std::shared_ptr<mod>{[&name]
|
||||||
{
|
{
|
||||||
|
@ -255,14 +250,19 @@ try
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto path(fullpath(name));
|
const auto path(fullpath(name));
|
||||||
log.debug("Attempting to load '%s' @ `%s'", name, path.string());
|
log.debug("Attempting to load '%s' @ `%s'",
|
||||||
|
name,
|
||||||
|
path.string());
|
||||||
|
|
||||||
return std::make_shared<mod>(path, flags);
|
return std::make_shared<mod>(path, flags);
|
||||||
}()}
|
}()}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
catch(const std::exception &e)
|
catch(const std::exception &e)
|
||||||
{
|
{
|
||||||
log.error("Failed to load '%s': %s", name, e.what());
|
log.error("Failed to load '%s': %s",
|
||||||
|
name,
|
||||||
|
e.what());
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,73 +271,25 @@ noexcept
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &
|
ircd::string_view
|
||||||
ircd::mods::module::path()
|
ircd::mods::module::path()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(unlikely(!*this))
|
return mods::path(*this);
|
||||||
{
|
|
||||||
static const std::string empty;
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &mod(**this);
|
|
||||||
return mod.location();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &
|
ircd::string_view
|
||||||
ircd::mods::module::name()
|
ircd::mods::module::name()
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(unlikely(!*this))
|
return mods::name(*this);
|
||||||
{
|
|
||||||
static const std::string empty;
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &mod(**this);
|
|
||||||
return mod.name();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<> uint8_t *
|
|
||||||
ircd::mods::module::ptr<uint8_t>(const std::string &name)
|
|
||||||
{
|
|
||||||
auto &mod(**this);
|
|
||||||
return mod.ptr<uint8_t>(mangle(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
template<>
|
|
||||||
const uint8_t *
|
|
||||||
ircd::mods::module::ptr<const uint8_t>(const std::string &name)
|
|
||||||
const
|
|
||||||
{
|
|
||||||
const auto &mod(**this);
|
|
||||||
return mod.ptr<const uint8_t>(mangle(name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::module::has(const std::string &name)
|
ircd::mods::module::has(const string_view &name)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
if(unlikely(!*this))
|
return mods::has(*this, name);
|
||||||
return false;
|
|
||||||
|
|
||||||
const auto &mod(**this);
|
|
||||||
return mod.has(mangle(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &
|
|
||||||
ircd::mods::module::mangle(const std::string &name)
|
|
||||||
const
|
|
||||||
{
|
|
||||||
if(unlikely(!*this))
|
|
||||||
{
|
|
||||||
static const std::string empty;
|
|
||||||
return empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &mod(**this);
|
|
||||||
return mod.mangle(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -346,7 +298,7 @@ const
|
||||||
//
|
//
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
ircd::mods::find_symbol(const std::string &symbol)
|
ircd::mods::find_symbol(const string_view &symbol)
|
||||||
{
|
{
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
const auto av(available());
|
const auto av(available());
|
||||||
|
@ -360,8 +312,8 @@ ircd::mods::find_symbol(const std::string &symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::has_symbol(const std::string &name,
|
ircd::mods::has_symbol(const string_view &name,
|
||||||
const std::string &symbol)
|
const string_view &symbol)
|
||||||
{
|
{
|
||||||
const auto path(fullpath(name));
|
const auto path(fullpath(name));
|
||||||
if(path.empty())
|
if(path.empty())
|
||||||
|
@ -372,16 +324,16 @@ ircd::mods::has_symbol(const std::string &name,
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string>
|
std::unordered_map<std::string, std::string>
|
||||||
ircd::mods::mangles(const std::string &fullpath)
|
ircd::mods::mangles(const string_view &fullpath)
|
||||||
{
|
{
|
||||||
return mangles(filesystem::path(fullpath));
|
return mangles(filesystem::path(std::string{fullpath}));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string>
|
std::unordered_map<std::string, std::string>
|
||||||
ircd::mods::mangles(const std::string &fullpath,
|
ircd::mods::mangles(const string_view &fullpath,
|
||||||
const std::string §ion)
|
const string_view §ion)
|
||||||
{
|
{
|
||||||
return mangles(filesystem::path(fullpath), section);
|
return mangles(filesystem::path(std::string{fullpath}), section);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string>
|
std::unordered_map<std::string, std::string>
|
||||||
|
@ -392,7 +344,7 @@ ircd::mods::mangles(const filesystem::path &path)
|
||||||
|
|
||||||
std::unordered_map<std::string, std::string>
|
std::unordered_map<std::string, std::string>
|
||||||
ircd::mods::mangles(const filesystem::path &path,
|
ircd::mods::mangles(const filesystem::path &path,
|
||||||
const std::string §ion)
|
const string_view §ion)
|
||||||
{
|
{
|
||||||
return mangles(mods::symbols(path, section));
|
return mangles(mods::symbols(path, section));
|
||||||
}
|
}
|
||||||
|
@ -414,16 +366,16 @@ ircd::mods::mangles(const std::vector<std::string> &symbols)
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
ircd::mods::symbols(const std::string &fullpath)
|
ircd::mods::symbols(const string_view &fullpath)
|
||||||
{
|
{
|
||||||
return symbols(filesystem::path(fullpath));
|
return symbols(filesystem::path(std::string{fullpath}));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
ircd::mods::symbols(const std::string &fullpath,
|
ircd::mods::symbols(const string_view &fullpath,
|
||||||
const std::string §ion)
|
const string_view §ion)
|
||||||
{
|
{
|
||||||
return symbols(filesystem::path(fullpath), section);
|
return symbols(filesystem::path(std::string{fullpath}), std::string{section});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
|
@ -438,19 +390,19 @@ ircd::mods::symbols(const filesystem::path &path)
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
ircd::mods::symbols(const filesystem::path &path,
|
ircd::mods::symbols(const filesystem::path &path,
|
||||||
const std::string §ion)
|
const string_view §ion)
|
||||||
{
|
{
|
||||||
return info<std::vector<std::string>>(path, [§ion]
|
return info<std::vector<std::string>>(path, [§ion]
|
||||||
(boost::dll::library_info &info)
|
(boost::dll::library_info &info)
|
||||||
{
|
{
|
||||||
return info.symbols(section);
|
return info.symbols(std::string{section});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
ircd::mods::sections(const std::string &fullpath)
|
ircd::mods::sections(const string_view &fullpath)
|
||||||
{
|
{
|
||||||
return sections(filesystem::path(fullpath));
|
return sections(filesystem::path(std::string{fullpath}));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string>
|
std::vector<std::string>
|
||||||
|
@ -470,10 +422,16 @@ ircd::mods::info(const filesystem::path &path,
|
||||||
F&& closure)
|
F&& closure)
|
||||||
{
|
{
|
||||||
if(!exists(path))
|
if(!exists(path))
|
||||||
throw filesystem_error("`%s' does not exist", path.string());
|
throw filesystem_error
|
||||||
|
{
|
||||||
|
"`%s' does not exist", path.string()
|
||||||
|
};
|
||||||
|
|
||||||
if(!is_regular_file(path))
|
if(!is_regular_file(path))
|
||||||
throw filesystem_error("`%s' is not a file", path.string());
|
throw filesystem_error
|
||||||
|
{
|
||||||
|
"`%s' is not a file", path.string()
|
||||||
|
};
|
||||||
|
|
||||||
boost::dll::library_info info(path);
|
boost::dll::library_info info(path);
|
||||||
return closure(info);
|
return closure(info);
|
||||||
|
@ -500,15 +458,27 @@ ircd::mods::paths
|
||||||
{};
|
{};
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ircd::mods::unpostfixed(const std::string &name)
|
ircd::mods::unpostfixed(const string_view &name)
|
||||||
{
|
{
|
||||||
return unpostfixed(filesystem::path(name)).string();
|
return unpostfixed(std::string{name});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
ircd::mods::postfixed(const std::string &name)
|
ircd::mods::unpostfixed(std::string name)
|
||||||
{
|
{
|
||||||
return postfixed(filesystem::path(name)).string();
|
return unpostfixed(filesystem::path(std::move(name))).string();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
ircd::mods::postfixed(const string_view &name)
|
||||||
|
{
|
||||||
|
return postfixed(std::string{name});
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string
|
||||||
|
ircd::mods::postfixed(std::string name)
|
||||||
|
{
|
||||||
|
return postfixed(filesystem::path(std::move(name))).string();
|
||||||
}
|
}
|
||||||
|
|
||||||
filesystem::path
|
filesystem::path
|
||||||
|
@ -549,11 +519,14 @@ ircd::mods::paths::paths()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::paths::add(const std::string &dir)
|
ircd::mods::paths::add(const string_view &dir)
|
||||||
{
|
{
|
||||||
using filesystem::path;
|
using filesystem::path;
|
||||||
|
|
||||||
const path path(prefix_if_relative(dir));
|
const path path
|
||||||
|
{
|
||||||
|
prefix_if_relative(std::string{dir})
|
||||||
|
};
|
||||||
|
|
||||||
if(!exists(path))
|
if(!exists(path))
|
||||||
throw filesystem_error
|
throw filesystem_error
|
||||||
|
@ -575,7 +548,7 @@ ircd::mods::paths::add(const std::string &dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::paths::add(const std::string &dir,
|
ircd::mods::paths::add(const string_view &dir,
|
||||||
std::nothrow_t)
|
std::nothrow_t)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -588,14 +561,14 @@ catch(const std::exception &e)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::paths::del(const std::string &dir)
|
ircd::mods::paths::del(const string_view &dir)
|
||||||
{
|
{
|
||||||
std::remove(begin(), end(), prefix_if_relative(dir).string());
|
std::remove(begin(), end(), prefix_if_relative(std::string{dir}).string());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ircd::mods::paths::added(const std::string &dir)
|
ircd::mods::paths::added(const string_view &dir)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
return std::find(begin(), end(), dir) != end();
|
return std::find(begin(), end(), dir) != end();
|
||||||
|
@ -606,6 +579,28 @@ const
|
||||||
// mods/mods.h
|
// mods/mods.h
|
||||||
//
|
//
|
||||||
|
|
||||||
|
template<> uint8_t *
|
||||||
|
ircd::mods::ptr<uint8_t>(mod &mod,
|
||||||
|
const string_view &sym)
|
||||||
|
{
|
||||||
|
return &mod.handle.get<uint8_t>(std::string{sym});
|
||||||
|
}
|
||||||
|
|
||||||
|
template<>
|
||||||
|
const uint8_t *
|
||||||
|
ircd::mods::ptr<const uint8_t>(const mod &mod,
|
||||||
|
const string_view &sym)
|
||||||
|
{
|
||||||
|
return &mod.handle.get<const uint8_t>(std::string{sym});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
ircd::mods::has(const mod &mod,
|
||||||
|
const string_view &name)
|
||||||
|
{
|
||||||
|
return mod.handle.has(std::string{name});
|
||||||
|
}
|
||||||
|
|
||||||
ircd::string_view
|
ircd::string_view
|
||||||
ircd::mods::name(const mod &mod)
|
ircd::mods::name(const mod &mod)
|
||||||
{
|
{
|
||||||
|
@ -623,6 +618,14 @@ ircd::mods::path(const mod &mod)
|
||||||
// (internal) mods.h
|
// (internal) mods.h
|
||||||
//
|
//
|
||||||
|
|
||||||
|
decltype(ircd::mods::mod::loading)
|
||||||
|
ircd::mods::mod::loading
|
||||||
|
{};
|
||||||
|
|
||||||
|
decltype(ircd::mods::mod::loaded)
|
||||||
|
ircd::mods::mod::loaded
|
||||||
|
{};
|
||||||
|
|
||||||
ircd::mods::mod::mod(const filesystem::path &path,
|
ircd::mods::mod::mod(const filesystem::path &path,
|
||||||
const load_mode::type &mode)
|
const load_mode::type &mode)
|
||||||
try
|
try
|
||||||
|
@ -718,6 +721,7 @@ try
|
||||||
description().size()? description() : "<no description>"s);
|
description().size()? description() : "<no description>"s);
|
||||||
|
|
||||||
// Without init exception, the module is now considered loaded.
|
// Without init exception, the module is now considered loaded.
|
||||||
|
assert(!loaded.count(name()));
|
||||||
loaded.emplace(name(), this);
|
loaded.emplace(name(), this);
|
||||||
}
|
}
|
||||||
catch(const boost::system::system_error &e)
|
catch(const boost::system::system_error &e)
|
||||||
|
@ -758,11 +762,20 @@ bool ircd::mapi::static_destruction;
|
||||||
ircd::mods::mod::~mod()
|
ircd::mods::mod::~mod()
|
||||||
noexcept try
|
noexcept try
|
||||||
{
|
{
|
||||||
|
log.debug("Attempting unload module '%s' @ `%s'",
|
||||||
|
name(),
|
||||||
|
location());
|
||||||
|
|
||||||
unload();
|
unload();
|
||||||
|
|
||||||
|
const size_t erased(loaded.erase(name()));
|
||||||
|
assert(erased == 1);
|
||||||
}
|
}
|
||||||
catch(const std::exception &e)
|
catch(const std::exception &e)
|
||||||
{
|
{
|
||||||
log::critical("Module @%p unload: %s", (const void *)this, e.what());
|
log.critical("Module @%p unload: %s",
|
||||||
|
(const void *)this,
|
||||||
|
e.what());
|
||||||
|
|
||||||
if(!ircd::debugmode)
|
if(!ircd::debugmode)
|
||||||
return;
|
return;
|
||||||
|
@ -774,11 +787,6 @@ ircd::mods::mod::unload()
|
||||||
if(!handle.is_loaded())
|
if(!handle.is_loaded())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const auto name(this->name());
|
|
||||||
log.debug("Attempting unload module '%s' @ `%s'", name, location());
|
|
||||||
const size_t erased(loaded.erase(name));
|
|
||||||
assert(erased == 1);
|
|
||||||
|
|
||||||
if(header->fini)
|
if(header->fini)
|
||||||
header->fini();
|
header->fini();
|
||||||
|
|
||||||
|
@ -794,66 +802,21 @@ ircd::mods::mod::unload()
|
||||||
ptr->unload();
|
ptr->unload();
|
||||||
});
|
});
|
||||||
|
|
||||||
log.debug("Attempting static unload for '%s' @ `%s'", name, location());
|
log.debug("Attempting static unload for '%s' @ `%s'",
|
||||||
|
name(),
|
||||||
|
location());
|
||||||
|
|
||||||
mapi::static_destruction = false;
|
mapi::static_destruction = false;
|
||||||
handle.unload();
|
handle.unload();
|
||||||
assert(!handle.is_loaded());
|
assert(!handle.is_loaded());
|
||||||
|
|
||||||
if(!mapi::static_destruction)
|
if(!mapi::static_destruction)
|
||||||
{
|
{
|
||||||
log.error("Module \"%s\" is stuck and failing to unload.", name);
|
log.critical("Module \"%s\" is stuck and failing to unload.", name());
|
||||||
log.warning("Module \"%s\" may result in undefined behavior if not fixed.", name);
|
log.critical("Module \"%s\" may result in undefined behavior if not fixed.", name());
|
||||||
} else {
|
} else {
|
||||||
log.info("Unloaded '%s'", name);
|
log.info("Unloaded '%s'", name());
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &
|
|
||||||
ircd::mods::mod::mangle(const std::string &name)
|
|
||||||
const
|
|
||||||
{
|
|
||||||
const auto it(mangles.find(name));
|
|
||||||
if(it == end(mangles))
|
|
||||||
return name;
|
|
||||||
|
|
||||||
const auto &mangled(it->second);
|
|
||||||
return mangled;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T *
|
|
||||||
ircd::mods::mod::ptr(const std::string &name)
|
|
||||||
{
|
|
||||||
return &handle.get<T>(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
const T *
|
|
||||||
ircd::mods::mod::ptr(const std::string &name)
|
|
||||||
const
|
|
||||||
{
|
|
||||||
return &handle.get<T>(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
T &
|
|
||||||
ircd::mods::mod::get(const std::string &name)
|
|
||||||
{
|
|
||||||
handle.get<T>(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
const T &
|
|
||||||
ircd::mods::mod::get(const std::string &name)
|
|
||||||
const
|
|
||||||
{
|
|
||||||
handle.get<T>(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
ircd::mods::mod::has(const std::string &name)
|
|
||||||
const
|
|
||||||
{
|
|
||||||
return handle.has(name);
|
|
||||||
}
|
|
||||||
|
|
18
ircd/mods.h
18
ircd/mods.h
|
@ -22,13 +22,13 @@ namespace ircd::mods
|
||||||
template<class R, class F> R info(const filesystem::path &, F&& closure);
|
template<class R, class F> R info(const filesystem::path &, F&& closure);
|
||||||
std::vector<std::string> sections(const filesystem::path &path);
|
std::vector<std::string> sections(const filesystem::path &path);
|
||||||
std::vector<std::string> symbols(const filesystem::path &path);
|
std::vector<std::string> symbols(const filesystem::path &path);
|
||||||
std::vector<std::string> symbols(const filesystem::path &path, const std::string §ion);
|
std::vector<std::string> symbols(const filesystem::path &path, const string_view §ion);
|
||||||
std::unordered_map<std::string, std::string> mangles(const std::vector<std::string> &);
|
std::unordered_map<std::string, std::string> mangles(const std::vector<std::string> &);
|
||||||
std::unordered_map<std::string, std::string> mangles(const filesystem::path &path);
|
std::unordered_map<std::string, std::string> mangles(const filesystem::path &path);
|
||||||
std::unordered_map<std::string, std::string> mangles(const filesystem::path &path, const std::string §ion);
|
std::unordered_map<std::string, std::string> mangles(const filesystem::path &path, const string_view §ion);
|
||||||
|
|
||||||
// Get the full path of a [valid] available module by name
|
// Get the full path of a [valid] available module by name
|
||||||
filesystem::path fullpath(const std::string &name);
|
filesystem::path fullpath(const string_view &name);
|
||||||
|
|
||||||
// Checks if loadable module containing a mapi header (does not verify the magic)
|
// Checks if loadable module containing a mapi header (does not verify the magic)
|
||||||
bool is_module(const filesystem::path &);
|
bool is_module(const filesystem::path &);
|
||||||
|
@ -40,8 +40,8 @@ namespace ircd::mods
|
||||||
struct ircd::mods::mod
|
struct ircd::mods::mod
|
||||||
:std::enable_shared_from_this<mod>
|
:std::enable_shared_from_this<mod>
|
||||||
{
|
{
|
||||||
static std::stack<mod *> loading; // State of current dlopen() recursion.
|
static std::stack<mod *> loading; // State of current dlopen() recursion.
|
||||||
static std::map<std::string, mod *> loaded;
|
static std::map<string_view, mod *, std::less<>> loaded;
|
||||||
|
|
||||||
filesystem::path path;
|
filesystem::path path;
|
||||||
load_mode::type mode;
|
load_mode::type mode;
|
||||||
|
@ -61,14 +61,6 @@ struct ircd::mods::mod
|
||||||
auto &version() const { return header->version; }
|
auto &version() const { return header->version; }
|
||||||
auto &description() const { return (*this)["description"]; }
|
auto &description() const { return (*this)["description"]; }
|
||||||
|
|
||||||
const std::string &mangle(const std::string &name) const;
|
|
||||||
|
|
||||||
bool has(const std::string &name) const;
|
|
||||||
template<class T> const T &get(const std::string &name) const;
|
|
||||||
template<class T> T &get(const std::string &name);
|
|
||||||
template<class T = uint8_t> const T *ptr(const std::string &name) const;
|
|
||||||
template<class T = uint8_t> T *ptr(const std::string &name);
|
|
||||||
|
|
||||||
bool unload();
|
bool unload();
|
||||||
|
|
||||||
mod(const filesystem::path &,
|
mod(const filesystem::path &,
|
||||||
|
|
Loading…
Reference in a new issue