artdaq  v3_07_01
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  {
31  fhicl::TableFragment<artdaq::DataSenderManager::Config> dataSenderConfig;
32  };
34  using Parameters = fhicl::WrappedTable<Config>;
35 
43  explicit RootNetOutput(fhicl::ParameterSet const& ps);
44 
49 
54  size_t dataReceiverCount() const { return sender_ptr_->destinationCount(); }
55 
56 protected:
63  virtual void SendMessage(artdaq::Fragment::sequence_id_t sequence_id, artdaq::Fragment::type_t messageType, TBufferFile& msg);
64 
65 private:
66  void connect();
67  void disconnect();
68  void sendMessage(uint64_t sequenceId, uint8_t messageType, TBufferFile& msg);
69 
70  std::unique_ptr<artdaq::DataSenderManager> sender_ptr_;
71  fhicl::ParameterSet data_pset_;
72  double init_timeout_s_;
73 };
74 
75 art::RootNetOutput::RootNetOutput(fhicl::ParameterSet const& ps)
76  : ArtdaqOutput(ps)
77  , sender_ptr_(nullptr)
78  , data_pset_(ps)
79 {
80  TLOG(TLVL_DEBUG) << "Begin: RootNetOutput::RootNetOutput(ParameterSet const& ps)";
81  // Make sure the ArtdaqSharedMemoryService is available
82  art::ServiceHandle<ArtdaqSharedMemoryService> shm;
83  init_timeout_s_ = ps.get<double>("init_fragment_timeout_seconds", 1.0);
84  connect();
85  TLOG(TLVL_DEBUG) << "End: RootNetOutput::RootNetOutput(ParameterSet const& ps)";
86 }
87 
89 {
90  TLOG(TLVL_DEBUG) << "Begin: RootNetOutput::~RootNetOutput()";
91  disconnect();
92  TLOG(TLVL_DEBUG) << "End: RootNetOutput::~RootNetOutput()";
93 }
94 
95 void art::RootNetOutput::SendMessage(artdaq::Fragment::sequence_id_t sequence_id, artdaq::Fragment::type_t messageType, TBufferFile& msg)
96 {
97  //
98  // Send message.
99  //
100  {
101  TLOG(TLVL_WRITE) << "RootNetOutput::SendMessage Sending a message with type code "
102  << artdaq::detail::RawFragmentHeader::SystemTypeToString(messageType);
103  sendMessage(sequence_id, messageType, msg);
104  TLOG(TLVL_WRITE) << "RootNetOutput::SendMessage: Message sent.";
105  }
106 }
107 
108 void art::RootNetOutput::connect()
109 {
110  auto start_time = std::chrono::steady_clock::now();
111 
112  char const* artapp_env = getenv("ARTDAQ_RANK");
113  if (artapp_env != NULL && my_rank < 0)
114  my_rank = std::atoi(artapp_env);
115 
116  while (my_rank == -1 && artdaq::TimeUtils::GetElapsedTime(start_time) < init_timeout_s_)
117  {
118  usleep(1000);
119  }
120  sender_ptr_.reset(new artdaq::DataSenderManager(data_pset_));
121 }
122 
123 void art::RootNetOutput::disconnect()
124 {
125  if (sender_ptr_) sender_ptr_.reset(nullptr);
126 }
127 
128 void art::RootNetOutput::sendMessage(uint64_t sequenceId, uint8_t messageType, TBufferFile& msg)
129 {
130  if (sender_ptr_ == nullptr)
131  {
132  TLOG(TLVL_DEBUG) << "Reconnecting DataSenderManager";
133  connect();
134  }
135 
136 #if DUMP_SEND_MESSAGE
137  std::string fileName = "sendMessage_" + std::to_string(my_rank) + "_" + std::to_string(getpid()) + "_" +
138  std::to_string(sequenceId) + ".bin";
139  std::fstream ostream(fileName, std::ios::out | std::ios::binary);
140  ostream.write(msg.Buffer(), msg.Length());
141  ostream.close();
142 #endif
143 
144  TLOG(TLVL_DEBUG) << "Sending message with sequenceID=" << sequenceId << ", type=" << (int)messageType
145  << ", length=" << msg.Length();
146  artdaq::NetMonHeader header;
147  header.data_length = static_cast<uint64_t>(msg.Length());
148  artdaq::Fragment fragment(std::ceil(msg.Length() / static_cast<double>(sizeof(artdaq::RawDataType))), sequenceId, 0,
149  messageType, header);
150 
151  memcpy(&*fragment.dataBegin(), msg.Buffer(), msg.Length());
152  sender_ptr_->sendFragment(std::move(fragment));
153  // Events are unique in art, so this will be the only send with this sequence ID!
154  sender_ptr_->RemoveRoutingTableEntry(sequenceId);
155 }
156 
157 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.
This is the base class for artdaq OutputModules, providing the serialization interface for art Events...
Definition: ArtdaqOutput.hh:99
virtual void SendMessage(artdaq::Fragment::sequence_id_t sequence_id, artdaq::Fragment::type_t messageType, TBufferFile &msg)
Send a message using DataSenderManager
~RootNetOutput()
RootNetOutput Destructor.
Allowed Configuration parameters of NetMonTransportService. May be used for configuration validation ...
Header with length information for NetMonTransport messages.
Definition: NetMonHeader.hh:13
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.
uint64_t data_length
The length of the message.
Definition: NetMonHeader.hh:15
fhicl::WrappedTable< Config > Parameters
Used for ParameterSet validation (if desired)