PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
kcenon::pacs::client::remote_node_manager Class Reference

#include <remote_node_manager.h>

Collaboration diagram for kcenon::pacs::client::remote_node_manager:
Collaboration graph

Classes

struct  impl
 

Public Member Functions

 remote_node_manager (std::shared_ptr< storage::node_repository > repo, node_manager_config config={}, std::shared_ptr< di::ILogger > logger=nullptr)
 Construct a remote node manager.
 
 ~remote_node_manager ()
 Destructor - stops health check if running.
 
 remote_node_manager (const remote_node_manager &)=delete
 
auto operator= (const remote_node_manager &) -> remote_node_manager &=delete
 
 remote_node_manager (remote_node_manager &&)=delete
 
auto operator= (remote_node_manager &&) -> remote_node_manager &=delete
 
auto add_node (const remote_node &node) -> kcenon::pacs::VoidResult
 Add a new remote node.
 
auto update_node (const remote_node &node) -> kcenon::pacs::VoidResult
 Update an existing remote node.
 
auto remove_node (std::string_view node_id) -> kcenon::pacs::VoidResult
 Remove a remote node.
 
auto get_node (std::string_view node_id) const -> std::optional< remote_node >
 Get a node by ID.
 
auto list_nodes () const -> std::vector< remote_node >
 List all registered nodes.
 
auto list_nodes_by_status (node_status status) const -> std::vector< remote_node >
 List nodes filtered by status.
 
auto verify_node (std::string_view node_id) -> kcenon::pacs::VoidResult
 Verify a node's connectivity synchronously.
 
auto verify_node_async (std::string_view node_id) -> std::future< kcenon::pacs::VoidResult >
 Verify a node's connectivity asynchronously.
 
void verify_all_nodes_async ()
 Verify all nodes asynchronously.
 
auto acquire_association (std::string_view node_id, std::span< const std::string > sop_classes) -> kcenon::pacs::Result< std::unique_ptr< network::association > >
 Acquire an association from the pool.
 
void release_association (std::string_view node_id, std::unique_ptr< network::association > assoc)
 Release an association back to the pool.
 
void start_health_check ()
 Start the automatic health check scheduler.
 
void stop_health_check ()
 Stop the automatic health check scheduler.
 
auto is_health_check_running () const noexcept -> bool
 Check if health check is running.
 
auto get_status (std::string_view node_id) const -> node_status
 Get the current status of a node.
 
void set_status_callback (node_status_callback callback)
 Set the status change callback.
 
auto get_statistics (std::string_view node_id) const -> node_statistics
 Get statistics for a node.
 
void reset_statistics (std::string_view node_id="")
 Reset statistics for a node.
 
auto config () const noexcept -> const node_manager_config &
 Get the current configuration.
 
void set_config (node_manager_config new_config)
 Update the configuration.
 

Private Attributes

std::unique_ptr< implimpl_
 

Detailed Description

Definition at line 93 of file remote_node_manager.h.

Constructor & Destructor Documentation

◆ remote_node_manager() [1/3]

kcenon::pacs::client::remote_node_manager::remote_node_manager ( std::shared_ptr< storage::node_repository > repo,
node_manager_config config = {},
std::shared_ptr< di::ILogger > logger = nullptr )
explicit

Construct a remote node manager.

Parameters
repoRepository for node persistence (required)
configConfiguration options
loggerLogger instance (optional, defaults to NullLogger)
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 288 of file remote_node_manager.cpp.

292 : impl_(std::make_unique<impl>()) {
293
294 impl_->repo = std::move(repo);
295 impl_->config = std::move(config);
296 impl_->logger = logger ? std::move(logger) : di::null_logger();
297
298 // Load existing nodes from repository
300
301 // Auto-start health check if configured
303 start_health_check();
304 }
305}
auto config() const noexcept -> const node_manager_config &
Get the current configuration.
bool auto_start_health_check
Start health check automatically on construction.
std::shared_ptr< storage::node_repository > repo

References kcenon::pacs::client::node_manager_config::auto_start_health_check, config(), kcenon::pacs::client::remote_node_manager::impl::config, impl_, kcenon::pacs::client::remote_node_manager::impl::load_nodes_from_repo(), kcenon::pacs::client::remote_node_manager::impl::logger, kcenon::pacs::di::null_logger(), kcenon::pacs::client::remote_node_manager::impl::repo, and start_health_check().

