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