Skip to content
Snippets Groups Projects
PluginEngine.cpp 6.65 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); }

void PluginEngine::PerformReads(ReadMode mode)
{
    m_Impl->m_Plugin->PerformReads(mode);
}

void PluginEngine::Release() { m_Impl->m_Plugin->Release(); }

void PluginEngine::Advance(const float timeoutSeconds)
{
    m_Impl->m_Plugin->Advance(timeoutSeconds);
}

void PluginEngine::Advance(const AdvanceMode mode, const float timeoutSeconds)
{
    m_Impl->m_Plugin->Advance(mode, timeoutSeconds);
}

void PluginEngine::AdvanceAsync(const AdvanceMode mode,
                                AdvanceAsyncCallback callback)
{
    m_Impl->m_Plugin->AdvanceAsync(mode, callback);
}

void PluginEngine::SetCallBack(
    std::function<void(const void *, std::string, std::string, std::string,
                       std::vector<size_t>)>
        callback)
{
    m_Impl->m_Plugin->SetCallBack(callback);
}

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 define(T)                                                              \
    void PluginEngine::DoWrite(Variable<T> &variable, const T *values)         \
    {                                                                          \
        m_Impl->m_Plugin->DoWrite(variable, values);                           \
    }                                                                          \
    void PluginEngine::DoScheduleRead(Variable<T> &variable, const T *values)  \
    {                                                                          \
        m_Impl->m_Plugin->DoScheduleRead(variable, values);                    \
    }                                                                          \
    void PluginEngine::DoScheduleRead(const std::string &variableName,         \
                                      const T *values)                         \
    {                                                                          \
        m_Impl->m_Plugin->DoScheduleRead(variableName, values);                \
    }
ADIOS2_FOREACH_TYPE_1ARG(define)
#undef define
void PluginEngine::DoWrite(VariableCompound &variable, const void *values)
{
    m_Impl->m_Plugin->DoWrite(variable, values);
}

#define define(T, L)                                                           \
    Variable<T> *PluginEngine::InquireVariable##L(const std::string &name,     \
                                                  const bool readIn)           \
    {                                                                          \
        return m_Impl->m_Plugin->InquireVariable##L(name, readIn);             \
    }
ADIOS2_FOREACH_TYPE_2ARGS(define)
#undef define
VariableBase *PluginEngine::InquireVariableUnknown(const std::string &name,
                                                   const bool readIn)
{
    return m_Impl->m_Plugin->InquireVariableUnknown(name, readIn);
}

} // end namespace adios