Here is the call graph for this function:

◆ ~remote_node_manager()

kcenon::pacs::client::remote_node_manager::~remote_node_manager ( )

Destructor - stops health check if running.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 307 of file remote_node_manager.cpp.

307 {
309
310 // Clear connection pool
311 {
312 std::lock_guard<std::mutex> lock(impl_->pool_mutex);
313 impl_->connection_pool.clear();
314 }
315}
void stop_health_check()
Stop the automatic health check scheduler.
std::unordered_map< std::string, std::deque< pooled_association > > connection_pool

References kcenon::pacs::client::remote_node_manager::impl::connection_pool, impl_, kcenon::pacs::client::remote_node_manager::impl::pool_mutex, and stop_health_check().

Here is the call graph for this function:

◆ remote_node_manager() [2/3]

kcenon::pacs::client::remote_node_manager::remote_node_manager ( const remote_node_manager & )
delete

◆ remote_node_manager() [3/3]

kcenon::pacs::client::remote_node_manager::remote_node_manager ( remote_node_manager && )
delete

Member Function Documentation

◆ acquire_association()

kcenon::pacs::Result< std::unique_ptr< network::association > > kcenon::pacs::client::remote_node_manager::acquire_association ( std::string_view node_id,
std::span< const std::string > sop_classes ) -> kcenon::pacs::Result<std::unique_ptr<network::association>>
nodiscard

Acquire an association from the pool.

Gets a pooled association or creates a new one if none available. The association is configured for the specified SOP classes.

Parameters
node_idID of the node to connect to
sop_classesSOP Class UIDs needed for the operation
Returns
Result containing the association or error
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 563 of file remote_node_manager.cpp.

565 {
566
567 std::string id_str(node_id);
568 std::optional<remote_node> node;
569
570 {
571 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
572 auto it = impl_->node_cache.find(id_str);
573 if (it != impl_->node_cache.end()) {
574 node = it->second;
575 }
576 }
577
578 if (!node) {
579 return kcenon::pacs::pacs_error<std::unique_ptr<network::association>>(
580 kcenon::pacs::error_codes::not_found,
581 "Node not found: " + id_str);
582 }
583
584 // Try to get from pool
585 {
586 std::lock_guard<std::mutex> lock(impl_->pool_mutex);
587 auto it = impl_->connection_pool.find(id_str);
588 if (it != impl_->connection_pool.end() && !it->second.empty()) {
589 auto pooled = std::move(it->second.front());
590 it->second.pop_front();
591
592 // Check if connection is still valid and not expired
593 auto age = std::chrono::steady_clock::now() - pooled.acquired_at;
594 if (age < impl_->config.pool_connection_ttl &&
595 pooled.assoc && pooled.assoc->is_established()) {
596 impl_->logger->debug_fmt("Reusing pooled association for {}", id_str);
597 return kcenon::pacs::ok(std::move(pooled.assoc));
598 }
599 }
600 }
601
602 // Create new association
603 network::association_config assoc_config;
604 assoc_config.calling_ae_title = impl_->config.local_ae_title;
605 assoc_config.called_ae_title = node->ae_title;
606
607 uint8_t context_id = 1;
608 for (const auto& sop_class : sop_classes) {
609 assoc_config.proposed_contexts.push_back({
610 context_id,
611 sop_class,
612 default_transfer_syntaxes
613 });
614 context_id += 2; // Context IDs must be odd
615 }
616
617 auto connect_result = network::association::connect(
618 node->host,
619 node->port,
620 assoc_config,
621 std::chrono::duration_cast<network::association::duration>(node->connection_timeout)
622 );
623
624 if (connect_result.is_err()) {
626 connect_result.error().message);
627 return connect_result.error();
628 }
629
630 // Update statistics
631 {
632 std::lock_guard<std::mutex> lock(impl_->stats_mutex);
633 impl_->statistics[id_str].total_connections++;
634 impl_->statistics[id_str].active_connections++;
635 }
636
637 return kcenon::pacs::ok(std::make_unique<network::association>(std::move(connect_result.value())));
638}
static Result< association > connect(const std::string &host, uint16_t port, const association_config &config, duration timeout=default_timeout)
Initiate an SCU association to a remote SCP.
@ offline
Node is not responding.
std::string local_ae_title
Our AE Title for outgoing associations.
void update_node_status(const std::string &node_id, node_status status, const std::string &error_msg="")
std::unordered_map< std::string, node_statistics > statistics
std::unordered_map< std::string, remote_node > node_cache

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, kcenon::pacs::network::association_config::called_ae_title, kcenon::pacs::network::association_config::calling_ae_title, config(), kcenon::pacs::client::remote_node_manager::impl::config, kcenon::pacs::network::association::connect(), kcenon::pacs::client::remote_node_manager::impl::connection_pool, impl_, kcenon::pacs::client::node_manager_config::local_ae_title, kcenon::pacs::client::remote_node_manager::impl::logger, kcenon::pacs::client::remote_node_manager::impl::node_cache, kcenon::pacs::client::offline, kcenon::pacs::client::remote_node_manager::impl::pool_mutex, kcenon::pacs::network::association_config::proposed_contexts, kcenon::pacs::client::remote_node_manager::impl::statistics, kcenon::pacs::client::remote_node_manager::impl::stats_mutex, and kcenon::pacs::client::remote_node_manager::impl::update_node_status().

