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 TRACE( 4, "BinaryFileOutput::initialize_FILE_ fd_=%d", fd_ );
00130 }
00131 else
00132 {
00133 file_ptr_ = std::make_unique<std::ofstream>(file_name, std::ofstream::binary);
00134 file_ptr_->rdbuf()->pubsetbuf(0, 0);
00135 }
00136 fstats_.recordFileOpen();
00137 }
00138
00139 void
00140 art::BinaryFileOutput::
00141 deinitialize_FILE_()
00142 {
00143 if (do_direct_)
00144 {
00145 close(fd_);
00146 fd_ = -1;
00147 }
00148 else
00149 file_ptr_.reset(nullptr);
00150 fstats_.recordFileClose();
00151 }
00152
00153 bool
00154 art::BinaryFileOutput::
00155 readParameterSet_(fhicl::ParameterSet const& pset)
00156 {
00157 TLOG_DEBUG(name_) << "BinaryFileOutput::readParameterSet_ method called with "
00158 << "ParameterSet = \"" << pset.to_string()
00159 << "\"." << TLOG_ENDL;
00160
00161 try
00162 {
00163 file_name_ = pset.get<std::string>("fileName");
00164 }
00165 catch (...)
00166 {
00167 TLOG_ERROR(name_)
00168 << "The fileName parameter was not specified "
00169 << "in the BinaryMPIOutput initialization PSet: \""
00170 << pset.to_string() << "\"." << TLOG_ENDL;
00171 return false;
00172 }
00173 do_direct_ = pset.get<bool>("directIO", false);
00174
00175 return true;
00176 }
00177
00178 #define USE_STATIC_BUFFER 0
00179 #if USE_STATIC_BUFFER == 1
00180 static unsigned char static_buffer[0xa00000];
00181 #endif
00182
00183 void
00184 art::BinaryFileOutput::
00185 write(EventPrincipal& ep)
00186 {
00187 using RawEvent = artdaq::Fragments;
00188 using RawEvents = std::vector<RawEvent>;
00189 using RawEventHandle = art::Handle<RawEvent>;
00190 using RawEventHandles = std::vector<RawEventHandle>;
00191
00192 auto result_handles = std::vector<art::GroupQueryResult>();
00193 ep.getManyByType(art::TypeID(typeid(RawEvent)), result_handles);
00194
00195 for (auto const& result_handle : result_handles)
00196 {
00197 auto const raw_event_handle = RawEventHandle(result_handle);
00198
00199 if (!raw_event_handle.isValid())
00200 continue;
00201
00202 for (auto const& fragment: *raw_event_handle)
00203 {
00204 auto sequence_id = fragment.sequenceID();
00205 auto fragid_id = fragment.fragmentID();
00206 TRACE( 2, "BinaryFileOutput::write seq=%lu frag=%i %p bytes=0x%lx start"
00207 , sequence_id, fragid_id, fragment.headerBeginBytes(), fragment.sizeBytes() );
00208 if (do_direct_)
00209 {
00210 ssize_t sts = ::write(fd_, reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
00211 TRACE( 3, "BinaryFileOutput::write seq=%lu frag=%i done sts=%ld errno=%d"
00212 , sequence_id, fragid_id, sts, errno );
00213 }
00214 else
00215 {
00216 # if USE_STATIC_BUFFER == 1
00217 file_ptr_->write((char*)static_buffer, fragment.sizeBytes());
00218 # else
00219 file_ptr_->write(reinterpret_cast<const char*>(fragment.headerBeginBytes()), fragment.sizeBytes());
00220 # endif
00221 TRACE( 3, "BinaryFileOutput::write seq=%lu frag=%i done errno=%d"
00222 , sequence_id, fragid_id, errno );
00223 }
00224 }
00225 }
00226 fstats_.recordEvent(ep.id());
00227 return;
00228 }
00229
00230 DEFINE_ART_MODULE(art::BinaryFileOutput)