artdaq  v3_06_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 <stdio.h>
22 #include <unistd.h>
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 public:
54  explicit BinaryFileOutput(ParameterSet const& ps);
55 
59  virtual ~BinaryFileOutput();
60 
61 private:
62  void beginJob() override;
63 
64  void endJob() override;
65 
66  void write(EventPrincipal&) override;
67 
68  void writeRun(RunPrincipal&) override {};
69  void writeSubRun(SubRunPrincipal&) override {};
70 
71  void initialize_FILE_();
72 
73  void deinitialize_FILE_();
74 
75  bool readParameterSet_(fhicl::ParameterSet const& pset);
76 
77 private:
78  std::string name_ = "BinaryFileOutput";
79  std::string file_name_ = "/tmp/artdaqdemo.binary";
80  bool do_direct_ = false;
81  int fd_ = -1; // Used for direct IO
82  std::unique_ptr<std::ofstream> file_ptr_ = {nullptr};
83  art::FileStatsCollector fstats_;
84 };
85 
86 art::BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps) : OutputModule(ps), fstats_{name_, processName()} {
87  TLOG(TLVL_DEBUG) << "Begin: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
88  readParameterSet_(ps);
89  TLOG(TLVL_DEBUG) << "End: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
90 }
91 
92 art::BinaryFileOutput::~BinaryFileOutput() { TLOG(TLVL_DEBUG) << "Begin/End: BinaryFileOutput::~BinaryFileOutput()\n"; }
93 
94 void art::BinaryFileOutput::beginJob() {
95  TLOG(TLVL_DEBUG) << "Begin: BinaryFileOutput::beginJob()\n";
96  initialize_FILE_();
97  TLOG(TLVL_DEBUG) << "End: BinaryFileOutput::beginJob()\n";
98 }
99 
100 void art::BinaryFileOutput::endJob() {
101  TLOG(TLVL_DEBUG) << "Begin: BinaryFileOutput::endJob()\n";
102  deinitialize_FILE_();
103  TLOG(TLVL_DEBUG) << "End: BinaryFileOutput::endJob()\n";
104 }
105 
106 void art::BinaryFileOutput::initialize_FILE_() {
107  std::string file_name = PostCloseFileRenamer{ fstats_ }.applySubstitutions(file_name_);
108  if (do_direct_) {
109  fd_ = open(file_name.c_str(), O_WRONLY | O_CREAT | O_DIRECT, 0660);
110  TLOG(TLVL_TRACE) << "initialize_FILE_ fd_=" << fd_;
111  } else {
112  file_ptr_ = std::make_unique<std::ofstream>(file_name, std::ofstream::binary);
113  TLOG(TLVL_TRACE) << "BinaryFileOutput::initialize_FILE_ file_ptr_=" << (void*)file_ptr_.get() << " errno=" << errno;
114  //file_ptr_->rdbuf()->pubsetbuf(0, 0);
115  }
116  fstats_.recordFileOpen();
117 }
118 
119 void art::BinaryFileOutput::deinitialize_FILE_() {
120  if (do_direct_) {
121  close(fd_);
122  fd_ = -1;
123  } else
124  file_ptr_.reset(nullptr);
125  fstats_.recordFileClose();
126 }
127 
128 bool art::BinaryFileOutput::readParameterSet_(fhicl::ParameterSet const& pset) {
129  TLOG(TLVL_DEBUG) << name_ << "BinaryFileOutput::readParameterSet_ method called with "
130  << "ParameterSet = \"" << pset.to_string() << "\".";
131  // determine the data sending parameters
132  try {
133  file_name_ = pset.get<std::string>("fileName");
134  } catch (...) {
135  TLOG(TLVL_ERROR) << name_ << "The fileName parameter was not specified "
136  << "in the BinaryFileOutput initialization PSet: \"" << pset.to_string() << "\".";
137  return false;
138  }
139  do_direct_ = pset.get<bool>("directIO", false);
140  // determine the data sending parameters
141  return true;
142 }
143 
144 #define USE_STATIC_BUFFER 0
145 #if USE_STATIC_BUFFER == 1
146 static unsigned char static_buffer[0xa00000];
147 #endif
148 
149 void art::BinaryFileOutput::write(EventPrincipal& ep) {
150  using RawEvent = artdaq::Fragments;
151  using RawEvents = std::vector<RawEvent>;
152  using RawEventHandle = art::Handle<RawEvent>;
153  using RawEventHandles = std::vector<RawEventHandle>;
154 
155  auto result_handles = std::vector<art::GroupQueryResult>();
156  auto const& wrapped = art::WrappedTypeID::make<RawEvent>();
157 #if ART_HEX_VERSION >= 0x30000
158  ModuleContext const mc{moduleDescription()};
159  ProcessTag const processTag{"", mc.moduleDescription().processName()};
160 
161  result_handles = ep.getMany(mc, wrapped, art::MatchAllSelector{}, processTag);
162 #else
163  result_handles = ep.getMany(wrapped, art::MatchAllSelector{});
164 #endif
165 
166  for (auto const& result_handle : result_handles) {
167  auto const raw_event_handle = RawEventHandle(result_handle);
168 
169  if (!raw_event_handle.isValid()) continue;
170 
171  for (auto const& fragment : *raw_event_handle) {
172  auto sequence_id = fragment.sequenceID();
173  auto fragid_id = fragment.fragmentID();
174  TLOG(TLVL_TRACE) << "BinaryFileOutput::write seq=" << sequence_id << " frag=" << fragid_id << " "
175  << reinterpret_cast<const void*>(fragment.headerBeginBytes()) << " bytes=0x" << std::hex
176  << fragment.sizeBytes() << " start";
177  if (do_direct_) {
178  ssize_t sts = ::write(fd_, reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
179  TLOG(5) << "BinaryFileOutput::write seq=" << sequence_id << " frag=" << fragid_id << " done sts=" << sts
180  << " errno=" << errno;
181  } else {
182 # if USE_STATIC_BUFFER == 1
183  file_ptr_->write((char*)static_buffer, fragment.sizeBytes());
184 # else
185  file_ptr_->write(reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
186 # endif
187  TLOG(5) << "BinaryFileOutput::write seq=" << sequence_id << " frag=" << fragid_id << " done errno=" << errno;
188  }
189  }
190  }
191 #if ART_HEX_VERSION < 0x30000
192  fstats_.recordEvent(ep.id());
193 #else
194  fstats_.recordEvent(ep.eventID());
195 #endif
196  return;
197 }
198 
199 DEFINE_ART_MODULE(art::BinaryFileOutput)
virtual ~BinaryFileOutput()
BinaryFileOutput Destructor.
BinaryFileOutput(ParameterSet const &ps)
BinaryFileOutput Constructor.
The BinaryFileOutput module streams art Events to a binary file, bypassing ROOT.