Here is the call graph for this function:

◆ add_node()

kcenon::pacs::VoidResult kcenon::pacs::client::remote_node_manager::add_node ( const remote_node & node) -> kcenon::pacs::VoidResult
nodiscard

Add a new remote node.

Parameters
nodeThe node to add
Returns
VoidResult indicating success or error
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 321 of file remote_node_manager.cpp.

321 {
322 if (node.node_id.empty()) {
324 kcenon::pacs::error_codes::invalid_argument,
325 "Node ID cannot be empty");
326 }
327
328 if (node.ae_title.empty()) {
330 kcenon::pacs::error_codes::invalid_argument,
331 "AE Title cannot be empty");
332 }
333
334 if (node.host.empty()) {
336 kcenon::pacs::error_codes::invalid_argument,
337 "Host cannot be empty");
338 }
339
340 // Check for duplicate
341 {
342 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
343 if (impl_->node_cache.find(node.node_id) != impl_->node_cache.end()) {
345 kcenon::pacs::error_codes::already_exists,
346 "Node with ID already exists: " + node.node_id);
347 }
348 }
349
350 // Persist to repository
351 if (impl_->repo) {
352#ifdef PACS_WITH_DATABASE_SYSTEM
353 auto result = impl_->repo->save(node);
354 if (result.is_err()) {
356 result.error().code,
357 "Failed to persist node: " + result.error().message);
358 }
359#else
360 auto result = impl_->repo->upsert(node);
361 if (result.is_err()) {
363 result.error().code,
364 "Failed to persist node: " + result.error().message);
365 }
366#endif
367 }
368
369 // Add to cache
370 {
371 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
372 impl_->node_cache[node.node_id] = node;
373 }
374
375 impl_->logger->info_fmt("Added remote node: {} ({}:{})",
376 node.node_id, node.host, node.port);
377
378 return kcenon::pacs::ok();
379}
VoidResult pacs_void_error(int code, const std::string &message, const std::string &details="")
Create a PACS void error result.
Definition result.h:249

References kcenon::pacs::client::remote_node::ae_title, kcenon::pacs::client::remote_node_manager::impl::cache_mutex, kcenon::pacs::client::remote_node::host, impl_, kcenon::pacs::client::remote_node_manager::impl::logger, kcenon::pacs::client::remote_node_manager::impl::node_cache, kcenon::pacs::client::remote_node::node_id, kcenon::pacs::pacs_void_error(), kcenon::pacs::client::remote_node::port, and kcenon::pacs::client::remote_node_manager::impl::repo.

Here is the call graph for this function:

◆ config()

const node_manager_config & kcenon::pacs::client::remote_node_manager::config ( ) const -> const node_manager_config&
nodiscardnoexcept

Get the current configuration.

Returns
Current manager configuration
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 757 of file remote_node_manager.cpp.

757 {
758 return impl_->config;
759}

References kcenon::pacs::client::remote_node_manager::impl::config, and impl_.

Referenced by acquire_association(), and remote_node_manager().

Here is the caller graph for this function:

◆ get_node()

std::optional< remote_node > kcenon::pacs::client::remote_node_manager::get_node ( std::string_view node_id) const -> std::optional<remote_node>
nodiscard

