artdaq  v3_09_01
RootNetOutput_module.cc
1 
2 #include <memory>
3 
4 #include "art/Framework/Services/Registry/ServiceHandle.h"
5 #include "artdaq/ArtModules/ArtdaqOutput.hh"
6 #include "artdaq/ArtModules/ArtdaqSharedMemoryService.h"
7 #include "artdaq/DAQdata/Globals.hh"
8 #include "artdaq/DAQdata/NetMonHeader.hh"
9 #include "artdaq/DAQrate/DataSenderManager.hh"
10 
11 // if TRACE_NAME has varible, it is safest to define after includes
12 #define TRACE_NAME (app_name + "_RootNetOutput").c_str()
13 
14 #define DUMP_SEND_MESSAGE 0
15 
16 namespace art {
17 class RootNetOutput;
18 }
19 
26 {
27 public:
35  explicit RootNetOutput(fhicl::ParameterSet const& ps);
36 
40  ~RootNetOutput() override;
41 
46  size_t dataReceiverCount() const { return sender_ptr_->destinationCount(); }
47 
48 protected:
53  void SendMessage(artdaq::FragmentPtr& fragment) override;
54 
55 private:
56  RootNetOutput(RootNetOutput const&) = delete;
57  RootNetOutput(RootNetOutput&&) = delete;
58  RootNetOutput& operator=(RootNetOutput const&) = delete;
59  RootNetOutput& operator=(RootNetOutput&&) = delete;
60 
61  void connect();
62  void disconnect();
63 
64  std::unique_ptr<artdaq::DataSenderManager> sender_ptr_;
65  fhicl::ParameterSet data_pset_;
66  double init_timeout_s_;
67 };
68 
69 art::RootNetOutput::RootNetOutput(fhicl::ParameterSet const& ps)
70  : ArtdaqOutput(ps)
71  , sender_ptr_(nullptr)
72  , data_pset_(ps)
73 {
74  TLOG(TLVL_DEBUG) << "Begin: RootNetOutput::RootNetOutput(ParameterSet const& ps)";
75  // Make sure the ArtdaqSharedMemoryService is available
76  art::ServiceHandle<ArtdaqSharedMemoryServiceInterface> shm;
77  init_timeout_s_ = ps.get<double>("init_fragment_timeout_seconds", 1.0);
78  connect();
79  TLOG(TLVL_DEBUG) << "End: RootNetOutput::RootNetOutput(ParameterSet const& ps)";
80 }
81 
83 {
84  TLOG(TLVL_DEBUG) << "Begin: RootNetOutput::~RootNetOutput()";
85  disconnect();
86  TLOG(TLVL_DEBUG) << "End: RootNetOutput::~RootNetOutput()";
87 }
88 
89 void art::RootNetOutput::SendMessage(artdaq::FragmentPtr& fragment)
90 {
91  //
92  // Send message.
93  //
94  {
95  TLOG(TLVL_WRITE) << "RootNetOutput::SendMessage Sending a message with type code "
96  << artdaq::detail::RawFragmentHeader::SystemTypeToString(fragment->type());
97  if (sender_ptr_ == nullptr)
98  {
99  TLOG(TLVL_DEBUG) << "Reconnecting DataSenderManager";
100  connect();
101  }
102 
103 #if DUMP_SEND_MESSAGE
104  std::string fileName = "sendMessage_" + std::to_string(my_rank) + "_" + std::to_string(getpid()) + "_" +
105  std::to_string(sequenceId) + ".bin";
106  std::fstream ostream(fileName, std::ios::out | std::ios::binary);
107  ostream.write(msg.Buffer(), msg.Length());
108  ostream.close();
109 #endif
110 
111  auto sequenceId = fragment->sequenceID();
112  TLOG(TLVL_DEBUG) << "Sending message with sequenceID=" << sequenceId << ", type=" << fragment->type()
113  << ", length=" << fragment->dataSizeBytes();
114 
115  sender_ptr_->sendFragment(std::move(*fragment));
116  // Events are unique in art, so this will be the only send with this sequence ID!
117  sender_ptr_->RemoveRoutingTableEntry(sequenceId);
118  TLOG(TLVL_WRITE) << "RootNetOutput::SendMessage: Message sent.";
119  }
120 }
121 
122 void art::RootNetOutput::connect()
123 {
124  auto start_time = std::chrono::steady_clock::now();
125 
126  char const* artapp_env = getenv("ARTDAQ_RANK");
127  if (artapp_env != nullptr && my_rank < 0)
128  {
129  my_rank = strtol(artapp_env, nullptr, 10);
130  }
131 
132  while (my_rank == -1 && artdaq::TimeUtils::GetElapsedTime(start_time) < init_timeout_s_)
133  {
134  usleep(1000);
135  }
136  sender_ptr_ = std::make_unique<artdaq::DataSenderManager>(data_pset_);
137 }
138 
139 void art::RootNetOutput::disconnect()
140 {
141  if (sender_ptr_)
142  {
143  sender_ptr_.reset(nullptr);
144  }
145 }
146 
147 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...
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