LCOV - code coverage report
Current view: top level - src/impl - node_impl.cc (source / functions) Hit Total Coverage
Test: vlink Lines: 190 217 87.6 %
Date: 2026-06-27 19:56:04 Functions: 50 56 89.3 %
Branches: 178 316 56.3 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2026 by Thun Lu. All rights reserved.
       3                 :            :  * Author: Thun Lu <thun.lu@zohomail.cn>
       4                 :            :  * Repo:   https://github.com/thun-res/vlink
       5                 :            :  *  _    __   __      _           __
       6                 :            :  * | |  / /  / /     (_) ____    / /__
       7                 :            :  * | | / /  / /     / / / __ \  / //_/
       8                 :            :  * | |/ /  / /___  / / / / / / / ,<
       9                 :            :  * |___/  /_____/ /_/ /_/ /_/ /_/|_|
      10                 :            :  *
      11                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
      12                 :            :  * you may not use this file except in compliance with the License.
      13                 :            :  * You may obtain a copy of the License at
      14                 :            :  *
      15                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
      16                 :            :  *
      17                 :            :  * Unless required by applicable law or agreed to in writing, software
      18                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      19                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      20                 :            :  * See the License for the specific language governing permissions and
      21                 :            :  * limitations under the License.
      22                 :            :  */
      23                 :            : 
      24                 :            : #include "./impl/node_impl.h"
      25                 :            : 
      26                 :            : #include <atomic>
      27                 :            : #include <charconv>
      28                 :            : #include <memory>
      29                 :            : #include <mutex>
      30                 :            : #include <shared_mutex>
      31                 :            : #include <utility>
      32                 :            : 
      33                 :            : #include "./base/bytes.h"
      34                 :            : #include "./base/logger.h"
      35                 :            : #include "./base/message_loop.h"
      36                 :            : #include "./extension/bag_writer.h"
      37                 :            : #include "./extension/discovery_reporter.h"
      38                 :            : #include "./impl/client_impl.h"
      39                 :            : #include "./impl/server_impl.h"
      40                 :            : #include "./private/license_check.h"
      41                 :            : #include "./version.h"
      42                 :            : 
      43                 :            : namespace vlink {
      44                 :            : 
      45                 :            : static constexpr bool kIgnoreIntraUrl{false};
      46                 :            : 
      47                 :            : // GlobalDiscoveryReporter
      48                 :            : struct GlobalDiscoveryReporter final {
      49                 :            :  public:
      50                 :       2098 :   static DiscoveryReporter* get(bool create_if_missing = true) {
      51   [ +  +  +  - ]:       2098 :     static GlobalDiscoveryReporter global;
      52                 :       2098 :     return global.get_instance(create_if_missing);
      53                 :            :   }
      54                 :            : 
      55                 :            :  private:
      56                 :            :   GlobalDiscoveryReporter() = default;
      57                 :            : 
      58                 :       2098 :   DiscoveryReporter* get_instance(bool create_if_missing) {
      59         [ +  - ]:       2098 :     std::lock_guard lock(mtx_);
      60                 :            : 
      61         [ +  - ]:       2098 :     check_disable_env();
      62                 :            : 
      63   [ +  +  +  -  :       2098 :     if (!create_if_missing || disabled_ || instance_) {
             +  +  +  + ]
      64                 :       2059 :       return instance_.get();
      65                 :            :     }
      66                 :            : 
      67         [ +  - ]:         39 :     instance_ = std::make_unique<DiscoveryReporter>();
      68         [ +  - ]:         39 :     instance_->async_run();
      69                 :            : 
      70                 :         39 :     return instance_.get();
      71                 :       2098 :   }
      72                 :            : 
      73                 :       2098 :   void check_disable_env() {
      74         [ +  + ]:       2098 :     if (disable_checked_) {
      75                 :       2046 :       return;
      76                 :            :     }
      77                 :            : 
      78                 :         52 :     disable_checked_ = true;
      79                 :            : 
      80   [ +  -  +  -  :         52 :     static std::string discovery = Utils::get_env("VLINK_DISCOVER_DISABLE");
          +  -  +  -  -  
                      - ]
      81                 :            : 
      82         [ -  + ]:         52 :     if (!discovery.empty()) {
      83                 :          0 :       int value = 0;
      84         [ #  # ]:          0 :       auto [p, error] = std::from_chars(discovery.data(), discovery.data() + discovery.size(), value);
      85                 :            : 
      86   [ #  #  #  # ]:          0 :       if (error == std::errc() && value == 1) {
      87   [ #  #  #  # ]:          0 :         VLOG_I("DiscoveryReporter: Global discovery reporter is disabled.");
      88                 :          0 :         disabled_ = true;
      89                 :          0 :         return;
      90                 :            :       }
      91                 :            :     }
      92                 :            :   }
      93                 :            : 
      94                 :         52 :   ~GlobalDiscoveryReporter() = default;
      95                 :            : 
      96                 :            :   std::mutex mtx_;
      97                 :            :   bool disable_checked_{false};
      98                 :            :   bool disabled_{false};
      99                 :            :   std::unique_ptr<DiscoveryReporter> instance_;
     100                 :            : 
     101                 :            :   VLINK_DISALLOW_COPY_AND_ASSIGN(GlobalDiscoveryReporter)
     102                 :            : };
     103                 :            : 
     104                 :       1952 : static bool should_report_discovery(const NodeImpl& node) {
     105         [ +  + ]:       1934 :   return node.is_discovery_enabled && !node.url.empty() &&
     106   [ +  +  +  +  :       3886 :          !(node.transport_type == TransportType::kDds && node.is_cdr_type) && !node.is_security_type &&
             +  -  +  + ]
     107                 :       1952 :          (!kIgnoreIntraUrl || node.transport_type != TransportType::kIntra);
     108                 :            : }
     109                 :            : 
     110                 :            : // AbstractNode
     111         [ +  - ]:          1 : std::any AbstractNode::get_native_handle() const { return nullptr; }
     112                 :            : 
     113                 :        840 : AbstractNode::AbstractNode() = default;
     114                 :            : 
     115                 :        840 : AbstractNode::~AbstractNode() = default;
     116                 :            : 
     117                 :            : // NodeImpl
     118                 :            : struct NodeImplHelper final {
     119                 :            :   std::atomic_bool is_interrupted{false};
     120                 :            : 
     121                 :            :   Conf::PropertiesMap property_map;
     122                 :            :   std::shared_mutex mtx;
     123                 :            :   std::shared_mutex status_mtx;
     124                 :            :   std::mutex post_mtx;
     125                 :            :   NodeImpl::StatusCallback status_callback;
     126                 :            :   std::atomic<MessageLoop*> message_loop{nullptr};
     127                 :            : 
     128                 :            :   std::shared_ptr<BagWriter> data_recorder;
     129                 :            : };
     130                 :            : 
     131                 :        814 : bool NodeImpl::is_support_loan() const { return false; }
     132                 :            : 
     133                 :          2 : Bytes NodeImpl::loan(int64_t size) {
     134                 :            :   (void)size;
     135                 :            : 
     136                 :          2 :   return Bytes();
     137                 :            : }
     138                 :            : 
     139                 :          5 : bool NodeImpl::return_loan(const Bytes& bytes) {
     140                 :            :   (void)bytes;
     141                 :            : 
     142                 :          5 :   return false;
     143                 :            : }
     144                 :            : 
     145                 :          0 : void NodeImpl::set_manual_unloan(bool manual_unloan) { (void)manual_unloan; }
     146                 :            : 
     147                 :          1 : bool NodeImpl::suspend() {
     148                 :            :   // has_suspend = true;
     149                 :            : 
     150   [ +  -  +  - ]:          2 :   VLOG_W("Function [suspend] is not supported.");
     151                 :            : 
     152                 :          1 :   return false;
     153                 :            : }
     154                 :            : 
     155                 :          1 : bool NodeImpl::resume() {
     156                 :            :   // has_suspend = false;
     157                 :            : 
     158   [ +  -  +  - ]:          2 :   VLOG_W("Function [resume] is not supported.");
     159                 :            : 
     160                 :          1 :   return false;
     161                 :            : }
     162                 :            : 
     163                 :          1 : bool NodeImpl::is_suspend() const {
     164   [ +  -  +  - ]:          2 :   VLOG_W("Function [is_suspend] is not supported.");
     165                 :            : 
     166                 :          1 :   return false;
     167                 :            : }
     168                 :            : 
     169                 :        988 : void NodeImpl::interrupt() { helper_->is_interrupted.store(true, std::memory_order_release); }
     170                 :            : 
     171                 :          2 : const struct Conf* NodeImpl::get_conf() const { return nullptr; }
     172                 :            : 
     173                 :          1 : const AbstractNode* NodeImpl::get_abstract_node() const { return nullptr; }
     174                 :            : 
     175                 :          1 : Status::BasePtr NodeImpl::get_status(Status::Type type) const {
     176                 :            :   (void)type;
     177                 :            : 
     178   [ +  -  +  - ]:          2 :   VLOG_W("Function [get_status] is not supported.");
     179                 :            : 
     180                 :          1 :   return std::make_shared<Status::Unknown>();
     181                 :            : }
     182                 :            : 
     183                 :        974 : bool NodeImpl::check_version(const Version& version) {
     184                 :        974 :   Version runtime_version{VLINK_VERSION_MAJOR, VLINK_VERSION_MINOR, VLINK_VERSION_PATCH};
     185                 :            : 
     186         [ +  + ]:        974 :   if VUNLIKELY (version != runtime_version) {
     187                 :            :     static std::atomic_bool print_warn{false};
     188                 :            : 
     189         [ +  + ]:          2 :     if VUNLIKELY (!print_warn.exchange(true, std::memory_order_relaxed)) {
     190   [ +  -  +  - ]:          2 :       VLOG_W("The version may be incompatible. [Compiled]: ", version.to_string(),
     191                 :            :              " [Runtime]: ", runtime_version.to_string(), ".");
     192                 :            :     }
     193                 :            : 
     194                 :          2 :     return false;
     195                 :            :   }
     196                 :            : 
     197                 :        972 :   return true;
     198                 :            : }
     199                 :            : 
     200                 :         28 : bool NodeImpl::attach(class MessageLoop* message_loop) {
     201                 :         28 :   MessageLoop* expected = nullptr;
     202                 :         28 :   return helper_->message_loop.compare_exchange_strong(expected, message_loop, std::memory_order_release,
     203                 :         28 :                                                        std::memory_order_relaxed);
     204                 :            : }
     205                 :            : 
     206                 :        634 : bool NodeImpl::detach() {
     207                 :        634 :   MessageLoop* message_loop = nullptr;
     208                 :            : 
     209                 :            :   {
     210         [ +  - ]:        634 :     std::lock_guard lock(helper_->post_mtx);
     211                 :            : 
     212                 :        634 :     message_loop = helper_->message_loop.exchange(nullptr, std::memory_order_acq_rel);
     213                 :        634 :   }
     214                 :            : 
     215         [ +  + ]:        634 :   if (!message_loop) {
     216                 :        609 :     return false;
     217                 :            :   }
     218                 :            : 
     219         [ +  - ]:         25 :   if (!message_loop->is_in_same_thread()) {
     220                 :         25 :     message_loop->wait_for_idle();
     221                 :            :   }
     222                 :            : 
     223                 :         25 :   return true;
     224                 :            : }
     225                 :            : 
     226                 :        925 : class MessageLoop* NodeImpl::get_message_loop() const { return helper_->message_loop.load(std::memory_order_acquire); }
     227                 :            : 
     228                 :         32 : void NodeImpl::register_status_handler(StatusCallback&& callback) {
     229   [ +  +  +  +  :         32 :   if VUNLIKELY (transport_type != TransportType::kDds && transport_type != TransportType::kDdsc &&
          +  +  +  +  +  
             +  +  +  +  
                      + ]
     230                 :            :                 transport_type != TransportType::kDdsr && transport_type != TransportType::kDdst) {
     231   [ +  -  +  - ]:         10 :     VLOG_W("Function [register_status_handler] is not supported.");
     232                 :          5 :     return;
     233                 :            :   }
     234                 :            : 
     235         [ +  - ]:         27 :   std::lock_guard lock(helper_->status_mtx);
     236                 :         27 :   helper_->status_callback = std::move(callback);
     237                 :         27 : }
     238                 :            : 
     239                 :        931 : bool NodeImpl::has_register_status() const {
     240   [ +  +  +  +  :        931 :   if VUNLIKELY (transport_type != TransportType::kDds && transport_type != TransportType::kDdsc &&
          +  +  +  +  +  
             +  +  +  +  
                      + ]
     241                 :            :                 transport_type != TransportType::kDdsr && transport_type != TransportType::kDdst) {
     242   [ +  -  +  - ]:         12 :     VLOG_W("Function [has_register_status] is not supported.");
     243                 :          6 :     return false;
     244                 :            :   }
     245                 :            : 
     246         [ +  - ]:        925 :   std::shared_lock lock(helper_->status_mtx);
     247                 :            : 
     248                 :        925 :   return helper_->status_callback != nullptr;
     249                 :        925 : }
     250                 :            : 
     251                 :         29 : void NodeImpl::call_status(Status::BasePtr ptr) {
     252   [ +  +  -  +  :         29 :   if VUNLIKELY (transport_type != TransportType::kDds && transport_type != TransportType::kDdsc &&
          -  +  -  -  -  
             +  -  -  -  
                      + ]
     253                 :            :                 transport_type != TransportType::kDdsr && transport_type != TransportType::kDdst) {
     254   [ #  #  #  # ]:          0 :     VLOG_W("Function [call_status] is not supported.");
     255                 :          1 :     return;
     256                 :            :   }
     257                 :            : 
     258                 :            :   {
     259         [ +  - ]:         29 :     std::lock_guard post_lock(helper_->post_mtx);
     260                 :            : 
     261                 :         29 :     auto* message_loop = helper_->message_loop.load(std::memory_order_acquire);
     262                 :            : 
     263         [ +  + ]:         29 :     if VLIKELY (message_loop) {
     264   [ +  -  +  - ]:          1 :       message_loop->post_task([this, ptr]() mutable {
     265         [ +  - ]:          1 :         std::shared_lock lock(helper_->status_mtx);
     266         [ +  - ]:          1 :         if VLIKELY (helper_->status_callback) {
     267         [ +  - ]:          1 :           helper_->status_callback(std::move(ptr));
     268                 :            :         }
     269                 :          1 :       });
     270                 :          1 :       return;
     271                 :            :     }
     272         [ +  + ]:         29 :   }
     273                 :            : 
     274         [ +  - ]:         28 :   std::shared_lock lock(helper_->status_mtx);
     275                 :            : 
     276         [ +  - ]:         28 :   if VLIKELY (helper_->status_callback) {
     277         [ +  - ]:         28 :     helper_->status_callback(std::move(ptr));
     278                 :            :   }
     279                 :         28 : }
     280                 :            : 
     281                 :        345 : void NodeImpl::set_property(const std::string& prop, const std::string& value) {
     282         [ +  - ]:        345 :   std::lock_guard lock(helper_->mtx);
     283   [ +  -  +  - ]:        345 :   helper_->property_map[prop] = value;
     284                 :        345 : }
     285                 :            : 
     286                 :        244 : std::string NodeImpl::get_property(const std::string& prop) const {
     287         [ +  - ]:        244 :   std::shared_lock lock(helper_->mtx);
     288                 :            : 
     289         [ +  - ]:        244 :   auto iter = helper_->property_map.find(prop);
     290                 :            : 
     291         [ +  + ]:        244 :   if VLIKELY (iter != helper_->property_map.end()) {
     292         [ +  - ]:        237 :     return iter->second;
     293                 :            :   }
     294                 :            : 
     295                 :          7 :   return {};
     296                 :        244 : }
     297                 :            : 
     298                 :        452 : Conf::PropertiesMap NodeImpl::get_all_properties() const {
     299         [ +  - ]:        452 :   std::shared_lock lock(helper_->mtx);
     300         [ +  - ]:        904 :   return helper_->property_map;
     301                 :        452 : }
     302                 :            : 
     303                 :         12 : void NodeImpl::set_discovery_enabled(bool enable) { is_discovery_enabled = enable; }
     304                 :            : 
     305                 :          5 : bool NodeImpl::get_discovery_enabled() const { return is_discovery_enabled; }
     306                 :            : 
     307                 :          1 : void NodeImpl::set_record_path(const std::string& path) {
     308                 :          1 :   std::shared_ptr<BagWriter> new_recorder;
     309                 :            : 
     310         [ -  + ]:          1 :   if (!path.empty()) {
     311         [ #  # ]:          0 :     new_recorder = BagWriter::filter_get(path);
     312                 :            :   }
     313                 :            : 
     314                 :          1 :   std::shared_ptr<BagWriter> old_recorder;
     315                 :            : 
     316                 :            :   {
     317         [ +  - ]:          1 :     std::lock_guard lock(helper_->mtx);
     318                 :          1 :     old_recorder = std::move(helper_->data_recorder);
     319                 :          1 :     helper_->data_recorder = std::move(new_recorder);
     320                 :          1 :   }
     321                 :            : 
     322                 :          1 :   old_recorder.reset();
     323                 :          1 : }
     324                 :            : 
     325                 :          0 : bool NodeImpl::enable_security(const Security::Config& cfg) {
     326         [ #  # ]:          0 :   auto sec_cfg = cfg;
     327                 :            : 
     328         [ #  # ]:          0 :   return enable_security(std::move(sec_cfg));
     329                 :          0 : }
     330                 :            : 
     331                 :         49 : bool NodeImpl::enable_security(Security::Config&& cfg) {
     332   [ +  +  +  +  :         49 :   if VUNLIKELY (transport_type == TransportType::kIntra || (transport_type == TransportType::kDds && is_cdr_type)) {
          -  +  -  +  +  
                      + ]
     333   [ +  -  +  - ]:         10 :     VLOG_W("Security::Config will ignore intra/dds(cdr) transport.");
     334                 :          5 :     return false;
     335                 :            :   }
     336                 :            : 
     337         [ +  - ]:         44 :   if VLIKELY (cfg.advanced.aad_context.empty()) {
     338         [ +  - ]:         44 :     cfg.advanced.aad_context = url;
     339         [ +  - ]:         44 :     cfg.advanced.aad_context += "|";
     340         [ +  - ]:         44 :     cfg.advanced.aad_context += ser_type;
     341         [ +  - ]:         44 :     cfg.advanced.aad_context += "|";
     342   [ +  -  +  - ]:         44 :     cfg.advanced.aad_context += std::to_string(static_cast<uint32_t>(schema_type));
     343                 :            :   }
     344                 :            : 
     345         [ +  - ]:         44 :   auto candidate = std::make_unique<Security>(std::move(cfg));
     346                 :            : 
     347         [ -  + ]:         44 :   if VUNLIKELY (!candidate->is_configured()) {
     348                 :            :     VLOG_W("Security::Config has no usable slot.");  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     349                 :            :     return false;                                    // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     350                 :            :   }
     351                 :            : 
     352   [ +  +  +  + ]:         44 :   bool needs_encrypt = (impl_type == kPublisher || impl_type == kSetter);
     353   [ +  +  +  + ]:         44 :   bool needs_decrypt = (impl_type == kSubscriber || impl_type == kGetter);
     354                 :            : 
     355                 :            : #if defined(NDEBUG) || defined(__ANDROID__)
     356                 :            :   if (impl_type == kClient) {
     357                 :            :     needs_encrypt = true;
     358                 :            :     const auto* client_impl = static_cast<const ClientImpl*>(this);
     359                 :            :     needs_decrypt = client_impl != nullptr && client_impl->is_resp_type;
     360                 :            :   } else if (impl_type == kServer) {
     361                 :            :     needs_decrypt = true;
     362                 :            :     const auto* server_impl = static_cast<const ServerImpl*>(this);
     363                 :            :     needs_encrypt = server_impl != nullptr && server_impl->is_resp_type;
     364                 :            :   }
     365                 :            : #else
     366         [ +  + ]:         44 :   if (impl_type == kClient) {
     367                 :          6 :     needs_encrypt = true;
     368         [ +  - ]:          6 :     const auto* client_impl = dynamic_cast<const ClientImpl*>(this);
     369   [ +  -  +  - ]:          6 :     needs_decrypt = client_impl != nullptr && client_impl->is_resp_type;
     370         [ +  + ]:         38 :   } else if (impl_type == kServer) {
     371                 :          7 :     needs_decrypt = true;
     372         [ +  - ]:          7 :     const auto* server_impl = dynamic_cast<const ServerImpl*>(this);
     373   [ +  -  +  - ]:          7 :     needs_encrypt = server_impl != nullptr && server_impl->is_resp_type;
     374                 :            :   }
     375                 :            : #endif
     376                 :            : 
     377   [ +  +  -  +  :         44 :   if VUNLIKELY (needs_encrypt && !candidate->can_encrypt()) {
                   -  + ]
     378                 :            :     VLOG_W("Security::Config cannot encrypt for this sender role.");  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     379                 :            :     return false;                                                     // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     380                 :            :   }
     381                 :            : 
     382   [ +  +  -  +  :         44 :   if VUNLIKELY (needs_decrypt && !candidate->can_decrypt()) {
                   -  + ]
     383                 :            :     VLOG_W("Security::Config cannot decrypt for this receiver role.");  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     384                 :            :     return false;                                                       // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     385                 :            :   }
     386                 :            : 
     387                 :         44 :   security = std::move(candidate);
     388                 :            : 
     389                 :         44 :   return true;
     390                 :         44 : }
     391                 :            : 
     392                 :          1 : void NodeImpl::set_ssl_options(const SslOptions& options) {
     393         [ +  - ]:          1 :   std::lock_guard lock(helper_->mtx);
     394                 :          1 :   options.parse_to(helper_->property_map);
     395                 :          1 : }
     396                 :            : 
     397                 :       2066 : void NodeImpl::try_record(ActionType action_type, const Bytes& data) {
     398         [ +  - ]:       2066 :   auto* global_recorder = BagWriter::global_get();
     399                 :            : 
     400                 :       2060 :   std::shared_ptr<BagWriter> data_recorder;
     401                 :            :   {
     402         [ +  - ]:       2060 :     std::shared_lock lock(helper_->mtx);
     403                 :       2061 :     data_recorder = helper_->data_recorder;
     404                 :       2067 :   }
     405                 :            : 
     406   [ +  -  +  -  :       2065 :   if VLIKELY (!global_recorder && !data_recorder) {
                   +  - ]
     407                 :       2064 :     return;
     408                 :            :   }
     409                 :            : 
     410                 :          0 :   if ((kIgnoreIntraUrl && transport_type == TransportType::kIntra) ||
     411   [ #  #  #  # ]:          0 :       (transport_type == TransportType::kDds && is_cdr_type)) {
     412                 :          0 :     return;
     413                 :            :   }
     414                 :            : 
     415                 :          0 :   Frame frame;
     416                 :          0 :   frame.timestamp = -1;
     417         [ #  # ]:          0 :   frame.url = url;
     418         [ #  # ]:          0 :   frame.ser_type = ser_type;
     419                 :          0 :   frame.schema_type = schema_type;
     420                 :          0 :   frame.action_type = action_type;
     421                 :          0 :   frame.data = Bytes::shallow_copy(data.data(), data.size());
     422                 :            : 
     423         [ #  # ]:          0 :   if VUNLIKELY (global_recorder) {
     424         [ #  # ]:          0 :     global_recorder->push(frame);
     425                 :            :   }
     426                 :            : 
     427         [ #  # ]:          0 :   if VUNLIKELY (data_recorder) {
     428         [ #  # ]:          0 :     data_recorder->push(frame);
     429                 :            :   }
     430         [ -  + ]:       2064 : }
     431                 :            : 
     432                 :        103 : void NodeImpl::reset_interrupted() { helper_->is_interrupted.store(false, std::memory_order_release); }
     433                 :            : 
     434                 :        203 : bool NodeImpl::is_interrupted() const { return helper_->is_interrupted.load(std::memory_order_acquire); }
     435                 :            : 
     436                 :        976 : void NodeImpl::init_ext() {
     437         [ +  + ]:        976 :   if (should_report_discovery(*this)) {
     438                 :        437 :     auto* global_reporter = GlobalDiscoveryReporter::get();
     439                 :            : 
     440         [ +  - ]:        437 :     if (global_reporter) {
     441   [ -  +  -  -  :        437 :       if (CpuProfiler::is_global_enabled() && !profiler) {
                   -  + ]
     442                 :            :         profiler = std::make_unique<CpuProfiler>();  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     443                 :            :       }
     444                 :            : 
     445                 :        437 :       global_reporter->add(this);
     446                 :            :     }
     447                 :            :   }
     448                 :            : 
     449                 :            : #ifdef VLINK_ENABLE_CHECK_LICENSE
     450                 :            :   [[maybe_unused]] static LicenseCheck license;
     451                 :            : #endif
     452                 :        976 : }
     453                 :            : 
     454                 :        976 : void NodeImpl::deinit_ext() {
     455         [ +  + ]:        976 :   if (!should_report_discovery(*this)) {
     456                 :        539 :     return;
     457                 :            :   }
     458                 :            : 
     459                 :        437 :   auto* global_reporter = GlobalDiscoveryReporter::get(false);
     460                 :            : 
     461         [ +  - ]:        437 :   if (global_reporter) {
     462                 :        437 :     global_reporter->remove(this);
     463                 :            : 
     464   [ -  +  -  -  :        437 :     if (CpuProfiler::is_global_enabled() && profiler) {
                   -  + ]
     465                 :            :       profiler->restart();  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     466                 :            :     }
     467                 :            :   }
     468                 :            : }
     469                 :            : 
     470                 :       1224 : void NodeImpl::global_init() {
     471                 :       1224 :   Logger::get();
     472                 :            : 
     473                 :       1224 :   Bytes::init_memory_pool();
     474                 :            : 
     475                 :       1224 :   BagWriter::global_get();
     476                 :            : 
     477                 :       1224 :   GlobalDiscoveryReporter::get(false);
     478                 :       1224 : }
     479                 :            : 
     480   [ +  -  +  - ]:       1221 : NodeImpl::NodeImpl(ImplType type) : impl_type(type), helper_(std::make_unique<NodeImplHelper>()) { global_init(); }
     481                 :            : 
     482                 :       1221 : NodeImpl::~NodeImpl() = default;
     483                 :            : 
     484                 :            : }  // namespace vlink

Generated by: LCOV version 1.14