00001 #ifndef ARTDAQ_DAQRATE_DATATRANSFERMANAGER_HH
00002 #define ARTDAQ_DAQRATE_DATATRANSFERMANAGER_HH
00003
00004 #include <map>
00005 #include <set>
00006 #include <memory>
00007 #include <thread>
00008 #include <condition_variable>
00009
00010 #include "fhiclcpp/fwd.h"
00011
00012 #include "artdaq-core/Data/Fragment.hh"
00013 #include "artdaq/TransferPlugins/TransferInterface.hh"
00014 #include "artdaq/DAQrate/detail/FragCounter.hh"
00015 #include "artdaq-utilities/Plugins/MetricManager.hh"
00016
00017 namespace artdaq
00018 {
00019 class DataReceiverManager;
00020 class FragmentStoreElement;
00021 }
00022
00028 class artdaq::DataReceiverManager
00029 {
00030 public:
00031
00046 explicit DataReceiverManager(const fhicl::ParameterSet& ps);
00047
00051 virtual ~DataReceiverManager();
00052
00059 FragmentPtr recvFragment(int& rank, size_t timeout_usec = 0);
00060
00065 size_t count() const;
00066
00072 size_t slotCount(size_t rank) const;
00073
00078 size_t byteCount() const;
00079
00083 void start_threads();
00084
00089 std::set<int> enabled_sources() const { return enabled_sources_; }
00090
00095 void suppress_source(int source);
00096
00100 void unsuppressAll();
00101
00109 void reject_fragment(int source_rank, FragmentPtr frag);
00110
00111 private:
00112 void runReceiver_(int);
00113
00114 bool fragments_ready_() const;
00115
00116 int get_next_source_() const;
00117
00118 std::atomic<bool> stop_requested_;
00119
00120 std::map<int, std::thread> source_threads_;
00121 std::map<int, std::unique_ptr<TransferInterface>> source_plugins_;
00122 std::set<int> enabled_sources_;
00123 std::set<int> suppressed_sources_;
00124
00125 std::map<int, FragmentStoreElement> fragment_store_;
00126
00127 std::mutex input_cv_mutex_;
00128 std::condition_variable input_cv_;
00129 std::mutex output_cv_mutex_;
00130 std::condition_variable output_cv_;
00131
00132 detail::FragCounter recv_frag_count_;
00133 detail::FragCounter recv_frag_size_;
00134 detail::FragCounter recv_seq_count_;
00135 bool suppress_noisy_senders_;
00136 size_t suppression_threshold_;
00137
00138 size_t receive_timeout_;
00139 };
00140
00148 class artdaq::FragmentStoreElement
00149 {
00150 public:
00154 FragmentStoreElement()
00155 : frags_()
00156 , empty_(true)
00157 , eod_marker_(-1)
00158 {
00159 std::cout << "FragmentStoreElement CONSTRUCTOR" << std::endl;
00160 }
00161
00166 bool empty() const
00167 {
00168 return empty_;
00169 }
00170
00175 void emplace_front(FragmentPtr&& frag)
00176 {
00177 std::unique_lock<std::mutex> lk(mutex_);
00178 frags_.emplace_front(std::move(frag));
00179 empty_ = false;
00180 }
00181
00186 void emplace_back(FragmentPtr&& frag)
00187 {
00188 std::unique_lock<std::mutex> lk(mutex_);
00189 frags_.emplace_back(std::move(frag));
00190 empty_ = false;
00191 }
00192
00197 FragmentPtr front()
00198 {
00199 std::unique_lock<std::mutex> lk(mutex_);
00200 auto current_fragment = std::move(frags_.front());
00201 frags_.pop_front();
00202 empty_ = frags_.size() == 0;
00203 return std::move(current_fragment);
00204 }
00205
00210 void SetEndOfData(size_t eod) { eod_marker_ = eod; }
00215 size_t GetEndOfData() const { return eod_marker_; }
00216
00217 private:
00218 mutable std::mutex mutex_;
00219 FragmentPtrs frags_;
00220 std::atomic<bool> empty_;
00221 size_t eod_marker_;
00222 };
00223
00224 inline
00225 size_t
00226 artdaq::DataReceiverManager::
00227 count() const
00228 {
00229 return recv_frag_count_.count();
00230 }
00231
00232 inline
00233 size_t
00234 artdaq::DataReceiverManager::
00235 slotCount(size_t rank) const
00236 {
00237 return recv_frag_count_.slotCount(rank);
00238 }
00239
00240 inline
00241 size_t
00242 artdaq::DataReceiverManager::
00243 byteCount() const
00244 {
00245 return recv_frag_size_.count();
00246 }
00247 #endif //ARTDAQ_DAQRATE_DATATRANSFERMANAGER_HH