<commit_before>#include "render_pipeline/rpcore/pluginbase/manager.hpp"

#include <unordered_set>

#include <boost/detail/winapi/dll.hpp>
#include <boost/dll/import.hpp>

#include <spdlog/fmt/fmt.h>

#include "render_pipeline/rpcore/mount_manager.hpp"
#include "render_pipeline/rpcore/render_pipeline.hpp"
#include "render_pipeline/rpcore/stage_manager.hpp"
#include "render_pipeline/rpcore/pluginbase/day_setting_types.hpp"
#include "render_pipeline/rppanda/stdpy/file.hpp"

#include "rplibs/yaml.hpp"

#include "rpcore/pluginbase/setting_types.hpp"

namespace rpcore {

class PluginManager::Impl
{
public:
    Impl(PluginManager& self, RenderPipeline& pipeline);

    void unload(void);

    /** Internal method to load a plugin. */
    std::shared_ptr<BasePlugin> load_plugin(const std::string& plugin_id);

public:
    PluginManager& self_;
    RenderPipeline& pipeline_;
    std::string plugin_dir_;

    bool requires_daytime_settings_;

    std::unordered_map<std::string, std::shared_ptr<BasePlugin>> instances_;

    std::unordered_set<std::string> enabled_plugins_;
    std::unordered_map<std::string, std::function<PluginCreatorType>> plugin_creators_;

    std::unordered_map<std::string, BasePlugin::PluginInfo> plugin_info_map_;

    ///< { plugin-id, SettingsType }
    std::unordered_map<std::string, SettingsDataType> settings_;

    ///< { plugin-id, DaySettingsType }
    std::unordered_map<std::string, DaySettingsDataType> day_settings_;
};

PluginManager::Impl::Impl(PluginManager& self, RenderPipeline& pipeline): self_(self), pipeline_(pipeline)
{
    // Used by the plugin configurator and to only load the required data
    requires_daytime_settings_ = true;
}

void PluginManager::Impl::unload(void)
{
    self_.debug("Unloading all plugins");

    self_.on_unload();

    for (auto& id_handle: instances_)
    {
        auto count = id_handle.second.use_count();
        if (count != 1)
            self_.warn(fmt::format("Plugin ({}) is used as {} on somewhere before unloading.", id_handle.first, count));

        // delete plugin instance.
        id_handle.second.reset();
    }
    instances_.clear();

    settings_.clear();
    day_settings_.clear();
    enabled_plugins_.clear();

    // unload plugins.
    plugin_creators_.clear();
}

std::shared_ptr<BasePlugin> PluginManager::Impl::load_plugin(const std::string& plugin_id)
{
    boost::filesystem::path plugin_path(plugin_dir_);

#if defined(RENDER_PIPELINE_BUILD_CFG_POSTFIX)
    plugin_path = boost::filesystem::absolute(plugin_path / plugin_id / ("rpplugin_" + plugin_id + RENDER_PIPELINE_BUILD_CFG_POSTFIX));
#else
    plugin_path = boost::filesystem::absolute(plugin_path / plugin_id / ("rpplugin_" + plugin_id));
#endif

    self_.trace(fmt::format("Importing shared library file ({}) from {}{}", plugin_id, plugin_path.string(), boost::dll::shared_library::suffix().string()));

    try<commit_msg>Support extended-length path for loading plugin<commit_after>#include "render_pipeline/rpcore/pluginbase/manager.hpp"

#include <unordered_set>

#include <boost/detail/winapi/dll.hpp>
#include <boost/dll/import.hpp>

#include <spdlog/fmt/fmt.h>

#include "render_pipeline/rpcore/mount_manager.hpp"
#include "render_pipeline/rpcore/render_pipeline.hpp"
#include "render_pipeline/rpcore/stage_manager.hpp"
#include "render_pipeline/rpcore/pluginbase/day_setting_types.hpp"
#include "render_pipeline/rppanda/stdpy/file.hpp"

#include "rplibs/yaml.hpp"

#include "rpcore/pluginbase/setting_types.hpp"

namespace rpcore {

class PluginManager::Impl
{
public:
    Impl(PluginManager& self, RenderPipeline& pipeline);

    void unload(void);

    /** Internal method to load a plugin. */
    std::shared_ptr<BasePlugin> load_plugin(const std::string& plugin_id);

public:
    PluginManager& self_;
    RenderPipeline& pipeline_;
    std::string plugin_dir_;

    bool requires_daytime_settings_;

    std::unordered_map<std::string, std::shared_ptr<BasePlugin>> instances_;

    std::unordered_set<std::string> enabled_plugins_;
    std::unordered_map<std::string, std::function<PluginCreatorType>> plugin_creators_;

    std::unordered_map<std::string, BasePlugin::PluginInfo> plugin_info_map_;

    ///< { plugin-id, SettingsType }
    std::unordered_map<std::string, SettingsDataType> settings_;

    ///< { plugin-id, DaySettingsType }
    std::unordered_map<std::string, DaySettingsDataType> day_settings_;
};

PluginManager::Impl::Impl(PluginManager& self, RenderPipeline& pipeline): self_(self), pipeline_(pipeline)
{
    // Used by the plugin configurator and to only load the required data
    requires_daytime_settings_ = true;
}

void PluginManager::Impl::unload(void)
{
    self_.debug("Unloading all plugins");

    self_.on_unload();

    for (auto& id_handle: instances_)
    {
        auto count = id_handle.second.use_count();
        if (count != 1)
            self_.warn(fmt::format("Plugin ({}) is used as {} on somewhere before unloading.", id_handle.first, count));

        // delete plugin instance.
        id_handle.second.reset();
    }
    instances_.clear();

    settings_.clear();
    day_settings_.clear();
    enabled_plugins_.clear();

    // unload plugins.
    plugin_creators_.clear();
}

std::shared_ptr<BasePlugin> PluginManager::Impl::load_plugin(const std::string& plugin_id)
{
    boost::filesystem::path plugin_path(plugin_dir_);

#if defined(RENDER_PIPELINE_BUILD_CFG_POSTFIX)
    plugin_path = boost::filesystem::absolute(plugin_path / plugin_id / ("rpplugin_" + plugin_id + RENDER_PIPELINE_BUILD_CFG_POSTFIX));
#else
    plugin_path = boost::filesystem::absolute(plugin_path / plugin_id / ("rpplugin_" + plugin_id));
#endif

#if defined(BOOST_OS_WINDOWS)
    // try to use extended-length in Windows
    // see http://www.boost.org/doc/libs/1_64_0/libs/filesystem/doc/reference.html#long-path-warning
    if (plugin_path.size() > 259)
    {
        self_.warn(fmt::format("Plugin ({}) path has long path. Try to use extended-length path.", plugin_id));
        plugin_path = "\\\\?\\" + plugin_path.string();
    }
#endif

    self_.trace(fmt::format("Importing shared library file ({}) from {}{}", plugin_id, plugin_path.string(), boost::dll::shared_library::suffix().string()));

    try
{'fraction_non_alphanumeric': 0.13507870221651141, 'fraction_numerical': 0.0014455509155155799, 'mean_word_length': 4.792558139534884, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 32, 'https://': 0, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3498087', 'n_tokens_mistral': 2000, 'n_tokens_neox': 1975, 'n_words': 355}