artdaq  v2_03_00
 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  file_ptr_->rdbuf()->pubsetbuf(0, 0);
135  }
136  fstats_.recordFileOpen();
137 }
138 
139 void
140 art::BinaryFileOutput::
141 deinitialize_FILE_()
142 {
143  if (do_direct_)
144  {
145  close(fd_);
146  fd_ = -1;
147  }
148  else
149  file_ptr_.reset(nullptr);
150  fstats_.recordFileClose();
151 }
152 
153 bool
154 art::BinaryFileOutput::
155 readParameterSet_(fhicl::ParameterSet const& pset)
156 {
157  TLOG_DEBUG(name_) << "BinaryFileOutput::readParameterSet_ method called with "
158  << "ParameterSet = \"" << pset.to_string()
159  << "\"." << TLOG_ENDL;
160  // determine the data sending parameters
161  try
162  {
163  file_name_ = pset.get<std::string>("fileName");
164  }
165  catch (...)
166  {
167  TLOG_ERROR(name_)
168  << "The fileName parameter was not specified "
169  << "in the BinaryMPIOutput initialization PSet: \""
170  << pset.to_string() << "\"." << TLOG_ENDL;
171  return false;
172  }
173  do_direct_ = pset.get<bool>("directIO", false);
174  // determine the data sending parameters
175  return true;
176 }
177 
178 #define USE_STATIC_BUFFER 0
179 #if USE_STATIC_BUFFER == 1
180 static unsigned char static_buffer[0xa00000];
181 #endif
182 
183 void
184 art::BinaryFileOutput::
185 write(EventPrincipal& ep)
186 {
187  using RawEvent = artdaq::Fragments;
188  using RawEvents = std::vector<RawEvent>;
189  using RawEventHandle = art::Handle<RawEvent>;
190  using RawEventHandles = std::vector<RawEventHandle>;
191 
192  auto result_handles = std::vector<art::GroupQueryResult>();
193  ep.getManyByType(art::TypeID(typeid(RawEvent)), result_handles);
194 
195  for (auto const& result_handle : result_handles)
196  {
197  auto const raw_event_handle = RawEventHandle(result_handle);
198 
199  if (!raw_event_handle.isValid())
200  continue;
201 
202  for (auto const& fragment: *raw_event_handle)
203  {
204  auto sequence_id = fragment.sequenceID();
205  auto fragid_id = fragment.fragmentID();
206  TRACE( 2, "BinaryFileOutput::write seq=%lu frag=%i %p bytes=0x%lx start"
207  , sequence_id, fragid_id, fragment.headerBeginBytes(), fragment.sizeBytes() );
208  if (do_direct_)
209  {
210  ssize_t sts = ::write(fd_, reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
211  TRACE( 3, "BinaryFileOutput::write seq=%lu frag=%i done sts=%ld errno=%d"
212  , sequence_id, fragid_id, sts, errno );
213  }
214  else
215  {
216 # if USE_STATIC_BUFFER == 1
217  file_ptr_->write((char*)static_buffer, fragment.sizeBytes());
218 # else
219  file_ptr_->write(reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
220 # endif
221  TRACE( 3, "BinaryFileOutput::write seq=%lu frag=%i done errno=%d"
222  , sequence_id, fragid_id, errno );
223  }
224  }
225  }
226  fstats_.recordEvent(ep.id());
227  return;
228 }
229 
230 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.