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