/search.css" rel="stylesheet" type="text/css"/> /search.js">
00001 #include "DybOutputFileRoller.h" 00002 #include "Event/RegistrationSequence.h" 00003 00004 #include "TString.h" // for Form() 00005 00006 #include <cstdlib> // for atoi() 00007 #include <sys/types.h> 00008 #include <sys/stat.h> 00009 #include <unistd.h> // for stat 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 // This condition map will be a trivial one just containing 00024 // "default" as set by the global condition above. It can be made 00025 // non-trivial when/if RootIO can handle reading input streams 00026 // with non-common boundaries. See #671. 00027 00028 //declareProperty("ConditionMap",m_condpropmap, 00029 // "Set the condition map for rolling each stream to a new output file"); 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 // Get IRootIOSvc 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; // we just won't play this time 00048 } 00049 00050 // munge the output filenames where needed 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; // already has a %d code that does something 00057 } 00058 00059 string::size_type ind = it->second.rfind("."); 00060 // shouldn't happen, but whatevs, we'll roll with it 00061 if (string::npos == ind) { 00062 ind = it->second.size(); 00063 } 00064 00065 // replace filename with one that has a %d code. 00066 fname = it->second.substr(0,ind) + "_%04d" + it->second.substr(ind); 00067 it->second = fname; 00068 } 00069 } 00070 00071 // specifically set default condition if one is given 00072 if (m_condition.size()) { 00073 m_condpropmap["default"] = m_condition; 00074 } 00075 00076 { // parse conditions map and strip out any explicit conditions 00077 // with no matching entry in output file map 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; // special init, count down on this if an E condition 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) { // bytes to mibibytes 00153 return StatusCode::SUCCESS; 00154 } 00155 info () << "Reached " << cd.size << " MiB size" << endreq; 00156 return this->roll(stream,cd); 00157 } 00158 00159 00160 // check based on execution cycle count 00161 StatusCode DybOutputFileRoller::check_e(std::string stream, ConditionData& cd) 00162 { 00163 info() << "check_e " << stream << " " << cd.cycles << " " << (void*)&cd << endreq; 00164 00165 // check for first time 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; // reset countdown 00175 info () << "Reached " << cd.size << " execution cycles" << endreq; 00176 return this->roll(stream,cd); 00177 } 00178 00179 // for this to work, the algorithm must be placed after something that 00180 // loads data into the TES. 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 // check for first time 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) { // not yet 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()) { // no output files, bail blissfully 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