artdaq  v2_03_02
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Pages
BinaryFileOutput_module.cc
1 #include "art/Framework/Core/ModuleMacros.h"
2 #include "art/Framework/Core/OutputModule.h"
3 #include "art/Framework/Principal/EventPrincipal.h"
4 #include "art/Framework/Principal/RunPrincipal.h"
5 #include "art/Framework/Principal/SubRunPrincipal.h"
6 #include "art/Framework/Principal/Handle.h"
7 #include "art/Persistency/Common/GroupQueryResult.h"
8 #include "art/Framework/IO/FileStatsCollector.h"
9 #include "art/Framework/IO/PostCloseFileRenamer.h"
10 #include "canvas/Utilities/DebugMacros.h"
11 #include "canvas/Utilities/Exception.h"
12 #include "fhiclcpp/ParameterSet.h"
13 
14 #include "artdaq-core/Data/Fragment.hh"
15 #include "artdaq/DAQdata/Globals.hh"
16 
17 #define TRACE_NAME "BinaryFileOutput"
18 
19 #include <iomanip>
20 #include <iostream>
21 #include <fstream>
22 #include <sstream>
23 #include <string>
24 #include <vector>
25 #include <memory>
26 #include <unistd.h>
27 #include <stdio.h>
28 
29 namespace art
30 {
31  class BinaryFileOutput;
32 }
33 
35 using fhicl::ParameterSet;
36 
40 class art::BinaryFileOutput final: public OutputModule
41 {
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 
87 BinaryFileOutput(ParameterSet const& ps)
88  : OutputModule(ps)
89  , fstats_{name_, processName()}
90 {
91  FDEBUG(1) << "Begin: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
92  readParameterSet_(ps);
93  FDEBUG(1) << "End: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
94 }
95 
98 {
99  FDEBUG(1) << "Begin/End: BinaryFileOutput::~BinaryFileOutput()\n";
100 }
101 
102 void
103 art::BinaryFileOutput::
104 beginJob()
105 {
106  FDEBUG(1) << "Begin: BinaryFileOutput::beginJob()\n";
107  initialize_FILE_();
108  FDEBUG(1) << "End: BinaryFileOutput::beginJob()\n";
109 }
110 
111 void
112 art::BinaryFileOutput::
113 endJob()
114 {
115  FDEBUG(1) << "Begin: BinaryFileOutput::endJob()\n";
116  deinitialize_FILE_();
117  FDEBUG(1) << "End: BinaryFileOutput::endJob()\n";
118 }
119 
120 
121 void
122 art::BinaryFileOutput::
123 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);
129  TRACE( 4, "BinaryFileOutput::initialize_FILE_ fd_=%d", fd_ );
130  }
131  else
132  {
133  file_ptr_ = std::make_unique<std::ofstream>(file_name, std::ofstream::binary);
134  TRACE( 4, "BinaryFileOutput::initialize_FILE_ file_ptr_=%p errno=%d", (void*)file_ptr_.get(), errno );
135  //file_ptr_->rdbuf()->pubsetbuf(0, 0);
136  }
137  fstats_.recordFileOpen();
138 }
139 
140 void
141 art::BinaryFileOutput::
142 deinitialize_FILE_()
143 {
144  if (do_direct_)
145  {
146  close(fd_);
147  fd_ = -1;
148  }
149  else
150  file_ptr_.reset(nullptr);
151  fstats_.recordFileClose();
152 }
153 
154 bool
155 art::BinaryFileOutput::
156 readParameterSet_(fhicl::ParameterSet const& pset)
157 {
158  TLOG_DEBUG(name_) << "BinaryFileOutput::readParameterSet_ method called with "
159  << "ParameterSet = \"" << pset.to_string()
160  << "\"." << TLOG_ENDL;
161  // determine the data sending parameters
162  try
163  {
164  file_name_ = pset.get<std::string>("fileName");
165  }
166  catch (...)
167  {
168  TLOG_ERROR(name_)
169  << "The fileName parameter was not specified "
170  << "in the BinaryMPIOutput initialization PSet: \""
171  << pset.to_string() << "\"." << TLOG_ENDL;
172  return false;
173  }
174  do_direct_ = pset.get<bool>("directIO", false);
175  // determine the data sending parameters
176  return true;
177 }
178 
179 #define USE_STATIC_BUFFER 0
180 #if USE_STATIC_BUFFER == 1
181 static unsigned char static_buffer[0xa00000];
182 #endif
183 
184 void
185 art::BinaryFileOutput::
186 write(EventPrincipal& ep)
187 {
188  using RawEvent = artdaq::Fragments;
189  using RawEvents = std::vector<RawEvent>;
190  using RawEventHandle = art::Handle<RawEvent>;
191  using RawEventHandles = std::vector<RawEventHandle>;
192 
193  auto result_handles = std::vector<art::GroupQueryResult>();
194  ep.getManyByType(art::TypeID(typeid(RawEvent)), result_handles);
195 
196  for (auto const& result_handle : result_handles)
197  {
198  auto const raw_event_handle = RawEventHandle(result_handle);
199 
200  if (!raw_event_handle.isValid())
201  continue;
202 
203  for (auto const& fragment: *raw_event_handle)
204  {
205  auto sequence_id = fragment.sequenceID();
206  auto fragid_id = fragment.fragmentID();
207  TRACE( 4, "BinaryFileOutput::write seq=%lu frag=%i %p bytes=0x%lx start"
208  , sequence_id, fragid_id, fragment.headerBeginBytes(), fragment.sizeBytes() );
209  if (do_direct_)
210  {
211  ssize_t sts = ::write(fd_, reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
212  TRACE( 5, "BinaryFileOutput::write seq=%lu frag=%i done sts=%ld errno=%d"
213  , sequence_id, fragid_id, sts, 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());
221 # endif
222  TRACE( 5, "BinaryFileOutput::write seq=%lu frag=%i done errno=%d"
223  , sequence_id, fragid_id, errno );
224  }
225  }
226  }
227  fstats_.recordEvent(ep.id());
228  return;
229 }
230 
231 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.