Get a node by ID.

Parameters
node_idID of the node to retrieve
Returns
Optional containing the node if found
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 466 of file remote_node_manager.cpp.

466 {
467 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
468 auto it = impl_->node_cache.find(std::string(node_id));
469 if (it != impl_->node_cache.end()) {
470 return it->second;
471 }
472 return std::nullopt;
473}

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, impl_, and kcenon::pacs::client::remote_node_manager::impl::node_cache.

◆ get_statistics()

node_statistics kcenon::pacs::client::remote_node_manager::get_statistics ( std::string_view node_id) const -> node_statistics
nodiscard

Get statistics for a node.

Parameters
node_idID of the node
Returns
Statistics for the node
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 735 of file remote_node_manager.cpp.

735 {
736 std::lock_guard<std::mutex> lock(impl_->stats_mutex);
737 auto it = impl_->statistics.find(std::string(node_id));
738 if (it != impl_->statistics.end()) {
739 return it->second;
740 }
741 return {};
742}

References impl_, kcenon::pacs::client::remote_node_manager::impl::statistics, and kcenon::pacs::client::remote_node_manager::impl::stats_mutex.

◆ get_status()

node_status kcenon::pacs::client::remote_node_manager::get_status ( std::string_view node_id) const -> node_status
nodiscard

Get the current status of a node.

Parameters
node_idID of the node
Returns
Current status (unknown if node not found)
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 717 of file remote_node_manager.cpp.

717 {
718 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
719 auto it = impl_->node_cache.find(std::string(node_id));
720 if (it != impl_->node_cache.end()) {
721 return it->second.status;
722 }
724}
@ unknown
Status not yet determined.

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, impl_, kcenon::pacs::client::remote_node_manager::impl::node_cache, and kcenon::pacs::client::unknown.

◆ is_health_check_running()

bool kcenon::pacs::client::remote_node_manager::is_health_check_running ( ) const -> bool
nodiscardnoexcept

Check if health check is running.

Returns
true if the health check scheduler is active
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 709 of file remote_node_manager.cpp.

709 {
710 return impl_->health_check_running.load();
711}

References kcenon::pacs::client::remote_node_manager::impl::health_check_running, and impl_.

◆ list_nodes()

std::vector< remote_node > kcenon::pacs::client::remote_node_manager::list_nodes ( ) const -> std::vector<remote_node>
nodiscard

List all registered nodes.

Returns
Vector of all nodes
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 475 of file remote_node_manager.cpp.

475 {
476 std::vector<remote_node> result;
477 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
478 result.reserve(impl_->node_cache.size());
479 for (const auto& [_, node] : impl_->node_cache) {
480 result.push_back(node);
481 }
482 return result;
483}

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, impl_, and kcenon::pacs::client::remote_node_manager::impl::node_cache.

◆ list_nodes_by_status()

std::vector< remote_node > kcenon::pacs::client::remote_node_manager::list_nodes_by_status ( node_status status) const -> std::vector<remote_node>
nodiscard

List nodes filtered by status.

Parameters
statusThe status to filter by
Returns
Vector of nodes with the specified status
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 485 of file remote_node_manager.cpp.

485 {
486 std::vector<remote_node> result;
487 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
488 for (const auto& [_, node] : impl_->node_cache) {
489 if (node.status == status) {
490 result.push_back(node);
491 }
492 }
493 return result;
494}

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, impl_, and kcenon::pacs::client::remote_node_manager::impl::node_cache.

◆ operator=() [1/2]

auto kcenon::pacs::client::remote_node_manager::operator= ( const remote_node_manager & ) -> remote_node_manager &=delete
delete

◆ operator=() [2/2]

auto kcenon::pacs::client::remote_node_manager::operator= ( remote_node_manager && ) -> remote_node_manager &=delete
delete

◆ release_association()

void kcenon::pacs::client::remote_node_manager::release_association ( std::string_view node_id,
std::unique_ptr< network::association > assoc )

Release an association back to the pool.

Returns an association to the pool for reuse. If the pool is full or the association is in a bad state, it will be closed instead.

Parameters
node_idID of the node the association is for
assocThe association to release
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 640 of file remote_node_manager.cpp.

