artdaq  v3_07_02
RootNetOutput_module.cc
1 
2 #include "art/Framework/Services/Registry/ServiceHandle.h"
3 #include "artdaq/ArtModules/ArtdaqOutput.hh"
4 #include "artdaq/ArtModules/ArtdaqSharedMemoryService.h"
5 #include "artdaq/DAQdata/Globals.hh"
6 #include "artdaq/DAQdata/NetMonHeader.hh"
7 #include "artdaq/DAQrate/DataSenderManager.hh"
8 
9 // if TRACE_NAME has varible, it is safest to define after includes
10 #define TRACE_NAME (app_name + "_RootNetOutput").c_str()
11 
12 #define DUMP_SEND_MESSAGE 0
13 
14 namespace art {
15 class RootNetOutput;
16 }
17 
24 {
25 public:
29  struct Config
30  {
32  fhicl::Atom<double> init_fragment_timeout_seconds{fhicl::Name{"init_fragment_timeout_seconds"}, fhicl::Comment{"Amount of time, in seconds, to wait for connect to complete"}, 1.0};
33  fhicl::TableFragment<artdaq::DataSenderManager::Config> dataSenderConfig;
34  };
36  using Parameters = fhicl::WrappedTable<Config>;
37 
45  explicit RootNetOutput(fhicl::ParameterSet const& ps);
46 
54  explicit RootNetOutput(Parameters const& ps);
55 
60 
65  size_t dataReceiverCount() const { return sender_ptr_->destinationCount(); }
66 
67 protected:
74  virtual void SendMessage(artdaq::FragmentPtr& fragment);
75 
76 private:
77  void connect();
78  void disconnect();
79 
80  std::unique_ptr<artdaq::DataSenderManager> sender_ptr_;
81  fhicl::ParameterSet data_pset_;
82  double init_timeout_s_;
83 };
84 
85 art::RootNetOutput::RootNetOutput(fhicl::ParameterSet const& ps)
86  : ArtdaqOutput(ps)
87  , sender_ptr_(nullptr)
88  , data_pset_(ps)
89 {
90  TLOG(TLVL_DEBUG) << "Begin: RootNetOutput::RootNetOutput(ParameterSet const& ps)";
91  // Make sure the ArtdaqSharedMemoryService is available
92  art::ServiceHandle<ArtdaqSharedMemoryService> shm;
93  init_timeout_s_ = ps.get<double>("init_fragment_timeout_seconds", 1.0);
94  connect();
95  TLOG(TLVL_DEBUG) << "End: RootNetOutput::RootNetOutput(ParameterSet const& ps)";
96 }
97 
99  : RootNetOutput(ps.get_PSet())
100 {}
101 
103 {
104  TLOG(TLVL_DEBUG) << "Begin: RootNetOutput::~RootNetOutput()";
105  disconnect();
106  TLOG(TLVL_DEBUG) << "End: RootNetOutput::~RootNetOutput()";
107 }
108 
109 void art::RootNetOutput::SendMessage(artdaq::FragmentPtr& fragment)
110 {
111  //
112  // Send message.
113  //
114  {
115  TLOG(TLVL_WRITE) << "RootNetOutput::SendMessage Sending a message with type code "
116  << artdaq::detail::RawFragmentHeader::SystemTypeToString(fragment->type());
117  if (sender_ptr_ == nullptr)
118  {
119  TLOG(TLVL_DEBUG) << "Reconnecting DataSenderManager";
120  connect();
121  }
122 
123 #if DUMP_SEND_MESSAGE
124  std::string fileName = "sendMessage_" + std::to_string(my_rank) + "_" + std::to_string(getpid()) + "_" +
125  std::to_string(sequenceId) + ".bin";
126  std::fstream ostream(fileName, std::ios::out | std::ios::binary);
127  ostream.write(msg.Buffer(), msg.Length());
128  ostream.close();
129 #endif
130 
131  auto sequenceId = fragment->sequenceID();
132  TLOG(TLVL_DEBUG) << "Sending message with sequenceID=" << sequenceId << ", type=" << fragment->type()
133  << ", length=" << fragment->dataSizeBytes();
134 
135  sender_ptr_->sendFragment(std::move(*fragment));
136  // Events are unique in art, so this will be the only send with this sequence ID!
137  sender_ptr_->RemoveRoutingTableEntry(sequenceId);
138  TLOG(TLVL_WRITE) << "RootNetOutput::SendMessage: Message sent.";
139  }
140 }
141 
142 void art::RootNetOutput::connect()
143 {
144  auto start_time = std::chrono::steady_clock::now();
145 
146  char const* artapp_env = getenv("ARTDAQ_RANK");
147  if (artapp_env != NULL && my_rank < 0)
148  my_rank = std::atoi(artapp_env);
149 
150  while (my_rank == -1 && artdaq::TimeUtils::GetElapsedTime(start_time) < init_timeout_s_)
151  {
152  usleep(1000);
153  }
154  sender_ptr_.reset(new artdaq::DataSenderManager(data_pset_));
155 }
156 
157 void art::RootNetOutput::disconnect()
158 {
159  if (sender_ptr_) sender_ptr_.reset(nullptr);
160 }
161 
162 DEFINE_ART_MODULE(art::RootNetOutput)
fhicl::TableFragment< artdaq::DataSenderManager::Config > dataSenderConfig
Configuration for DataSenderManager. See artdaq::DataSenderManager::Config.
Sends Fragment objects using TransferInterface plugins. Uses Routing Tables if confgiured, otherwise will Round-Robin Fragments to the destinations.
fhicl::Atom< double > init_fragment_timeout_seconds
init_fragment_timeout_seconds (Default: 1.0): Amount of time, in seconds, to wait for connect to comp...
This is the base class for artdaq OutputModules, providing the serialization interface for art Events...
~RootNetOutput()
RootNetOutput Destructor.
virtual void SendMessage(artdaq::FragmentPtr &fragment)
Send a message using DataSenderManager
Allowed Configuration parameters of NetMonTransportService. May be used for configuration validation ...
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.
fhicl::WrappedTable< Config > Parameters
Used for ParameterSet validation (if desired)