1 #include "otsdaq-core/WorkLoopManager/WorkLoopManager.h"
2 #include "otsdaq-core/MessageFacility/MessageFacility.h"
3 #include "otsdaq-core/Macros/CoutHeaderMacros.h"
4 #include "otsdaq-core/XmlUtilities/HttpXmlDocument.h"
5 #include "otsdaq-core/SOAPUtilities/SOAPCommand.h"
7 #include <toolbox/task/WorkLoopFactory.h>
18 WorkLoopManager::WorkLoopManager(toolbox::task::ActionSignature* job) :
19 cWorkLoopType_(
"waiting"),
22 requestName_ (job_->name())
24 __MOUT__ <<
"Request name: " << requestName_ <<
" jobName: " << job_->name() << std::endl;
29 WorkLoopManager::~WorkLoopManager(
void)
35 return processRequest(composeWorkLoopName(requestNumber_++, cgi));
39 HttpXmlDocument WorkLoopManager::processRequest(
const xoap::MessageReference& message)
41 return processRequest(composeWorkLoopName(requestNumber_++, message),&message);
45 HttpXmlDocument WorkLoopManager::processRequest(std::string workLoopName,
const xoap::MessageReference* message)
48 std::stringstream requestNumberStream;
49 RequestNumber requestNumber = getWorkLoopRequestNumber(workLoopName);
50 requestNumberStream << requestNumber;
51 std::stringstream reportStream;
53 __MOUT__ <<
"Processing request! WorkLoops: " << workLoops_.size() <<
" req: " << requestNumber << std::endl;
54 if(workLoops_.size() >= maxWorkLoops)
56 if(!removeTimedOutRequests())
58 reportStream <<
"Too many running requests (" << workLoops_.size() <<
"), try later!" << std::endl;
59 __MOUT__ <<
"ERROR: " << reportStream.str() << std::endl;
61 xmlDocument.addTextElementToData(
"RequestStatus",
"ERROR");
62 xmlDocument.addTextElementToData(
"RequestName" , getWorkLoopRequest(workLoopName));
63 xmlDocument.addTextElementToData(
"RequestNumber", requestNumberStream.str());
64 xmlDocument.addTextElementToData(
"ErrorReport" , reportStream.str());
68 time(&(workLoops_[requestNumber].requestStartTime));
69 workLoops_[requestNumber].requestLastTimeChecked = workLoops_[requestNumber].requestStartTime;
70 workLoops_[requestNumber].request = getWorkLoopRequest(workLoopName);
71 workLoops_[requestNumber].result =
"EMPTY";
72 workLoops_[requestNumber].progress = 0;
73 workLoops_[requestNumber].done =
false;
74 workLoops_[requestNumber].workLoopName = workLoopName;
76 workLoops_[requestNumber].message = *message;
79 workLoops_[requestNumber].workLoop = toolbox::task::getWorkLoopFactory()->getWorkLoop(workLoopName, cWorkLoopType_);
81 catch (xcept::Exception & e)
83 reportStream <<
"Can't create workloop, try again." << std::endl;
84 __MOUT__ <<
"ERROR: " << reportStream.str() << std::endl;
85 xmlDocument.addTextElementToData(
"RequestStatus",
"ERROR");
86 xmlDocument.addTextElementToData(
"RequestName" , getWorkLoopRequest(workLoopName));
87 xmlDocument.addTextElementToData(
"RequestNumber", requestNumberStream.str());
88 xmlDocument.addTextElementToData(
"ErrorReport" , reportStream.str());
89 removeWorkLoop(requestNumber);
95 workLoops_[requestNumber].workLoop->submit(job_);
97 catch (xcept::Exception & e)
99 reportStream <<
"Can't submit workloop job, try again." << std::endl;
100 __MOUT__ <<
"ERROR: " << reportStream.str() << std::endl;
101 xmlDocument.addTextElementToData(
"RequestStatus",
"ERROR");
102 xmlDocument.addTextElementToData(
"RequestName" , getWorkLoopRequest(workLoopName));
103 xmlDocument.addTextElementToData(
"RequestNumber", requestNumberStream.str());
104 xmlDocument.addTextElementToData(
"ErrorReport" , reportStream.str());
105 removeWorkLoop(requestNumber);
110 workLoops_[requestNumber].workLoop->activate();
112 catch (xcept::Exception & e)
114 reportStream <<
"Can't activate workloop, try again." << std::endl;
115 __MOUT__ <<
"ERROR: " << reportStream.str() << std::endl;
116 xmlDocument.addTextElementToData(
"RequestStatus",
"ERROR");
117 xmlDocument.addTextElementToData(
"RequestName" , getWorkLoopRequest(workLoopName));
118 xmlDocument.addTextElementToData(
"RequestNumber", requestNumberStream.str());
119 xmlDocument.addTextElementToData(
"ErrorReport" , reportStream.str());
120 removeWorkLoop(requestNumber);
124 __MOUT__ <<
"SUCCESS: Request is being processed!" << std::endl;
126 xmlDocument.addTextElementToData(
"RequestStatus",
"SUCCESS");
127 xmlDocument.addTextElementToData(
"RequestName" , getWorkLoopRequest(workLoopName));
128 xmlDocument.addTextElementToData(
"RequestNumber", requestNumberStream.str());
134 bool WorkLoopManager::report(toolbox::task::WorkLoop* workLoop, std::string result,
float progress,
bool status)
136 RequestNumber requestNumber = getWorkLoopRequestNumber(workLoop);
146 workLoops_[requestNumber].result = result;
147 workLoops_[requestNumber].progress = progress;
148 workLoops_[requestNumber].done = status;
153 xoap::MessageReference WorkLoopManager::getMessage(toolbox::task::WorkLoop* workLoop)
155 RequestNumber requestNumber = getWorkLoopRequestNumber(workLoop);
156 return workLoops_[requestNumber].message;
160 bool WorkLoopManager::getRequestResult(cgicc::Cgicc &cgi,
HttpXmlDocument &xmlDocument)
162 std::stringstream reportStream;
163 std::string requestNumberString = cgi.getElement(
"RequestNumber")->getValue();
164 RequestNumber requestNumber = strtoull(requestNumberString.c_str(), 0 , 10);
166 __MOUT__ <<
"Request: " << requestName_ <<
" RequestNumber=" << requestNumberString
167 <<
" assigned # " << requestNumber << std::endl;
169 if(workLoops_.find(requestNumber) == workLoops_.end())
171 reportStream <<
"Can't find request " << requestNumber <<
" within the currently active " << workLoops_.size() <<
" requests!";
172 __MOUT__ <<
"WARNING: " << reportStream.str() << std::endl;
173 xmlDocument.addTextElementToData(
"RequestStatus",
"WARNING");
174 xmlDocument.addTextElementToData(
"RequestName" ,
"Unknown");
175 xmlDocument.addTextElementToData(
"RequestNumber", requestNumberString);
176 xmlDocument.addTextElementToData(
"ErrorReport" , reportStream.str());
180 if(!workLoops_[requestNumber].done)
182 reportStream <<
"Still processing request " << requestNumber;
183 __MOUT__ <<
"WARNING: " << reportStream.str() << std::endl;
185 time(&(workLoops_[requestNumber].requestLastTimeChecked));
187 xmlDocument.addTextElementToData(
"RequestStatus" ,
"MESSAGE");
188 xmlDocument.addTextElementToData(
"RequestName" , workLoops_[requestNumber].request);
189 xmlDocument.addTextElementToData(
"RequestNumber" , requestNumberString);
190 xmlDocument.addTextElementToData(
"ErrorReport" , reportStream.str());
191 std::stringstream progress;
192 progress << workLoops_[requestNumber].progress;
193 xmlDocument.addTextElementToData(
"RequestProgress", progress.str());
198 xmlDocument.addTextElementToData(
"RequestStatus" , workLoops_[requestNumber].result);
199 xmlDocument.addTextElementToData(
"RequestName" , workLoops_[requestNumber].request);
200 xmlDocument.addTextElementToData(
"RequestNumber" , requestNumberString);
201 std::stringstream progress;
202 progress << workLoops_[requestNumber].progress;
203 xmlDocument.addTextElementToData(
"RequestProgress", progress.str());
205 removeWorkLoop(requestNumber);
210 bool WorkLoopManager::removeWorkLoop(toolbox::task::WorkLoop* workLoop)
212 return removeWorkLoop(getWorkLoopRequestNumber(workLoop));
216 bool WorkLoopManager::removeWorkLoop(RequestNumber requestNumber)
218 if(workLoops_.find(requestNumber) == workLoops_.end())
220 __MOUT__ <<
"WorkLoop " << requestNumber <<
" is not in the WorkLoops list!" << std::endl;
224 if(workLoops_[requestNumber].workLoop == 0)
226 __MOUT__ <<
"WorkLoop " << requestNumber <<
" was not created at all!" << std::endl;
227 workLoops_.erase(requestNumber);
233 workLoops_[requestNumber].workLoop->cancel();
235 catch (xcept::Exception & e)
237 __MOUT__ <<
"Can't cancel WorkLoop " << requestNumber << std::endl;
243 workLoops_[requestNumber].workLoop->remove(job_);
245 catch (xcept::Exception & e)
253 __MOUT__ <<
"Deleting WorkLoop " << requestNumber << std::endl;
254 toolbox::task::getWorkLoopFactory()->removeWorkLoop(workLoops_[requestNumber].workLoopName, cWorkLoopType_);
255 workLoops_.erase(requestNumber);
260 bool WorkLoopManager::removeProcessedRequests(
void)
262 std::map<RequestNumber, WorkLoopStruct>::iterator it = workLoops_.begin();
263 while(it != workLoops_.end())
265 removeWorkLoop((it++)->first);
272 bool WorkLoopManager::removeTimedOutRequests(
void)
276 std::map<RequestNumber, WorkLoopStruct>::iterator it = workLoops_.begin();
277 __MOUT__ <<
"Removing timed out " << std::endl;
278 for( ; it != workLoops_.end(); it++)
279 if(it->second.done && difftime(now,it->second.requestLastTimeChecked) > timeOutInSeconds)
281 __MOUT__ <<
"Removing timed out request #" << it->first <<
" after " << difftime(now,it->second.requestLastTimeChecked) <<
" seconds." << std::endl;
282 removeWorkLoop(it->first);
285 __MOUT__ <<
"Done Removing timed out " << std::endl;
293 std::string WorkLoopManager::composeWorkLoopName(RequestNumber requestNumber, cgicc::Cgicc &cgi)
295 std::stringstream name;
296 name << requestNumber <<
"-" << cgi.getElement(requestName_)->getValue();
297 __MOUT__ <<
"Request: " << requestName_
298 <<
" Value=" << cgi.getElement(requestName_)->getValue()
299 <<
" WLName: " << name.str()
305 std::string WorkLoopManager::composeWorkLoopName(RequestNumber requestNumber,
const xoap::MessageReference& message)
308 std::stringstream name;
309 name << requestNumber <<
"-" << soapCommand.getCommand();
310 __MOUT__ <<
"Request: " << requestName_
311 <<
" Value=" << soapCommand.getCommand()
312 <<
" WLName: " << name.str()
314 if(soapCommand.hasParameters())
317 char separator =
',';
318 for(SOAPParameters::const_iterator it=soapCommand.getParameters().begin(); it!=soapCommand.getParameters().end(); it++)
320 if(it != soapCommand.getParameters().begin())
322 name << it->first <<
"|" << it->second;
329 //========================================================================================================================
330 WorkLoopManager::RequestNumber WorkLoopManager::getWorkLoopRequestNumber(toolbox::task::WorkLoop* workLoop)
332 return getWorkLoopRequestNumber(workLoop->getName());
335 //========================================================================================================================
336 WorkLoopManager::RequestNumber WorkLoopManager::getWorkLoopRequestNumber(std::string workLoopName)
338 workLoopName = workLoopName.substr(0,workLoopName.find('-
'));
339 return strtoull(workLoopName.c_str(), 0 , 10);
342 //========================================================================================================================
343 std::string WorkLoopManager::getWorkLoopRequest(toolbox::task::WorkLoop* workLoop)
345 return getWorkLoopRequest(workLoop->getName());
348 //========================================================================================================================
349 std::string WorkLoopManager::getWorkLoopRequest(std::string workLoopName)
351 return workLoopName.substr(workLoopName.find('-
')+1,workLoopName.find(std::string("/")+cWorkLoopType_)-workLoopName.find('-
')-1);
354 //========================================================================================================================
355 void WorkLoopManager::translateWorkLoopName(toolbox::task::WorkLoop* workLoop, SOAPCommand& soapCommand)
357 std::string request = getWorkLoopRequest(workLoop);
358 if(request.find('<
') == std::string::npos)
360 __MOUT__ << "Simple request" << std::endl;
361 soapCommand.setCommand(request);
365 size_t ltPosition = request.find('<
');
366 size_t gtPosition = request.find('>
');
367 size_t begin = ltPosition+1;
369 size_t commaPosition;
371 soapCommand.setCommand(request.substr(0,ltPosition));
372 while((commaPosition = request.find(',
',begin)) != std::string::npos)
374 orPosition = request.find('|
',begin);
375 soapCommand.setParameter(request.substr(begin,orPosition-begin),request.substr(orPosition+1,commaPosition-orPosition-1));
376 begin = commaPosition+1;
377 __MOUT__ << "Comma: " << commaPosition << std::endl;
379 orPosition = request.find('|
',begin);
380 soapCommand.setParameter(request.substr(begin,orPosition-begin),request.substr(orPosition+1,gtPosition-orPosition-1));
382 __MOUT__ << soapCommand << std::endl;
383 //__MOUT__ << name.substr(name.find(',
')+1,name.find('/
')-name.find(',
')-1) << std::endl;