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