642 {
643
644 std::string id_str(node_id);
645
646 // Update statistics
647 {
648 std::lock_guard<std::mutex> lock(impl_->stats_mutex);
649 auto it = impl_->statistics.find(id_str);
650 if (it != impl_->statistics.end() && it->second.active_connections > 0) {
651 it->second.active_connections--;
652 }
653 }
654
655 if (!assoc || !assoc->is_established()) {
656 return;
657 }
658
659 // Check pool capacity
660 {
661 std::lock_guard<std::mutex> lock(impl_->pool_mutex);
662 auto& pool = impl_->connection_pool[id_str];
663 if (pool.size() < impl_->config.max_pool_connections_per_node) {
664 impl::pooled_association pooled;
665 pooled.assoc = std::move(assoc);
666 pooled.acquired_at = std::chrono::steady_clock::now();
667 pool.push_back(std::move(pooled));
668 impl_->logger->debug_fmt("Returned association to pool for {}", id_str);
669 return;
670 }
671 }
672
673 // Pool is full, release the association
674 [[maybe_unused]] auto release_result = assoc->release();
675}
size_t max_pool_connections_per_node
Maximum pooled connections per node.

References kcenon::pacs::client::remote_node_manager::impl::pooled_association::acquired_at, kcenon::pacs::client::remote_node_manager::impl::pooled_association::assoc, kcenon::pacs::client::remote_node_manager::impl::config, kcenon::pacs::client::remote_node_manager::impl::connection_pool, impl_, kcenon::pacs::client::remote_node_manager::impl::logger, kcenon::pacs::client::node_manager_config::max_pool_connections_per_node, kcenon::pacs::client::remote_node_manager::impl::pool_mutex, kcenon::pacs::client::remote_node_manager::impl::statistics, and kcenon::pacs::client::remote_node_manager::impl::stats_mutex.

◆ remove_node()

kcenon::pacs::VoidResult kcenon::pacs::client::remote_node_manager::remove_node ( std::string_view node_id) -> kcenon::pacs::VoidResult
nodiscard

Remove a remote node.

Parameters
node_idID of the node to remove
Returns
VoidResult indicating success or error
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 422 of file remote_node_manager.cpp.

422 {
423 std::string id_str(node_id);
424
425 // Check if exists
426 {
427 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
428 if (impl_->node_cache.find(id_str) == impl_->node_cache.end()) {
430 kcenon::pacs::error_codes::not_found,
431 "Node not found: " + id_str);
432 }
433 }
434
435 // Remove from repository
436 if (impl_->repo) {
437 auto result = impl_->repo->remove(std::string(node_id));
438 if (result.is_err()) {
439 return result;
440 }
441 }
442
443 // Remove from cache
444 {
445 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
446 impl_->node_cache.erase(id_str);
447 }
448
449 // Remove from connection pool
450 {
451 std::lock_guard<std::mutex> lock(impl_->pool_mutex);
452 impl_->connection_pool.erase(id_str);
453 }
454
455 // Remove statistics
456 {
457 std::lock_guard<std::mutex> lock(impl_->stats_mutex);
458 impl_->statistics.erase(id_str);
459 }
460
461 impl_->logger->info_fmt("Removed remote node: {}", id_str);
462
463 return kcenon::pacs::ok();
464}

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, kcenon::pacs::client::remote_node_manager::impl::connection_pool, impl_, kcenon::pacs::client::remote_node_manager::impl::logger, kcenon::pacs::client::remote_node_manager::impl::node_cache, kcenon::pacs::pacs_void_error(), kcenon::pacs::client::remote_node_manager::impl::pool_mutex, kcenon::pacs::client::remote_node_manager::impl::repo, kcenon::pacs::client::remote_node_manager::impl::statistics, and kcenon::pacs::client::remote_node_manager::impl::stats_mutex.

Here is the call graph for this function:

◆ reset_statistics()

void kcenon::pacs::client::remote_node_manager::reset_statistics ( std::string_view node_id = "")

Reset statistics for a node.

Parameters
node_idID of the node (empty to reset all)
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 744 of file remote_node_manager.cpp.

744 {
745 std::lock_guard<std::mutex> lock(impl_->stats_mutex);
746 if (node_id.empty()) {
747 impl_->statistics.clear();
748 } else {
749 impl_->statistics.erase(std::string(node_id));
750 }
751}

