00001
00002
00003 #define TRACE_NAME "BinaryFileOutput"
00004
00005 #include "art/Framework/Core/ModuleMacros.h"
00006 #include "art/Framework/Core/OutputModule.h"
00007 #include "art/Framework/Principal/EventPrincipal.h"
00008 #include "art/Framework/Principal/RunPrincipal.h"
00009 #include "art/Framework/Principal/SubRunPrincipal.h"
00010 #include "art/Framework/Principal/Handle.h"
00011 #include "art/Persistency/Common/GroupQueryResult.h"
00012 #include "art/Framework/IO/FileStatsCollector.h"
00013 #include "art/Framework/IO/PostCloseFileRenamer.h"
00014 #include "canvas/Utilities/DebugMacros.h"
00015 #include "canvas/Utilities/Exception.h"
00016 #include "fhiclcpp/ParameterSet.h"
00017
00018 #include "artdaq-core/Data/Fragment.hh"
00019 #include "artdaq/DAQdata/Globals.hh"
00020
00021 #include <iomanip>
00022 #include <iostream>
00023 #include <fstream>
00024 #include <sstream>
00025 #include <string>
00026 #include <vector>
00027 #include <memory>
00028 #include <unistd.h>
00029 #include <stdio.h>
00030
00031 namespace art
00032 {
00033 class BinaryFileOutput;
00034 }
00035
00036 using art::BinaryFileOutput;
00037 using fhicl::ParameterSet;
00038
00042 class art::BinaryFileOutput final: public OutputModule
00043 {
00044 public:
00056 explicit BinaryFileOutput(ParameterSet const& ps);
00057
00061 virtual ~BinaryFileOutput();
00062
00063 private:
00064 void beginJob() override;
00065
00066 void endJob() override;
00067
00068 void write(EventPrincipal&) override;
00069
00070 void writeRun(RunPrincipal&) override {};
00071 void writeSubRun(SubRunPrincipal&) override {};
00072
00073 void initialize_FILE_();
00074
00075 void deinitialize_FILE_();
00076
00077 bool readParameterSet_(fhicl::ParameterSet const& pset);
00078
00079 private:
00080 std::string name_ = "BinaryFileOutput";
00081 std::string file_name_ = "/tmp/artdaqdemo.binary";
00082 bool do_direct_ = false;
00083 int fd_ = -1;
00084 std::unique_ptr<std::ofstream> file_ptr_ = {nullptr};
00085 art::FileStatsCollector fstats_;
00086 };
00087
00088 art::BinaryFileOutput::
00089 BinaryFileOutput(ParameterSet const& ps)
00090 : OutputModule(ps)
00091 , fstats_{ name_, processName() }
00092 {
00093 TLOG(TLVL_DEBUG) << "Begin: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
00094 readParameterSet_(ps);
00095 TLOG(TLVL_DEBUG) << "End: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
00096 }
00097
00098 art::BinaryFileOutput::
00099 ~BinaryFileOutput()
00100 {
00101 TLOG(TLVL_DEBUG) << "Begin/End: BinaryFileOutput::~BinaryFileOutput()\n";
00102 }
00103
00104 void
00105 art::BinaryFileOutput::
00106 beginJob()
00107 {
00108 TLOG(TLVL_DEBUG) << "Begin: BinaryFileOutput::beginJob()\n";
00109 initialize_FILE_();
00110 TLOG(TLVL_DEBUG) << "End: BinaryFileOutput::beginJob()\n";
00111 }
00112
00113 void
00114 art::BinaryFileOutput::
00115 endJob()
00116 {
00117 TLOG(TLVL_DEBUG) << "Begin: BinaryFileOutput::endJob()\n";
00118 deinitialize_FILE_();
00119 TLOG(TLVL_DEBUG) << "End: BinaryFileOutput::endJob()\n";
00120 }
00121
00122
00123 void
00124 art::BinaryFileOutput::
00125 initialize_FILE_()
00126 {
00127 std::string file_name = PostCloseFileRenamer{ fstats_ }.applySubstitutions(file_name_);
00128 if (do_direct_)
00129 {
00130 fd_ = open(file_name.c_str(), O_WRONLY | O_CREAT | O_DIRECT, 0660);
00131 TLOG(TLVL_TRACE) << "initialize_FILE_ fd_=" << fd_;
00132 }
00133 else
00134 {
00135 file_ptr_ = std::make_unique<std::ofstream>(file_name, std::ofstream::binary);
00136 TLOG(TLVL_TRACE) << "BinaryFileOutput::initialize_FILE_ file_ptr_=" << (void*)file_ptr_.get() << " errno=" << errno;
00137
00138 }
00139 fstats_.recordFileOpen();
00140 }
00141
00142 void
00143 art::BinaryFileOutput::
00144 deinitialize_FILE_()
00145 {
00146 if (do_direct_)
00147 {
00148 close(fd_);
00149 fd_ = -1;
00150 }
00151 else
00152 file_ptr_.reset(nullptr);
00153 fstats_.recordFileClose();
00154 }
00155
00156 bool
00157 art::BinaryFileOutput::
00158 readParameterSet_(fhicl::ParameterSet const& pset)
00159 {
00160 TLOG(TLVL_DEBUG) << name_ << "BinaryFileOutput::readParameterSet_ method called with "
00161 << "ParameterSet = \"" << pset.to_string()
00162 << "\".";
00163
00164 try
00165 {
00166 file_name_ = pset.get<std::string>("fileName");
00167 }
00168 catch (...)
00169 {
00170 TLOG(TLVL_ERROR) << name_
00171 << "The fileName parameter was not specified "
00172 << "in the BinaryFileOutput initialization PSet: \""
00173 << pset.to_string() << "\".";
00174 return false;
00175 }
00176 do_direct_ = pset.get<bool>("directIO", false);
00177
00178 return true;
00179 }
00180
00181 #define USE_STATIC_BUFFER 0
00182 #if USE_STATIC_BUFFER == 1
00183 static unsigned char static_buffer[0xa00000];
00184 #endif
00185
00186 void
00187 art::BinaryFileOutput::
00188 write(EventPrincipal& ep)
00189 {
00190 using RawEvent = artdaq::Fragments;
00191 using RawEvents = std::vector<RawEvent>;
00192 using RawEventHandle = art::Handle<RawEvent>;
00193 using RawEventHandles = std::vector<RawEventHandle>;
00194
00195 auto result_handles = std::vector<art::GroupQueryResult>();
00196 auto const& wrapped = art::WrappedTypeID::make<RawEvent>();
00197 result_handles = ep.getMany(wrapped, art::MatchAllSelector{});
00198
00199 for (auto const& result_handle : result_handles)
00200 {
00201 auto const raw_event_handle = RawEventHandle(result_handle);
00202
00203 if (!raw_event_handle.isValid())
00204 continue;
00205
00206 for (auto const& fragment : *raw_event_handle)
00207 {
00208 auto sequence_id = fragment.sequenceID();
00209 auto fragid_id = fragment.fragmentID();
00210 TLOG(TLVL_TRACE) << "BinaryFileOutput::write seq=" << sequence_id
00211 << " frag=" << fragid_id << " " << reinterpret_cast<const void*>(fragment.headerBeginBytes())
00212 << " bytes=0x" << std::hex << fragment.sizeBytes() << " start";
00213 if (do_direct_)
00214 {
00215 ssize_t sts = ::write(fd_, reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
00216 TLOG(5) << "BinaryFileOutput::write seq=" << sequence_id << " frag=" << fragid_id << " done sts=" << sts << " errno=" << errno;
00217 }
00218 else
00219 {
00220 # if USE_STATIC_BUFFER == 1
00221 file_ptr_->write((char*)static_buffer, fragment.sizeBytes());
00222 # else
00223 file_ptr_->write(reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
00224 # endif
00225 TLOG(5) << "BinaryFileOutput::write seq=" << sequence_id << " frag=" << fragid_id << " done errno=" << errno;
00226 }
00227 }
00228 }
00229 fstats_.recordEvent(ep.id());
00230 return;
00231 }
00232
00233 DEFINE_ART_MODULE(art::BinaryFileOutput)