Skip to content
Snippets Groups Projects
PluginEngine.cpp 6.3 KiB
Newer Older
/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * PluginEngine.cpp
 *
 *  Created on: July 17, 2017
 *      Author: Chuck Atkins <chuck.atkins@kitware.com>
 */

#include "PluginEngine.h"
#include "PluginEngineInterface.h"

#include <functional>
#include <map>
#include <memory>
#include <stdexcept>
#include <utility>

#include "adios2/helper/adiosDynamicBinder.h"

namespace adios2
{

/******************************************************************************/

struct PluginEngine::Impl
{
    using Registry =
        std::map<std::string, std::pair<EngineCreateFun, EngineDestroyFun>>;
    static Registry m_Registry;

    std::string m_PluginName;
    std::unique_ptr<adios2::DynamicBinder> m_Binder;
    EngineCreateFun m_HandleCreate;
    EngineDestroyFun m_HandleDestroy;
    PluginEngineInterface *m_Plugin = nullptr;
};
PluginEngine::Impl::Registry PluginEngine::Impl::m_Registry;

/******************************************************************************/

void PluginEngine::RegisterPlugin(const std::string pluginName,
                                  EngineCreateFun create,
                                  EngineDestroyFun destroy)
{
    PluginEngine::Impl::m_Registry.emplace(pluginName,
                                           std::make_pair(create, destroy));
}

/******************************************************************************/

PluginEngine::PluginEngine(IO &io, const std::string &name, const Mode openMode,
                           MPI_Comm mpiComm)
: Engine("Plugin", io, name, openMode, mpiComm), m_Impl(new Impl)
{
    Init();
    m_Impl->m_Plugin =
        m_Impl->m_HandleCreate(io, m_Impl->m_PluginName, openMode, mpiComm);
}

PluginEngine::~PluginEngine() { m_Impl->m_HandleDestroy(m_Impl->m_Plugin); }

William F Godoy's avatar
William F Godoy committed
StepStatus PluginEngine::BeginStep(StepMode mode, const float timeoutSeconds)
pnorbert's avatar
pnorbert committed
{
    return m_Impl->m_Plugin->BeginStep(mode, timeout_sec);
}
void PluginEngine::PerformPuts() { m_Impl->m_Plugin->PerformPuts(); }
void PluginEngine::PerformGets() { m_Impl->m_Plugin->PerformGets(); }
void PluginEngine::EndStep() { m_Impl->m_Plugin->EndStep(); }

void PluginEngine::Close(const int transportIndex)
{
    m_Impl->m_Plugin->Close(transportIndex);
}

void PluginEngine::Init()
{
    auto paramPluginNameIt = m_IO.m_Parameters.find("PluginName");
    if (paramPluginNameIt == m_IO.m_Parameters.end())
    {
        throw std::invalid_argument("PluginEngine: PluginName must be "
                                    "specified in engine parameters");
    }
    m_Impl->m_PluginName = paramPluginNameIt->second;

    // First we check to see if we can find the plugin currently registerd
    auto registryEntryIt =
        PluginEngine::Impl::m_Registry.find(m_Impl->m_PluginName);

    if (registryEntryIt != PluginEngine::Impl::m_Registry.end())
    {
        m_Impl->m_HandleCreate = registryEntryIt->second.first;
        m_Impl->m_HandleDestroy = registryEntryIt->second.second;
    }
    else
    {
        // It's not currently registered so try to load it from a shared
        // library
        //
        auto paramPluginLibraryIt = m_IO.m_Parameters.find("PluginLibrary");
        if (paramPluginLibraryIt == m_IO.m_Parameters.end())
        {
            throw std::invalid_argument(
                "PluginEngine: PluginLibrary must be specified in "
                "engine parameters if no PluginName "
                "is specified");
        }
        std::string &pluginLibrary = paramPluginLibraryIt->second;

        m_Impl->m_Binder.reset(new adios2::DynamicBinder(pluginLibrary));

        m_Impl->m_HandleCreate = reinterpret_cast<EngineCreatePtr>(
            m_Impl->m_Binder->GetSymbol("EngineCreate"));
        if (!m_Impl->m_HandleCreate)
        {
            throw std::runtime_error("PluginEngine: Unable to locate "
                                     "EngineCreate symbol in specified plugin "
                                     "library");
        }

        m_Impl->m_HandleDestroy = reinterpret_cast<EngineDestroyPtr>(
            m_Impl->m_Binder->GetSymbol("EngineDestroy"));
        if (!m_Impl->m_HandleDestroy)
        {
            throw std::runtime_error("PluginEngine: Unable to locate "
                                     "EngineDestroy symbol in specified plugin "
                                     "library");
        }
    }
}

#define declare(T)                                                             \
    void PluginEngine::DoPutSync(Variable<T> &variable, const T *values)       \
        m_Impl->m_Plugin->DoPutSync(variable, values);                         \
    void PluginEngine::DoPutDeferred(Variable<T> &variable, const T *values)   \
        m_Impl->m_Plugin->DoPutDeferred(variable, values);                     \
    void PluginEngine::DoPutDeferred(Variable<T> &variable, const T &value)    \
        m_Impl->m_Plugin->DoPutDeferred(variable, value);                      \
    }                                                                          \
    void PluginEngine::DoGetSync(Variable<T> &variable, T *values)             \
    {                                                                          \
        m_Impl->m_Plugin->DoGetSync(variable, values);                         \
    }                                                                          \
    void PluginEngine::DoGetDeferred(Variable<T> &variable, T *values)         \
    {                                                                          \
        m_Impl->m_Plugin->DoGetDeferred(variable, values);                     \
    }                                                                          \
    void PluginEngine::DoGetDeferred(Variable<T> &variable, T &value)          \
        m_Impl->m_Plugin->DoGetDeferred(variable, value);                      \
ADIOS2_FOREACH_TYPE_1ARG(declare)
#undef declare

} // end namespace adios2