References impl_, kcenon::pacs::client::remote_node_manager::impl::statistics, and kcenon::pacs::client::remote_node_manager::impl::stats_mutex.

◆ set_config()

void kcenon::pacs::client::remote_node_manager::set_config ( node_manager_config new_config)

Update the configuration.

Note: Some changes may not take effect until health check is restarted.

Parameters
new_configNew configuration to apply
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 761 of file remote_node_manager.cpp.

761 {
762 impl_->config = std::move(new_config);
763}

References kcenon::pacs::client::remote_node_manager::impl::config, and impl_.

◆ set_status_callback()

void kcenon::pacs::client::remote_node_manager::set_status_callback ( node_status_callback callback)

Set the status change callback.

The callback is invoked whenever a node's status changes. Only one callback can be set; setting a new one replaces the old.

Parameters
callbackFunction to call on status change
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 726 of file remote_node_manager.cpp.

726 {
727 std::lock_guard<std::mutex> lock(impl_->callback_mutex);
728 impl_->status_callback = std::move(callback);
729}

References kcenon::pacs::client::remote_node_manager::impl::callback_mutex, impl_, and kcenon::pacs::client::remote_node_manager::impl::status_callback.

◆ start_health_check()

void kcenon::pacs::client::remote_node_manager::start_health_check ( )

Start the automatic health check scheduler.

Begins periodic verification of all nodes at the configured interval. Does nothing if already running.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 681 of file remote_node_manager.cpp.

681 {
682 if (impl_->health_check_running.load()) {
683 return;
684 }
685
686 impl_->health_check_running.store(true);
687 impl_->health_check_thread = std::thread([this]() {
689 });
690
691 impl_->logger->info("Started health check scheduler");
692}

References kcenon::pacs::client::remote_node_manager::impl::health_check_loop(), kcenon::pacs::client::remote_node_manager::impl::health_check_running, kcenon::pacs::client::remote_node_manager::impl::health_check_thread, impl_, and kcenon::pacs::client::remote_node_manager::impl::logger.

Referenced by remote_node_manager().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ stop_health_check()

void kcenon::pacs::client::remote_node_manager::stop_health_check ( )

Stop the automatic health check scheduler.

Stops periodic verification. Does nothing if not running.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 694 of file remote_node_manager.cpp.

694 {
695 if (!impl_->health_check_running.load()) {
696 return;
697 }
698
699 impl_->health_check_running.store(false);
700 impl_->health_check_cv.notify_all();
701
702 if (impl_->health_check_thread.joinable()) {
704 }
705
706 impl_->logger->info("Stopped health check scheduler");
707}

References kcenon::pacs::client::remote_node_manager::impl::health_check_cv, kcenon::pacs::client::remote_node_manager::impl::health_check_running, kcenon::pacs::client::remote_node_manager::impl::health_check_thread, impl_, and kcenon::pacs::client::remote_node_manager::impl::logger.

Referenced by ~remote_node_manager().

Here is the caller graph for this function:

◆ update_node()

kcenon::pacs::VoidResult kcenon::pacs::client::remote_node_manager::update_node ( const remote_node & node) -> kcenon::pacs::VoidResult
nodiscard

Update an existing remote node.

Parameters
nodeThe node to update (node_id must match existing)
Returns
VoidResult indicating success or error
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 381 of file remote_node_manager.cpp.

381 {
382 // Check if exists
383 {
384 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
385 if (impl_->node_cache.find(node.node_id) == impl_->node_cache.end()) {
387 kcenon::pacs::error_codes::not_found,
388 "Node not found: " + node.node_id);
389 }
390 }
391
392 // Update repository
393 if (impl_->repo) {
394#ifdef PACS_WITH_DATABASE_SYSTEM
395 auto result = impl_->repo->save(node);
396 if (result.is_err()) {
398 result.error().code,
399 "Failed to update node: " + result.error().message);
400 }
401#else
402 auto result = impl_->repo->upsert(node);
403 if (result.is_err()) {
405 result.error().code,
406 "Failed to update node: " + result.error().message);
407 }
408#endif
409 }
410
411 // Update cache
412 {
413 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
414 impl_->node_cache[node.node_id] = node;
415 }
416
417 impl_->logger->info_fmt("Updated remote node: {}", node.node_id);
418
419 return kcenon::pacs::ok();
420}

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, impl_, kcenon::pacs::client::remote_node_manager::impl::logger, kcenon::pacs::client::remote_node_manager::impl::node_cache, kcenon::pacs::client::remote_node::node_id, kcenon::pacs::pacs_void_error(), and kcenon::pacs::client::remote_node_manager::impl::repo.

