artdaq  v3_12_02
BinaryFileOutput_module.cc
1 #include "TRACE/tracemf.h"
2 #define TRACE_NAME "BinaryFileOutput"
3 
4 #include "art/Framework/Core/ModuleMacros.h"
5 #include "art/Framework/Core/OutputModule.h"
6 #include "art/Framework/IO/FileStatsCollector.h"
7 #include "art/Framework/IO/PostCloseFileRenamer.h"
8 #include "art/Framework/Principal/EventPrincipal.h"
9 #include "art/Framework/Principal/Handle.h"
10 #include "art/Framework/Principal/RunPrincipal.h"
11 #include "art/Framework/Principal/SubRunPrincipal.h"
12 #include "art/Persistency/Common/GroupQueryResult.h"
13 #include "art/Persistency/Provenance/ModuleContext.h"
14 #include "canvas/Persistency/Common/WrappedTypeID.h"
15 #include "canvas/Persistency/Common/Wrapper.h"
16 #include "canvas/Utilities/DebugMacros.h"
17 #include "canvas/Utilities/Exception.h"
18 #include "fhiclcpp/ParameterSet.h"
19 
20 #include "artdaq-core/Data/Fragment.hh"
21 #include "artdaq/DAQdata/Globals.hh"
22 
23 #include <unistd.h>
24 #include <cstdio>
25 #include <fstream>
26 #include <iomanip>
27 #include <iostream>
28 #include <memory>
29 #include <sstream>
30 #include <string>
31 #include <vector>
32 
33 namespace art {
34 class BinaryFileOutput;
35 }
36 
38 using fhicl::ParameterSet;
39 
43 class art::BinaryFileOutput final : public OutputModule
44 {
45 public:
57  explicit BinaryFileOutput(ParameterSet const& ps);
58 
62  ~BinaryFileOutput() override;
63 
64 private:
65  void beginJob() override;
66 
67  void endJob() override;
68 
69  void write(EventPrincipal& /*ep*/) override;
70 
71  void writeRun(RunPrincipal& /*r*/) override{};
72  void writeSubRun(SubRunPrincipal& /*sr*/) override{};
73 
74  void initialize_FILE_();
75 
76  void deinitialize_FILE_();
77 
78  bool readParameterSet_(fhicl::ParameterSet const& pset);
79 
80 private:
81  BinaryFileOutput(BinaryFileOutput const&) = delete;
83  BinaryFileOutput& operator=(BinaryFileOutput const&) = delete;
84  BinaryFileOutput& operator=(BinaryFileOutput&&) = delete;
85 
86  std::string name_ = "BinaryFileOutput";
87  std::string file_name_ = "/tmp/artdaqdemo.binary";
88  bool do_direct_ = false;
89  int fd_ = -1; // Used for direct IO
90  std::unique_ptr<std::ofstream> file_ptr_ = {nullptr};
91  art::FileStatsCollector fstats_;
92 };
93 
95  : OutputModule(ps), fstats_{name_, processName()}
96 {
97  TLOG(TLVL_DEBUG + 32) << "Begin: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
98  readParameterSet_(ps);
99  TLOG(TLVL_DEBUG + 32) << "End: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
100 }
101 
102 art::BinaryFileOutput::~BinaryFileOutput() { TLOG(TLVL_DEBUG + 32) << "Begin/End: BinaryFileOutput::~BinaryFileOutput()\n"; }
103 
104 void art::BinaryFileOutput::beginJob()
105 {
106  TLOG(TLVL_DEBUG + 32) << "Begin: BinaryFileOutput::beginJob()\n";
107  initialize_FILE_();
108  TLOG(TLVL_DEBUG + 32) << "End: BinaryFileOutput::beginJob()\n";
109 }
110 
111 void art::BinaryFileOutput::endJob()
112 {
113  TLOG(TLVL_DEBUG + 32) << "Begin: BinaryFileOutput::endJob()\n";
114  deinitialize_FILE_();
115  TLOG(TLVL_DEBUG + 32) << "End: BinaryFileOutput::endJob()\n";
116 }
117 
118 void art::BinaryFileOutput::initialize_FILE_()
119 {
120  std::string file_name = PostCloseFileRenamer{fstats_}.applySubstitutions(file_name_);
121  if (do_direct_)
122  {
123  fd_ = open(file_name.c_str(), O_WRONLY | O_CREAT | O_DIRECT, 0660); // O_DIRECT - ref. artdaq-core/Core/QuickVec.hh:#define QV_ALIGN 512 and artdaq issue #24437
124  TLOG(TLVL_DEBUG + 33) << "initialize_FILE_ fd_=" << fd_;
125  }
126  else
127  {
128  file_ptr_ = std::make_unique<std::ofstream>(file_name, std::ofstream::binary);
129  TLOG(TLVL_DEBUG + 33) << "BinaryFileOutput::initialize_FILE_ file_ptr_=" << static_cast<void*>(file_ptr_.get()) << " errno=" << errno;
130  // file_ptr_->rdbuf()->pubsetbuf(0, 0);
131  }
132  fstats_.recordFileOpen();
133 }
134 
135 void art::BinaryFileOutput::deinitialize_FILE_()
136 {
137  if (do_direct_)
138  {
139  close(fd_);
140  fd_ = -1;
141  }
142  else
143  {
144  file_ptr_.reset(nullptr);
145  }
146  fstats_.recordFileClose();
147 }
148 
149 bool art::BinaryFileOutput::readParameterSet_(fhicl::ParameterSet const& pset)
150 {
151  TLOG(TLVL_DEBUG + 32) << name_ << "BinaryFileOutput::readParameterSet_ method called with "
152  << "ParameterSet = \"" << pset.to_string() << "\".";
153  // determine the data sending parameters
154  try
155  {
156  file_name_ = pset.get<std::string>("fileName");
157  }
158  catch (...)
159  {
160  TLOG(TLVL_ERROR) << name_ << "The fileName parameter was not specified "
161  << "in the BinaryFileOutput initialization PSet: \"" << pset.to_string() << "\".";
162  return false;
163  }
164  do_direct_ = pset.get<bool>("directIO", false);
165  // determine the data sending parameters
166  return true;
167 }
168 
169 #define USE_STATIC_BUFFER 0
170 #if USE_STATIC_BUFFER == 1
171 static unsigned char static_buffer[0xa00000];
172 #endif
173 
174 void art::BinaryFileOutput::write(EventPrincipal& ep)
175 {
176  using RawEvent = artdaq::Fragments;
177  using RawEvents = std::vector<RawEvent>;
178  using RawEventHandle = art::Handle<RawEvent>;
179  using RawEventHandles = std::vector<RawEventHandle>;
180 
181  auto result_handles = std::vector<art::GroupQueryResult>();
182  auto const& wrapped = art::WrappedTypeID::make<RawEvent>();
183  ModuleContext const mc{moduleDescription()};
184  ProcessTag const processTag{"", mc.moduleDescription().processName()};
185 
186  result_handles = ep.getMany(mc, wrapped, art::MatchAllSelector{}, processTag);
187 
188  for (auto const& result_handle : result_handles)
189  {
190  auto const raw_event_handle = RawEventHandle(result_handle);
191 
192  if (!raw_event_handle.isValid())
193  {
194  continue;
195  }
196 
197  for (auto const& fragment : *raw_event_handle)
198  {
199  auto sequence_id = fragment.sequenceID();
200  auto fragid_id = fragment.fragmentID();
201  TLOG(TLVL_DEBUG + 33) << "BinaryFileOutput::write seq=" << sequence_id << " frag=" << fragid_id << " "
202  << reinterpret_cast<const void*>(fragment.headerBeginBytes()) << " bytes=0x" << std::hex // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
203  << fragment.sizeBytes() << " start";
204  if (do_direct_)
205  {
206  ssize_t sts = ::write(fd_, reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
207  TLOG(TLVL_DEBUG + 34) << "BinaryFileOutput::write seq=" << sequence_id << " frag=" << fragid_id << " done sts=" << sts
208  << " errno=" << errno;
209  }
210  else
211  {
212 #if USE_STATIC_BUFFER == 1
213  file_ptr_->write((char*)static_buffer, fragment.sizeBytes());
214 #else
215  file_ptr_->write(reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes()); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
216 #endif
217  TLOG(TLVL_DEBUG + 34) << "BinaryFileOutput::write seq=" << sequence_id << " frag=" << fragid_id << " done errno=" << errno;
218  }
219  }
220  }
221  fstats_.recordEvent(ep.eventID());
222 }
223 
224 DEFINE_ART_MODULE(art::BinaryFileOutput) // NOLINT(performance-unnecessary-value-param)
~BinaryFileOutput() override
BinaryFileOutput Destructor.
BinaryFileOutput(ParameterSet const &ps)
BinaryFileOutput Constructor.
The BinaryFileOutput module streams art Events to a binary file, bypassing ROOT.