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