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 FDEBUG(1) << "Begin: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
00094 readParameterSet_(ps);
00095 FDEBUG(1) << "End: BinaryFileOutput::BinaryFileOutput(ParameterSet const& ps)\n";
00096 }
00097
00098 art::BinaryFileOutput::
00099 ~BinaryFileOutput()
00100 {
00101 FDEBUG(1) << "Begin/End: BinaryFileOutput::~BinaryFileOutput()\n";
00102 }
00103
00104 void
00105 art::BinaryFileOutput::
00106 beginJob()
00107 {
00108 FDEBUG(1) << "Begin: BinaryFileOutput::beginJob()\n";
00109 initialize_FILE_();
00110 FDEBUG(1) << "End: BinaryFileOutput::beginJob()\n";
00111 }
00112
00113 void
00114 art::BinaryFileOutput::
00115 endJob()
00116 {
00117 FDEBUG(1) << "Begin: BinaryFileOutput::endJob()\n";
00118 deinitialize_FILE_();
00119 FDEBUG(1) << "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_ARB(4, "BinaryFileOutput") << "initialize_FILE_ fd_=" << fd_ << TLOG_ENDL;
00132 }
00133 else
00134 {
00135 file_ptr_ = std::make_unique<std::ofstream>(file_name, std::ofstream::binary);
00136 TRACE(4, "BinaryFileOutput::initialize_FILE_ file_ptr_=%p errno=%d", (void*)file_ptr_.get(), 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_DEBUG(name_) << "BinaryFileOutput::readParameterSet_ method called with "
00161 << "ParameterSet = \"" << pset.to_string()
00162 << "\"." << TLOG_ENDL;
00163
00164 try
00165 {
00166 file_name_ = pset.get<std::string>("fileName");
00167 }
00168 catch (...)
00169 {
00170 TLOG_ERROR(name_)
00171 << "The fileName parameter was not specified "
00172 << "in the BinaryFileOutput initialization PSet: \""
00173 << pset.to_string() << "\"." << TLOG_ENDL;
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 #if ART_HEX_VERSION < 0x20906
00197 ep.getManyByType(art::TypeID(typeid(RawEvent)), result_handles);
00198 #else
00199 auto const& wrapped = art::WrappedTypeID::make<RawEvent>();
00200 result_handles = ep.getMany(wrapped, art::MatchAllSelector{});
00201 #endif
00202
00203 for (auto const& result_handle : result_handles)
00204 {
00205 auto const raw_event_handle = RawEventHandle(result_handle);
00206
00207 if (!raw_event_handle.isValid())
00208 continue;
00209
00210 for (auto const& fragment : *raw_event_handle)
00211 {
00212 auto sequence_id = fragment.sequenceID();
00213 auto fragid_id = fragment.fragmentID();
00214 TRACE(4, "BinaryFileOutput::write seq=%lu frag=%i %p bytes=0x%lx start"
00215 , sequence_id, fragid_id, fragment.headerBeginBytes(), fragment.sizeBytes());
00216 if (do_direct_)
00217 {
00218 ssize_t sts = ::write(fd_, reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
00219 TRACE(5, "BinaryFileOutput::write seq=%lu frag=%i done sts=%ld errno=%d"
00220 , sequence_id, fragid_id, sts, errno);
00221 }
00222 else
00223 {
00224 # if USE_STATIC_BUFFER == 1
00225 file_ptr_->write((char*)static_buffer, fragment.sizeBytes());
00226 # else
00227 file_ptr_->write(reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
00228 # endif
00229 TRACE(5, "BinaryFileOutput::write seq=%lu frag=%i done errno=%d"
00230 , sequence_id, fragid_id, errno);
00231 }
00232 }
00233 }
00234 fstats_.recordEvent(ep.id());
00235 return;
00236 }
00237
00238 DEFINE_ART_MODULE(art::BinaryFileOutput)