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