This is an automated email from the ASF dual-hosted git repository. martinzink pushed a commit to branch controller_c_api_requirements in repository https://gitbox.apache.org/repos/asf/nifi-minifi-cpp.git
commit e83dbf2d710de9bf1ee2e9382f63f6956f105f9d Author: Adam Debreceni <[email protected]> AuthorDate: Mon Mar 2 17:23:32 2026 +0100 MINIFICPP-2715 - Use a single integer as c api version --- Extensions.md | 10 ++- .../include/utils/ExtensionInitUtils.h | 4 +- extensions/ExtensionInitializer.cpp | 4 +- .../llamacpp/processors/ExtensionInitializer.cpp | 8 +-- extensions/opencv/OpenCVLoader.cpp | 6 +- .../python/pythonlibloader/PythonLibLoader.cpp | 4 +- extensions/python/pythonloader/PyProcLoader.cpp | 4 +- extensions/sftp/SFTPLoader.cpp | 8 +-- libminifi/include/core/extension/ApiVersion.h | 16 ++--- libminifi/include/core/extension/Extension.h | 8 +-- libminifi/src/core/extension/ApiVersion.cpp | 15 ++++- libminifi/src/core/extension/Extension.cpp | 76 +++++++++++----------- libminifi/src/minifi-c.cpp | 15 +++-- .../extension-verification-test/CApiExtension.cpp | 6 +- .../extension-verification-test/CMakeLists.txt | 18 ++--- .../CppApiExtension.cpp | 4 +- .../CreateNotCalled.cpp} | 26 ++------ .../ExtensionVerificationTests.cpp | 49 +++++++------- minifi-api/include/minifi-c/minifi-c.h | 11 ++-- 19 files changed, 141 insertions(+), 151 deletions(-) diff --git a/Extensions.md b/Extensions.md index 159232f9a..f75c068e6 100644 --- a/Extensions.md +++ b/Extensions.md @@ -30,8 +30,7 @@ One possible example of this is: ```C++ extern "C" const char* const MinifiApiVersion = MINIFI_API_VERSION; -extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) { - MinifiExtension* extension = nullptr; +extern "C" void MinifiInitExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { minifi::api::core::useProcessorClassDescription<minifi::extensions::llamacpp::processors::RunLlamaCppInference>([&] (const MinifiProcessorClassDefinition& description) { MinifiExtensionCreateInfo ext_create_info{ .name = minifi::api::utils::toStringView(MAKESTRING(EXTENSION_NAME)), @@ -41,9 +40,8 @@ extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) { .processors_count = 1, .processors_ptr = &description, }; - extension = MinifiCreateExtension(&ext_create_info); + MinifiCreateExtension(extension, &ext_create_info); }); - return extension; } ``` @@ -69,7 +67,7 @@ Some extensions (e.g. `OpenCVExtension`) require initialization before use. You need to define an `MinifiInitCppExtension` function of type `MinifiExtension*(MinifiConfig*)` to be called. ```C++ -extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { +extern "C" void MinifiInitCppExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { const auto success = org::apache::nifi::minifi::utils::Environment::setEnvironmentVariable("OPENCV_FFMPEG_CAPTURE_OPTIONS", "rtsp_transport;udp", false /*overwrite*/); if (!success) { return nullptr; @@ -82,7 +80,7 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { .processors_count = 0, .processors_ptr = nullptr }; - return minifi::utils::MinifiCreateCppExtension(&ext_create_info); + minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info); } ``` diff --git a/extension-framework/include/utils/ExtensionInitUtils.h b/extension-framework/include/utils/ExtensionInitUtils.h index 57f1d063f..75da5c1ae 100644 --- a/extension-framework/include/utils/ExtensionInitUtils.h +++ b/extension-framework/include/utils/ExtensionInitUtils.h @@ -30,8 +30,8 @@ inline MinifiStringView toStringView(std::string_view str) { using ConfigReader = std::function<std::optional<std::string>(std::string_view key)>; -static inline MinifiExtension* MinifiCreateCppExtension(const MinifiExtensionCreateInfo* create_info) { - return MINIFI_CREATE_EXTENSION_FN(create_info); +static inline void MinifiCreateCppExtension(MinifiExtension* extension, const MinifiExtensionCreateInfo* create_info) { + MINIFI_CREATE_EXTENSION_FN(extension, create_info); } } // namespace org::apache::nifi::minifi::utils diff --git a/extensions/ExtensionInitializer.cpp b/extensions/ExtensionInitializer.cpp index e735a78e7..47a4c2185 100644 --- a/extensions/ExtensionInitializer.cpp +++ b/extensions/ExtensionInitializer.cpp @@ -22,7 +22,7 @@ namespace minifi = org::apache::nifi::minifi; -extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { +extern "C" void MinifiInitCppExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { MinifiExtensionCreateInfo ext_create_info{ .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)), .version = minifi::utils::toStringView(minifi::AgentBuild::VERSION), @@ -31,5 +31,5 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { .processors_count = 0, .processors_ptr = nullptr }; - return minifi::utils::MinifiCreateCppExtension(&ext_create_info); + minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info); } diff --git a/extensions/llamacpp/processors/ExtensionInitializer.cpp b/extensions/llamacpp/processors/ExtensionInitializer.cpp index 29316f8b3..8c223dc70 100644 --- a/extensions/llamacpp/processors/ExtensionInitializer.cpp +++ b/extensions/llamacpp/processors/ExtensionInitializer.cpp @@ -24,10 +24,9 @@ namespace minifi = org::apache::nifi::minifi; -extern "C" const char* const MinifiApiVersion = MINIFI_API_VERSION; +extern "C" const uint32_t MinifiApiVersion = MINIFI_API_VERSION; -extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) { - MinifiExtension* extension = nullptr; +extern "C" void MinifiInitExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { minifi::api::core::useProcessorClassDescription<minifi::extensions::llamacpp::processors::RunLlamaCppInference>([&] (const MinifiProcessorClassDefinition& description) { MinifiExtensionCreateInfo ext_create_info{ .name = minifi::api::utils::toStringView(MAKESTRING(EXTENSION_NAME)), @@ -37,7 +36,6 @@ extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) { .processors_count = 1, .processors_ptr = &description, }; - extension = MinifiCreateExtension(&ext_create_info); + MinifiCreateExtension(extension, &ext_create_info); }); - return extension; } diff --git a/extensions/opencv/OpenCVLoader.cpp b/extensions/opencv/OpenCVLoader.cpp index 53f61dbca..87c6615c5 100644 --- a/extensions/opencv/OpenCVLoader.cpp +++ b/extensions/opencv/OpenCVLoader.cpp @@ -24,7 +24,7 @@ namespace minifi = org::apache::nifi::minifi; -extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { +extern "C" void MinifiInitCppExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { // By default in OpenCV, ffmpeg capture is hardcoded to use TCP and this is a workaround // also if UDP timeout, ffmpeg will retry with TCP // Note: @@ -32,7 +32,7 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { // 2. The command will not overwrite value if "OPENCV_FFMPEG_CAPTURE_OPTIONS" already exists. const auto success = org::apache::nifi::minifi::utils::Environment::setEnvironmentVariable("OPENCV_FFMPEG_CAPTURE_OPTIONS", "rtsp_transport;udp", false /*overwrite*/); if (!success) { - return nullptr; + return; } MinifiExtensionCreateInfo ext_create_info{ .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)), @@ -42,5 +42,5 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { .processors_count = 0, .processors_ptr = nullptr }; - return minifi::utils::MinifiCreateCppExtension(&ext_create_info); + minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info); } diff --git a/extensions/python/pythonlibloader/PythonLibLoader.cpp b/extensions/python/pythonlibloader/PythonLibLoader.cpp index 9c9a35d28..79ef21556 100644 --- a/extensions/python/pythonlibloader/PythonLibLoader.cpp +++ b/extensions/python/pythonlibloader/PythonLibLoader.cpp @@ -98,7 +98,7 @@ class PythonLibLoader { std::shared_ptr<minifi::core::logging::Logger> logger_ = minifi::core::logging::LoggerFactory<PythonLibLoader>::getLogger(); }; -extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* config) { +extern "C" void MinifiInitCppExtension(MinifiExtension* extension, MinifiConfig* config) { static PythonLibLoader python_lib_loader([&] (std::string_view key) -> std::optional<std::string> { std::optional<std::string> result; MinifiConfigGet(config, minifi::utils::toStringView(key), [] (void* user_data, MinifiStringView value) { @@ -114,5 +114,5 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* config) { .processors_count = 0, .processors_ptr = nullptr }; - return minifi::utils::MinifiCreateCppExtension(&ext_create_info); + minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info); } diff --git a/extensions/python/pythonloader/PyProcLoader.cpp b/extensions/python/pythonloader/PyProcLoader.cpp index d4edf9cf2..e92bbea41 100644 --- a/extensions/python/pythonloader/PyProcLoader.cpp +++ b/extensions/python/pythonloader/PyProcLoader.cpp @@ -33,7 +33,7 @@ static minifi::extensions::python::PythonCreator& getPythonCreator() { // the symbols of the python library extern "C" const int LOAD_MODULE_AS_GLOBAL = 1; -extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* config) { +extern "C" void MinifiInitCppExtension(MinifiExtension* extension, MinifiConfig* config) { getPythonCreator().configure([&] (std::string_view key) -> std::optional<std::string> { std::optional<std::string> result; MinifiConfigGet(config, minifi::utils::toStringView(key), [] (void* user_data, MinifiStringView value) { @@ -49,5 +49,5 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* config) { .processors_count = 0, .processors_ptr = nullptr }; - return minifi::utils::MinifiCreateCppExtension(&ext_create_info); + minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info); } diff --git a/extensions/sftp/SFTPLoader.cpp b/extensions/sftp/SFTPLoader.cpp index 333ab173e..c8309cc60 100644 --- a/extensions/sftp/SFTPLoader.cpp +++ b/extensions/sftp/SFTPLoader.cpp @@ -25,13 +25,13 @@ namespace minifi = org::apache::nifi::minifi; -extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { +extern "C" void MinifiInitCppExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { if (libssh2_init(0) != 0) { - return nullptr; + return; } if (curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK) { libssh2_exit(); - return nullptr; + return; } MinifiExtensionCreateInfo ext_create_info{ .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)), @@ -44,5 +44,5 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { .processors_count = 0, .processors_ptr = nullptr }; - return minifi::utils::MinifiCreateCppExtension(&ext_create_info); + minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info); } diff --git a/libminifi/include/core/extension/ApiVersion.h b/libminifi/include/core/extension/ApiVersion.h index 01acb82cb..34b917a32 100644 --- a/libminifi/include/core/extension/ApiVersion.h +++ b/libminifi/include/core/extension/ApiVersion.h @@ -21,17 +21,9 @@ namespace org::apache::nifi::minifi::core::extension { -struct ApiVersion { - int major; - int minor; - int patch; - - std::string str() const { - return std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(patch); - } -}; - -ApiVersion getAgentApiVersion(); -void setAgentApiVersion(ApiVersion api_version); +uint32_t getAgentApiVersion(); +uint32_t getMinSupportedApiVersion(); +void test_setAgentApiVersion(uint32_t api_version); +void test_setMinSupportedApiVersion(uint32_t min_api_version); } // namespace org::apache::nifi::minifi::core::extension diff --git a/libminifi/include/core/extension/Extension.h b/libminifi/include/core/extension/Extension.h index 356efed4c..85cf4fc60 100644 --- a/libminifi/include/core/extension/Extension.h +++ b/libminifi/include/core/extension/Extension.h @@ -51,7 +51,7 @@ class Extension { bool initialize(const std::shared_ptr<minifi::Configure>& configure); - [[nodiscard]] ApiVersion apiVersion() const {return api_version_;} + bool setInfo(Info info); private: #ifdef WIN32 @@ -71,12 +71,12 @@ class Extension { bool unload(); void* findSymbol(const char* name); - std::string name_; + std::string library_name_; std::filesystem::path library_path_; gsl::owner<void*> handle_ = nullptr; - ApiVersion api_version_; - std::unique_ptr<Info> info_; + std::optional<Info> info_; + uint32_t api_version_{0}; const std::shared_ptr<logging::Logger> logger_; }; diff --git a/libminifi/src/core/extension/ApiVersion.cpp b/libminifi/src/core/extension/ApiVersion.cpp index 1f515b25b..15f59d18b 100644 --- a/libminifi/src/core/extension/ApiVersion.cpp +++ b/libminifi/src/core/extension/ApiVersion.cpp @@ -20,14 +20,23 @@ namespace org::apache::nifi::minifi::core::extension { -static ApiVersion agent_api_version{.major = MINIFI_API_MAJOR_VERSION, .minor = MINIFI_API_MINOR_VERSION, .patch = MINIFI_API_PATCH_VERSION}; +static uint32_t agent_api_version{MINIFI_API_VERSION}; +static uint32_t min_supported_api_version{MINIFI_API_VERSION}; -ApiVersion getAgentApiVersion() { +uint32_t getAgentApiVersion() { return agent_api_version; } -void setAgentApiVersion(ApiVersion api_version) { +void test_setAgentApiVersion(uint32_t api_version) { agent_api_version = api_version; } +uint32_t getMinSupportedApiVersion() { + return min_supported_api_version; +} + +void test_setMinSupportedApiVersion(uint32_t min_api_version) { + min_supported_api_version = min_api_version; +} + } // namespace org::apache::nifi::minifi::core::extension \ No newline at end of file diff --git a/libminifi/src/core/extension/Extension.cpp b/libminifi/src/core/extension/Extension.cpp index 9073b6c9a..9382da9d1 100644 --- a/libminifi/src/core/extension/Extension.cpp +++ b/libminifi/src/core/extension/Extension.cpp @@ -42,10 +42,9 @@ namespace org::apache::nifi::minifi::core::extension { -Extension::Extension(std::string name, std::filesystem::path library_path) - : name_(std::move(name)), +Extension::Extension(std::string library_name, std::filesystem::path library_path) + : library_name_(std::move(library_name)), library_path_(std::move(library_path)), - api_version_(getAgentApiVersion()), logger_(logging::LoggerFactory<Extension>::getLogger()) { } @@ -57,59 +56,51 @@ bool Extension::load(bool global) { handle_ = dlopen(library_path_.string().c_str(), RTLD_NOW | RTLD_LOCAL); // NOLINT(cppcoreguidelines-owning-memory) } if (!handle_) { - logger_->log_error("Failed to load extension '{}' at '{}': {}", name_, library_path_, dlerror()); + logger_->log_error("Failed to load extension '{}' at '{}': {}", library_name_, library_path_, dlerror()); return false; } - logger_->log_trace("Dlopen succeeded for extension '{}' at '{}'", name_, library_path_); + logger_->log_trace("Dlopen succeeded for extension '{}' at '{}'", library_name_, library_path_); if (findSymbol("MinifiInitCppExtension")) { - logger_->log_trace("Loaded cpp extension '{}' at '{}'", name_, library_path_); + logger_->log_trace("Loaded cpp extension '{}' at '{}'", library_name_, library_path_); return true; } if (!findSymbol("MinifiInitExtension")) { - logger_->log_error("Failed to load as c extension '{}' at '{}': No initializer found", name_, library_path_); + logger_->log_error("Failed to load as c extension '{}' at '{}': No initializer found", library_name_, library_path_); return false; } - auto api_version = reinterpret_cast<const char* const*>(findSymbol("MinifiApiVersion")); - if (!api_version) { - logger_->log_error("Failed to load c extension '{}' at '{}': No MinifiApiVersion symbol found", name_, library_path_); + auto api_version_ptr = reinterpret_cast<const uint32_t*>(findSymbol("MinifiApiVersion")); + if (!api_version_ptr) { + logger_->log_error("Failed to load c extension '{}' at '{}': No MinifiApiVersion symbol found", library_name_, library_path_); return false; } - utils::SVMatch match; - if (!utils::regexSearch(*api_version, match, utils::Regex{R"(^([0-9]+)\.([0-9]+)\.([0-9]+)$)"})) { - logger_->log_error("Failed to load c extension '{}' at '{}': Api version is in invalid format: '{}'", name_, library_path_, *api_version); + api_version_ = *api_version_ptr; + if (api_version_ < getMinSupportedApiVersion()) { + logger_->log_error("Failed to load c extension '{}' at '{}': Api version is no longer supported, application supports {}-{} while extension is {}", + library_name_, library_path_, getMinSupportedApiVersion(), getAgentApiVersion(), api_version_); return false; } - gsl_Assert(match.size() == 4); - api_version_.major = std::stoi(match[1]); - api_version_.minor = std::stoi(match[2]); - api_version_.patch = std::stoi(match[3]); - if (api_version_.major != getAgentApiVersion().major) { - logger_->log_error("Failed to load c extension '{}' at '{}': Api major version mismatch, application is '{}' while extension is '{}'", - name_, library_path_, getAgentApiVersion().str(), *api_version); + if (api_version_ > getAgentApiVersion()) { + logger_->log_error("Failed to load c extension '{}' at '{}': Extension is built for a newer version, application supports {}-{} while extension is {}", + library_name_, library_path_, getMinSupportedApiVersion(), getAgentApiVersion(), api_version_); return false; } - if (api_version_.minor > getAgentApiVersion().minor) { - logger_->log_error("Failed to load c extension '{}' at '{}': Extension is built for a newer version, application is '{}' while extension is '{}'", - name_, library_path_, getAgentApiVersion().str(), *api_version); - return false; - } - logger_->log_debug("Loaded c extension '{}' at '{}': Application version is '{}', extension version is '{}'", - name_, library_path_, getAgentApiVersion().str(), *api_version); + logger_->log_debug("Loaded c extension '{}' at '{}': Application version is {}, extension version is {}", + library_name_, library_path_, getAgentApiVersion(), api_version_); return true; } bool Extension::unload() { - logger_->log_trace("Unloading library '{}' at '{}'", name_, library_path_); + logger_->log_trace("Unloading library '{}' at '{}'", library_name_, library_path_); if (!handle_) { - logger_->log_error("Extension does not have a handle_ '{}' at '{}'", name_, library_path_); + logger_->log_error("Extension does not have a handle_ '{}' at '{}'", library_name_, library_path_); return true; } dlerror(); if (dlclose(handle_)) { - logger_->log_error("Failed to unload extension '{}' at '{}': {}", name_, library_path_, dlerror()); + logger_->log_error("Failed to unload extension '{}' at '{}': {}", library_name_, library_path_, dlerror()); return false; } - logger_->log_trace("Unloaded extension '{}' at '{}'", name_, library_path_); + logger_->log_trace("Unloaded extension '{}' at '{}'", library_name_, library_path_); handle_ = nullptr; return true; } @@ -146,25 +137,34 @@ Extension::~Extension() { #endif } +bool Extension::setInfo(Info info) { + if (info_) { + return false; + } + info_ = std::move(info); + return true; +} + bool Extension::initialize(const std::shared_ptr<minifi::Configure>& configure) { - logger_->log_trace("Initializing extension '{}'", name_); + logger_->log_trace("Initializing extension '{}'", library_name_); void* init_symbol_ptr = findSymbol("MinifiInitCppExtension"); if (!init_symbol_ptr) { init_symbol_ptr = findSymbol("MinifiInitExtension"); } if (!init_symbol_ptr) { - logger_->log_error("No initializer for '{}'", name_); + logger_->log_error("No initializer for '{}'", library_name_); return false; } - logger_->log_debug("Found initializer for '{}'", name_); - auto init_fn = reinterpret_cast<MinifiExtension*(*)(MinifiConfig*)>(init_symbol_ptr); + logger_->log_debug("Found initializer for '{}'", library_name_); + auto init_fn = reinterpret_cast<void(*)(MinifiExtension*, MinifiConfig*)>(init_symbol_ptr); auto config_handle = reinterpret_cast<MinifiConfig*>(configure.get()); - info_.reset(reinterpret_cast<Info*>(init_fn(config_handle))); + auto extension_handle = reinterpret_cast<MinifiExtension*>(this); + init_fn(extension_handle, config_handle); if (!info_) { - logger_->log_error("Failed to initialize extension '{}'", name_); + logger_->log_error("Failed to initialize extension '{}'", library_name_); return false; } - logger_->log_debug("Initialized extension '{}'", name_); + logger_->log_debug("Initialized extension '{}', name = '{}', version = '{}'", library_name_, info_->name, info_->version); return true; } diff --git a/libminifi/src/minifi-c.cpp b/libminifi/src/minifi-c.cpp index e670c4415..0936f4808 100644 --- a/libminifi/src/minifi-c.cpp +++ b/libminifi/src/minifi-c.cpp @@ -225,10 +225,9 @@ void useCProcessorClassDescription(const MinifiProcessorClassDefinition& class_d extern "C" { -MinifiExtension* MinifiCreateExtension(const MinifiExtensionCreateInfo* extension_create_info) { +MinifiStatus MinifiCreateExtension(MinifiExtension* extension, const MinifiExtensionCreateInfo* extension_create_info) { + gsl_Assert(extension); gsl_Assert(extension_create_info); - auto current_extension = minifi::core::extension::ExtensionManager::getExtensionBeingInitialized(); - gsl_Assert(current_extension); auto extension_name = toString(extension_create_info->name); minifi::BundleIdentifier bundle{ .name = extension_name, @@ -243,16 +242,20 @@ MinifiExtension* MinifiCreateExtension(const MinifiExtensionCreateInfo* extensio bundle_components.processors.emplace_back(description); }); } - return reinterpret_cast<MinifiExtension*>(new org::apache::nifi::minifi::core::extension::Extension::Info{ + bool success = reinterpret_cast<org::apache::nifi::minifi::core::extension::Extension*>(extension)->setInfo(org::apache::nifi::minifi::core::extension::Extension::Info{ .name = toString(extension_create_info->name), .version = toString(extension_create_info->version), .deinit = extension_create_info->deinit, .user_data = extension_create_info->user_data }); + if (success) { + return MINIFI_STATUS_SUCCESS; + } + return MINIFI_STATUS_UNKNOWN_ERROR; } -MinifiExtension* MINIFI_CREATE_EXTENSION_FN(const MinifiExtensionCreateInfo* extension_create_info) { - return MinifiCreateExtension(extension_create_info); +MinifiStatus MINIFI_CREATE_EXTENSION_FN(MinifiExtension* extension, const MinifiExtensionCreateInfo* extension_create_info) { + return MinifiCreateExtension(extension, extension_create_info); } MinifiStatus MinifiProcessContextGetProperty(MinifiProcessContext* context, MinifiStringView property_name, MinifiFlowFile* flowfile, diff --git a/libminifi/test/integration/extension-verification-test/CApiExtension.cpp b/libminifi/test/integration/extension-verification-test/CApiExtension.cpp index e6fd7cfbc..bbd51809a 100644 --- a/libminifi/test/integration/extension-verification-test/CApiExtension.cpp +++ b/libminifi/test/integration/extension-verification-test/CApiExtension.cpp @@ -24,9 +24,9 @@ namespace minifi = org::apache::nifi::minifi; -extern "C" const char* const MinifiApiVersion = MINIFI_TEST_API_VERSION; +extern "C" const uint32_t MinifiApiVersion = MINIFI_TEST_API_VERSION; -extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) { +extern "C" void MinifiInitExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { MinifiExtensionCreateInfo ext_create_info{ .name = minifi::api::utils::toStringView(MAKESTRING(EXTENSION_NAME)), .version = minifi::api::utils::toStringView(MAKESTRING(EXTENSION_VERSION)), @@ -35,5 +35,5 @@ extern "C" MinifiExtension* MinifiInitExtension(MinifiConfig* /*config*/) { .processors_count = 0, .processors_ptr = nullptr, }; - return MinifiCreateExtension(&ext_create_info); + MinifiCreateExtension(extension, &ext_create_info); } \ No newline at end of file diff --git a/libminifi/test/integration/extension-verification-test/CMakeLists.txt b/libminifi/test/integration/extension-verification-test/CMakeLists.txt index 32c068106..fa428b044 100644 --- a/libminifi/test/integration/extension-verification-test/CMakeLists.txt +++ b/libminifi/test/integration/extension-verification-test/CMakeLists.txt @@ -41,7 +41,7 @@ function(create_c_test_extension extension-name custom_api_version) set(extension-name "test-extension-loading-${extension-name}") create_loading_test_extension(${extension-name} CApiExtension.cpp) target_link_libraries(${extension-name} minifi-cpp-extension-lib) - target_compile_definitions(${extension-name} PRIVATE MINIFI_TEST_API_VERSION="${custom_api_version}") + target_compile_definitions(${extension-name} PRIVATE MINIFI_TEST_API_VERSION=${custom_api_version}) target_compile_definitions(${extension-name} PRIVATE "EXTENSION_NAME=${extension-name}" "EXTENSION_VERSION=${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") endfunction() @@ -69,11 +69,13 @@ create_loading_test_extension(test-extension-loading-valid-build-id-cpp CppApiEx target_link_libraries(test-extension-loading-valid-build-id-cpp dummy-core-minifi) target_compile_definitions(test-extension-loading-valid-build-id-cpp PRIVATE MINIFI_CREATE_EXTENSION_FN=MinifiCreateCppExtension_${BUILD_IDENTIFIER}) -create_c_test_extension(same-version "1.1.1") -create_c_test_extension(greater-major-version "2.0.0") -create_c_test_extension(smaller-major-version "0.1.0") -create_c_test_extension(greater-minor-version "1.2.0") -create_c_test_extension(smaller-minor-version "1.0.1") -create_c_test_extension(greater-patch-version "1.1.2") -create_c_test_extension(smaller-patch-version "1.1.0") +create_c_test_extension(max-version 10) +create_c_test_extension(valid-version 7) +create_c_test_extension(min-version 5) +create_c_test_extension(greater-version 11) +create_c_test_extension(smaller-version 4) create_loading_test_extension(test-extension-loading-missing-init InvalidMissingInitExtension.cpp) + +create_loading_test_extension(test-extension-loading-create-not-called CreateNotCalled.cpp) +target_link_libraries(test-extension-loading-create-not-called minifi-c-api) +target_compile_definitions(test-extension-loading-create-not-called PRIVATE MINIFI_TEST_API_VERSION=10) diff --git a/libminifi/test/integration/extension-verification-test/CppApiExtension.cpp b/libminifi/test/integration/extension-verification-test/CppApiExtension.cpp index 0503a8c17..59daee45d 100644 --- a/libminifi/test/integration/extension-verification-test/CppApiExtension.cpp +++ b/libminifi/test/integration/extension-verification-test/CppApiExtension.cpp @@ -24,7 +24,7 @@ namespace minifi = org::apache::nifi::minifi; -extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { +extern "C" void MinifiInitCppExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { MinifiExtensionCreateInfo ext_create_info{ .name = minifi::utils::toStringView(MAKESTRING(MODULE_NAME)), .version = minifi::utils::toStringView("1.0.0"), @@ -33,5 +33,5 @@ extern "C" MinifiExtension* MinifiInitCppExtension(MinifiConfig* /*config*/) { .processors_count = 0, .processors_ptr = nullptr }; - return minifi::utils::MinifiCreateCppExtension(&ext_create_info); + minifi::utils::MinifiCreateCppExtension(extension, &ext_create_info); } diff --git a/libminifi/include/core/extension/ApiVersion.h b/libminifi/test/integration/extension-verification-test/CreateNotCalled.cpp similarity index 60% copy from libminifi/include/core/extension/ApiVersion.h copy to libminifi/test/integration/extension-verification-test/CreateNotCalled.cpp index 01acb82cb..ec6e5394d 100644 --- a/libminifi/include/core/extension/ApiVersion.h +++ b/libminifi/test/integration/extension-verification-test/CreateNotCalled.cpp @@ -1,5 +1,6 @@ /** -* Licensed to the Apache Software Foundation (ASF) under one or more +* + * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 @@ -15,23 +16,10 @@ * limitations under the License. */ -#pragma once +#include "minifi-c.h" -#include <string> +extern "C" const uint32_t MinifiApiVersion = MINIFI_TEST_API_VERSION; -namespace org::apache::nifi::minifi::core::extension { - -struct ApiVersion { - int major; - int minor; - int patch; - - std::string str() const { - return std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(patch); - } -}; - -ApiVersion getAgentApiVersion(); -void setAgentApiVersion(ApiVersion api_version); - -} // namespace org::apache::nifi::minifi::core::extension +extern "C" void MinifiInitExtension(MinifiExtension* extension, MinifiConfig* /*config*/) { + // NOT CALLING CREATE +} \ No newline at end of file diff --git a/libminifi/test/integration/extension-verification-test/ExtensionVerificationTests.cpp b/libminifi/test/integration/extension-verification-test/ExtensionVerificationTests.cpp index 6fa304691..a31700bf7 100644 --- a/libminifi/test/integration/extension-verification-test/ExtensionVerificationTests.cpp +++ b/libminifi/test/integration/extension-verification-test/ExtensionVerificationTests.cpp @@ -32,7 +32,8 @@ class ExtensionLoadingTestController { LogTestController::getInstance().clear(); LogTestController::getInstance().setTrace<core::extension::ExtensionManager>(); LogTestController::getInstance().setTrace<core::extension::Extension>(); - minifi::core::extension::setAgentApiVersion({.major = 1, .minor = 1, .patch = 1}); + minifi::core::extension::test_setAgentApiVersion(10); + minifi::core::extension::test_setMinSupportedApiVersion(5); auto config = minifi::Configure::create(); config->set(minifi::Configuration::nifi_extension_path, pattern); return config; @@ -46,9 +47,9 @@ TEST_CASE("Can load cpp-api extensions with same build id") { REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded cpp extension 'test-extension-loading-valid-build-id-cpp'")); } -TEST_CASE("Can load c-api extensions with same version") { - ExtensionLoadingTestController controller{"*test-extension-loading-same-version*"}; - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c extension 'test-extension-loading-same-version'")); +TEST_CASE("Can load c-api extensions with max version") { + ExtensionLoadingTestController controller{"*test-extension-loading-max-version*"}; + REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c extension 'test-extension-loading-max-version'")); } TEST_CASE("Can't load cpp-api extensions with different build id") { @@ -56,35 +57,35 @@ TEST_CASE("Can't load cpp-api extensions with different build id") { REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to load extension 'test-extension-loading-invalid-build-id-cpp'")); } -TEST_CASE("Can't load c-api extensions with greater major version") { - ExtensionLoadingTestController controller{"*test-extension-loading-greater-major-version*"}; - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to load c extension 'test-extension-loading-greater-major-version'")); - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Api major version mismatch, application is '1.1.1' while extension is '2.0.0'")); +TEST_CASE("Can load c-api extensions with min version") { + ExtensionLoadingTestController controller{"*test-extension-loading-min-version*"}; + REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c extension 'test-extension-loading-min-version'")); } -TEST_CASE("Can't load c-api extensions with smaller major version") { - ExtensionLoadingTestController controller{"*test-extension-loading-smaller-major-version*"}; - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to load c extension 'test-extension-loading-smaller-major-version'")); - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Api major version mismatch, application is '1.1.1' while extension is '0.1.0'")); +TEST_CASE("Can load c-api extensions with valid version") { + ExtensionLoadingTestController controller{"*test-extension-loading-valid-version*"}; + REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c extension 'test-extension-loading-valid-version'")); } -TEST_CASE("Can't load c-api extensions with greater minor version") { - ExtensionLoadingTestController controller{"*test-extension-loading-greater-minor-version*"}; - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to load c extension 'test-extension-loading-greater-minor-version'")); +TEST_CASE("Can't load c-api extensions with greater version") { + ExtensionLoadingTestController controller{"*test-extension-loading-greater-version*"}; + REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to load c extension 'test-extension-loading-greater-version'")); REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Extension is built for a newer version")); } -TEST_CASE("Can load c-api extensions with smaller minor version") { - ExtensionLoadingTestController controller{"*test-extension-loading-smaller-minor-version*"}; - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c extension 'test-extension-loading-smaller-minor-version'")); +TEST_CASE("Can't load c-api extensions with smaller version") { + ExtensionLoadingTestController controller{"*test-extension-loading-smaller-version*"}; + REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to load c extension 'test-extension-loading-smaller-version'")); + REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Api version is no longer supported, application supports 5-10 while extension is 4")); } -TEST_CASE("Can load c-api extensions with greater patch version") { - ExtensionLoadingTestController controller{"*test-extension-loading-greater-patch-version*"}; - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c extension 'test-extension-loading-greater-patch-version'")); +TEST_CASE("Can't load c-api extensions with no MinifiInitExtension function") { + ExtensionLoadingTestController controller{"*test-extension-loading-missing-init*"}; + REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to load as c extension 'test-extension-loading-missing-init'")); } -TEST_CASE("Can load c-api extensions with smaller patch version") { - ExtensionLoadingTestController controller{"*test-extension-loading-smaller-patch-version*"}; - REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Loaded c extension 'test-extension-loading-smaller-patch-version'")); +TEST_CASE("Can't load c-api extensions with no MinifiCreateExtension call") { + ExtensionLoadingTestController controller{"*test-extension-loading-create-not-called*"}; + REQUIRE(minifi::test::utils::verifyLogLinePresenceInPollTime(0s, "Failed to initialize extension 'test-extension-loading-create-not-called'")); } + diff --git a/minifi-api/include/minifi-c/minifi-c.h b/minifi-api/include/minifi-c/minifi-c.h index 5bab74941..9a80b5791 100644 --- a/minifi-api/include/minifi-c/minifi-c.h +++ b/minifi-api/include/minifi-c/minifi-c.h @@ -34,11 +34,6 @@ extern "C" { #define MINIFI_PRIVATE_JOIN_HELPER(X, Y) X ## _ ## Y #define MINIFI_PRIVATE_JOIN(X, Y) MINIFI_PRIVATE_JOIN_HELPER(X, Y) -#define MINIFI_API_MAJOR_VERSION 0 -#define MINIFI_API_MINOR_VERSION 1 -#define MINIFI_API_PATCH_VERSION 0 -#define MINIFI_API_VERSION MINIFI_PRIVATE_STRINGIFY(MINIFI_API_MAJOR_VERSION) "." MINIFI_PRIVATE_STRINGIFY(MINIFI_API_MINOR_VERSION) "." MINIFI_PRIVATE_STRINGIFY(MINIFI_API_PATCH_VERSION) - #define MINIFI_NULL nullptr #define MINIFI_OWNED @@ -46,6 +41,10 @@ extern "C" { #define MINIFI_CREATE_EXTENSION_FN MinifiCreateExtension #endif +enum : uint32_t { + MINIFI_API_VERSION = 1 +}; + typedef bool MinifiBool; typedef enum MinifiInputRequirement : uint32_t { @@ -189,7 +188,7 @@ typedef struct MinifiExtensionCreateInfo { const MinifiProcessorClassDefinition* processors_ptr; } MinifiExtensionCreateInfo; -MinifiExtension* MINIFI_CREATE_EXTENSION_FN(const MinifiExtensionCreateInfo* create_info); +MinifiStatus MINIFI_CREATE_EXTENSION_FN(MinifiExtension* extension, const MinifiExtensionCreateInfo* create_info); MINIFI_OWNED MinifiPublishedMetrics* MinifiPublishedMetricsCreate(size_t count, const MinifiStringView* metric_names, const double* metric_values);
