00001 #ifndef ARTDAQ_DAQRATE_DATATRANSFERMANAGER_HH
00002 #define ARTDAQ_DAQRATE_DATATRANSFERMANAGER_HH
00003
00004 #include <map>
00005 #include <set>
00006 #include <memory>
00007 #include <condition_variable>
00008
00009 #include "fhiclcpp/fwd.h"
00010
00011 #include "artdaq-core/Data/Fragment.hh"
00012 #include "artdaq/TransferPlugins/TransferInterface.hh"
00013 #include "artdaq/DAQrate/detail/FragCounter.hh"
00014 #include "artdaq-utilities/Plugins/MetricManager.hh"
00015
00016 namespace artdaq
00017 {
00018 class FragmentReceiverManager;
00019 class FragmentStoreElement;
00020 }
00021
00027 class artdaq::FragmentReceiverManager
00028 {
00029 public:
00030
00045 explicit FragmentReceiverManager(const fhicl::ParameterSet& ps);
00046
00050 virtual ~FragmentReceiverManager();
00051
00058 FragmentPtr recvFragment(int& rank, size_t timeout_usec = 0);
00059
00064 size_t count() const;
00065
00071 size_t slotCount(size_t rank) const;
00072
00077 size_t byteCount() const;
00078
00082 void start_threads();
00083
00088 std::set<int> enabled_sources() const;
00089
00094 std::set<int> running_sources() const;
00095
00096 private:
00097 void runReceiver_(int);
00098
00099 bool fragments_ready_() const;
00100
00101 int get_next_source_() const;
00102
00103 std::atomic<bool> stop_requested_;
00104
00105 std::map<int, boost::thread> source_threads_;
00106 std::map<int, std::unique_ptr<TransferInterface>> source_plugins_;
00107 std::unordered_map<int, std::pair<size_t, double>> source_metric_data_;
00108 std::unordered_map<int, std::chrono::steady_clock::time_point> source_metric_send_time_;
00109 std::unordered_map<int, std::atomic<bool>> enabled_sources_;
00110 std::unordered_map<int, std::atomic<bool>> running_sources_;
00111
00112 std::map<int, FragmentStoreElement> fragment_store_;
00113
00114 std::mutex input_cv_mutex_;
00115 std::condition_variable input_cv_;
00116 std::mutex output_cv_mutex_;
00117 std::condition_variable output_cv_;
00118
00119 detail::FragCounter recv_frag_count_;
00120 detail::FragCounter recv_frag_size_;
00121 detail::FragCounter recv_seq_count_;
00122 bool suppress_noisy_senders_;
00123 size_t suppression_threshold_;
00124
00125 size_t receive_timeout_;
00126 mutable int last_source_;
00127 };
00128
00136 class artdaq::FragmentStoreElement
00137 {
00138 public:
00142 FragmentStoreElement()
00143 : frags_()
00144 , empty_(true)
00145 , eod_marker_(-1)
00146 {
00147 std::cout << "FragmentStoreElement CONSTRUCTOR" << std::endl;
00148 }
00149
00154 bool empty() const
00155 {
00156 return empty_;
00157 }
00158
00163 void emplace_front(FragmentPtr&& frag)
00164 {
00165 std::unique_lock<std::mutex> lk(mutex_);
00166 frags_.emplace_front(std::move(frag));
00167 empty_ = false;
00168 }
00169
00174 void emplace_back(FragmentPtr&& frag)
00175 {
00176 std::unique_lock<std::mutex> lk(mutex_);
00177 frags_.emplace_back(std::move(frag));
00178 empty_ = false;
00179 }
00180
00185 FragmentPtr front()
00186 {
00187 std::unique_lock<std::mutex> lk(mutex_);
00188 auto current_fragment = std::move(frags_.front());
00189 frags_.pop_front();
00190 empty_ = frags_.size() == 0;
00191 return current_fragment;
00192 }
00193
00198 void SetEndOfData(size_t eod) { eod_marker_ = eod; }
00203 size_t GetEndOfData() const { return eod_marker_; }
00204
00209 size_t size() const { return frags_.size(); }
00210
00211 private:
00212 mutable std::mutex mutex_;
00213 FragmentPtrs frags_;
00214 std::atomic<bool> empty_;
00215 size_t eod_marker_;
00216 };
00217
00218 inline
00219 size_t
00220 artdaq::FragmentReceiverManager::
00221 count() const
00222 {
00223 return recv_frag_count_.count();
00224 }
00225
00226 inline
00227 size_t
00228 artdaq::FragmentReceiverManager::
00229 slotCount(size_t rank) const
00230 {
00231 return recv_frag_count_.slotCount(rank);
00232 }
00233
00234 inline
00235 size_t
00236 artdaq::FragmentReceiverManager::
00237 byteCount() const
00238 {
00239 return recv_frag_size_.count();
00240 }
00241 #endif //ARTDAQ_DAQRATE_DATATRANSFERMANAGER_HH