From 576b34531ea40387bb92fec8866bae54136b3c97 Mon Sep 17 00:00:00 2001 From: Martin Zink Date: Mon, 26 Jan 2026 18:12:19 +0100 Subject: [PATCH 1/6] MINIFICPP-2708 Controller Service C API --- Extensions.md | 4 +- core-framework/include/agent/agent_docs.h | 13 +- .../core/controller/ControllerServiceBase.h | 6 +- .../controller/ControllerServiceFactoryImpl.h | 4 +- .../tests/MultipartUploadStateStorageTest.cpp | 2 +- .../controllers/NetworkPrioritizerService.h | 2 +- .../core/controller/ControllerService.h | 9 +- libminifi/include/utils/CControllerService.h | 110 +++++++++++++ libminifi/include/utils/CProcessor.h | 9 +- .../src/controllers/SSLContextService.cpp | 2 +- libminifi/src/minifi-c.cpp | 148 ++++++++++++++++-- .../test/libtest/integration/HTTPHandlers.h | 13 +- .../libtest/unit/ControllerServiceUtils.h | 2 +- .../unit/NetworkPrioritizerServiceTests.cpp | 2 +- .../core}/ControllerServiceMetadata.h | 6 +- minifi-api/include/minifi-c/minifi-c.h | 34 ++++ .../include/minifi-cpp/agent/agent_docs.h | 4 +- .../minifi-cpp/controllers/RecordSetReader.h | 4 +- .../minifi-cpp/controllers/RecordSetWriter.h | 4 +- .../controllers/SSLContextServiceInterface.h | 7 +- ...erServiceApi.h => ControllerServiceType.h} | 6 +- ...on.h => ControllerServiceTypeDefinition.h} | 2 +- .../controller/ControllerServiceDescriptor.h | 1 + .../controller/ControllerServiceFactory.h | 5 +- minifi-api/minifi-c-api.def | 3 + 25 files changed, 343 insertions(+), 59 deletions(-) create mode 100644 libminifi/include/utils/CControllerService.h rename minifi-api/{include/minifi-cpp/core/controller => common/include/minifi-cpp/core}/ControllerServiceMetadata.h (84%) rename minifi-api/include/minifi-cpp/core/{ControllerServiceApi.h => ControllerServiceType.h} (84%) rename minifi-api/include/minifi-cpp/core/{ControllerServiceApiDefinition.h => ControllerServiceTypeDefinition.h} (96%) diff --git a/Extensions.md b/Extensions.md index 11c96b93d6..fb3114bedb 100644 --- a/Extensions.md +++ b/Extensions.md @@ -87,7 +87,9 @@ extern "C" void MinifiInitCppExtension(MinifiExtensionContext* /*extension_conte .deinit = nullptr, .user_data = nullptr, .processors_count = 0, - .processors_ptr = nullptr + .processors_ptr = nullptr, + .controller_services_count = 0, + .controller_services_ptr = nullptr, }; minifi::utils::MinifiRegisterCppExtension(extension, &extension_definition); } diff --git a/core-framework/include/agent/agent_docs.h b/core-framework/include/agent/agent_docs.h index 14544f2d6b..4c7e250356 100644 --- a/core-framework/include/agent/agent_docs.h +++ b/core-framework/include/agent/agent_docs.h @@ -16,18 +16,17 @@ */ #pragma once -#include "minifi-cpp/agent/agent_docs.h" - #include #include #include #include -#include "utils/StringUtils.h" #include "core/ClassName.h" -#include "minifi-cpp/core/OutputAttribute.h" -#include "minifi-cpp/core/ControllerServiceApi.h" +#include "minifi-cpp/agent/agent_docs.h" +#include "minifi-cpp/core/ControllerServiceType.h" #include "minifi-cpp/core/DynamicProperty.h" +#include "minifi-cpp/core/OutputAttribute.h" +#include "utils/StringUtils.h" namespace org::apache::nifi::minifi { @@ -44,8 +43,8 @@ inline auto toVector(std::span attributes) return std::vector(attributes.begin(), attributes.end()); } -inline auto toVector(std::span apis) { - return std::vector(apis.begin(), apis.end()); +inline auto toVector(std::span apis) { + return std::vector(apis.begin(), apis.end()); } inline auto toVector(std::span properties) { diff --git a/core-framework/include/core/controller/ControllerServiceBase.h b/core-framework/include/core/controller/ControllerServiceBase.h index 63d1813c72..a02bf2caef 100644 --- a/core-framework/include/core/controller/ControllerServiceBase.h +++ b/core-framework/include/core/controller/ControllerServiceBase.h @@ -28,8 +28,8 @@ #include "core/Connectable.h" #include "minifi-cpp/core/controller/ControllerServiceApi.h" #include "minifi-cpp/core/controller/ControllerServiceHandle.h" -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" -#include "minifi-cpp/core/controller/ControllerServiceMetadata.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" +#include "minifi-cpp/core/ControllerServiceMetadata.h" #define ADD_COMMON_VIRTUAL_FUNCTIONS_FOR_CONTROLLER_SERVICES \ bool supportsDynamicProperties() const override { return SupportsDynamicProperties; } @@ -96,7 +96,7 @@ class ControllerServiceBase : public ControllerServiceApi { } - static constexpr auto ImplementsApis = std::array{}; + static constexpr auto ImplementsApis = std::array{}; protected: std::string name_; diff --git a/core-framework/include/core/controller/ControllerServiceFactoryImpl.h b/core-framework/include/core/controller/ControllerServiceFactoryImpl.h index 4060e9d18e..a30bd48c65 100644 --- a/core-framework/include/core/controller/ControllerServiceFactoryImpl.h +++ b/core-framework/include/core/controller/ControllerServiceFactoryImpl.h @@ -17,10 +17,12 @@ #pragma once -#include #include +#include #include + #include "core/ClassName.h" +#include "minifi-cpp/core/ControllerServiceMetadata.h" #include "minifi-cpp/core/controller/ControllerServiceFactory.h" namespace org::apache::nifi::minifi::core::controller { diff --git a/extensions/aws/tests/MultipartUploadStateStorageTest.cpp b/extensions/aws/tests/MultipartUploadStateStorageTest.cpp index 3b3b2d0397..66b0f3e12a 100644 --- a/extensions/aws/tests/MultipartUploadStateStorageTest.cpp +++ b/extensions/aws/tests/MultipartUploadStateStorageTest.cpp @@ -32,7 +32,7 @@ class MultipartUploadStateStorageTestFixture { MultipartUploadStateStorageTestFixture() { LogTestController::getInstance().setDebug(); const auto storage_uuid = minifi::utils::IdGenerator::getIdGenerator()->generate(); - state_storage_ = std::make_unique(core::controller::ControllerServiceMetadata{ + state_storage_ = std::make_unique(core::ControllerServiceMetadata{ .uuid = storage_uuid, .name = "KeyValueStateStorage", .logger = logging::LoggerFactory::getLogger(storage_uuid) diff --git a/libminifi/include/controllers/NetworkPrioritizerService.h b/libminifi/include/controllers/NetworkPrioritizerService.h index f893a9f68e..684a72ce99 100644 --- a/libminifi/include/controllers/NetworkPrioritizerService.h +++ b/libminifi/include/controllers/NetworkPrioritizerService.h @@ -51,7 +51,7 @@ class NetworkPrioritizerService : public core::controller::ControllerServiceBase public: using ControllerServiceBase::ControllerServiceBase; - explicit NetworkPrioritizerService(core::controller::ControllerServiceMetadata metadata, + explicit NetworkPrioritizerService(core::ControllerServiceMetadata metadata, std::shared_ptr clock) : ControllerServiceBase(std::move(metadata)), clock_(std::move(clock)) { diff --git a/libminifi/include/core/controller/ControllerService.h b/libminifi/include/core/controller/ControllerService.h index 8133c4dd83..8b2b1a3906 100644 --- a/libminifi/include/core/controller/ControllerService.h +++ b/libminifi/include/core/controller/ControllerService.h @@ -27,7 +27,7 @@ #include "core/ConfigurableComponentImpl.h" #include "core/Connectable.h" #include "minifi-cpp/core/controller/ControllerServiceApi.h" -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" namespace org::apache::nifi::minifi::core::controller { @@ -44,6 +44,7 @@ class ControllerService : public ConfigurableComponentImpl, public CoreComponent public: explicit ControllerServiceDescriptorImpl(ControllerService& impl): impl_(impl) {} void setSupportedProperties(std::span properties) override; + void setSupportedProperties(std::span properties) override; private: ControllerService& impl_; @@ -130,7 +131,7 @@ class ControllerService : public ConfigurableComponentImpl, public CoreComponent return impl_->supportsDynamicProperties(); } - static constexpr auto ImplementsApis = std::array{}; + static constexpr auto ImplementsApis = std::array{}; protected: std::unique_ptr impl_; @@ -146,6 +147,10 @@ inline void ControllerService::ControllerServiceDescriptorImpl::setSupportedProp impl_.setSupportedProperties(properties); } +inline void ControllerService::ControllerServiceDescriptorImpl::setSupportedProperties(std::span properties) { + impl_.setSupportedProperties(properties); +} + inline std::expected ControllerService::ControllerServiceContextImpl::getProperty(std::string_view name) const { return impl_.getProperty(name); } diff --git a/libminifi/include/utils/CControllerService.h b/libminifi/include/utils/CControllerService.h new file mode 100644 index 0000000000..60b8639e08 --- /dev/null +++ b/libminifi/include/utils/CControllerService.h @@ -0,0 +1,110 @@ +/** +* 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 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +#include "minifi-c/minifi-c.h" +#include "minifi-cpp/Exception.h" +#include "minifi-cpp/core/ControllerServiceMetadata.h" +#include "minifi-cpp/core/Property.h" +#include "minifi-cpp/core/controller/ControllerServiceApi.h" + +namespace org::apache::nifi::minifi::utils { +class CControllerService; + + +struct CControllerServiceClassDescription { + std::string full_name; + std::vector class_properties; + MinifiControllerServiceCallbacks callbacks; +}; + +class CControllerService final : public core::controller::ControllerServiceApi, public core::controller::ControllerServiceHandle { + public: + CControllerService(CControllerServiceClassDescription class_description, core::ControllerServiceMetadata metadata) + : class_description_(std::move(class_description)), + metadata_(std::move(metadata)) { + MinifiControllerServiceMetadata c_metadata; + auto uuid_str = metadata_.uuid.to_string(); + c_metadata.uuid = MinifiStringView{.data = uuid_str.data(), .length = uuid_str.length()}; + c_metadata.name = MinifiStringView{.data = metadata_.name.data(), .length = metadata_.name.length()}; + c_metadata.logger = reinterpret_cast(&metadata_.logger); + impl_ = class_description_.callbacks.create(c_metadata); + } + CControllerService(CControllerServiceClassDescription class_description, core::ControllerServiceMetadata metadata, gsl::owner impl) + : class_description_(std::move(class_description)), + impl_(impl), + metadata_(std::move(metadata)) {} + ~CControllerService() override { + class_description_.callbacks.destroy(impl_); + } + + [[nodiscard]] bool supportsDynamicProperties() const override { + return false; + } + + void initialize(core::controller::ControllerServiceDescriptor& descriptor) override { + descriptor.setSupportedProperties(std::span(class_description_.class_properties)); + } + + void onEnable(core::controller::ControllerServiceContext& controller_service_context, + const std::shared_ptr&, + const std::vector>&) override { + const auto enable_status = class_description_.callbacks.enable(impl_, reinterpret_cast(&controller_service_context)); + if (enable_status != MINIFI_STATUS_SUCCESS) { + throw Exception(PROCESS_SCHEDULE_EXCEPTION, "Could not enable controller service"); + } + } + + void notifyStop() override { + class_description_.callbacks.notifyStop(impl_); + } + + ControllerServiceHandle* getControllerServiceHandle() override { + return this; + } + + [[nodiscard]] std::string getName() const { + return metadata_.name; + } + + [[nodiscard]] Identifier getUUID() const { + return metadata_.uuid; + } + + [[nodiscard]] void* getImpl() const { + return this->impl_; + } + + [[nodiscard]] const CControllerServiceClassDescription& getClassDescription() const { + return class_description_; + } + + private: + CControllerServiceClassDescription class_description_; + gsl::owner impl_; + minifi::core::ControllerServiceMetadata metadata_; +}; + +void useCControllerServiceClassDescription(const MinifiControllerServiceClassDefinition& class_description, + const BundleIdentifier& bundle_id, + const std::function& fn); + +} // namespace org::apache::nifi::minifi::utils diff --git a/libminifi/include/utils/CProcessor.h b/libminifi/include/utils/CProcessor.h index 057d2e59d5..e6424ead5d 100644 --- a/libminifi/include/utils/CProcessor.h +++ b/libminifi/include/utils/CProcessor.h @@ -18,6 +18,7 @@ #pragma once #include +#include #include "minifi-cpp/core/Annotation.h" #include "core/ProcessorMetrics.h" @@ -63,18 +64,18 @@ class CProcessor : public minifi::core::ProcessorApi { CProcessor(CProcessorClassDescription class_description, minifi::core::ProcessorMetadata metadata) : class_description_(std::move(class_description)), metrics_extension_(std::make_shared(*this)) { - metadata_ = metadata; + metadata_ = std::move(metadata); MinifiProcessorMetadata c_metadata; - auto uuid_str = metadata.uuid.to_string(); + const auto uuid_str = metadata.uuid.to_string(); c_metadata.uuid = MinifiStringView{.data = uuid_str.data(), .length = uuid_str.length()}; - c_metadata.name = MinifiStringView{.data = metadata.name.data(), .length = metadata.name.length()}; + c_metadata.name = MinifiStringView{.data = metadata_.name.data(), .length = metadata_.name.length()}; c_metadata.logger = reinterpret_cast(&metadata_.logger); impl_ = class_description_.callbacks.create(c_metadata); } CProcessor(CProcessorClassDescription class_description, minifi::core::ProcessorMetadata metadata, gsl::owner impl) : class_description_(std::move(class_description)), impl_(impl), - metadata_(metadata), + metadata_(std::move(metadata)), metrics_extension_(std::make_shared(*this)) {} ~CProcessor() override { class_description_.callbacks.destroy(impl_); diff --git a/libminifi/src/controllers/SSLContextService.cpp b/libminifi/src/controllers/SSLContextService.cpp index dccdadeeda..c0b02d0859 100644 --- a/libminifi/src/controllers/SSLContextService.cpp +++ b/libminifi/src/controllers/SSLContextService.cpp @@ -596,7 +596,7 @@ void SSLContextService::verifyCertificateExpiration() { std::shared_ptr SSLContextService::createAndEnable(std::string_view name, const std::shared_ptr& configuration) { auto uuid = utils::IdGenerator::getIdGenerator()->generate(); auto logger = core::logging::LoggerFactory::getLogger(uuid); - auto service = std::make_shared(name, uuid, std::make_unique(core::controller::ControllerServiceMetadata{ + auto service = std::make_shared(name, uuid, std::make_unique(core::ControllerServiceMetadata{ .uuid = uuid, .name = std::string{name}, .logger = logger, diff --git a/libminifi/src/minifi-c.cpp b/libminifi/src/minifi-c.cpp index dac7bbe216..eda2b465a1 100644 --- a/libminifi/src/minifi-c.cpp +++ b/libminifi/src/minifi-c.cpp @@ -36,12 +36,17 @@ #include "minifi-cpp/core/logging/Logger.h" #include "minifi-cpp/core/state/PublishedMetricProvider.h" #include "utils/CProcessor.h" +#include "utils/CControllerService.h" #include "utils/PropertyErrors.h" namespace minifi = org::apache::nifi::minifi; namespace { +MinifiStringView minifiStringView(const std::string_view s) { + return MinifiStringView{.data = s.data(), .length = s.size()}; +} + std::string toString(MinifiStringView sv) { return {sv.data, sv.length}; } @@ -146,6 +151,37 @@ class CProcessorFactory : public minifi::core::ProcessorFactory { minifi::utils::CProcessorClassDescription class_description_; }; +class CControllerServiceFactory : public minifi::core::controller::ControllerServiceFactory { + public: + CControllerServiceFactory(std::string group_name, std::string class_name, minifi::utils::CControllerServiceClassDescription class_description) + : group_name_(std::move(group_name)), + class_name_(std::move(class_name)), + class_description_(std::move(class_description)) {} + std::unique_ptr create(minifi::core::ControllerServiceMetadata metadata) override { + return std::make_unique(class_description_, std::move(metadata)); + } + + [[nodiscard]] std::string getGroupName() const override { + return group_name_; + } + + [[nodiscard]] std::string getClassName() const override { + return class_name_; + } + + CControllerServiceFactory() = delete; + CControllerServiceFactory(const CControllerServiceFactory&) = delete; + CControllerServiceFactory& operator=(const CControllerServiceFactory&) = delete; + CControllerServiceFactory(CControllerServiceFactory&&) = delete; + CControllerServiceFactory& operator=(CControllerServiceFactory&&) = delete; + ~CControllerServiceFactory() override = default; + + private: + std::string group_name_; + std::string class_name_; + minifi::utils::CControllerServiceClassDescription class_description_; +}; + } // namespace namespace org::apache::nifi::minifi::utils { @@ -221,6 +257,32 @@ void useCProcessorClassDescription(const MinifiProcessorClassDefinition& class_d fn(description, c_class_description); } +void useCControllerServiceClassDescription(const MinifiControllerServiceClassDefinition& class_description, + const std::function& fn) { + std::vector properties; + properties.reserve(class_description.class_properties_count); + for (size_t i = 0; i < class_description.class_properties_count; ++i) { + properties.push_back(createProperty(&class_description.class_properties_ptr[i])); + } + + auto name_segments = minifi::utils::string::split(toStringView(class_description.full_name), "::"); + gsl_Assert(!name_segments.empty()); + + minifi::ClassDescription description{ + .type_ = minifi::ResourceType::ControllerService, + .short_name_ = name_segments.back(), + .full_name_ = minifi::utils::string::join(".", name_segments), + .description_ = toString(class_description.description), + .class_properties_ = properties, + }; + + minifi::utils::CControllerServiceClassDescription c_class_description{ + .full_name = toString(class_description.full_name), + .class_properties = properties, + .callbacks = class_description.callbacks + }; + fn(description, c_class_description); +} } // namespace org::apache::nifi::minifi::utils extern "C" { @@ -240,14 +302,14 @@ MinifiExtension* MinifiRegisterExtension(MinifiExtensionContext* extension_conte return MINIFI_NULL; } -MinifiStatus MinifiRegisterProcessor(MinifiExtension* extension_handle, const MinifiProcessorClassDefinition* processor) { - gsl_Assert(extension_handle); +MinifiStatus MinifiRegisterProcessor(MinifiExtension* extension, const MinifiProcessorClassDefinition* processor) { + gsl_Assert(extension); gsl_Assert(processor); - auto extension_info = reinterpret_cast(extension_handle)->getInfo(); + auto extension_info = reinterpret_cast(extension)->getInfo(); if (!extension_info) { return MINIFI_STATUS_UNKNOWN_ERROR; } - minifi::BundleIdentifier bundle{ + const minifi::BundleIdentifier bundle{ .name = extension_info->name, .version = extension_info->version }; @@ -261,6 +323,28 @@ MinifiStatus MinifiRegisterProcessor(MinifiExtension* extension_handle, const Mi return MINIFI_STATUS_SUCCESS; } +MinifiStatus MinifiRegisterControllerService(MinifiExtension* extension, const MinifiControllerServiceClassDefinition* controller_service) { + gsl_Assert(extension); + gsl_Assert(controller_service); + auto extension_info = reinterpret_cast(extension)->getInfo(); + if (!extension_info) { + return MINIFI_STATUS_UNKNOWN_ERROR; + } + const minifi::BundleIdentifier bundle{ + .name = extension_info->name, + .version = extension_info->version + }; + auto& bundle_components = minifi::ClassDescriptionRegistry::getMutableClassDescriptions()[bundle]; + minifi::utils::useCControllerServiceClassDescription(*controller_service, [&] (const auto& description, const auto& c_class_description) { + minifi::core::ClassLoader::getDefaultClassLoader().getClassLoader(extension_info->name).registerClass( + description.short_name_, + std::make_unique(extension_info->name, toString(controller_service->full_name), c_class_description)); + bundle_components.controller_services.emplace_back(description); + }); + return MINIFI_STATUS_SUCCESS; +} + + MinifiExtension* MINIFI_REGISTER_EXTENSION_FN(MinifiExtensionContext* extension_context, const MinifiExtensionDefinition* extension_definition) { return MinifiRegisterExtension(extension_context, extension_definition); } @@ -271,7 +355,7 @@ MinifiStatus MinifiProcessContextGetProperty(MinifiProcessContext* context, Mini auto result = reinterpret_cast(context)->getProperty(toStringView(property_name), flowfile != MINIFI_NULL ? reinterpret_cast*>(flowfile)->get() : nullptr); if (result) { - result_cb(user_ctx, MinifiStringView{.data = result.value().data(), .length = result.value().length()}); + result_cb(user_ctx, minifiStringView(result.value())); return MINIFI_STATUS_SUCCESS; } switch (static_cast(result.error().value())) { @@ -292,10 +376,7 @@ void MinifiConfigGet(MinifiExtensionContext* extension_context, MinifiStringView gsl_Assert(extension_context); auto value = reinterpret_cast(extension_context)->config->get(toString(key)); if (value) { - cb(user_ctx, MinifiStringView{ - .data = value->data(), - .length = value->length() - }); + cb(user_ctx, minifiStringView(*value)); } } @@ -441,7 +522,7 @@ MinifiBool MinifiFlowFileGetAttribute(MinifiProcessSession* session, MinifiFlowF if (!value.has_value()) { return false; } - cb(user_ctx, MinifiStringView{.data = value->data(), .length = value->size()}); + cb(user_ctx, minifiStringView(*value)); return true; } @@ -450,8 +531,53 @@ void MinifiFlowFileGetAttributes(MinifiProcessSession* session, MinifiFlowFile* gsl_Assert(session != MINIFI_NULL); gsl_Assert(flowfile != MINIFI_NULL); for (auto& [key, value] : (*reinterpret_cast*>(flowfile))->getAttributes()) { - cb(user_ctx, MinifiStringView{.data = key.data(), .length = key.size()}, MinifiStringView{.data = value.data(), .length = value.size()}); + cb(user_ctx, minifiStringView(key), minifiStringView(value)); + } +} + +MinifiStatus MinifiControllerServiceContextGetProperty(MinifiControllerServiceContext* context, MinifiStringView property_name, + void (*result_cb)(void* user_ctx, MinifiStringView result), void* user_ctx) { + gsl_Assert(context != MINIFI_NULL); + auto result = reinterpret_cast(context)->getProperty(toStringView(property_name)); + if (result) { + result_cb(user_ctx, minifiStringView(result.value())); + return MINIFI_STATUS_SUCCESS; + } + switch (static_cast(result.error().value())) { + case minifi::core::PropertyErrorCode::NotSupportedProperty: return MINIFI_STATUS_NOT_SUPPORTED_PROPERTY; + case minifi::core::PropertyErrorCode::DynamicPropertiesNotSupported: return MINIFI_STATUS_DYNAMIC_PROPERTIES_NOT_SUPPORTED; + case minifi::core::PropertyErrorCode::PropertyNotSet: return MINIFI_STATUS_PROPERTY_NOT_SET; + case minifi::core::PropertyErrorCode::ValidationFailed: return MINIFI_STATUS_VALIDATION_FAILED; + default: return MINIFI_STATUS_UNKNOWN_ERROR; } } + +MinifiStatus MinifiProcessContextGetControllerService( + MinifiProcessContext* process_context, + const MinifiStringView controller_service_name, + const MinifiStringView controller_service_type, + void** controller_service_out) { + if (!controller_service_out) { + return MINIFI_STATUS_UNKNOWN_ERROR; + } + + gsl_Assert(process_context != MINIFI_NULL); + const auto context = reinterpret_cast(process_context); + const auto name_str = std::string{toStringView(controller_service_name)}; + const auto service_shared_ptr = context->getControllerService(name_str, context->getProcessorInfo().getUUID()); + if (!service_shared_ptr) { + return MINIFI_STATUS_VALIDATION_FAILED; + } + if (const minifi::utils::CControllerService* c_controller_service = dynamic_cast(&*service_shared_ptr)) { + const auto class_description = c_controller_service->getClassDescription(); + if (class_description.full_name == toStringView(controller_service_type)) { + *controller_service_out = c_controller_service->getImpl(); + return MINIFI_STATUS_SUCCESS; + } + } + return MINIFI_STATUS_VALIDATION_FAILED; +} + + } // extern "C" diff --git a/libminifi/test/libtest/integration/HTTPHandlers.h b/libminifi/test/libtest/integration/HTTPHandlers.h index 25a0dba5d4..40304948af 100644 --- a/libminifi/test/libtest/integration/HTTPHandlers.h +++ b/libminifi/test/libtest/integration/HTTPHandlers.h @@ -21,21 +21,22 @@ #include #include #include +#include #include +#include #include #include -#include -#include -#include "civetweb.h" #include "CivetServer.h" -#include "concurrentqueue.h" -#include "rapidjson/document.h" -#include "utils/HTTPUtils.h" #include "ServerAwareHandler.h" #include "c2/C2Payload.h" +#include "civetweb.h" +#include "concurrentqueue.h" +#include "minifi-cpp/properties/Configure.h" #include "properties/Configure.h" +#include "rapidjson/document.h" #include "unit/Catch.h" +#include "utils/HTTPUtils.h" namespace org::apache::nifi::minifi::test { diff --git a/libminifi/test/libtest/unit/ControllerServiceUtils.h b/libminifi/test/libtest/unit/ControllerServiceUtils.h index 7f541c1dbe..941ec8b73c 100644 --- a/libminifi/test/libtest/unit/ControllerServiceUtils.h +++ b/libminifi/test/libtest/unit/ControllerServiceUtils.h @@ -29,7 +29,7 @@ std::unique_ptr make_controller_service(std if (!uuid) { uuid = minifi::utils::IdGenerator::getIdGenerator()->generate(); } - auto controller_service_impl = std::make_unique(core::controller::ControllerServiceMetadata{ + auto controller_service_impl = std::make_unique(core::ControllerServiceMetadata{ .uuid = uuid.value(), .name = std::string{name}, .logger = minifi::core::logging::LoggerFactory::getLogger(uuid.value()) diff --git a/libminifi/test/unit/NetworkPrioritizerServiceTests.cpp b/libminifi/test/unit/NetworkPrioritizerServiceTests.cpp index a54ba109ac..a05d21ad2b 100644 --- a/libminifi/test/unit/NetworkPrioritizerServiceTests.cpp +++ b/libminifi/test/unit/NetworkPrioritizerServiceTests.cpp @@ -31,7 +31,7 @@ std::shared_ptr createNetworkPrioritizerSer const std::shared_ptr& clock = std::make_shared()) { return std::make_shared( name, utils::Identifier{}, - std::make_unique(core::controller::ControllerServiceMetadata{ + std::make_unique(core::ControllerServiceMetadata{ .uuid = utils::Identifier{}, .name = name, .logger = logging::LoggerFactory::getLogger() diff --git a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceMetadata.h b/minifi-api/common/include/minifi-cpp/core/ControllerServiceMetadata.h similarity index 84% rename from minifi-api/include/minifi-cpp/core/controller/ControllerServiceMetadata.h rename to minifi-api/common/include/minifi-cpp/core/ControllerServiceMetadata.h index 3c6fb63b74..22200a84d8 100644 --- a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceMetadata.h +++ b/minifi-api/common/include/minifi-cpp/core/ControllerServiceMetadata.h @@ -1,5 +1,5 @@ /** - * 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 @@ -21,7 +21,7 @@ #include "minifi-cpp/utils/Id.h" #include "minifi-cpp/core/logging/Logger.h" -namespace org::apache::nifi::minifi::core::controller { +namespace org::apache::nifi::minifi::core { struct ControllerServiceMetadata { utils::Identifier uuid; @@ -29,4 +29,4 @@ struct ControllerServiceMetadata { std::shared_ptr logger; }; -} // namespace org::apache::nifi::minifi::core::controller +} // namespace org::apache::nifi::minifi::core diff --git a/minifi-api/include/minifi-c/minifi-c.h b/minifi-api/include/minifi-c/minifi-c.h index edf8c79ba7..fd647d0ee0 100644 --- a/minifi-api/include/minifi-c/minifi-c.h +++ b/minifi-api/include/minifi-c/minifi-c.h @@ -100,6 +100,8 @@ typedef struct MinifiExtensionContext MinifiExtensionContext; typedef struct MinifiPublishedMetrics MinifiPublishedMetrics; typedef struct MinifiAgent MinifiAgent; +typedef struct MinifiControllerServiceContext MinifiControllerServiceContext; + typedef enum MinifiStatus : uint32_t { MINIFI_STATUS_SUCCESS = 0, MINIFI_STATUS_UNKNOWN_ERROR = 1, @@ -153,6 +155,12 @@ typedef struct MinifiProcessorMetadata { MinifiLogger* logger; // borrowed reference, live until the processor is live } MinifiProcessorMetadata; +typedef struct MinifiControllerServiceMetadata { + MinifiStringView uuid; + MinifiStringView name; + MinifiLogger* logger; // borrowed reference, live until the controller service is live +} MinifiControllerServiceMetadata; + typedef struct MinifiProcessorCallbacks { MINIFI_OWNED void*(*create)(MinifiProcessorMetadata); void(*destroy)(MINIFI_OWNED void*); @@ -164,6 +172,13 @@ typedef struct MinifiProcessorCallbacks { MINIFI_OWNED MinifiPublishedMetrics*(*calculateMetrics)(void*); } MinifiProcessorCallbacks; +typedef struct MinifiControllerServiceCallbacks { + MINIFI_OWNED void*(*create)(MinifiControllerServiceMetadata); + void(*destroy)(MINIFI_OWNED void*); + MinifiStatus(*enable)(void*, MinifiControllerServiceContext*); + void(*notifyStop)(void*); +} MinifiControllerServiceCallbacks; + typedef struct MinifiProcessorClassDefinition { MinifiStringView full_name; // '::'-delimited fully qualified name e.g. 'org::apache::nifi::minifi::GenerateFlowFile' MinifiStringView description; @@ -183,6 +198,15 @@ typedef struct MinifiProcessorClassDefinition { MinifiProcessorCallbacks callbacks; } MinifiProcessorClassDefinition; +typedef struct MinifiControllerServiceClassDefinition { + MinifiStringView full_name; // '::'-delimited fully qualified name e.g. 'org::apache::nifi::minifi::extensions::gcp::GCPCredentialsControllerService + MinifiStringView description; + size_t class_properties_count; + const MinifiPropertyDefinition* class_properties_ptr; + + MinifiControllerServiceCallbacks callbacks; +} MinifiControllerServiceClassDefinition; + typedef struct MinifiExtensionDefinition { MinifiStringView name; MinifiStringView version; @@ -197,12 +221,17 @@ MinifiExtension* MINIFI_REGISTER_EXTENSION_FN(MinifiExtensionContext* extension_ MinifiStatus MinifiRegisterProcessor(MinifiExtension* extension, const MinifiProcessorClassDefinition* processor); +MinifiStatus MinifiRegisterControllerService(MinifiExtension* extension, const MinifiControllerServiceClassDefinition* controller_service); + MINIFI_OWNED MinifiPublishedMetrics* MinifiPublishedMetricsCreate(size_t count, const MinifiStringView* metric_names, const double* metric_values); MinifiStatus MinifiProcessContextGetProperty(MinifiProcessContext* context, MinifiStringView property_name, MinifiFlowFile* flowfile, void(*cb)(void* user_ctx, MinifiStringView property_value), void* user_ctx); MinifiBool MinifiProcessContextHasNonEmptyProperty(MinifiProcessContext* context, MinifiStringView property_name); +MinifiStatus MinifiProcessContextGetControllerService( + MinifiProcessContext* process_context, MinifiStringView controller_service_name, MinifiStringView controller_service_type, void** controller_service_out); + void MinifiLoggerSetMaxLogSize(MinifiLogger*, int32_t); void MinifiLoggerLogString(MinifiLogger*, MinifiLogLevel, MinifiStringView); MinifiBool MinifiLoggerShouldLog(MinifiLogger*, MinifiLogLevel); @@ -229,6 +258,11 @@ MinifiBool MinifiFlowFileGetAttribute(MinifiProcessSession* session, MinifiFlowF void(*cb)(void* user_ctx, MinifiStringView attribute_value), void* user_ctx); void MinifiFlowFileGetAttributes(MinifiProcessSession* session, MinifiFlowFile* flowfile, void(*cb)(void* user_ctx, MinifiStringView attribute_name, MinifiStringView attribute_value), void* user_ctx); +MinifiStatus MinifiControllerServiceContextGetProperty(MinifiControllerServiceContext* context, + MinifiStringView property_name, + void(*cb)(void* user_ctx, MinifiStringView property_value), + void* user_ctx); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus diff --git a/minifi-api/include/minifi-cpp/agent/agent_docs.h b/minifi-api/include/minifi-cpp/agent/agent_docs.h index 61a759bed7..781dfb735c 100644 --- a/minifi-api/include/minifi-cpp/agent/agent_docs.h +++ b/minifi-api/include/minifi-cpp/agent/agent_docs.h @@ -22,7 +22,7 @@ #include #include "minifi-cpp/core/Annotation.h" -#include "minifi-cpp/core/ControllerServiceApi.h" +#include "minifi-cpp/core/ControllerServiceType.h" #include "minifi-cpp/core/DynamicProperty.h" #include "minifi-cpp/core/OutputAttribute.h" #include "minifi-cpp/core/Property.h" @@ -44,7 +44,7 @@ struct ClassDescription { std::vector dynamic_properties_{}; std::vector class_relationships_{}; std::vector output_attributes_{}; - std::vector api_implementations{}; + std::vector api_implementations{}; bool supports_dynamic_properties_ = false; bool supports_dynamic_relationships_ = false; std::string inputRequirement_{}; diff --git a/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h b/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h index 536491272e..c05d20396c 100644 --- a/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h +++ b/minifi-api/include/minifi-cpp/controllers/RecordSetReader.h @@ -17,7 +17,7 @@ #pragma once #include "minifi-cpp/core/controller/ControllerServiceHandle.h" -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" #include "minifi-cpp/core/Record.h" #include "utils/Enum.h" #include "utils/ProcessorConfigUtils.h" @@ -28,7 +28,7 @@ namespace org::apache::nifi::minifi::core { class RecordSetReader : public controller::ControllerServiceHandle { public: - static constexpr auto ProvidesApi = core::ControllerServiceApiDefinition{ + static constexpr auto ProvidesApi = core::ControllerServiceTypeDefinition{ .artifact = "minifi-system", .group = "org.apache.nifi.minifi", .type = "org.apache.nifi.minifi.core.RecordSetReader", diff --git a/minifi-api/include/minifi-cpp/controllers/RecordSetWriter.h b/minifi-api/include/minifi-cpp/controllers/RecordSetWriter.h index 10e17f536f..9e131168aa 100644 --- a/minifi-api/include/minifi-cpp/controllers/RecordSetWriter.h +++ b/minifi-api/include/minifi-cpp/controllers/RecordSetWriter.h @@ -18,7 +18,7 @@ #include "minifi-cpp/core/controller/ControllerServiceHandle.h" -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" #include "minifi-cpp/core/FlowFile.h" #include "minifi-cpp/core/ProcessSession.h" #include "minifi-cpp/core/Record.h" @@ -28,7 +28,7 @@ namespace org::apache::nifi::minifi::core { class RecordSetWriter : public controller::ControllerServiceHandle { public: - static constexpr auto ProvidesApi = core::ControllerServiceApiDefinition{ + static constexpr auto ProvidesApi = core::ControllerServiceTypeDefinition{ .artifact = "minifi-system", .group = "org.apache.nifi.minifi", .type = "org.apache.nifi.minifi.core.RecordSetWriter", diff --git a/minifi-api/include/minifi-cpp/controllers/SSLContextServiceInterface.h b/minifi-api/include/minifi-cpp/controllers/SSLContextServiceInterface.h index bc21a20929..0c17e260b3 100644 --- a/minifi-api/include/minifi-cpp/controllers/SSLContextServiceInterface.h +++ b/minifi-api/include/minifi-cpp/controllers/SSLContextServiceInterface.h @@ -16,13 +16,12 @@ */ #pragma once -#include +#include #include #include #include -#include -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" #include "minifi-cpp/agent/agent_version.h" #include "minifi-cpp/core/controller/ControllerServiceHandle.h" @@ -38,7 +37,7 @@ namespace org::apache::nifi::minifi::controllers { */ class SSLContextServiceInterface : public core::controller::ControllerServiceHandle { public: - static constexpr auto ProvidesApi = core::ControllerServiceApiDefinition{ + static constexpr auto ProvidesApi = core::ControllerServiceTypeDefinition{ .artifact = "minifi-system", .group = "org.apache.nifi.minifi", .type = "org.apache.nifi.minifi.controllers.SSLContextServiceInterface", diff --git a/minifi-api/include/minifi-cpp/core/ControllerServiceApi.h b/minifi-api/include/minifi-cpp/core/ControllerServiceType.h similarity index 84% rename from minifi-api/include/minifi-cpp/core/ControllerServiceApi.h rename to minifi-api/include/minifi-cpp/core/ControllerServiceType.h index fe0d450f7d..6d5b39de3d 100644 --- a/minifi-api/include/minifi-cpp/core/ControllerServiceApi.h +++ b/minifi-api/include/minifi-cpp/core/ControllerServiceType.h @@ -17,16 +17,16 @@ #pragma once #include -#include "minifi-cpp/core/ControllerServiceApiDefinition.h" +#include "minifi-cpp/core/ControllerServiceTypeDefinition.h" namespace org::apache::nifi::minifi::core { -struct ControllerServiceApi { +struct ControllerServiceType { std::string artifact; std::string group; std::string type; - ControllerServiceApi(const ControllerServiceApiDefinition& definition) // NOLINT(runtime/explicit) + ControllerServiceType(const ControllerServiceTypeDefinition& definition) // NOLINT(runtime/explicit) : artifact(definition.artifact), group(definition.group), type(definition.type) {} diff --git a/minifi-api/include/minifi-cpp/core/ControllerServiceApiDefinition.h b/minifi-api/include/minifi-cpp/core/ControllerServiceTypeDefinition.h similarity index 96% rename from minifi-api/include/minifi-cpp/core/ControllerServiceApiDefinition.h rename to minifi-api/include/minifi-cpp/core/ControllerServiceTypeDefinition.h index 37084baeaa..f40d871a6f 100644 --- a/minifi-api/include/minifi-cpp/core/ControllerServiceApiDefinition.h +++ b/minifi-api/include/minifi-cpp/core/ControllerServiceTypeDefinition.h @@ -20,7 +20,7 @@ namespace org::apache::nifi::minifi::core { -struct ControllerServiceApiDefinition { +struct ControllerServiceTypeDefinition { std::string_view artifact; std::string_view group; std::string_view type; diff --git a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceDescriptor.h b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceDescriptor.h index 525a6d6cea..39fb6da89d 100644 --- a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceDescriptor.h +++ b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceDescriptor.h @@ -26,6 +26,7 @@ class ControllerServiceDescriptor { virtual ~ControllerServiceDescriptor() = default; virtual void setSupportedProperties(std::span properties) = 0; + virtual void setSupportedProperties(std::span properties) = 0; }; } // namespace org::apache::nifi::minifi::core::controller diff --git a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h index 725944bfa3..aafc571dcd 100644 --- a/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h +++ b/minifi-api/include/minifi-cpp/core/controller/ControllerServiceFactory.h @@ -17,10 +17,11 @@ #pragma once -#include #include +#include #include -#include "minifi-cpp/core/controller/ControllerServiceMetadata.h" + +#include "minifi-cpp/core/ControllerServiceMetadata.h" namespace org::apache::nifi::minifi::core::controller { diff --git a/minifi-api/minifi-c-api.def b/minifi-api/minifi-c-api.def index 8b41b8f25a..b2cdcf4f43 100644 --- a/minifi-api/minifi-c-api.def +++ b/minifi-api/minifi-c-api.def @@ -2,9 +2,12 @@ LIBRARY core-minifi.dll EXPORTS MinifiRegisterExtension MinifiRegisterProcessor + MinifiRegisterControllerService MinifiPublishedMetricsCreate + MinifiProcessContextGetControllerService MinifiProcessContextGetProperty MinifiProcessContextHasNonEmptyProperty + MinifiControllerServiceContextGetProperty MinifiLoggerSetMaxLogSize MinifiLoggerLogString MinifiLoggerShouldLog From 11c5382ece54801acf73b72d175bd322548829c6 Mon Sep 17 00:00:00 2001 From: Martin Zink Date: Mon, 13 Apr 2026 17:48:48 +0200 Subject: [PATCH 2/6] review changes --- Extensions.md | 4 ---- libminifi/include/utils/CProcessor.h | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Extensions.md b/Extensions.md index fb3114bedb..51077009fe 100644 --- a/Extensions.md +++ b/Extensions.md @@ -86,10 +86,6 @@ extern "C" void MinifiInitCppExtension(MinifiExtensionContext* /*extension_conte .version = minifi::utils::toStringView(minifi::AgentBuild::VERSION), .deinit = nullptr, .user_data = nullptr, - .processors_count = 0, - .processors_ptr = nullptr, - .controller_services_count = 0, - .controller_services_ptr = nullptr, }; minifi::utils::MinifiRegisterCppExtension(extension, &extension_definition); } diff --git a/libminifi/include/utils/CProcessor.h b/libminifi/include/utils/CProcessor.h index e6424ead5d..210f82b069 100644 --- a/libminifi/include/utils/CProcessor.h +++ b/libminifi/include/utils/CProcessor.h @@ -63,8 +63,8 @@ class CProcessor : public minifi::core::ProcessorApi { public: CProcessor(CProcessorClassDescription class_description, minifi::core::ProcessorMetadata metadata) : class_description_(std::move(class_description)), + metadata_(std::move(metadata)), metrics_extension_(std::make_shared(*this)) { - metadata_ = std::move(metadata); MinifiProcessorMetadata c_metadata; const auto uuid_str = metadata.uuid.to_string(); c_metadata.uuid = MinifiStringView{.data = uuid_str.data(), .length = uuid_str.length()}; From 09e550c7df7c31e22ce21490cd9147f575cbed95 Mon Sep 17 00:00:00 2001 From: Martin Zink Date: Wed, 1 Apr 2026 13:03:10 +0200 Subject: [PATCH 3/6] API changes from MINIFICPP-2764 --- minifi-api/include/minifi-c/minifi-c.h | 1 + 1 file changed, 1 insertion(+) diff --git a/minifi-api/include/minifi-c/minifi-c.h b/minifi-api/include/minifi-c/minifi-c.h index fd647d0ee0..2b74c3dc12 100644 --- a/minifi-api/include/minifi-c/minifi-c.h +++ b/minifi-api/include/minifi-c/minifi-c.h @@ -100,6 +100,7 @@ typedef struct MinifiExtensionContext MinifiExtensionContext; typedef struct MinifiPublishedMetrics MinifiPublishedMetrics; typedef struct MinifiAgent MinifiAgent; +typedef struct MinifiControllerService MinifiControllerService; typedef struct MinifiControllerServiceContext MinifiControllerServiceContext; typedef enum MinifiStatus : uint32_t { From ef2279547d8f6ea5855ae1a827e394f0fb0c6e0b Mon Sep 17 00:00:00 2001 From: Martin Zink Date: Tue, 28 Apr 2026 10:58:38 +0200 Subject: [PATCH 4/6] CControllerService rule of 5 --- libminifi/include/utils/CControllerService.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libminifi/include/utils/CControllerService.h b/libminifi/include/utils/CControllerService.h index 60b8639e08..8d20b06d4c 100644 --- a/libminifi/include/utils/CControllerService.h +++ b/libminifi/include/utils/CControllerService.h @@ -52,6 +52,10 @@ class CControllerService final : public core::controller::ControllerServiceApi, : class_description_(std::move(class_description)), impl_(impl), metadata_(std::move(metadata)) {} + CControllerService(const CControllerService&) = delete; + CControllerService& operator=(const CControllerService&) = delete; + CControllerService(CControllerService&&) = delete; + CControllerService& operator=(CControllerService&&) = delete; ~CControllerService() override { class_description_.callbacks.destroy(impl_); } From d1941810cfc0aafb2557f792058a18185c22235f Mon Sep 17 00:00:00 2001 From: Martin Zink Date: Tue, 28 Apr 2026 10:59:44 +0200 Subject: [PATCH 5/6] notifyStop -> disable on C API --- libminifi/include/utils/CControllerService.h | 2 +- minifi-api/include/minifi-c/minifi-c.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libminifi/include/utils/CControllerService.h b/libminifi/include/utils/CControllerService.h index 8d20b06d4c..9dea54dbef 100644 --- a/libminifi/include/utils/CControllerService.h +++ b/libminifi/include/utils/CControllerService.h @@ -78,7 +78,7 @@ class CControllerService final : public core::controller::ControllerServiceApi, } void notifyStop() override { - class_description_.callbacks.notifyStop(impl_); + class_description_.callbacks.disable(impl_); } ControllerServiceHandle* getControllerServiceHandle() override { diff --git a/minifi-api/include/minifi-c/minifi-c.h b/minifi-api/include/minifi-c/minifi-c.h index 2b74c3dc12..ff59300e7c 100644 --- a/minifi-api/include/minifi-c/minifi-c.h +++ b/minifi-api/include/minifi-c/minifi-c.h @@ -177,7 +177,7 @@ typedef struct MinifiControllerServiceCallbacks { MINIFI_OWNED void*(*create)(MinifiControllerServiceMetadata); void(*destroy)(MINIFI_OWNED void*); MinifiStatus(*enable)(void*, MinifiControllerServiceContext*); - void(*notifyStop)(void*); + void(*disable)(void*); } MinifiControllerServiceCallbacks; typedef struct MinifiProcessorClassDefinition { From 4da567952c0e26a3e2df6b4d7450cfe67abd9c73 Mon Sep 17 00:00:00 2001 From: Martin Zink Date: Tue, 28 Apr 2026 11:19:17 +0200 Subject: [PATCH 6/6] expand comment about logger being non nullable --- minifi-api/include/minifi-c/minifi-c.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/minifi-api/include/minifi-c/minifi-c.h b/minifi-api/include/minifi-c/minifi-c.h index ff59300e7c..a120f503af 100644 --- a/minifi-api/include/minifi-c/minifi-c.h +++ b/minifi-api/include/minifi-c/minifi-c.h @@ -153,13 +153,13 @@ typedef enum MinifiLogLevel : uint32_t { typedef struct MinifiProcessorMetadata { MinifiStringView uuid; MinifiStringView name; - MinifiLogger* logger; // borrowed reference, live until the processor is live + MinifiLogger* logger; // borrowed non-null reference, live until the processor is live } MinifiProcessorMetadata; typedef struct MinifiControllerServiceMetadata { MinifiStringView uuid; MinifiStringView name; - MinifiLogger* logger; // borrowed reference, live until the controller service is live + MinifiLogger* logger; // borrowed non-null reference, live until the controller service is live } MinifiControllerServiceMetadata; typedef struct MinifiProcessorCallbacks {