1 #include "otsdaq-core/DataManager/DataManager.h"
2 #include "otsdaq-core/ConfigurationInterface/ConfigurationManager.h"
3 #include "otsdaq-core/DataManager/CircularBuffer.h"
4 #include "otsdaq-core/DataManager/DataConsumer.h"
5 #include "otsdaq-core/DataManager/DataProducerBase.h"
6 #include "otsdaq-core/Macros/CoutMacros.h"
7 #include "otsdaq-core/MessageFacility/MessageFacility.h"
8 #include "otsdaq-core/PluginMakers/MakeDataProcessor.h"
34 const std::string& supervisorConfigurationPath)
35 :
Configurable(theXDAQContextConfigTree, supervisorConfigurationPath)
36 , parentSupervisorHasFrontends_(false)
38 __CFG_COUT__ <<
"Constructed." << __E__;
42 DataManager::~DataManager(
void)
44 __CFG_COUT__ <<
"Destructor." << __E__;
45 DataManager::destroyBuffers();
46 __CFG_COUT__ <<
"Destructed." << __E__;
50 void DataManager::dumpStatus(std::ostream* out)
const
52 *out <<
"Buffer count: " << buffers_.size() << __E__;
53 for(
auto& bufferPair : buffers_)
56 <<
"Buffer '" << bufferPair.first <<
"' status=" << bufferPair.second.status_
57 <<
" producers=" << bufferPair.second.producers_.size()
58 <<
" consumers=" << bufferPair.second.consumers_.size() << __E__;
61 <<
"Producers:" << __E__;
62 for(
auto& producer : bufferPair.second.producers_)
64 *out <<
"\t\t\t" << producer->getProcessorID() <<
" ["
65 << bufferPair.second.buffer_->getProducerBufferSize(
66 producer->getProcessorID())
70 <<
"Consumers:" << __E__;
71 for(
auto& consumer : bufferPair.second.consumers_)
73 *out <<
"\t\t\t" << consumer->getProcessorID() << __E__;
79 void DataManager::configure(
void)
81 const std::string transitionName =
"Configuring";
83 const std::string COL_NAME_bufferGroupLink =
"LinkToDataBufferTable";
84 const std::string COL_NAME_processorGroupLink =
"LinkToDataProcessorTable";
85 const std::string COL_NAME_processorType =
"ProcessorType";
86 const std::string COL_NAME_processorPlugin =
"ProcessorPluginName";
87 const std::string COL_NAME_processorLink =
"LinkToProcessorTable";
88 const std::string COL_NAME_appUID =
"ApplicationUID";
90 __CFG_COUT__ << transitionName <<
" DataManager" << __E__;
91 __CFG_COUT__ <<
"Path: " << theConfigurationPath_ +
"/" + COL_NAME_bufferGroupLink
97 for(
const auto& buffer :
98 theXDAQContextConfigTree_
99 .getNode(theConfigurationPath_ +
"/" + COL_NAME_bufferGroupLink)
102 __CFG_COUT__ <<
"Data Buffer Name: " << buffer.first << __E__;
103 if(buffer.second.getNode(TableViewColumnInfo::COL_NAME_STATUS).getValue<
bool>())
105 std::vector<unsigned int> producersVectorLocation;
106 std::vector<unsigned int> consumersVectorLocation;
107 auto bufferConfigurationList =
108 buffer.second.getNode(COL_NAME_processorGroupLink)
110 unsigned int location = 0;
111 for(
const auto& bufferConfiguration : bufferConfigurationList)
113 __CFG_COUT__ <<
"Processor id: " << bufferConfiguration.first << __E__;
114 if(bufferConfiguration.second
115 .getNode(TableViewColumnInfo::COL_NAME_STATUS)
118 if(bufferConfiguration.second.getNode(COL_NAME_processorType)
119 .getValue<std::string>() ==
"Producer")
121 producersVectorLocation.push_back(location);
123 else if(bufferConfiguration.second.getNode(COL_NAME_processorType)
124 .getValue<std::string>() ==
"Consumer")
126 consumersVectorLocation.push_back(location);
130 __CFG_SS__ <<
"Node ProcessorType in "
131 << bufferConfiguration.first <<
" of type "
132 << bufferConfiguration.second
133 .getNode(COL_NAME_processorPlugin)
134 .getValue<std::string>()
135 <<
" is invalid. The only accepted types are Producer "
138 __CFG_MOUT_ERR__ << ss.str();
146 if(!parentSupervisorHasFrontends_ &&
147 producersVectorLocation.size() ==
150 __CFG_SS__ <<
"Node Data Buffer " << buffer.first <<
" has "
151 << producersVectorLocation.size() <<
" Producers"
152 <<
" and " << consumersVectorLocation.size() <<
" Consumers"
153 <<
" there must be at least 1 Producer "
155 "for the buffer!" << __E__;
156 __CFG_MOUT_ERR__ << ss.str();
160 if(parentSupervisorHasFrontends_)
162 <<
"Parent supervisor has front-ends, so FE-producers may "
163 <<
"be instantiated in the configure steps of the FESupervisor."
166 configureBuffer<std::string, std::map<std::string, std::string> >(
169 for(
auto& producerLocation : producersVectorLocation)
173 __CFG_COUT__ <<
"Creating producer... "
174 << bufferConfigurationList[producerLocation].first << __E__;
190 bufferConfigurationList[producerLocation]
191 .second.getNode(COL_NAME_processorPlugin)
192 .getValue<std::string>(),
193 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
194 .getNode(COL_NAME_appUID)
195 .getValue<std::string>(),
197 bufferConfigurationList[producerLocation].first,
198 theXDAQContextConfigTree_,
199 theConfigurationPath_ +
"/" + COL_NAME_bufferGroupLink +
"/" +
200 buffer.first +
"/" + COL_NAME_processorGroupLink +
"/" +
201 bufferConfigurationList[producerLocation].first +
"/" +
202 COL_NAME_processorLink));
206 __CFG_SS__ <<
"Construction failed for producer '"
207 << bufferConfigurationList[producerLocation].first
208 <<
"!' Null pointer returned." << __E__;
211 __CFG_COUT__ << tmpCastCheck->getProcessorID() << __E__;
215 dumpStatus((std::ostream*)&ss);
216 __CFG_COUT__ << ss.str() << __E__;
219 catch(
const std::bad_cast& e)
221 __CFG_SS__ <<
"Failed to instantiate producer plugin named '"
222 << bufferConfigurationList[producerLocation].first
224 << bufferConfigurationList[producerLocation]
225 .second.getNode(COL_NAME_processorPlugin)
226 .getValue<std::string>()
227 <<
"' due to the following error: \n"
228 << e.what() << __E__;
229 __CFG_MOUT_ERR__ << ss.str();
232 catch(
const cet::exception& e)
234 __CFG_SS__ <<
"Failed to instantiate producer plugin named '"
235 << bufferConfigurationList[producerLocation].first
237 << bufferConfigurationList[producerLocation]
238 .second.getNode(COL_NAME_processorPlugin)
239 .getValue<std::string>()
240 <<
"' due to the following error: \n"
241 << e.what() << __E__;
242 __CFG_MOUT_ERR__ << ss.str();
245 catch(
const std::runtime_error& e)
247 __CFG_SS__ <<
"Failed to instantiate producer plugin named '"
248 << bufferConfigurationList[producerLocation].first
250 << bufferConfigurationList[producerLocation]
251 .second.getNode(COL_NAME_processorPlugin)
252 .getValue<std::string>()
253 <<
"' due to the following error: \n"
254 << e.what() << __E__;
255 __CFG_MOUT_ERR__ << ss.str();
260 __CFG_SS__ <<
"Failed to instantiate producer plugin named '"
261 << bufferConfigurationList[producerLocation].first
263 << bufferConfigurationList[producerLocation]
264 .second.getNode(COL_NAME_processorPlugin)
265 .getValue<std::string>()
266 <<
"' due to an unknown error." << __E__;
267 __CFG_MOUT_ERR__ << ss.str();
272 __CFG_COUT__ << bufferConfigurationList[producerLocation].first
273 <<
" has been created!" << __E__;
276 for(
auto& consumerLocation : consumersVectorLocation)
280 __CFG_COUT__ <<
"Creating consumer... "
281 << bufferConfigurationList[consumerLocation].first << __E__;
299 bufferConfigurationList[consumerLocation]
300 .second.getNode(COL_NAME_processorPlugin)
301 .getValue<std::string>(),
302 theXDAQContextConfigTree_.getBackNode(theConfigurationPath_)
303 .getNode(COL_NAME_appUID)
304 .getValue<std::string>(),
306 bufferConfigurationList[consumerLocation].first,
307 theXDAQContextConfigTree_,
308 theConfigurationPath_ +
"/" + COL_NAME_bufferGroupLink +
"/" +
309 buffer.first +
"/" + COL_NAME_processorGroupLink +
"/" +
310 bufferConfigurationList[consumerLocation].first +
"/" +
311 COL_NAME_processorLink));
315 __CFG_SS__ <<
"Construction failed for consumer '"
316 << bufferConfigurationList[consumerLocation].first
317 <<
"!' Null pointer returned." << __E__;
323 dumpStatus((std::ostream*)&ss);
324 __CFG_COUT__ << ss.str() << __E__;
327 catch(
const std::bad_cast& e)
329 __CFG_SS__ <<
"Failed to instantiate consumer plugin named '"
330 << bufferConfigurationList[consumerLocation].first
332 << bufferConfigurationList[consumerLocation]
333 .second.getNode(COL_NAME_processorPlugin)
334 .getValue<std::string>()
335 <<
"' due to the following error: \n"
336 << e.what() << __E__;
337 __CFG_MOUT_ERR__ << ss.str();
340 catch(
const cet::exception& e)
342 __CFG_SS__ <<
"Failed to instantiate consumer plugin named '"
343 << bufferConfigurationList[consumerLocation].first
345 << bufferConfigurationList[consumerLocation]
346 .second.getNode(COL_NAME_processorPlugin)
347 .getValue<std::string>()
348 <<
"' due to the following error: \n"
349 << e.what() << __E__;
350 __CFG_MOUT_ERR__ << ss.str();
353 catch(
const std::runtime_error& e)
355 __CFG_SS__ <<
"Failed to instantiate consumer plugin named '"
356 << bufferConfigurationList[consumerLocation].first
358 << bufferConfigurationList[consumerLocation]
359 .second.getNode(COL_NAME_processorPlugin)
360 .getValue<std::string>()
361 <<
"' due to the following error: \n"
362 << e.what() << __E__;
363 __CFG_MOUT_ERR__ << ss.str();
368 __CFG_SS__ <<
"Failed to instantiate consumer plugin named '"
369 << bufferConfigurationList[consumerLocation].first
371 << bufferConfigurationList[consumerLocation]
372 .second.getNode(COL_NAME_processorPlugin)
373 .getValue<std::string>()
374 <<
"' due to an unknown error." << __E__;
375 __CFG_MOUT_ERR__ << ss.str();
379 __CFG_COUT__ << bufferConfigurationList[consumerLocation].first
380 <<
" has been created!" << __E__;
387 void DataManager::halt(
void)
389 const std::string transitionName =
"Halting";
391 __CFG_COUT__ << transitionName <<
" DataManager " << __E__;
400 __CFG_COUT_WARN__ <<
"An error occurred while halting the Data Manager, ignoring."
406 __CFG_COUT__ << transitionName <<
" DataManager stopped. Now destruct buffers..."
409 DataManager::destroyBuffers();
414 void DataManager::pause(
void)
416 const std::string transitionName =
"Pausing";
418 __CFG_COUT__ << transitionName <<
" DataManager " << __E__;
420 DataManager::pauseAllBuffers();
424 void DataManager::resume(
void)
426 const std::string transitionName =
"Resuming";
428 __CFG_COUT__ << transitionName <<
" DataManager " << __E__;
430 DataManager::resumeAllBuffers();
434 void DataManager::start(std::string runNumber)
436 const std::string transitionName =
"Starting";
438 __CFG_COUT__ << transitionName <<
" DataManager " << __E__;
444 void DataManager::stop()
446 const std::string transitionName =
"Stopping";
448 __CFG_COUT__ << transitionName <<
" DataManager " << __E__;
450 DataManager::stopAllBuffers();
456 void DataManager::destroyBuffers(
void)
458 DataManager::stopAllBuffers();
460 for(
auto& bufferPair : buffers_)
464 for(
auto& producer : bufferPair.second.producers_)
466 bufferPair.second.producers_.clear();
468 for(
auto& consumer : bufferPair.second.consumers_)
470 bufferPair.second.consumers_.clear();
472 delete bufferPair.second.buffer_;
633 const std::string& feProducerID)
635 __CFG_COUT__ <<
"Un-Registering FE-producer '" << feProducerID <<
"' from buffer '"
636 << bufferID <<
"'..." << __E__;
638 auto bufferIt = buffers_.find(bufferID);
639 if(bufferIt == buffers_.end())
641 __CFG_SS__ <<
"While Un-Registering FE-producer '" << feProducerID
642 <<
",' buffer '" << bufferID <<
"' not found!" << __E__;
651 for(
auto feProducerIt = bufferIt->second.producers_.begin();
652 feProducerIt != bufferIt->second.producers_.end();
655 if((*feProducerIt)->getProcessorID() == feProducerID)
659 bufferIt->second.producers_.erase(feProducerIt);
664 __CFG_COUT__ <<
"Un-Registered FE-producer '" << feProducerID <<
"' from buffer '"
665 << bufferID <<
".'" << __E__;
668 dumpStatus((std::ostream*)&ss);
669 __CFG_COUT__ << ss.str() << __E__;
680 void DataManager::registerProducer(
const std::string& bufferUID,
683 __CFG_COUT__ <<
"Registering producer '" << producer->getProcessorID()
684 <<
"' to buffer '" << bufferUID <<
"'..." << __E__;
686 auto bufferIt = buffers_.find(bufferUID);
687 if(bufferIt == buffers_.end())
689 __CFG_SS__ <<
"Can't find buffer UID '" + bufferUID <<
"' for producer '"
690 << producer->getProcessorID()
691 <<
".' Make sure that your configuration is correct!" << __E__;
693 ss <<
"\n\n Here is the list of buffers:" << __E__;
694 for(
const auto bufferPair : buffers_)
695 ss << bufferPair.first << __E__;
702 __CFG_SS__ <<
"Before!" << __E__;
703 dumpStatus((std::ostream*)&ss);
704 __CFG_COUT__ << ss.str() << __E__;
707 __CFG_COUTV__(producer->getBufferSize());
708 bufferIt->second.buffer_->registerProducer(producer, producer->getBufferSize());
709 bufferIt->second.producers_.push_back(producer);
712 __CFG_SS__ <<
"After!" << __E__;
713 dumpStatus((std::ostream*)&ss);
714 __CFG_COUT__ << ss.str() << __E__;
719 void DataManager::registerConsumer(
const std::string& bufferUID,
DataConsumer* consumer)
721 __CFG_COUT__ <<
"Registering consumer '" << consumer->getProcessorID()
722 <<
"' to buffer '" << bufferUID <<
"'..." << __E__;
724 auto bufferIt = buffers_.find(bufferUID);
725 if(bufferIt == buffers_.end())
727 __CFG_SS__ <<
"Can't find buffer UID '" + bufferUID <<
"' for consumer '"
728 << consumer->getProcessorID()
729 <<
".' Make sure that your configuration is correct!" << __E__;
731 ss <<
"\n\n Here is the list of buffers:" << __E__;
732 for(
const auto bufferPair : buffers_)
733 ss << bufferPair.first << __E__;
739 __CFG_SS__ <<
"Before!" << __E__;
740 dumpStatus((std::ostream*)&ss);
741 __CFG_COUT__ << ss.str() << __E__;
744 bufferIt->second.buffer_->registerConsumer(consumer);
745 bufferIt->second.consumers_.push_back(consumer);
748 __CFG_SS__ <<
"After!" << __E__;
749 dumpStatus((std::ostream*)&ss);
750 __CFG_COUT__ << ss.str() << __E__;
757 for(
auto it = buffers_.begin(); it != buffers_.end(); it++)
758 startBuffer(it->first, runNumber);
762 void DataManager::stopAllBuffers(
void)
764 for(
auto it = buffers_.begin(); it != buffers_.end(); it++)
765 stopBuffer(it->first);
769 void DataManager::resumeAllBuffers(
void)
771 for(
auto it = buffers_.begin(); it != buffers_.end(); it++)
772 resumeBuffer(it->first);
776 void DataManager::pauseAllBuffers(
void)
778 for(
auto it = buffers_.begin(); it != buffers_.end(); it++)
779 pauseBuffer(it->first);
783 void DataManager::startBuffer(
const std::string& bufferUID, std::string runNumber)
785 __CFG_COUT__ <<
"Starting... " << bufferUID << __E__;
787 buffers_[bufferUID].buffer_->reset();
788 for(
auto& it : buffers_[bufferUID].consumers_)
793 it->startProcessingData(runNumber);
797 __CFG_COUT_WARN__ <<
"An error occurred while starting consumer '"
798 << it->getProcessorID() <<
"'..." << __E__;
803 for(
auto& it : buffers_[bufferUID].producers_)
808 it->startProcessingData(runNumber);
812 __CFG_COUT_WARN__ <<
"An error occurred while starting producer '"
813 << it->getProcessorID() <<
"'..." << __E__;
818 buffers_[bufferUID].status_ = Running;
823 void DataManager::stopBuffer(
const std::string& bufferUID)
825 __CFG_COUT__ <<
"Stopping... " << bufferUID << __E__;
827 __CFG_COUT__ <<
"Stopping producers..." << __E__;
828 for(
auto& it : buffers_[bufferUID].producers_)
833 it->stopProcessingData();
837 __CFG_COUT_WARN__ <<
"An error occurred while stopping producer '"
838 << it->getProcessorID() <<
"'..." << __E__;
844 unsigned int timeOut = 0;
845 const unsigned int ratio = 100;
846 const unsigned int sleepTime = 1000 * ratio;
847 unsigned int totalSleepTime =
850 .buffer_->getTotalNumberOfSubBuffers();
851 if(totalSleepTime < 5000000)
852 totalSleepTime = 5000000;
853 while(!buffers_[bufferUID].buffer_->isEmpty())
856 timeOut += sleepTime;
857 if(timeOut > totalSleepTime)
859 __CFG_COUT__ <<
"Couldn't flush all buffers! Timing out after "
860 << totalSleepTime / 1000000. <<
" seconds!" << __E__;
861 buffers_[bufferUID].buffer_->isEmpty();
865 __CFG_COUT__ <<
"Stopping consumers, buffer MUST BE EMPTY. Is buffer empty? "
866 << (buffers_[bufferUID].buffer_->isEmpty() ?
"yes" :
"no") << __E__;
868 for(
auto& it : buffers_[bufferUID].consumers_)
873 it->stopProcessingData();
877 __CFG_COUT_WARN__ <<
"An error occurred while stopping consumer '"
878 << it->getProcessorID() <<
"'..." << __E__;
883 buffers_[bufferUID].buffer_->reset();
884 buffers_[bufferUID].status_ = Initialized;
888 void DataManager::resumeBuffer(
const std::string& bufferUID)
890 __CFG_COUT__ <<
"Resuming... " << bufferUID << __E__;
892 for(
auto& it : buffers_[bufferUID].consumers_)
893 it->resumeProcessingData();
894 for(
auto& it : buffers_[bufferUID].producers_)
895 it->resumeProcessingData();
897 buffers_[bufferUID].status_ = Running;
901 void DataManager::pauseBuffer(
const std::string& bufferUID)
903 __CFG_COUT__ <<
"Pausing... " << bufferUID << __E__;
905 for(
auto& it : buffers_[bufferUID].producers_)
906 it->pauseProcessingData();
908 unsigned int timeOut = 0;
909 const unsigned int sleepTime = 1000;
910 while(!buffers_[bufferUID].buffer_->isEmpty())
913 timeOut += sleepTime;
916 buffers_[bufferUID].buffer_->getTotalNumberOfSubBuffers())
921 __CFG_COUT__ <<
"Couldn't flush all buffers! Timing out after "
922 << buffers_[bufferUID].buffer_->getTotalNumberOfSubBuffers() *
924 <<
" seconds!" << __E__;
928 for(
auto& it : buffers_[bufferUID].consumers_)
929 it->pauseProcessingData();
930 buffers_[bufferUID].status_ = Initialized;
void unregisterFEProducer(const std::string &bufferID, const std::string &feProducerID)
void startAllBuffers(const std::string &runNumber)