7 #include <framework/modules/rootio/SeqRootOutputModule.h>
8 #include <framework/datastore/DataStore.h>
9 #include <framework/core/Environment.h>
15 #include <TVirtualStreamerInfo.h>
32 setDescription(
"Save a sequential ROOT file (non-standard I/O format used in DAQ). See https://confluence.desy.de/display/BI/Software+PersistencyModules for further information and a comparison with the .root format.");
34 m_msghandler =
nullptr;
35 m_streamerinfo =
nullptr;
36 m_streamerinfo_size = 0;
38 vector<string> emptyvector;
40 addParam(
"outputFileName" , m_outputFileName,
41 "Output file name. Add a .gz suffix to save a gzip-compressed file. Parameter can be overridden using the -o argument to basf2.",
42 string(
"SeqRootOutput.sroot"));
43 addParam(
"compressionLevel", m_compressionLevel,
44 "Compression Level: 0 for no, 1 for low, 9 for high compression. Level 1 usually reduces size by 50%, higher levels have no noticable effect. NOTE: Because of a ROOT bug ( https://sft.its.cern.ch/jira/browse/ROOT-4550 ), this option currently causes memory leaks and is disabled.",
46 addParam(
"saveObjs", m_saveObjs,
"List of objects/arrays to be saved", emptyvector);
47 addParam(
"fileNameIsPattern", m_fileNameIsPattern,
"If true interpret the output filename as a boost::format pattern "
48 "instead of the standard where subsequent files are named .sroot-N. For example 'myfile-f%08d.sroot'",
false);
52 SeqRootOutputModule::~SeqRootOutputModule()
54 if (m_streamerinfo !=
nullptr)
delete m_streamerinfo;
57 void SeqRootOutputModule::initialize()
59 const std::string& outputFileArgument = Environment::Instance().getOutputFileOverride();
60 if (!outputFileArgument.empty())
61 m_outputFileName = outputFileArgument;
67 m_msghandler =
new MsgHandler(m_compressionLevel);
71 m_streamer->setStreamingObjects(m_saveObjs);
76 m_file =
new SeqFile(m_outputFileName.c_str(),
"w", m_streamerinfo, m_streamerinfo_size, m_fileNameIsPattern);
78 B2INFO(
"SeqRootOutput: initialized.");
82 void SeqRootOutputModule::beginRun()
86 gettimeofday(&m_t0,
nullptr);
91 B2INFO(
"SeqRootOutput: beginRun called.");
94 void SeqRootOutputModule::event()
97 EvtMessage* msg = m_streamer->streamDataStore(
false);
100 int stat = m_file->write(msg->
buffer());
106 double dsize = (double)stat / 1000.0;
108 m_size2 += dsize * dsize;
112 void SeqRootOutputModule::endRun()
117 gettimeofday(&m_tend,
nullptr);
118 auto etime = (double)((m_tend.tv_sec - m_t0.tv_sec) * 1000000 +
119 (m_tend.tv_usec - m_t0.tv_usec));
124 double flowmb = m_size / etime * 1000.0;
125 double avesize = m_size / (double)m_nevt;
126 double avesize2 = m_size2 / (double)m_nevt;
127 double sigma2 = avesize2 - avesize * avesize;
128 double sigma = sqrt(sigma2);
130 B2INFO(
"SeqRootOutput : " << m_nevt <<
" events written with total bytes of " << m_size <<
" kB");
131 B2INFO(
"SeqRootOutput : flow rate = " << flowmb <<
" (MB/s)");
132 B2INFO(
"SeqRootOutput : event size = " << avesize <<
" +- " << sigma <<
" (kB)");
134 B2INFO(
"SeqRootOutput: endRun done.");
138 void SeqRootOutputModule::terminate()
144 B2INFO(
"terminate called");
148 void SeqRootOutputModule::getStreamerInfos()
156 B2FATAL(
"DataStoreStreamer : m_msghandler is NULL.");
160 TList* minilist = nullptr ;
161 for (
int durability = 0; durability < DataStore::c_NDurabilityTypes; durability++) {
164 for (
auto& iter : map) {
165 const TClass* entryClass = iter.second.objClass;
166 TVirtualStreamerInfo* vinfo = entryClass->GetStreamerInfo();
167 B2INFO(
"Recording StreamerInfo : durability " << durability <<
" : Class Name " << entryClass->GetName());
168 if (!minilist) minilist =
new TList();
169 minilist->Add(vinfo);
176 m_msghandler->add(minilist,
"StreamerInfo");
178 EvtMessage* msg = m_msghandler->encode_msg(MSG_STREAMERINFO);
179 (msg->
header())->nObjects = 1;
180 (msg->
header())->nArrays = 0;
183 m_streamerinfo_size = *((
int*)(msg->
buffer()));
186 if (m_streamerinfo_size > 0) {
187 B2INFO(
"Get StreamerInfo from DataStore : " << m_streamerinfo_size <<
"bytes");
188 if (m_streamerinfo !=
nullptr) {
189 B2FATAL(
"getStreamerInfo() is called twice in the same run ");
191 m_streamerinfo =
new char[ m_streamerinfo_size ];
193 memcpy(m_streamerinfo, msg->
buffer(), m_streamerinfo_size);
195 B2FATAL(
"Invalid size of StreamerInfo : " << m_streamerinfo_size <<
"bytes");
200 B2FATAL(
"Failed to get StreamerInfo : ");