Plugins
ADIOS now has the ability for users to load their own engines and operators through the plugin interface. The basic steps for doing this are:
Write your plugin class, which needs to inherit from the appropriate
Plugin*Interface
class.Build as a shared library and add the path to your shared library to the
ADIOS2_PLUGIN_PATH
environment variable.Start using your plugin in your application.
These steps are discussed in further detail below.
Writing Your Plugin Class
Engine Plugin
Your engine plugin class needs to inherit from the PluginEngineInterface
class in the adios2/engine/plugin/PluginEngineInterface.h
header.
Depending on the type of engine you want to implement, you’ll need to override a number of methods that are inherited from the adios2::core::Engine
class.
These are briefly described in the following table.
More detailed documentation can be found in adios2/core/Engine.h
.
Method |
Engine Type |
Description |
---|---|---|
|
Read/Write |
Indicates the beginning of a step |
|
Read/Write |
Indicates the end of a step |
|
Read/Write |
Returns current step info |
|
Read/Write |
Close a particular transport |
|
Read/Write |
Engine initialization |
|
Read/Write |
Initialize parameters |
|
Read/Write |
Initialize transports |
|
Write |
Execute all deferred mode |
|
Write |
Flushes data and metadata to a transport |
|
Write |
Implementation for |
|
Write |
Implementation for |
|
Write |
Implementation for |
|
Read |
Execute all deferred mode |
|
Read |
Implementation for |
|
Read |
Implementation for |
Examples showing how to implement an engine plugin can be found in examples/plugins/engine
.
An example write engine is ExampleWritePlugin.h
, while an example read engine is in ExampleReadPlugin.h
.
The writer is a simple file writing engine that creates a directory (called ExamplePlugin
by default) and writes variable information to vars.txt and actual data to data.txt.
The reader example reads the files output by the writer example.
In addition to implementing the methods above, you’ll need to implement EngineCreate()
and EngineDestroy()
functions so ADIOS can create/destroy the engine object.
Because of C++ name mangling, you’ll need to use extern "C"
.
Looking at ExampleWritePlugin.h
, this looks like:
extern "C" {
adios2::plugin::ExampleWritePlugin *
EngineCreate(adios2::core::IO &io, const std::string &name,
const adios2::Mode mode, adios2::helper::Comm comm)
{
return new adios2::plugin::ExampleWritePlugin(io, name, mode,
comm.Duplicate());
}
void EngineDestroy(adios2::plugin::ExampleWritePlugin * obj)
{
delete obj;
}
}
Operator Plugin
Your operator plugin class needs to inherit from the PluginOperatorInterface
class in the adios2/operator/plugin/PluginOperatorInterface.h
header.
There’s three methods that you’ll need to override from the adios2::core::Operator
class, which are described below.
Method |
Description |
---|---|
|
Performs the operation, e.g., compress data |
|
Performs the inverse operation, e.g., decompress data |
|
Checks that a given data type can be processed |
An example showing how to implement an operator plugin can be found at plugins/EncryptionOperator.h
and plugins/EncryptionOperator.cpp
.
This operator uses libsodium for encrypting and decrypting data.
In addition to implementing the methods above, you’ll need to implement OperatorCreate()
and OperatorDestroy()
functions so ADIOS can create/destroy the operator object.
Because of C++ name mangling, you’ll need to use extern "C"
.
Looking at EncryptionOperator
, this looks like:
extern "C" {
adios2::plugin::EncryptionOperator *
OperatorCreate(const adios2::Params ¶meters)
{
return new adios2::plugin::EncryptionOperator(parameters);
}
void OperatorDestroy(adios2::plugin::EncryptionOperator * obj)
{
delete obj;
}
}
Using Your Plugin in an Application
For both types of plugins, loading the plugin is done by setting the PluginName
and PluginLibrary
parameters in an adios2::Params
object or <parameter>
XML tag.
Engine Plugins
For engine plugins, this looks like:
adios2::ADIOS adios;
adios2::IO io = adios.DeclareIO("writer");
io.SetEngine("Plugin");
adios2::Params params;
params["PluginName"] = "WritePlugin";
params["PluginLibrary"] = "PluginEngineWrite";
// If the engine plugin has any other parameters, these can be added to
// the same params object and they will be forwarded to the engine
io.SetParameters(params);
Where “WritePlugin” is the name that ADIOS will use to keep track of the plugin, and “PluginEngineWrite” is the shared library name. At this point you can open the engine and use it as you would any other ADIOS engine. You also shouldn’t need to make any changes to your CMake files for your application.
The second option is using an ADIOS XML config file. If you’d like to load your plugins through an XML config file, the following shows an example XML when using Engine Plugins:
<adios-config>
<io name="writer">
<engine type="Plugin">
<parameter key="PluginName" value="WritePlugin" />
<parameter key="PluginLibrary" value="PluginEngineWrite" />
<!-- any parameters needed for your plugin can be added here in the parameter tag -->
</engine>
</io>
<io name="reader">
<engine type="Plugin">
<parameter key="PluginName" value="ReadPlugin" />
<parameter key="PluginLibrary" value="PluginEngineRead" />
<!-- any parameters needed for your plugin can be added here in the parameter tag -->
</engine>
</io>
</adios-config>
The examples examples/plugins/engine/examplePluginEngine_write.cpp
and examples/plugins/engine/examplePluginEngine_read.cpp
are an example of how to use the engine plugins described above.
Operator Plugins
For operator plugins, the code to use your plugin looks like:
// for an adios2::Variable<T> var
adios2::Params params;
params["PluginName"] = "MyOperator";
params["PluginLibrary"] = "EncryptionOperator";
// example param required for the EncryptionOperator
params["SecretKeyFile"] = "test-key";
var.AddOperation("plugin", params);
If you’d like to load your operator plugin through an XML config file, the following shows an example:
<adios-config>
<io name="writer">
<variable name="data">
<operation type="plugin">
<parameter key="PluginName" value="OperatorPlugin"/>
<parameter key="PluginLibrary" value="EncryptionOperator" />
<parameter key="SecretKeyFile" value="test-key" />
</operation>
</variable>
<engine type="BP5">
</engine>
</io>
</adios-config>
The examples examples/plugins/operator/examplePluginOperator_write.cpp
and examples/plugins/engine/examplePluginOperator_read.cpp
show an example of how to use the EncryptionOperator
plugin described above.
Note
You don’t need to add the lib
prefix or the shared library ending (e.g., .so
, .dll
, etc.) when
setting PluginLibrary
.
ADIOS will add these when searching for your plugin library.
If you do add the prefix/suffix, ADIOS will still be able to find your plugin.
It’s also possible to put the full path to the shared library here, instead of using ADIOS2_PLUGIN_PATH
.