Here is the call graph for this function:

◆ verify_all_nodes_async()

void kcenon::pacs::client::remote_node_manager::verify_all_nodes_async ( )

Verify all nodes asynchronously.

Initiates verification of all registered nodes. Results are reported via status callbacks.

Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 543 of file remote_node_manager.cpp.

543 {
544 std::vector<std::string> node_ids;
545 {
546 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
547 for (const auto& [id, _] : impl_->node_cache) {
548 node_ids.push_back(id);
549 }
550 }
551
552 for (const auto& id : node_ids) {
553 std::thread([this, id]() {
554 [[maybe_unused]] auto result = verify_node(id);
555 }).detach();
556 }
557}
auto verify_node(std::string_view node_id) -> kcenon::pacs::VoidResult
Verify a node's connectivity synchronously.

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, impl_, kcenon::pacs::client::remote_node_manager::impl::node_cache, and verify_node().

Here is the call graph for this function:

◆ verify_node()

kcenon::pacs::VoidResult kcenon::pacs::client::remote_node_manager::verify_node ( std::string_view node_id) -> kcenon::pacs::VoidResult
nodiscard

Verify a node's connectivity synchronously.

Sends a C-ECHO to the specified node and waits for response. Updates the node's status based on the result.

Parameters
node_idID of the node to verify
Returns
VoidResult indicating success (online) or error (offline/error)
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 500 of file remote_node_manager.cpp.

500 {
501 std::optional<remote_node> node;
502 {
503 std::lock_guard<std::mutex> lock(impl_->cache_mutex);
504 auto it = impl_->node_cache.find(std::string(node_id));
505 if (it != impl_->node_cache.end()) {
506 node = it->second;
507 }
508 }
509
510 if (!node) {
512 kcenon::pacs::error_codes::not_found,
513 "Node not found: " + std::string(node_id));
514 }
515
516 impl_->update_node_status(std::string(node_id), node_status::verifying);
517
518 auto result = impl_->perform_echo(*node);
519
520 if (result.is_ok()) {
521 impl_->update_node_status(std::string(node_id), node_status::online);
522 if (impl_->repo) {
523 [[maybe_unused]] auto update_result = impl_->repo->update_last_verified(node_id);
524 }
525 } else {
526 impl_->update_node_status(std::string(node_id), node_status::offline,
527 result.error().message);
528 }
529
530 return result;
531}
@ verifying
Verification in progress.
@ online
Node is responding to C-ECHO.
kcenon::pacs::VoidResult perform_echo(const remote_node &node)

References kcenon::pacs::client::remote_node_manager::impl::cache_mutex, impl_, kcenon::pacs::client::remote_node_manager::impl::node_cache, kcenon::pacs::client::offline, kcenon::pacs::client::online, kcenon::pacs::pacs_void_error(), kcenon::pacs::client::remote_node_manager::impl::perform_echo(), kcenon::pacs::client::remote_node_manager::impl::repo, kcenon::pacs::client::remote_node_manager::impl::update_node_status(), and kcenon::pacs::client::verifying.

Referenced by verify_all_nodes_async(), and verify_node_async().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ verify_node_async()

std::future< kcenon::pacs::VoidResult > kcenon::pacs::client::remote_node_manager::verify_node_async ( std::string_view node_id) -> std::future<kcenon::pacs::VoidResult>
nodiscard

Verify a node's connectivity asynchronously.

Returns immediately with a future that will contain the result.

Parameters
node_idID of the node to verify
Returns
Future containing the verification result
Examples
/home/runner/work/pacs_system/pacs_system/include/kcenon/pacs/client/remote_node_manager.h.

Definition at line 533 of file remote_node_manager.cpp.

534 {
535
536 std::string id_str(node_id);
537
538 return std::async(std::launch::async, [this, id_str]() {
539 return verify_node(id_str);
540 });
541}

References verify_node().

Here is the call graph for this function:

Member Data Documentation

◆ impl_


The documentation for this class was generated from the following files: