LCOV - code coverage report
Current view: top level - src/impl - node_impl.cc (source / functions) Hit Total Coverage
Test: vlink Lines: 186 217 85.7 %
Date: 2026-07-26 14:05:51 Functions: 50 55 90.9 %
Branches: 164 304 53.9 %

           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                 :       2177 :   static DiscoveryReporter* get(bool create_if_missing = true) {
      51   [ +  +  +  - ]:       2177 :     static GlobalDiscoveryReporter global;
      52                 :       2177 :     return global.get_instance(create_if_missing);
      53                 :            :   }
      54                 :            : 
      55                 :            :  private:
      56                 :            :   GlobalDiscoveryReporter() = default;
      57                 :            : 
      58                 :       2177 :   DiscoveryReporter* get_instance(bool create_if_missing) {
      59         [ +  - ]:       2177 :     std::lock_guard lock(mtx_);
      60                 :            : 
      61         [ +  - ]:       2177 :     check_disable_env();
      62                 :            : 
      63   [ +  +  +  -  :       2177 :     if (!create_if_missing || disabled_ || instance_) {
             +  +  +  + ]
      64                 :       2138 :       return instance_.get();
      65                 :            :     }
      66                 :            : 
      67         [ +  - ]:         39 :     instance_ = std::make_unique<DiscoveryReporter>();
      68         [ +  - ]:         39 :     instance_->async_run();
      69                 :            : 
      70                 :         39 :     return instance_.get();
      71                 :       2177 :   }
      72                 :            : 
      73                 :       2177 :   void check_disable_env() {
      74         [ +  + ]:       2177 :     if (disable_checked_) {
      75                 :       2124 :       return;
      76                 :            :     }
      77                 :            : 
      78                 :         53 :     disable_checked_ = true;
      79                 :            : 
      80   [ +  -  +  -  :         53 :     static std::string discovery = Utils::get_env("VLINK_DISCOVER_DISABLE");
          +  -  +  -  -  
                      - ]
      81                 :            : 
      82         [ -  + ]:         53 :     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                 :         53 :   ~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                 :       2046 : static bool should_report_discovery(const NodeImpl& node) {
     105   [ +  +  +  +  :       2046 :   return node.is_discovery_enabled && !node.url.empty() && !node.is_security_type &&
                   +  + ]
     106                 :       2046 :          (!kIgnoreIntraUrl || node.transport_type != TransportType::kIntra);
     107                 :            : }
     108                 :            : 
     109                 :            : // AbstractNode
     110         [ +  - ]:          1 : std::any AbstractNode::get_native_handle() const { return nullptr; }
     111                 :            : 
     112                 :        868 : AbstractNode::AbstractNode() = default;
     113                 :            : 
     114                 :        868 : AbstractNode::~AbstractNode() = default;
     115                 :            : 
     116                 :            : // NodeImpl
     117                 :            : struct NodeImplHelper final {
     118                 :            :   std::atomic_bool is_interrupted{false};
     119                 :            : 
     120                 :            :   Conf::PropertiesMap property_map;
     121                 :            :   std::shared_mutex mtx;
     122                 :            :   std::shared_mutex status_mtx;
     123                 :            :   std::mutex post_mtx;
     124                 :            :   NodeImpl::StatusCallback status_callback;
     125                 :            :   std::atomic<MessageLoop*> message_loop{nullptr};
     126                 :            : 
     127                 :            :   std::shared_ptr<BagWriter> data_recorder;
     128                 :            :   std::atomic_bool data_recorder_enabled{false};
     129                 :            : };
     130                 :            : 
     131                 :        860 : 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                 :          7 : bool NodeImpl::return_loan(const Bytes& bytes) {
     140                 :            :   (void)bytes;
     141                 :            : 
     142                 :          7 :   return false;
     143                 :            : }
     144                 :            : 
     145                 :          1 : bool NodeImpl::suspend() {
     146                 :            :   // has_suspend = true;
     147                 :            : 
     148   [ +  -  +  - ]:          2 :   VLOG_W("Function [suspend] is not supported.");
     149                 :            : 
     150                 :          1 :   return false;
     151                 :            : }
     152                 :            : 
     153                 :          1 : bool NodeImpl::resume() {
     154                 :            :   // has_suspend = false;
     155                 :            : 
     156   [ +  -  +  - ]:          2 :   VLOG_W("Function [resume] is not supported.");
     157                 :            : 
     158                 :          1 :   return false;
     159                 :            : }
     160                 :            : 
     161                 :          1 : bool NodeImpl::is_suspend() const {
     162   [ +  -  +  - ]:          2 :   VLOG_W("Function [is_suspend] is not supported.");
     163                 :            : 
     164                 :          1 :   return false;
     165                 :            : }
     166                 :            : 
     167                 :       1035 : void NodeImpl::interrupt() { helper_->is_interrupted.store(true, std::memory_order_release); }
     168                 :            : 
     169                 :          2 : const struct Conf* NodeImpl::get_conf() const { return nullptr; }
     170                 :            : 
     171                 :          1 : const AbstractNode* NodeImpl::get_abstract_node() const { return nullptr; }
     172                 :            : 
     173                 :          1 : Status::BasePtr NodeImpl::get_status(Status::Type type) const {
     174                 :            :   (void)type;
     175                 :            : 
     176   [ +  -  +  - ]:          2 :   VLOG_W("Function [get_status] is not supported.");
     177                 :            : 
     178                 :          1 :   return std::make_shared<Status::Unknown>();
     179                 :            : }
     180                 :            : 
     181                 :       1021 : bool NodeImpl::check_version(const Version& version) {
     182                 :       1021 :   Version runtime_version{VLINK_VERSION_MAJOR, VLINK_VERSION_MINOR, VLINK_VERSION_PATCH};
     183                 :            : 
     184         [ +  + ]:       1021 :   if VUNLIKELY (version != runtime_version) {
     185                 :            :     static std::atomic_bool print_warn{false};
     186                 :            : 
     187         [ +  + ]:          2 :     if VUNLIKELY (!print_warn.exchange(true, std::memory_order_relaxed)) {
     188   [ +  -  +  - ]:          2 :       VLOG_W("The version may be incompatible. [Compiled]: ", version.to_string(),
     189                 :            :              " [Runtime]: ", runtime_version.to_string(), ".");
     190                 :            :     }
     191                 :            : 
     192                 :          2 :     return false;
     193                 :            :   }
     194                 :            : 
     195                 :       1019 :   return true;
     196                 :            : }
     197                 :            : 
     198                 :         28 : bool NodeImpl::attach(class MessageLoop* message_loop) {
     199                 :         28 :   MessageLoop* expected = nullptr;
     200                 :         28 :   return helper_->message_loop.compare_exchange_strong(expected, message_loop, std::memory_order_release,
     201                 :         28 :                                                        std::memory_order_relaxed);
     202                 :            : }
     203                 :            : 
     204                 :        635 : bool NodeImpl::detach() {
     205                 :        635 :   MessageLoop* message_loop = nullptr;
     206                 :            : 
     207                 :            :   {
     208         [ +  - ]:        635 :     std::lock_guard lock(helper_->post_mtx);
     209                 :            : 
     210                 :        635 :     message_loop = helper_->message_loop.exchange(nullptr, std::memory_order_acq_rel);
     211                 :        635 :   }
     212                 :            : 
     213         [ +  + ]:        635 :   if (!message_loop) {
     214                 :        610 :     return false;
     215                 :            :   }
     216                 :            : 
     217         [ +  - ]:         25 :   if (!message_loop->is_in_same_thread()) {
     218                 :         25 :     message_loop->wait_for_idle();
     219                 :            :   }
     220                 :            : 
     221                 :         25 :   return true;
     222                 :            : }
     223                 :            : 
     224                 :        926 : class MessageLoop* NodeImpl::get_message_loop() const { return helper_->message_loop.load(std::memory_order_acquire); }
     225                 :            : 
     226                 :         29 : void NodeImpl::register_status_handler(StatusCallback&& callback) {
     227   [ +  +  +  +  :         29 :   if VUNLIKELY (transport_type != TransportType::kDds && transport_type != TransportType::kDdsc &&
          +  +  +  +  +  
                      + ]
     228                 :            :                 transport_type != TransportType::kDdsr) {
     229   [ +  -  +  - ]:         10 :     VLOG_W("Function [register_status_handler] is not supported.");
     230                 :          5 :     return;
     231                 :            :   }
     232                 :            : 
     233         [ +  - ]:         24 :   std::lock_guard lock(helper_->status_mtx);
     234                 :         24 :   helper_->status_callback = std::move(callback);
     235                 :         24 : }
     236                 :            : 
     237                 :        912 : bool NodeImpl::has_register_status() const {
     238   [ +  +  +  +  :        912 :   if VUNLIKELY (transport_type != TransportType::kDds && transport_type != TransportType::kDdsc &&
          +  +  +  +  +  
                      + ]
     239                 :            :                 transport_type != TransportType::kDdsr) {
     240   [ +  -  +  - ]:         12 :     VLOG_W("Function [has_register_status] is not supported.");
     241                 :          6 :     return false;
     242                 :            :   }
     243                 :            : 
     244         [ +  - ]:        906 :   std::shared_lock lock(helper_->status_mtx);
     245                 :            : 
     246                 :        906 :   return helper_->status_callback != nullptr;
     247                 :        906 : }
     248                 :            : 
     249                 :         29 : void NodeImpl::call_status(Status::BasePtr ptr) {
     250   [ +  +  -  +  :         29 :   if VUNLIKELY (transport_type != TransportType::kDds && transport_type != TransportType::kDdsc &&
          -  +  -  -  -  
                      + ]
     251                 :            :                 transport_type != TransportType::kDdsr) {
     252   [ #  #  #  # ]:          0 :     VLOG_W("Function [call_status] is not supported.");
     253                 :          1 :     return;
     254                 :            :   }
     255                 :            : 
     256                 :            :   {
     257         [ +  - ]:         29 :     std::lock_guard post_lock(helper_->post_mtx);
     258                 :            : 
     259                 :         29 :     auto* message_loop = helper_->message_loop.load(std::memory_order_acquire);
     260                 :            : 
     261         [ +  + ]:         29 :     if VLIKELY (message_loop) {
     262   [ +  -  +  - ]:          1 :       message_loop->post_task([this, ptr]() mutable {
     263         [ +  - ]:          1 :         std::shared_lock lock(helper_->status_mtx);
     264         [ +  - ]:          1 :         if VLIKELY (helper_->status_callback) {
     265         [ +  - ]:          1 :           helper_->status_callback(std::move(ptr));
     266                 :            :         }
     267                 :          1 :       });
     268                 :          1 :       return;
     269                 :            :     }
     270         [ +  + ]:         29 :   }
     271                 :            : 
     272         [ +  - ]:         28 :   std::shared_lock lock(helper_->status_mtx);
     273                 :            : 
     274         [ +  - ]:         28 :   if VLIKELY (helper_->status_callback) {
     275         [ +  - ]:         28 :     helper_->status_callback(std::move(ptr));
     276                 :            :   }
     277                 :         28 : }
     278                 :            : 
     279                 :        345 : void NodeImpl::set_property(const std::string& prop, const std::string& value) {
     280         [ +  - ]:        345 :   std::lock_guard lock(helper_->mtx);
     281   [ +  -  +  - ]:        345 :   helper_->property_map[prop] = value;
     282                 :        345 : }
     283                 :            : 
     284                 :        244 : std::string NodeImpl::get_property(const std::string& prop) const {
     285         [ +  - ]:        244 :   std::shared_lock lock(helper_->mtx);
     286                 :            : 
     287         [ +  - ]:        244 :   auto iter = helper_->property_map.find(prop);
     288                 :            : 
     289         [ +  + ]:        244 :   if VLIKELY (iter != helper_->property_map.end()) {
     290         [ +  - ]:        237 :     return iter->second;
     291                 :            :   }
     292                 :            : 
     293                 :          7 :   return {};
     294                 :        244 : }
     295                 :            : 
     296                 :        452 : Conf::PropertiesMap NodeImpl::get_all_properties() const {
     297         [ +  - ]:        452 :   std::shared_lock lock(helper_->mtx);
     298         [ +  - ]:        904 :   return helper_->property_map;
     299                 :        452 : }
     300                 :            : 
     301                 :         25 : void NodeImpl::set_discovery_enabled(bool enable) { is_discovery_enabled = enable; }
     302                 :            : 
     303                 :          5 : bool NodeImpl::get_discovery_enabled() const { return is_discovery_enabled; }
     304                 :            : 
     305                 :          1 : void NodeImpl::set_record_path(const std::string& path) {
     306                 :          1 :   std::shared_ptr<BagWriter> new_recorder;
     307                 :            : 
     308         [ -  + ]:          1 :   if (!path.empty()) {
     309         [ #  # ]:          0 :     new_recorder = BagWriter::filter_get(path);
     310                 :            :   }
     311                 :            : 
     312                 :          1 :   std::shared_ptr<BagWriter> old_recorder;
     313                 :            : 
     314                 :            :   {
     315         [ +  - ]:          1 :     std::lock_guard lock(helper_->mtx);
     316                 :          1 :     old_recorder = std::move(helper_->data_recorder);
     317                 :          1 :     helper_->data_recorder = std::move(new_recorder);
     318                 :          1 :     helper_->data_recorder_enabled.store(helper_->data_recorder != nullptr, std::memory_order_release);
     319                 :          1 :   }
     320                 :            : 
     321                 :          1 :   old_recorder.reset();
     322                 :          1 : }
     323                 :            : 
     324                 :          0 : bool NodeImpl::enable_security(const Security::Config& cfg) {
     325         [ #  # ]:          0 :   auto sec_cfg = cfg;
     326                 :            : 
     327         [ #  # ]:          0 :   return enable_security(std::move(sec_cfg));
     328                 :          0 : }
     329                 :            : 
     330                 :         47 : bool NodeImpl::enable_security(Security::Config&& cfg) {
     331   [ +  +  +  +  :         47 :   if VUNLIKELY (transport_type == TransportType::kIntra || (transport_type == TransportType::kDds && is_cdr_type)) {
          -  +  -  +  +  
                      + ]
     332   [ +  -  +  - ]:          6 :     VLOG_W("Security::Config will ignore intra/dds(cdr) transport.");
     333                 :          3 :     return false;
     334                 :            :   }
     335                 :            : 
     336         [ +  - ]:         44 :   if VLIKELY (cfg.advanced.aad_context.empty()) {
     337         [ +  - ]:         44 :     cfg.advanced.aad_context = url;
     338         [ +  - ]:         44 :     cfg.advanced.aad_context += "|";
     339         [ +  - ]:         44 :     cfg.advanced.aad_context += ser_type;
     340         [ +  - ]:         44 :     cfg.advanced.aad_context += "|";
     341   [ +  -  +  - ]:         44 :     cfg.advanced.aad_context += std::to_string(static_cast<uint32_t>(schema_type));
     342                 :            :   }
     343                 :            : 
     344         [ +  - ]:         44 :   auto candidate = std::make_unique<Security>(std::move(cfg));
     345                 :            : 
     346         [ -  + ]:         44 :   if VUNLIKELY (!candidate->is_configured()) {
     347                 :            :     VLOG_W("Security::Config has no usable slot.");  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     348                 :            :     return false;                                    // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     349                 :            :   }
     350                 :            : 
     351   [ +  +  +  + ]:         44 :   bool needs_encrypt = (impl_type == kPublisher || impl_type == kSetter);
     352   [ +  +  +  + ]:         44 :   bool needs_decrypt = (impl_type == kSubscriber || impl_type == kGetter);
     353                 :            : 
     354                 :            : #if defined(NDEBUG) || defined(__ANDROID__)
     355                 :            :   if (impl_type == kClient) {
     356                 :            :     needs_encrypt = true;
     357                 :            :     const auto* client_impl = static_cast<const ClientImpl*>(this);
     358                 :            :     needs_decrypt = client_impl != nullptr && client_impl->is_resp_type;
     359                 :            :   } else if (impl_type == kServer) {
     360                 :            :     needs_decrypt = true;
     361                 :            :     const auto* server_impl = static_cast<const ServerImpl*>(this);
     362                 :            :     needs_encrypt = server_impl != nullptr && server_impl->is_resp_type;
     363                 :            :   }
     364                 :            : #else
     365         [ +  + ]:         44 :   if (impl_type == kClient) {
     366                 :          6 :     needs_encrypt = true;
     367         [ +  - ]:          6 :     const auto* client_impl = dynamic_cast<const ClientImpl*>(this);
     368   [ +  -  +  - ]:          6 :     needs_decrypt = client_impl != nullptr && client_impl->is_resp_type;
     369         [ +  + ]:         38 :   } else if (impl_type == kServer) {
     370                 :          7 :     needs_decrypt = true;
     371         [ +  - ]:          7 :     const auto* server_impl = dynamic_cast<const ServerImpl*>(this);
     372   [ +  -  +  - ]:          7 :     needs_encrypt = server_impl != nullptr && server_impl->is_resp_type;
     373                 :            :   }
     374                 :            : #endif
     375                 :            : 
     376   [ +  +  -  +  :         44 :   if VUNLIKELY (needs_encrypt && !candidate->can_encrypt()) {
                   -  + ]
     377                 :            :     VLOG_W("Security::Config cannot encrypt for this sender role.");  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     378                 :            :     return false;                                                     // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     379                 :            :   }
     380                 :            : 
     381   [ +  +  -  +  :         44 :   if VUNLIKELY (needs_decrypt && !candidate->can_decrypt()) {
                   -  + ]
     382                 :            :     VLOG_W("Security::Config cannot decrypt for this receiver role.");  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     383                 :            :     return false;                                                       // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     384                 :            :   }
     385                 :            : 
     386                 :         44 :   security = std::move(candidate);
     387                 :            : 
     388                 :         44 :   return true;
     389                 :         44 : }
     390                 :            : 
     391                 :          1 : void NodeImpl::set_ssl_options(const SslOptions& options) {
     392         [ +  - ]:          1 :   std::lock_guard lock(helper_->mtx);
     393                 :          1 :   options.parse_to(helper_->property_map);
     394                 :          1 : }
     395                 :            : 
     396                 :       2620 : void NodeImpl::try_record(ActionType action_type, const Bytes& data) {
     397         [ +  - ]:       2620 :   auto* global_recorder = BagWriter::global_get();
     398                 :       2614 :   const bool data_recorder_enabled = helper_->data_recorder_enabled.load(std::memory_order_acquire);
     399                 :            : 
     400   [ +  -  +  -  :       2621 :   if VLIKELY (!global_recorder && !data_recorder_enabled) {
                   +  - ]
     401                 :       2621 :     return;
     402                 :            :   }
     403                 :            : 
     404                 :          0 :   std::shared_ptr<BagWriter> data_recorder;
     405                 :            : 
     406         [ #  # ]:          0 :   if (data_recorder_enabled) {
     407         [ #  # ]:          0 :     std::shared_lock lock(helper_->mtx);
     408                 :          0 :     data_recorder = helper_->data_recorder;
     409                 :          0 :   }
     410                 :            : 
     411   [ #  #  #  #  :          0 :   if VLIKELY (!global_recorder && !data_recorder) {
                   #  # ]
     412                 :          0 :     return;
     413                 :            :   }
     414                 :            : 
     415                 :            :   if constexpr (kIgnoreIntraUrl) {
     416                 :            :     if (transport_type == TransportType::kIntra) {
     417                 :            :       return;
     418                 :            :     }
     419                 :            :   }
     420                 :            : 
     421                 :          0 :   Frame frame;
     422                 :          0 :   frame.timestamp = -1;
     423         [ #  # ]:          0 :   frame.url = url;
     424         [ #  # ]:          0 :   frame.ser_type = ser_type;
     425                 :          0 :   frame.schema_type = schema_type;
     426                 :          0 :   frame.action_type = action_type;
     427                 :          0 :   frame.data = Bytes::shallow_copy(data.data(), data.size());
     428                 :            : 
     429         [ #  # ]:          0 :   if VUNLIKELY (global_recorder) {
     430         [ #  # ]:          0 :     global_recorder->push(frame);
     431                 :            :   }
     432                 :            : 
     433         [ #  # ]:          0 :   if VUNLIKELY (data_recorder) {
     434         [ #  # ]:          0 :     data_recorder->push(frame);
     435                 :            :   }
     436         [ #  # ]:          0 : }
     437                 :            : 
     438                 :        118 : void NodeImpl::reset_interrupted() { helper_->is_interrupted.store(false, std::memory_order_release); }
     439                 :            : 
     440                 :        235 : bool NodeImpl::is_interrupted() const { return helper_->is_interrupted.load(std::memory_order_acquire); }
     441                 :            : 
     442                 :       1023 : void NodeImpl::init_ext() {
     443         [ +  + ]:       1023 :   if (should_report_discovery(*this)) {
     444                 :        454 :     auto* global_reporter = GlobalDiscoveryReporter::get();
     445                 :            : 
     446         [ +  - ]:        454 :     if (global_reporter) {
     447   [ -  +  -  -  :        454 :       if (CpuProfiler::is_global_enabled() && !profiler) {
                   -  + ]
     448                 :            :         profiler = std::make_unique<CpuProfiler>();  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     449                 :            :       }
     450                 :            : 
     451                 :        454 :       global_reporter->add(this);
     452                 :            :     }
     453                 :            :   }
     454                 :            : 
     455                 :            : #ifdef VLINK_ENABLE_CHECK_LICENSE
     456                 :            :   [[maybe_unused]] static LicenseCheck license;
     457                 :            : #endif
     458                 :       1023 : }
     459                 :            : 
     460                 :       1023 : void NodeImpl::deinit_ext() {
     461         [ +  + ]:       1023 :   if (!should_report_discovery(*this)) {
     462                 :        569 :     return;
     463                 :            :   }
     464                 :            : 
     465                 :        454 :   auto* global_reporter = GlobalDiscoveryReporter::get(false);
     466                 :            : 
     467         [ +  - ]:        454 :   if (global_reporter) {
     468                 :        454 :     global_reporter->remove(this);
     469                 :            : 
     470   [ -  +  -  -  :        454 :     if (CpuProfiler::is_global_enabled() && profiler) {
                   -  + ]
     471                 :            :       profiler->restart();  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     472                 :            :     }
     473                 :            :   }
     474                 :            : }
     475                 :            : 
     476                 :       1269 : void NodeImpl::global_init() {
     477                 :       1269 :   Logger::get();
     478                 :            : 
     479                 :       1269 :   Bytes::init_memory_pool();
     480                 :            : 
     481                 :       1269 :   BagWriter::global_get();
     482                 :            : 
     483                 :       1269 :   GlobalDiscoveryReporter::get(false);
     484                 :       1269 : }
     485                 :            : 
     486   [ +  -  +  - ]:       1266 : NodeImpl::NodeImpl(ImplType type) : impl_type(type), helper_(std::make_unique<NodeImplHelper>()) { global_init(); }
     487                 :            : 
     488                 :       1266 : NodeImpl::~NodeImpl() = default;
     489                 :            : 
     490                 :            : }  // namespace vlink

Generated by: LCOV version 1.14