diff --git a/CMakeLists.txt b/CMakeLists.txt index cdfbac1..d3f398f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,12 +16,12 @@ find_package(fmt REQUIRED) find_package(Boost COMPONENTS unit_test_framework program_options REQUIRED) -daq_add_dal_library(application.schema.xml hermes.schema.xml fdmodules.schema.xml trigger.schema.xml wiec.schema.xml PDS.schema.xml tde.schema.xml CTB.schema.xml CIB.schema.xml +daq_add_dal_library(application.schema.xml hermes.schema.xml fdmodules.schema.xml trigger.schema.xml wiec.schema.xml socket.schema.xml PDS.schema.xml tde.schema.xml CTB.schema.xml CIB.schema.xml NAMESPACE dunedaq::appmodel DEP_PKGS confmodel SOURCES ConfigurationHelper.cpp ConfigObjectFactory.cpp - CRTReaderApplication.cpp + CRTFrameBuilderApplication.cpp CTBApplication.cpp DaphneApplication.cpp DFApplication.cpp diff --git a/schema/appmodel/application.schema.xml b/schema/appmodel/application.schema.xml index b989837..a75dba2 100644 --- a/schema/appmodel/application.schema.xml +++ b/schema/appmodel/application.schema.xml @@ -80,22 +80,21 @@ - + - + - - + + - - + @@ -192,6 +191,16 @@ + + + + + + + + + + @@ -405,8 +414,8 @@ - - + + @@ -527,8 +536,11 @@ - - + + + + + diff --git a/schema/appmodel/fdmodules.schema.xml b/schema/appmodel/fdmodules.schema.xml index 7cd6c8e..c061de8 100644 --- a/schema/appmodel/fdmodules.schema.xml +++ b/schema/appmodel/fdmodules.schema.xml @@ -80,7 +80,7 @@ - + @@ -88,24 +88,24 @@ - - + + - - + + - - + + - - + + - - + + @@ -153,10 +153,6 @@ - - - - @@ -245,8 +241,6 @@ - - @@ -259,8 +253,6 @@ - - diff --git a/schema/appmodel/socket.schema.xml b/schema/appmodel/socket.schema.xml new file mode 100644 index 0000000..abee5a7 --- /dev/null +++ b/schema/appmodel/socket.schema.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + diff --git a/schema/appmodel/wiec.schema.xml b/schema/appmodel/wiec.schema.xml index 9321b4b..2c6eca5 100644 --- a/schema/appmodel/wiec.schema.xml +++ b/schema/appmodel/wiec.schema.xml @@ -80,7 +80,7 @@ - + @@ -120,13 +120,6 @@ - - - - - - - diff --git a/src/CRTFrameBuilderApplication.cpp b/src/CRTFrameBuilderApplication.cpp new file mode 100644 index 0000000..57f215b --- /dev/null +++ b/src/CRTFrameBuilderApplication.cpp @@ -0,0 +1,202 @@ +/** + * @file CRTFrameBuilderApplication.cpp + * + * Implementation of CRTFrameBuilderApplication's generate_modules dal method + * + * This is part of the DUNE DAQ Software Suite, copyright 2023. + * Licensing/copyright details are in the COPYING file that you should have + * received with this code. + */ + +#include "appmodel/CRTFrameBuilderApplication.hpp" + +#include "appmodel/appmodelIssues.hpp" + +#include "appmodel/DetectorFrameBuilderConf.hpp" +#include "appmodel/SocketWriterConf.hpp" +#include "appmodel/SocketWriterModule.hpp" +#include "appmodel/QueueConnectionRule.hpp" +#include "appmodel/QueueDescriptor.hpp" +#include "appmodel/SocketDetectorToDaqConnection.hpp" + +#include "ConfigObjectFactory.hpp" + +#include "confmodel/Connection.hpp" +#include "confmodel/DetectorStream.hpp" +#include "confmodel/DetectorToDaqConnection.hpp" +#include "confmodel/DetDataSender.hpp" +#include "confmodel/DetDataReceiver.hpp" + +#include "logging/Logging.hpp" + +#include + +#include +#include +#include + +namespace dunedaq::appmodel { + +std::vector +CRTFrameBuilderApplication::contained_resources() const { + return to_resources(get_detector_connections()); +} + +void + CRTFrameBuilderApplication::generate_modules(std::shared_ptr helper) const +{ + + TLOG_DEBUG(6) << "Generating modules for application " << this->UID(); + + std::vector modules; + + ConfigObjectFactory obj_fac(this); + + // + // Extract basic configuration objects + // + + // Detector frame builder + const auto det_frame_builder_conf = get_detector_frame_builder(); + if (det_frame_builder_conf == nullptr) { + throw(BadConf(ERS_HERE, "No DetectorFrameBuilderModule configuration given")); + } + const std::string builder_class = det_frame_builder_conf->get_template_for(); + + // Data writer + const auto writer_conf = get_data_writer(); + if (writer_conf == nullptr) { + throw(BadConf(ERS_HERE, "No DataWriterModule configuration given")); + } + const std::string writer_class = writer_conf->get_template_for(); + + // + // Process the queue rules looking for inputs to our socket writer modules + // + const QueueDescriptor* crtframebuilder_output_qdesc = nullptr; + auto queue_rules = get_queue_rules(); + if (queue_rules.size() != 1) { + throw(BadConf(ERS_HERE, "Strictly 1 queue rule is expected")); + } + crtframebuilder_output_qdesc = queue_rules[0]->get_descriptor(); + + // + // Scan Detector 2 DAQ connections to extract sender, receiver and stream information + // + + // Loop over the detector to daq connections and generate: + // - One detector frame builder per data sender + // - One data writer per data sender + // - One queue per data sender + + for (auto d2d_conn : get_detector_connections()) { + + auto d2d_conn_uid = d2d_conn->UID(); + + // Are we sure? + if (helper->is_disabled(d2d_conn)) { + TLOG_DEBUG(7) << "Ignoring disabled DetectorToDaqConnection " << d2d_conn_uid; + continue; + } + + TLOG_DEBUG(6) << "Processing DetectorToDaqConnection " << d2d_conn_uid; + + auto receiver = d2d_conn->receiver(); + + uint16_t sender_idx = 0; // NOLINT(build/unsigned) + + // Loop over senders + for (auto sender : d2d_conn->senders()) { + + // Are we sure? + if (helper->is_disabled(sender)) { + TLOG_DEBUG(7) << "Ignoring disabled DataSender " << sender->UID(); + continue; + } + + + bool has_enabled_det_stream = false; + // Loop over streams + for (auto stream : sender->get_streams()) { + + // Are we sure? + if (helper->is_disabled(stream)) { + TLOG_DEBUG(7) << "Ignoring disabled DetectorStream " << stream->UID(); + continue; + } + + has_enabled_det_stream = true; + break; + } + + if (!has_enabled_det_stream) { + continue; + } + + const auto sender_idx_str = std::to_string(sender_idx); + + // Create a connection that is dedicated to this sender + std::string sender_conn_uid(d2d_conn_uid + sender_idx_str); + auto sender_conn_obj = obj_fac.create("SocketDetectorToDaqConnection", sender_conn_uid); + sender_conn_obj.set_objs("net_senders", { &sender->config_object() }); + sender_conn_obj.set_obj("net_receiver", &receiver->config_object()); + const auto* sender_conn = obj_fac.get_dal(sender_conn_obj.UID()); + const auto* sender_conn_conf_obj = &sender_conn->config_object(); + + // Create data queue + conffwk::ConfigObject queue_obj = obj_fac.create_queue_obj(crtframebuilder_output_qdesc, sender_idx_str); + const auto* queue = obj_fac.get_dal(queue_obj.UID()); + const auto* queue_conf_obj = &queue->config_object(); + + //----------------------------------------------------------------- + // + // Create DetectorFrameBuilderModule object + // + + // + // Instantiate DetectorFrameBuilderModule of type CRTBernFrameBuilderModule/CRTGrenobleFrameBuilderModule + // + + // Create the detector frame builder object + + std::string builder_uid(fmt::format("crt-frame-builder-{}-{}", this->UID(), sender_idx_str)); + TLOG_DEBUG(6) << fmt::format("creating OKS configuration object for detector frame builder class {} with id {}", builder_class, builder_uid); + auto builder_obj = obj_fac.create(builder_class, builder_uid); + + // Populate configuration and interfaces + builder_obj.set_obj("configuration", &det_frame_builder_conf->config_object()); + builder_obj.set_obj("connection", sender_conn_conf_obj); + builder_obj.set_objs("outputs", { queue_conf_obj }); + + modules.push_back(obj_fac.get_dal(builder_obj.UID())); + + //----------------------------------------------------------------- + // + // Create DataWriterModule object + // + + // + // Instantiate DataWriterModule of type SocketWriterModule + // + + // Create the SocketWriterModule object + + std::string writer_uid(fmt::format("socket-writer-{}-{}", this->UID(), sender_idx_str)); + TLOG_DEBUG(6) << fmt::format("Creating OKS configuration object for socket writer class {} with id {}", writer_class, writer_uid); + auto writer_obj = obj_fac.create(writer_class, writer_uid); + + // Populate configuration and interfaces + writer_obj.set_obj("configuration", &writer_conf->config_object()); + writer_obj.set_obj("connection", sender_conn_conf_obj); + writer_obj.set_objs("inputs", { queue_conf_obj }); + + modules.push_back(obj_fac.get_dal(writer_obj.UID())); + + ++sender_idx; + } + } + + obj_fac.update_modules(modules); +} + +} // namespace dunedaq::appmodel diff --git a/src/CRTReaderApplication.cpp b/src/CRTReaderApplication.cpp deleted file mode 100644 index f68f5e3..0000000 --- a/src/CRTReaderApplication.cpp +++ /dev/null @@ -1,179 +0,0 @@ -/** - * @file CRTReaderApplication.cpp - * - * Implementation of CRTReaderApplication's generate_modules dal method - * - * This is part of the DUNE DAQ Software Suite, copyright 2023. - * Licensing/copyright details are in the COPYING file that you should have - * received with this code. - */ - -#include "appmodel/CRTReaderApplication.hpp" - -#include "appmodel/appmodelIssues.hpp" - -#include "appmodel/DataReaderConf.hpp" -#include "appmodel/SocketWriterConf.hpp" -#include "appmodel/SocketWriterModule.hpp" -#include "appmodel/DataMoveCallbackConf.hpp" -#include "appmodel/QueueConnectionRule.hpp" -#include "appmodel/QueueDescriptor.hpp" - -#include "ConfigObjectFactory.hpp" - -#include "confmodel/Connection.hpp" -#include "confmodel/DetectorStream.hpp" -#include "confmodel/DetectorToDaqConnection.hpp" - -#include "logging/Logging.hpp" - -#include - -#include -#include - -namespace dunedaq::appmodel { - -std::vector -CRTReaderApplication::contained_resources() const { - return to_resources(get_detector_connections()); -} - -void - CRTReaderApplication::generate_modules(std::shared_ptr helper) const -{ - - TLOG_DEBUG(6) << "Generating modules for application " << this->UID(); - - std::vector modules; - - ConfigObjectFactory obj_fac(this); - - // - // Extract basic configuration objects - // - - // Data reader - const auto reader_conf = get_data_reader(); - if (reader_conf == 0) { - throw(BadConf(ERS_HERE, "No DataReaderModule configuration given")); - } - const std::string reader_class = reader_conf->get_template_for(); - - // Data writers - const auto writer_confs = get_data_writers(); - if (writer_confs.size() == 0) { - throw(BadConf(ERS_HERE, "No DataWriterModule configuration given")); - } - - // - // Get the callback descriptor - // - const DataMoveCallbackDescriptor* raw_data_callback_desc = get_callback_desc(); - - if (raw_data_callback_desc == nullptr) { - throw(BadConf(ERS_HERE, "No Raw Data Callback descriptor given")); - } - - // - // Scan Detector 2 DAQ connections to extract sender, receiver and stream information - // - - // Loop over the detector to daq connections and generate one data reader per connection - - // Collect all streams - std::map callback_confs_by_sid; - - uint16_t conn_idx = 0; - - for (auto d2d_conn : get_detector_connections()) { - - // Are we sure? - if (helper->is_disabled(d2d_conn)) { - TLOG_DEBUG(7) << "Ignoring disabled DetectorToDaqConnection " << d2d_conn->UID(); - continue; - } - - TLOG_DEBUG(6) << "Processing DetectorToDaqConnection " << d2d_conn->UID(); - // get the readout groups and the interfaces and streams therein; 1 reaout group corresponds to 1 data reader module - - std::vector enabled_det_streams; - // Loop over streams - for (auto stream : d2d_conn->streams()) { - - // Are we sure? - if (helper->is_disabled(stream)) { - TLOG_DEBUG(7) << "Ignoring disabled DetectorStream " << stream->UID(); - continue; - } - - enabled_det_streams.push_back(stream); - } - - // Create the raw data callbacks - std::vector raw_data_callback_objs; - - // Create data queues - for (auto ds : enabled_det_streams) { - conffwk::ConfigObject callback_obj = obj_fac.create_callback_sid_obj(raw_data_callback_desc, ds->get_source_id()); - const auto* callback_conf = obj_fac.get_dal(callback_obj.UID()); - raw_data_callback_objs.push_back(&callback_conf->config_object()); - callback_confs_by_sid[ds->get_source_id()] = callback_conf; - } - - //----------------------------------------------------------------- - // - // Create DataReaderModule object - // - - // - // Instantiate DataReaderModule of type CRTBernReaderModule/CRTGrenobleReaderModule - // - - // Create the Data reader object - - std::string reader_uid(fmt::format("crtdatareader-{}-{}", this->UID(), std::to_string(conn_idx++))); - TLOG_DEBUG(6) << fmt::format("creating OKS configuration object for Data reader class {} with id {}", reader_class, reader_uid); - auto reader_obj = obj_fac.create(reader_class, reader_uid); - - // Populate configuration and interfaces (leave output queues for later) - reader_obj.set_obj("configuration", &reader_conf->config_object()); - reader_obj.set_objs("connections", { &d2d_conn->config_object() }); - reader_obj.set_objs("raw_data_callbacks", raw_data_callback_objs); - - modules.push_back(obj_fac.get_dal(reader_obj.UID())); - - //----------------------------------------------------------------- - // - // Create DataWriterModule objects - // - - // - // Instantiate DataWriterModule of type SocketWriterModule - // - - // Create the SocketWriterModule objects - - conn_idx = 0; - - for (const auto writer_conf : writer_confs) { - - const std::string writer_class = writer_conf->get_template_for(); - - std::string writer_uid(fmt::format("socketdatawriter-{}-{}", this->UID(), std::to_string(conn_idx++))); - TLOG_DEBUG(6) << fmt::format( - "Creating OKS configuration object for socket data writer class {} with id {}", writer_class, writer_uid); - auto writer_obj = obj_fac.create(writer_class, writer_uid); - - // Populate configuration and interfaces - writer_obj.set_obj("configuration", &writer_conf->config_object()); - writer_obj.set_objs("connections", {&d2d_conn->config_object()}); - - modules.push_back(obj_fac.get_dal(writer_obj.UID())); - } - } - - obj_fac.update_modules(modules); -} - -} // namespace dunedaq::appmodel diff --git a/src/ReadoutApplication.cpp b/src/ReadoutApplication.cpp index d269d3a..4b32153 100644 --- a/src/ReadoutApplication.cpp +++ b/src/ReadoutApplication.cpp @@ -237,15 +237,22 @@ ReadoutApplication::generate_modules(std::shared_ptr helper // Here I want to resolve the type of connection (network, felix, or?) // Rules of engagement: if the receiver interface is network or felix, the receivers should be castable to the counterpart - if (reader_class == "DPDKReaderModule" || reader_class == "SocketReaderModule") { + if (reader_class == "DPDKReaderModule") { if (!d2d_conn->castable("NetworkDetectorToDaqConnection")) { throw(BadConf(ERS_HERE, fmt::format("{} requires NetworkDetectorToDaqConnection, found {} of class {}", reader_class, d2d_conn->UID(), d2d_conn->class_name()))); } - if ((reader_class == "DPDKReaderModule" && !det_receiver->cast()) || - (reader_class == "SocketReaderModule" && !det_receiver->cast())) { + if (!det_receiver->cast()) { throw(BadConf(ERS_HERE, fmt::format("{} requires NWDetDataReceiver, found {} of class {}", reader_class, det_receiver->UID(), det_receiver->class_name()))); } } + else if (reader_class == "SocketReaderModule") { + if (!d2d_conn->castable("SocketDetectorToDaqConnection")) { + throw(BadConf(ERS_HERE, fmt::format("{} requires SocketDetectorToDaqConnection, found {} of class {}", reader_class, d2d_conn->UID(), d2d_conn->class_name()))); + } + if (!det_receiver->cast()) { + throw(BadConf(ERS_HERE, fmt::format("{} requires SocketReceiver, found {} of class {}", reader_class, det_receiver->UID(), det_receiver->class_name()))); + } + } else if (reader_class == "FelixReaderModule") { if (!d2d_conn->castable("FelixDetectorToDaqConnection")) { throw(BadConf(ERS_HERE, fmt::format("{} requires FelixDetectorToDaqConnection, found {} of class {}", reader_class, d2d_conn->UID(), d2d_conn->class_name()))); diff --git a/test/apps/generate_modules_test.cxx b/test/apps/generate_modules_test.cxx index 98c5fcd..cd4f8fa 100644 --- a/test/apps/generate_modules_test.cxx +++ b/test/apps/generate_modules_test.cxx @@ -118,15 +118,6 @@ main(int argc, char* argv[]) } } - auto socketwriter_module = daq_module->cast(); - if (socketwriter_module != nullptr) { - auto callback_conf = socketwriter_module->get_raw_data_callback(); - if (callback_conf != nullptr) { - auto cbObj = callback_conf->config_object(); - cbObj.print_ref(std::cout, *confdb, " "); - } - } - std::cout << std::endl; } } else {