00001 #include "OutputFileRollerTool.h"
00002
00003 #include "Event/RegistrationSequence.h"
00004
00005 #include "TString.h"
00006
00007 #include <cstdlib>
00008 #include <sys/types.h>
00009 #include <sys/stat.h>
00010 #include <unistd.h>
00011
00012 using namespace std;
00013 using namespace DayaBay;
00014
00015 OutputFileRollerTool::OutputFileRollerTool(const std::string& type,
00016 const std::string& name,
00017 const IInterface* parent)
00018 : GaudiTool(type,name,parent)
00019 , m_current_execnum(0)
00020 , m_rio(0), m_initialized(false)
00021 {
00022 declareInterface<IRegSeqVisitor>(this);
00023
00024 declareProperty("Condition",m_condition="",
00025 "Set the default condition for rolling to a new output file");
00026
00027 declareProperty("StartNumber", m_startOffset=0,
00028 "Set the starting file number offset, def=0 (first file gets 1).");
00029
00030
00031
00032
00033
00034
00035
00036
00037 }
00038
00039 OutputFileRollerTool::~OutputFileRollerTool()
00040 {
00041 }
00042
00043 StatusCode OutputFileRollerTool::_initialize()
00044 {
00045 m_initialized = true;
00046
00047
00048 StatusCode sc = this->service("RootIOCnvSvc",m_rio);
00049 if (sc.isFailure()) return sc;
00050
00051 m_filemap = m_rio->fileMap();
00052 if (!m_filemap.size()) {
00053 info () << "Output filemap is empty, nothing for me to do." << endreq;
00054 return StatusCode::SUCCESS;
00055 }
00056
00057
00058 {
00059 IRootIOSvc::FileMap::iterator it, done = m_filemap.end();
00060 for (it = m_filemap.begin(); it != done; ++it) {
00061 string fname = Form(it->second.c_str(),0);
00062 if (fname != it->second) {
00063 continue;
00064 }
00065
00066 string::size_type ind = it->second.rfind(".");
00067
00068 if (string::npos == ind) {
00069 ind = it->second.size();
00070 }
00071
00072
00073 fname = it->second.substr(0,ind) + "_%04d" + it->second.substr(ind);
00074 it->second = fname;
00075 }
00076 }
00077
00078
00079 if (m_condition.size()) {
00080 m_condpropmap["default"] = m_condition;
00081 }
00082
00083 {
00084
00085 ConditionPropertyMap_t::iterator it, done = m_condpropmap.end();
00086 for (it=m_condpropmap.begin(); it != done; ++it) {
00087 string stream = it->first;
00088 string condition = it->second;
00089
00090 if (stream != "default") {
00091 IRootIOSvc::FileMap::iterator fit = m_filemap.find(stream);
00092 if (fit == m_filemap.end()) {
00093 error() << "Condition \"" << condition
00094 << "\" for stream \"" << stream
00095 << "\" has no output file. "
00096 << "An entry can be specified with nuwa.py's"
00097 << " -O/--output-stream option"
00098 << endreq;
00099 return StatusCode::FAILURE;
00100 }
00101 }
00102
00103 string::size_type clen = condition.size();
00104 if (!clen) {
00105 error() << "Given a null condition for stream \""
00106 << stream << "\"" << endreq;
00107 return StatusCode::FAILURE;
00108 }
00109 int size = atoi(condition.substr(0,clen-1).c_str());
00110 char unit = condition[clen-1];
00111 ConditionData cd = ConditionData(size,unit);
00112 cd.cycles = size;
00113 m_cdmap[stream] = cd;
00114 info() << "Condition for stream " << stream << ": " << size << unit << endreq;
00115 sc = this->roll(stream,m_cdmap[stream]);
00116 if (sc.isFailure()) return sc;
00117 }
00118 }
00119
00120 return StatusCode::SUCCESS;
00121 }
00122 StatusCode OutputFileRollerTool::roll(std::string stream, ConditionData& cd)
00123 {
00124 ++cd.count;
00125
00126 IRootIOSvc::FileMap::iterator fit = m_filemap.find(stream);
00127 if (fit == m_filemap.end()) {
00128 error() << "Failed to find output filespec for \"" << stream << "\"" << endreq;
00129 return StatusCode::FAILURE;
00130 }
00131
00132 string fname = Form(fit->second.c_str(),cd.count+m_startOffset);
00133 m_rio->associateOutput(fname.c_str(),stream.c_str());
00134
00135 info() << "Rolled " << stream << " to file " << fname << endreq;
00136
00137 return StatusCode::SUCCESS;
00138 }
00139
00140 StatusCode OutputFileRollerTool::check_m(std::string stream, ConditionData& cd)
00141 {
00142 IRootIOSvc::FileMap fm = m_rio->fileMap();
00143 IRootIOSvc::FileMap::iterator fit = fm.find(stream);
00144 if (fit == fm.end()) {
00145 error() << "Failed to find an output file for stream \"" << stream << "\""
00146 << endreq;
00147 return StatusCode::FAILURE;
00148 }
00149 string fname = fit->second;
00150 struct stat si;
00151 int err = stat(fname.c_str(), &si);
00152 if (err) {
00153 warning() << "Failed to stat " << fname
00154 << ". Maybe no output yet? Letting it go."
00155 << endreq;
00156 return StatusCode::SUCCESS;
00157 }
00158
00159 if (si.st_size/1000000 < cd.size) {
00160 return StatusCode::SUCCESS;
00161 }
00162 info () << "Reached " << cd.size << " MiB size" << endreq;
00163 return this->roll(stream,cd);
00164 }
00165
00166
00167
00168 StatusCode OutputFileRollerTool::check_e(std::string stream, ConditionData& cd)
00169 {
00170 debug() << "check_e " << stream << " " << cd.cycles << " " << (void*)&cd << endreq;
00171
00172
00173 if (cd.cycles < 0) {
00174 cd.cycles = cd.size;
00175 }
00176
00177 if (cd.cycles>0) {
00178 --cd.cycles;
00179 return StatusCode::SUCCESS;
00180 }
00181 cd.cycles = cd.size-1;
00182 info () << "Reached " << cd.size << " execution cycles" << endreq;
00183 return this->roll(stream,cd);
00184 }
00185
00186
00187
00188 StatusCode OutputFileRollerTool::check_s(std::string stream, ConditionData& cd)
00189 {
00190 RegistrationSequence* rs =
00191 get<RegistrationSequence>(RegistrationSequence::defaultLocation());
00192
00193 TimeStamp now = rs->earliest();
00194
00195
00196 if (cd.timestamp == TimeStamp::GetBOT()) {
00197 cd.timestamp = now;
00198 return StatusCode::SUCCESS;
00199 }
00200
00201 TimeStamp dt = now - cd.timestamp;
00202 int deltat = (int)((double)dt);
00203 if (deltat < cd.size) {
00204 return StatusCode::SUCCESS;
00205 }
00206
00207 cd.timestamp = now;
00208 info () << "Reached " << cd.size << " seconds at " << now << endreq;
00209 return this->roll(stream,cd);
00210 }
00211
00212 StatusCode OutputFileRollerTool::visit(DayaBay::RegistrationSequence& rs)
00213 {
00214 if (!m_initialized) {
00215
00216
00217 this->_initialize();
00218 }
00219
00220 if (!m_filemap.size()) {
00221 return StatusCode::SUCCESS;
00222 }
00223
00224 TimeStamp now = rs.earliest();
00225 ++m_current_execnum;
00226 debug() << "Execution #" << m_current_execnum << " @ " << now << endreq;
00227
00228 CDMap_t::iterator it, done = m_cdmap.end();
00229 for (it=m_cdmap.begin(); it != done; ++it) {
00230 string stream = it->first;
00231 ConditionData& cd = it->second;
00232
00233 StatusCode sc;
00234
00235 switch (cd.unit) {
00236 case 'M':
00237 sc = check_m(stream,cd);
00238 break;
00239 case 'E':
00240 sc = check_e(stream,cd);
00241 break;
00242 case 'S':
00243 sc = check_s(stream,cd);
00244 break;
00245 default:
00246 error() << "Unknown condition unit '" << cd.unit << "'"
00247 << " for stream \"" << stream << "\""
00248 << endreq;
00249 sc = StatusCode::FAILURE;
00250 }
00251 if (sc.isFailure()) return sc;
00252 }
00253 return StatusCode::SUCCESS;
00254 }