artdaq  v3_12_02
RootNetOutput_module.cc
1 #include "TRACE/tracemf.h"
2 
3 #include "artdaq/ArtModules/ArtdaqOutput.hh"
4 #include "artdaq/ArtModules/ArtdaqSharedMemoryServiceInterface.h"
5 #include "artdaq/DAQdata/Globals.hh"
6 #include "artdaq/DAQrate/DataSenderManager.hh"
7 
8 #include "art/Framework/Core/ModuleMacros.h"
9 #include "art/Framework/Services/Registry/ServiceHandle.h"
10 #include "fhiclcpp/ParameterSet.h"
11 
12 #include <memory>
13 
14 // if TRACE_NAME has variable, it is safest to define after includes
15 #define TRACE_NAME (app_name + "_RootNetOutput").c_str()
16 
17 #define DUMP_SEND_MESSAGE 0
18 
19 namespace art {
20 class RootNetOutput;
21 }
22 
29 {
30 public:
38  explicit RootNetOutput(fhicl::ParameterSet const& ps);
39 
43  ~RootNetOutput() override;
44 
49  size_t dataReceiverCount() const { return sender_ptr_->destinationCount(); }
50 
51 protected:
56  void SendMessage(artdaq::FragmentPtr& fragment) override;
57 
58 private:
59  RootNetOutput(RootNetOutput const&) = delete;
60  RootNetOutput(RootNetOutput&&) = delete;
61  RootNetOutput& operator=(RootNetOutput const&) = delete;
62  RootNetOutput& operator=(RootNetOutput&&) = delete;
63 
64  void connect();
65  void disconnect();
66 
67  std::unique_ptr<artdaq::DataSenderManager> sender_ptr_;
68  fhicl::ParameterSet data_pset_;
69  double init_timeout_s_;
70 };
71 
72 art::RootNetOutput::RootNetOutput(fhicl::ParameterSet const& ps)
73  : ArtdaqOutput(ps)
74  , sender_ptr_(nullptr)
75  , data_pset_(ps)
76 {
77  TLOG(TLVL_DEBUG + 32) << "Begin: RootNetOutput::RootNetOutput(ParameterSet const& ps)";
78  // Make sure the ArtdaqSharedMemoryService is available
79  art::ServiceHandle<ArtdaqSharedMemoryServiceInterface> shm;
80  init_timeout_s_ = ps.get<double>("init_fragment_timeout_seconds", 1.0);
81  connect();
82  TLOG(TLVL_DEBUG + 32) << "End: RootNetOutput::RootNetOutput(ParameterSet const& ps)";
83 }
84 
86 {
87  TLOG(TLVL_DEBUG + 32) << "Begin: RootNetOutput::~RootNetOutput()";
88  disconnect();
89  TLOG(TLVL_DEBUG + 32) << "End: RootNetOutput::~RootNetOutput()";
90 }
91 
92 void art::RootNetOutput::SendMessage(artdaq::FragmentPtr& fragment)
93 {
94  //
95  // Send message.
96  //
97  {
98  TLOG(TLVL_WRITE) << "RootNetOutput::SendMessage Sending a message with type code "
99  << artdaq::detail::RawFragmentHeader::SystemTypeToString(fragment->type());
100  if (sender_ptr_ == nullptr)
101  {
102  TLOG(TLVL_DEBUG + 32) << "Reconnecting DataSenderManager";
103  connect();
104  }
105 
106 #if DUMP_SEND_MESSAGE
107  std::string fileName = "sendMessage_" + std::to_string(my_rank) + "_" + std::to_string(getpid()) + "_" +
108  std::to_string(sequenceId) + ".bin";
109  std::fstream ostream(fileName, std::ios::out | std::ios::binary);
110  ostream.write(msg.Buffer(), msg.Length());
111  ostream.close();
112 #endif
113 
114  auto sequenceId = fragment->sequenceID();
115  TLOG(TLVL_DEBUG + 32) << "Sending message with sequenceID=" << sequenceId << ", type=" << static_cast<int>(fragment->type())
116  << ", length=" << fragment->dataSizeBytes();
117 
118  sender_ptr_->sendFragment(std::move(*fragment));
119  // Events are unique in art, so this will be the only send with this sequence ID!
120  sender_ptr_->RemoveRoutingTableEntry(sequenceId);
121  TLOG(TLVL_WRITE) << "RootNetOutput::SendMessage: Message sent.";
122  }
123 }
124 
125 void art::RootNetOutput::connect()
126 {
127  auto start_time = std::chrono::steady_clock::now();
128 
129  char const* artapp_env = getenv("ARTDAQ_RANK");
130  if (artapp_env != nullptr && my_rank < 0)
131  {
132  my_rank = strtol(artapp_env, nullptr, 10);
133  }
134 
135  while (my_rank == -1 && artdaq::TimeUtils::GetElapsedTime(start_time) < init_timeout_s_)
136  {
137  usleep(1000);
138  }
139  sender_ptr_ = std::make_unique<artdaq::DataSenderManager>(data_pset_);
140 }
141 
142 void art::RootNetOutput::disconnect()
143 {
144  if (sender_ptr_)
145  {
146  sender_ptr_.reset(nullptr);
147  }
148 }
149 
150 DEFINE_ART_MODULE(art::RootNetOutput) // NOLINT(performance-unnecessary-value-param)
This is the base class for artdaq OutputModules, providing the serialization interface for art Events...
Definition: ArtdaqOutput.hh:88
size_t dataReceiverCount() const
Get the number of data receivers.
An art::OutputModule which sends events using DataSenderManager. This module is designed for transpor...
RootNetOutput(fhicl::ParameterSet const &ps)
RootNetOutput Constructor.
~RootNetOutput() override
RootNetOutput Destructor.
void SendMessage(artdaq::FragmentPtr &fragment) override
Send a message using DataSenderManager