From e99970fc76e2b9c1478463eff996103a0d6dd170 Mon Sep 17 00:00:00 2001 From: Joao Figueiredo Date: Tue, 17 Sep 2024 13:23:42 +0000 Subject: [PATCH] Lock NMOS before finding resources --- .../ossrf-nmos-api/config/nmos_config.json | 12 ++-- .../include/bisect/nmoscpp/nmos_controller.h | 4 ++ .../lib/src/nmos_controller.cpp | 67 +++++++++++-------- cpp/libs/bisect_nmoscpp/lib/src/utils.cpp | 7 ++ .../ossrf_nmos_api/lib/src/nmos_client.cpp | 8 +-- 5 files changed, 59 insertions(+), 39 deletions(-) diff --git a/cpp/demos/ossrf-nmos-api/config/nmos_config.json b/cpp/demos/ossrf-nmos-api/config/nmos_config.json index cae96fd..e255749 100644 --- a/cpp/demos/ossrf-nmos-api/config/nmos_config.json +++ b/cpp/demos/ossrf-nmos-api/config/nmos_config.json @@ -5,7 +5,7 @@ "label": "BISECT OSSRF Node", "description": "BISECT OSSRF node", "host_addresses": [ - "192.168.1.79" + "192.168.1.85" ], "interfaces": [ { @@ -24,10 +24,10 @@ "locked": true } ], - "registry_address": "192.168.1.79", + "registry_address": "192.168.1.85", "registry_version": "v1.3", "registration_port": 8010, - "system_address": "192.168.1.79", + "system_address": "192.168.1.85", "system_version": "v1.0", "system_port": 8010 } @@ -44,7 +44,7 @@ "description": "BISECT OSSRF receiver video", "network": { "primary": { - "interface_address": "192.168.1.79", + "interface_address": "192.168.1.85", "interface_name": "wlp1s0" } }, @@ -60,7 +60,7 @@ "description": "BISECT OSSRF sender video 1", "network": { "primary": { - "source_address": "192.168.1.79", + "source_address": "192.168.1.85", "interface_name": "wlp1s0", "destination_address": "239.10.10.10", "destination_port": 5004 @@ -85,7 +85,7 @@ "description": "BISECT OSSRF sender video 2", "network": { "primary": { - "source_address": "192.168.1.79", + "source_address": "192.168.1.85", "interface_name": "wlp1s0", "destination_address": "239.10.10.11", "destination_port": 5005 diff --git a/cpp/libs/bisect_nmoscpp/lib/include/bisect/nmoscpp/nmos_controller.h b/cpp/libs/bisect_nmoscpp/lib/include/bisect/nmoscpp/nmos_controller.h index 656742e..9abf870 100644 --- a/cpp/libs/bisect_nmoscpp/lib/include/bisect/nmoscpp/nmos_controller.h +++ b/cpp/libs/bisect_nmoscpp/lib/include/bisect/nmoscpp/nmos_controller.h @@ -96,6 +96,10 @@ namespace bisect::nmoscpp std::function erase_resource_after_; + + std::function(unsigned int milliseconds, nmos::resources& resources, + const nmos::id& id)> + find_resource_after_; }; using nmos_controller_uptr = std::unique_ptr; diff --git a/cpp/libs/bisect_nmoscpp/lib/src/nmos_controller.cpp b/cpp/libs/bisect_nmoscpp/lib/src/nmos_controller.cpp index fce3516..e431abd 100644 --- a/cpp/libs/bisect_nmoscpp/lib/src/nmos_controller.cpp +++ b/cpp/libs/bisect_nmoscpp/lib/src/nmos_controller.cpp @@ -286,6 +286,27 @@ nmos_controller_t::nmos_controller_t(logger_t& logger, web::json::value configur return {}; }; + find_resource_after_ = [this](unsigned int milliseconds, nmos::resources& resources, + const nmos::id& id) -> expected { + auto lock = base_controller_.node_model_.read_lock(); + if(nmos::details::wait_for(base_controller_.node_model_.shutdown_condition, lock, + std::chrono::milliseconds(delay_millis), + [&] { return base_controller_.node_model_.shutdown; })) + { + BST_FAIL("Could not lock node model in order to read the resources in it"); + } + + const auto resource_it = nmos::find_resource(resources, id); + if(resource_it == resources.end()) + { + base_controller_.node_model_.notify(); + BST_FAIL("Resource with id {} not found", utility::us2s(id)); + } + + base_controller_.node_model_.notify(); + return *resource_it; + }; + if(!nmos::experimental::fields::http_trace(base_controller_.node_model_.settings)) { // Disable TRACE method @@ -515,7 +536,7 @@ maybe_ok nmos_controller_t::insert_connection_resource(nmos::resource&& resource auto id = resource.id; BST_CHECK( insert_resource_after_(delay_millis, base_controller_.node_model_.connection_resources, std::move(resource))); - BST_CHECK(find_resource(id)); + BST_CHECK(find_connection_resource(id)); return {}; } @@ -548,28 +569,24 @@ maybe_ok nmos_controller_t::modify_connection_receiver(const nmos_receiver_t& co expected nmos_controller_t::find_resource(const nmos::id& id) { - const auto resource_it = nmos::find_resource(base_controller_.node_model_.node_resources, id); - BST_ENFORCE(resource_it != base_controller_.node_model_.node_resources.end(), - "trying to find a non-existing NMOS resource {}", utility::us2s(id)); - return *resource_it; + return find_resource_after_(delay_millis, base_controller_.node_model_.node_resources, id); } expected nmos_controller_t::find_connection_resource(const nmos::id& id) { - const auto resource_it = nmos::find_resource(base_controller_.node_model_.connection_resources, id); - BST_ENFORCE(resource_it != base_controller_.node_model_.connection_resources.end(), - "trying to find a non-existing NMOS connection resource {}", utility::us2s(id)); - return *resource_it; + return find_resource_after_(delay_millis, base_controller_.node_model_.connection_resources, id); } maybe_ok nmos_controller_t::erase_resource(const nmos::id& resource_id) { BST_CHECK(erase_resource_after_(delay_millis, base_controller_.node_model_.node_resources, resource_id)); + auto resource = find_resource(resource_id); - const auto resource = nmos::find_resource(base_controller_.node_model_.node_resources, resource_id); - BST_ENFORCE(base_controller_.node_model_.node_resources.end() == resource, - "NMOS Resource with id {} was not deleted", utility::us2s(resource_id)); + if(!is_error(resource)) + { + BST_FAIL("Error erasing resource."); + } return {}; } @@ -577,31 +594,27 @@ maybe_ok nmos_controller_t::erase_resource(const nmos::id& resource_id) maybe_ok nmos_controller_t::erase_connection_resource(const nmos::id& resource_id) { BST_CHECK(erase_resource_after_(delay_millis, base_controller_.node_model_.connection_resources, resource_id)); + auto resource = find_connection_resource(resource_id); - const auto resource = nmos::find_resource(base_controller_.node_model_.connection_resources, resource_id); - BST_ENFORCE(base_controller_.node_model_.connection_resources.end() == resource, - "NMOS Connection resource with id {} was not deleted", utility::us2s(resource_id)); + if(!is_error(resource)) + { + BST_FAIL("Error erasing connection resource."); + } return {}; } maybe_ok nmos_controller_t::erase_device(const nmos::id& device_id) { - const auto device = - nmos::find_resource(base_controller_.node_model_.node_resources, {device_id, nmos::types::device}); + BST_ASSIGN(device, find_resource(device_id)); std::vector maybe_result_deleting_sub_resources; std::transform( - device->sub_resources.begin(), device->sub_resources.end(), + device.sub_resources.begin(), device.sub_resources.end(), std::back_inserter(maybe_result_deleting_sub_resources), [this, resources = base_controller_.node_model_.node_resources](const nmos::id& sub_resource_id) -> maybe_ok { - const auto resource = nmos::find_resource(resources, sub_resource_id); - if(resources.end() == resource) - { - slog::log(base_controller_.gate_, SLOG_FLF) - << "Sub-resource does not exist: " << sub_resource_id; - } + const auto resource = find_resource(sub_resource_id); if(resource->type == nmos::types::receiver || resource->type == nmos::types::sender) { return erase_connection_resource(resource->id); @@ -625,11 +638,7 @@ maybe_ok nmos_controller_t::erase_device(const nmos::id& device_id) maybe_ok nmos_controller_t::update_transport_file(const nmos::id& sender_id) { - const auto sender_it = - nmos::find_resource(base_controller_.node_model_.node_resources, {sender_id, nmos::types::sender}); - BST_ENFORCE(sender_it == base_controller_.node_model_.node_resources.end(), - "trying to update the transport file of a non-existing NMOS sender {}", utility::us2s(sender_id)); - auto& sender = *sender_it; + BST_ASSIGN(sender, find_resource(sender_id)); modify_connection_resource(sender_id, [this, &sender](nmos::resource& connection_sender) { web::json::value endpoint_transportfile; diff --git a/cpp/libs/bisect_nmoscpp/lib/src/utils.cpp b/cpp/libs/bisect_nmoscpp/lib/src/utils.cpp index 1c91d79..01d05a8 100644 --- a/cpp/libs/bisect_nmoscpp/lib/src/utils.cpp +++ b/cpp/libs/bisect_nmoscpp/lib/src/utils.cpp @@ -27,6 +27,11 @@ using namespace bisect::core::detail; using namespace bisect::nmoscpp; namespace conan_sdp = sdp; +namespace +{ + constexpr auto delay_millis{0}; +} + // Example Connection API activation callback to resolve "auto" values when /staged is transitioned to /active nmos::connection_resource_auto_resolver bisect::nmoscpp::make_node_implementation_auto_resolver(const nmos::settings& settings, @@ -181,6 +186,8 @@ nmos::interlace_mode bisect::get_interlace_mode(const nmos::settings& settings) : nmos::interlace_modes::progressive; } +/******************************** warning ********************************/ +/* before calling this function make sure that the model is locked in */ bisect::maybe_ok bisect::nmoscpp::build_transport_file(const nmos::resources& node_resources, nmos_event_handler_t* event_handler, const nmos::resource& sender, diff --git a/cpp/libs/ossrf_nmos_api/lib/src/nmos_client.cpp b/cpp/libs/ossrf_nmos_api/lib/src/nmos_client.cpp index c5687f7..b7f3c72 100644 --- a/cpp/libs/ossrf_nmos_api/lib/src/nmos_client.cpp +++ b/cpp/libs/ossrf_nmos_api/lib/src/nmos_client.cpp @@ -82,10 +82,10 @@ maybe_ok nmos_client_t::add_receiver(const std::string& device_id, const std::st receiver_config.master_enable = true; - BST_CHECK(impl_->context_->nmos().add_receiver(device_id, receiver_config)); - auto r = std::make_shared(device_id, receiver_config, callback); impl_->context_->resources().insert(device_id, std::move(r)); + BST_CHECK(impl_->context_->nmos().add_receiver(device_id, receiver_config)); + BST_CHECK(update_device_sub_resources(impl_->context_, device_id)); return {}; @@ -98,10 +98,10 @@ maybe_ok nmos_client_t::add_sender(const std::string& device_id, const std::stri sender_config.master_enable = true; + auto s = std::make_shared(device_id, sender_config, callback); + impl_->context_->resources().insert(device_id, std::move(s)); BST_CHECK(impl_->context_->nmos().add_sender(device_id, sender_config)); - auto r = std::make_shared(device_id, sender_config, callback); - impl_->context_->resources().insert(device_id, std::move(r)); BST_CHECK(update_device_sub_resources(impl_->context_, device_id)); return {};