$treeview $search $mathjax $extrastylesheet
otsdaq
v2_03_00
$projectbrief
|
$projectbrief
|
$searchbox |
00001 #include "otsdaq-core/WorkLoopManager/WorkLoopManager.h" 00002 #include "otsdaq-core/Macros/CoutMacros.h" 00003 #include "otsdaq-core/MessageFacility/MessageFacility.h" 00004 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h" 00005 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h" 00006 00007 #include <toolbox/task/WorkLoopFactory.h> 00008 00009 #include <cassert> 00010 #include <cstdlib> 00011 #include <iostream> 00012 #include <sstream> 00013 00014 using namespace ots; 00015 00016 //======================================================================================================================== 00017 WorkLoopManager::WorkLoopManager(toolbox::task::ActionSignature* job) 00018 : cWorkLoopType_("waiting"), job_(job), requestNumber_(0), requestName_(job_->name()) 00019 { 00020 __COUT__ << "Request name: " << requestName_ << " jobName: " << job_->name() 00021 << std::endl; 00022 } 00023 00024 //======================================================================================================================== 00025 WorkLoopManager::~WorkLoopManager(void) {} 00026 00027 //======================================================================================================================== 00028 HttpXmlDocument WorkLoopManager::processRequest(cgicc::Cgicc& cgi) 00029 { 00030 return processRequest(composeWorkLoopName(requestNumber_++, cgi)); 00031 } 00032 00033 //======================================================================================================================== 00034 HttpXmlDocument WorkLoopManager::processRequest(const xoap::MessageReference& message) 00035 { 00036 return processRequest(composeWorkLoopName(requestNumber_++, message), &message); 00037 } 00038 00039 //======================================================================================================================== 00040 HttpXmlDocument WorkLoopManager::processRequest(std::string workLoopName, 00041 const xoap::MessageReference* message) 00042 { 00043 HttpXmlDocument xmlDocument; 00044 std::stringstream requestNumberStream; 00045 RequestNumber requestNumber = getWorkLoopRequestNumber(workLoopName); 00046 requestNumberStream << requestNumber; 00047 std::stringstream reportStream; 00048 00049 __COUT__ << "Processing request! WorkLoops: " << workLoops_.size() 00050 << " req: " << requestNumber << std::endl; 00051 if(workLoops_.size() >= maxWorkLoops) 00052 { 00053 if(!removeTimedOutRequests()) 00054 { 00055 reportStream << "Too many running requests (" << workLoops_.size() 00056 << "), try later!" << std::endl; 00057 __COUT__ << "ERROR: " << reportStream.str() << std::endl; 00058 00059 xmlDocument.addTextElementToData("RequestStatus", "ERROR"); 00060 xmlDocument.addTextElementToData("RequestName", 00061 getWorkLoopRequest(workLoopName)); 00062 xmlDocument.addTextElementToData("RequestNumber", requestNumberStream.str()); 00063 xmlDocument.addTextElementToData("ErrorReport", reportStream.str()); 00064 return xmlDocument; 00065 } 00066 } 00067 time(&(workLoops_[requestNumber].requestStartTime)); 00068 workLoops_[requestNumber].requestLastTimeChecked = 00069 workLoops_[requestNumber].requestStartTime; 00070 workLoops_[requestNumber].request = getWorkLoopRequest(workLoopName); 00071 workLoops_[requestNumber].result = "EMPTY"; 00072 workLoops_[requestNumber].progress = 0; 00073 workLoops_[requestNumber].done = false; 00074 workLoops_[requestNumber].workLoopName = workLoopName; 00075 if(message != 0) 00076 workLoops_[requestNumber].message = *message; 00077 try 00078 { 00079 workLoops_[requestNumber].workLoop = 00080 toolbox::task::getWorkLoopFactory()->getWorkLoop(workLoopName, 00081 cWorkLoopType_); 00082 } 00083 catch(xcept::Exception& e) 00084 { 00085 reportStream << "Can't create workloop, try again." << std::endl; 00086 __COUT__ << "ERROR: " << reportStream.str() << std::endl; 00087 xmlDocument.addTextElementToData("RequestStatus", "ERROR"); 00088 xmlDocument.addTextElementToData("RequestName", getWorkLoopRequest(workLoopName)); 00089 xmlDocument.addTextElementToData("RequestNumber", requestNumberStream.str()); 00090 xmlDocument.addTextElementToData("ErrorReport", reportStream.str()); 00091 removeWorkLoop(requestNumber); 00092 return xmlDocument; 00093 } 00094 00095 try 00096 { 00097 workLoops_[requestNumber].workLoop->submit(job_); 00098 } 00099 catch(xcept::Exception& e) 00100 { 00101 reportStream << "Can't submit workloop job, try again." << std::endl; 00102 __COUT__ << "ERROR: " << reportStream.str() << std::endl; 00103 xmlDocument.addTextElementToData("RequestStatus", "ERROR"); 00104 xmlDocument.addTextElementToData("RequestName", getWorkLoopRequest(workLoopName)); 00105 xmlDocument.addTextElementToData("RequestNumber", requestNumberStream.str()); 00106 xmlDocument.addTextElementToData("ErrorReport", reportStream.str()); 00107 removeWorkLoop(requestNumber); 00108 return xmlDocument; 00109 } 00110 try 00111 { 00112 workLoops_[requestNumber].workLoop->activate(); 00113 } 00114 catch(xcept::Exception& e) 00115 { 00116 reportStream << "Can't activate workloop, try again." << std::endl; 00117 __COUT__ << "ERROR: " << reportStream.str() << std::endl; 00118 xmlDocument.addTextElementToData("RequestStatus", "ERROR"); 00119 xmlDocument.addTextElementToData("RequestName", getWorkLoopRequest(workLoopName)); 00120 xmlDocument.addTextElementToData("RequestNumber", requestNumberStream.str()); 00121 xmlDocument.addTextElementToData("ErrorReport", reportStream.str()); 00122 removeWorkLoop(requestNumber); 00123 return xmlDocument; 00124 } 00125 00126 __COUT__ << "SUCCESS: Request is being processed!" << std::endl; 00127 00128 xmlDocument.addTextElementToData("RequestStatus", "SUCCESS"); 00129 xmlDocument.addTextElementToData("RequestName", getWorkLoopRequest(workLoopName)); 00130 xmlDocument.addTextElementToData("RequestNumber", requestNumberStream.str()); 00131 00132 return xmlDocument; 00133 } 00134 00135 //======================================================================================================================== 00136 bool WorkLoopManager::report(toolbox::task::WorkLoop* workLoop, 00137 std::string result, 00138 float progress, 00139 bool status) 00140 { 00141 RequestNumber requestNumber = getWorkLoopRequestNumber(workLoop); 00142 00143 /* 00144 __COUT__ << "Reporting result for request " << getWorkLoopRequest(workLoop) << " 00145 with req#: " << requestNumber << std::endl; if(workLoops_.find(requestNumber) == 00146 workLoops_.end()) 00147 { 00148 __COUT__ << "This MUST NEVER happen. You must find out what is wrong!" << 00149 std::endl; assert(0); 00150 } 00151 */ 00152 workLoops_[requestNumber].result = result; 00153 workLoops_[requestNumber].progress = progress; 00154 workLoops_[requestNumber].done = status; 00155 return true; 00156 } 00157 00158 //======================================================================================================================== 00159 xoap::MessageReference WorkLoopManager::getMessage(toolbox::task::WorkLoop* workLoop) 00160 { 00161 RequestNumber requestNumber = getWorkLoopRequestNumber(workLoop); 00162 return workLoops_[requestNumber].message; 00163 } 00164 00165 //======================================================================================================================== 00166 bool WorkLoopManager::getRequestResult(cgicc::Cgicc& cgi, HttpXmlDocument& xmlDocument) 00167 { 00168 std::stringstream reportStream; 00169 std::string requestNumberString = cgi.getElement("RequestNumber")->getValue(); 00170 RequestNumber requestNumber = strtoull(requestNumberString.c_str(), 0, 10); 00171 00172 __COUT__ << "Request: " << requestName_ << " RequestNumber=" << requestNumberString 00173 << " assigned # " << requestNumber << std::endl; 00174 00175 if(workLoops_.find(requestNumber) == workLoops_.end()) 00176 { 00177 reportStream << "Can't find request " << requestNumber 00178 << " within the currently active " << workLoops_.size() 00179 << " requests!"; 00180 __COUT__ << "WARNING: " << reportStream.str() << std::endl; 00181 xmlDocument.addTextElementToData("RequestStatus", "WARNING"); 00182 xmlDocument.addTextElementToData("RequestName", "Unknown"); 00183 xmlDocument.addTextElementToData("RequestNumber", requestNumberString); 00184 xmlDocument.addTextElementToData("ErrorReport", reportStream.str()); 00185 return false; 00186 } 00187 00188 if(!workLoops_[requestNumber].done) 00189 { 00190 reportStream << "Still processing request " << requestNumber; 00191 __COUT__ << "WARNING: " << reportStream.str() << std::endl; 00192 // Resetting timer since there is a listener 00193 time(&(workLoops_[requestNumber].requestLastTimeChecked)); 00194 00195 xmlDocument.addTextElementToData("RequestStatus", "MESSAGE"); 00196 xmlDocument.addTextElementToData("RequestName", 00197 workLoops_[requestNumber].request); 00198 xmlDocument.addTextElementToData("RequestNumber", requestNumberString); 00199 xmlDocument.addTextElementToData("ErrorReport", reportStream.str()); 00200 std::stringstream progress; 00201 progress << workLoops_[requestNumber].progress; 00202 xmlDocument.addTextElementToData("RequestProgress", progress.str()); 00203 return false; 00204 } 00205 00206 // Request done and ready to be retrieved so I can remove it from the queue 00207 xmlDocument.addTextElementToData("RequestStatus", workLoops_[requestNumber].result); 00208 xmlDocument.addTextElementToData("RequestName", workLoops_[requestNumber].request); 00209 xmlDocument.addTextElementToData("RequestNumber", requestNumberString); 00210 std::stringstream progress; 00211 progress << workLoops_[requestNumber].progress; 00212 xmlDocument.addTextElementToData("RequestProgress", progress.str()); 00213 00214 removeWorkLoop(requestNumber); 00215 return true; 00216 } 00217 00218 //======================================================================================================================== 00219 bool WorkLoopManager::removeWorkLoop(toolbox::task::WorkLoop* workLoop) 00220 { 00221 return removeWorkLoop(getWorkLoopRequestNumber(workLoop)); 00222 } 00223 00224 //======================================================================================================================== 00225 bool WorkLoopManager::removeWorkLoop(RequestNumber requestNumber) 00226 { 00227 if(workLoops_.find(requestNumber) == workLoops_.end()) 00228 { 00229 __COUT__ << "WorkLoop " << requestNumber << " is not in the WorkLoops list!" 00230 << std::endl; 00231 return false; 00232 } 00233 00234 if(workLoops_[requestNumber].workLoop == 0) 00235 { 00236 __COUT__ << "WorkLoop " << requestNumber << " was not created at all!" 00237 << std::endl; 00238 workLoops_.erase(requestNumber); 00239 return false; 00240 } 00241 00242 try 00243 { 00244 workLoops_[requestNumber].workLoop->cancel(); 00245 } 00246 catch(xcept::Exception& e) 00247 { 00248 __COUT__ << "Can't cancel WorkLoop " << requestNumber << std::endl; 00249 // diagService_->reportError("Failed to start Job Control monitoring. Exception: 00250 // "+string(e.what()),DIAGWARN); 00251 return false; 00252 } 00253 try 00254 { 00255 workLoops_[requestNumber].workLoop->remove(job_); 00256 } 00257 catch(xcept::Exception& e) 00258 { 00259 // ATTENTION! 00260 // If the workloop job thread returns false, then the workloop job is 00261 // automatically removed and it can't be removed again Leaving this try catch 00262 // allows me to be general in the job threads so I can return true (repeat loop) 00263 // or false ( loop only once) without crashing 00264 // __COUT__ << "WARNING: Can't remove request WorkLoop: " << requestNumber << 00265 // std::endl; 00266 } 00267 __COUT__ << "Deleting WorkLoop " << requestNumber << std::endl; 00268 toolbox::task::getWorkLoopFactory()->removeWorkLoop( 00269 workLoops_[requestNumber].workLoopName, 00270 cWorkLoopType_); // delete workLoops_[requestNumber].workLoop; is done by the 00271 // factory 00272 workLoops_.erase(requestNumber); 00273 return true; 00274 } 00275 00276 //======================================================================================================================== 00277 bool WorkLoopManager::removeProcessedRequests(void) 00278 { 00279 std::map<RequestNumber, WorkLoopStruct>::iterator it = workLoops_.begin(); 00280 while(it != workLoops_.end()) 00281 if(it->second.done) 00282 removeWorkLoop((it++)->first); 00283 else 00284 ++it; 00285 return true; 00286 } 00287 00288 //======================================================================================================================== 00289 bool WorkLoopManager::removeTimedOutRequests(void) 00290 { 00291 time_t now; 00292 time(&now); 00293 std::map<RequestNumber, WorkLoopStruct>::iterator it = workLoops_.begin(); 00294 __COUT__ << "Removing timed out " << std::endl; 00295 for(; it != workLoops_.end(); it++) 00296 if(it->second.done && 00297 difftime(now, it->second.requestLastTimeChecked) > timeOutInSeconds) 00298 { 00299 __COUT__ << "Removing timed out request #" << it->first << " after " 00300 << difftime(now, it->second.requestLastTimeChecked) << " seconds." 00301 << std::endl; 00302 removeWorkLoop(it->first); 00303 return true; // since I return I don't care if the iterator pointer is 00304 // screwed after I erase the element 00305 } 00306 __COUT__ << "Done Removing timed out " << std::endl; 00307 return false; 00308 } 00309 00310 // WorkLoopName Format: 00311 // RequestNumber-CommandToExecute<Argument1Name:Argument1Value,Argument2Name:Argument2Value...> 00312 // Then the WorkLoop adds at the end /waiting 00313 //======================================================================================================================== 00314 std::string WorkLoopManager::composeWorkLoopName(RequestNumber requestNumber, 00315 cgicc::Cgicc& cgi) 00316 { 00317 std::stringstream name; 00318 name << requestNumber << "-" << cgi.getElement(requestName_)->getValue(); 00319 __COUT__ << "Request: " << requestName_ 00320 << " Value=" << cgi.getElement(requestName_)->getValue() 00321 << " WLName: " << name.str() << std::endl; 00322 return name.str(); 00323 } 00324 00325 //======================================================================================================================== 00326 std::string WorkLoopManager::composeWorkLoopName(RequestNumber requestNumber, 00327 const xoap::MessageReference& message) 00328 { 00329 SOAPCommand soapCommand(message); 00330 std::stringstream name; 00331 name << requestNumber << "-" << soapCommand.getCommand(); 00332 __COUT__ << "Request: " << requestName_ << " Value=" << soapCommand.getCommand() 00333 << " WLName: " << name.str() << std::endl; 00334 if(soapCommand.hasParameters()) 00335 { 00336 name << '<'; 00337 char separator = ','; 00338 for(SOAPParameters::const_iterator it = soapCommand.getParameters().begin(); 00339 it != soapCommand.getParameters().end(); 00340 it++) 00341 { 00342 if(it != soapCommand.getParameters().begin()) 00343 name << separator; 00344 name << it->first << "|" << it->second; 00345 } 00346 name << '>'; 00347 } 00348 return name.str(); 00349 } 00350 00351 //======================================================================================================================== 00352 WorkLoopManager::RequestNumber WorkLoopManager::getWorkLoopRequestNumber( 00353 toolbox::task::WorkLoop* workLoop) 00354 { 00355 return getWorkLoopRequestNumber(workLoop->getName()); 00356 } 00357 00358 //======================================================================================================================== 00359 WorkLoopManager::RequestNumber WorkLoopManager::getWorkLoopRequestNumber( 00360 std::string workLoopName) 00361 { 00362 workLoopName = workLoopName.substr(0, workLoopName.find('-')); 00363 return strtoull(workLoopName.c_str(), 0, 10); 00364 } 00365 00366 //======================================================================================================================== 00367 std::string WorkLoopManager::getWorkLoopRequest(toolbox::task::WorkLoop* workLoop) 00368 { 00369 return getWorkLoopRequest(workLoop->getName()); 00370 } 00371 00372 //======================================================================================================================== 00373 std::string WorkLoopManager::getWorkLoopRequest(std::string workLoopName) 00374 { 00375 return workLoopName.substr(workLoopName.find('-') + 1, 00376 workLoopName.find(std::string("/") + cWorkLoopType_) - 00377 workLoopName.find('-') - 1); 00378 } 00379 00380 //======================================================================================================================== 00381 void WorkLoopManager::translateWorkLoopName(toolbox::task::WorkLoop* workLoop, 00382 SOAPCommand& soapCommand) 00383 { 00384 std::string request = getWorkLoopRequest(workLoop); 00385 if(request.find('<') == std::string::npos) 00386 { 00387 __COUT__ << "Simple request" << std::endl; 00388 soapCommand.setCommand(request); 00389 } 00390 else 00391 { 00392 size_t ltPosition = request.find('<'); 00393 size_t gtPosition = request.find('>'); 00394 size_t begin = ltPosition + 1; 00395 size_t orPosition; 00396 size_t commaPosition; 00397 00398 soapCommand.setCommand(request.substr(0, ltPosition)); 00399 while((commaPosition = request.find(',', begin)) != std::string::npos) 00400 { 00401 orPosition = request.find('|', begin); 00402 soapCommand.setParameter( 00403 request.substr(begin, orPosition - begin), 00404 request.substr(orPosition + 1, commaPosition - orPosition - 1)); 00405 begin = commaPosition + 1; 00406 __COUT__ << "Comma: " << commaPosition << std::endl; 00407 } 00408 orPosition = request.find('|', begin); 00409 soapCommand.setParameter( 00410 request.substr(begin, orPosition - begin), 00411 request.substr(orPosition + 1, gtPosition - orPosition - 1)); 00412 } 00413 __COUT__ << soapCommand << std::endl; 00414 //__COUT__ << name.substr(name.find(',')+1,name.find('/')-name.find(',')-1) << 00415 // std::endl; 00416 }