00001 #ifndef artdaq_Application_CommandableFragmentGenerator_hh
00002 #define artdaq_Application_CommandableFragmentGenerator_hh
00003
00004
00005 #include <arpa/inet.h>
00006 #include <netinet/in.h>
00007 #include <sys/types.h>
00008 #include <sys/socket.h>
00009 #include <unistd.h>
00010
00011 #include <atomic>
00012 #include <condition_variable>
00013 #include <mutex>
00014 #include <queue>
00015 #include <chrono>
00016 #include <array>
00017 #include <list>
00018
00019 #include "fhiclcpp/fwd.h"
00020 #include "fhiclcpp/ParameterSet.h"
00021 #include "artdaq-core/Data/Fragment.hh"
00022 #include "artdaq-core/Generators/FragmentGenerator.hh"
00023 #include "artdaq-utilities/Plugins/MetricManager.hh"
00024 #include "artdaq/DAQrate/detail/RequestMessage.hh"
00025 #include "artdaq/DAQdata/Globals.hh"
00026
00027 namespace artdaq
00028 {
00032 enum class RequestMode
00033 {
00034 Single,
00035 Buffer,
00036 Window,
00037 Ignored
00038 };
00039
00082 class CommandableFragmentGenerator : public FragmentGenerator
00083 {
00084 public:
00085
00091 CommandableFragmentGenerator();
00092
00127 explicit CommandableFragmentGenerator(const fhicl::ParameterSet& ps);
00128
00134 virtual ~CommandableFragmentGenerator();
00135
00136
00143 void joinThreads();
00144
00150 bool getNext(FragmentPtrs& output) override final;
00151
00152
00158 void applyRequestsIgnoredMode(artdaq::FragmentPtrs& frags);
00159
00165 void applyRequestsSingleMode(artdaq::FragmentPtrs& frags);
00166
00172 void applyRequestsBufferMode(artdaq::FragmentPtrs& frags);
00173
00179 void applyRequestsWindowMode(artdaq::FragmentPtrs& frags);
00180
00186 bool applyRequests(FragmentPtrs& output);
00187
00191 void setupRequestListener();
00192
00200 bool sendEmptyFragment(FragmentPtrs& frags, size_t sequenceId, std::string desc);
00201
00207 void sendEmptyFragments(FragmentPtrs& frags);
00208
00212 void startDataThread();
00213
00217 void startMonitoringThread();
00218
00222 void startRequestReceiverThread();
00223
00228 void getDataLoop();
00229
00234 bool waitForDataBufferReady();
00235
00240 bool dataBufferIsTooLarge();
00241
00245 void getDataBufferStats();
00246
00252 void checkDataBuffer();
00253
00257 void getMonitoringDataLoop();
00258
00262 void receiveRequestsLoop();
00263
00268 std::vector<Fragment::fragment_id_t> fragmentIDs() override
00269 {
00270 return fragment_ids_;
00271 }
00272
00273
00274
00275
00276
00291 void StartCmd(int run, uint64_t timeout, uint64_t timestamp);
00292
00302 void StopCmd(uint64_t timeout, uint64_t timestamp);
00303
00313 void PauseCmd(uint64_t timeout, uint64_t timestamp);
00314
00323 void ResumeCmd(uint64_t timeout, uint64_t timestamp);
00324
00335 std::string ReportCmd(std::string const& which = "");
00336
00341 virtual std::string metricsReportingInstanceName() const
00342 {
00343 return instance_name_for_metrics_;
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00366 bool exception() const { return exception_.load(); }
00367
00368 protected:
00369
00370
00371
00372
00373
00374
00375
00376
00377
00382 int run_number() const { return run_number_; }
00387 int subrun_number() const { return subrun_number_; }
00392 uint64_t timeout() const { return timeout_; }
00397 uint64_t timestamp() const { return timestamp_; }
00398
00403 bool should_stop() const { return should_stop_.load(); }
00404
00409 bool check_stop();
00410
00415 int board_id() const { return board_id_; }
00416
00422 int fragment_id() const;
00423
00428 size_t ev_counter() const { return ev_counter_.load(); }
00429
00436 size_t ev_counter_inc(size_t step = 1, bool force = false);
00437
00442 void set_exception(bool exception) { exception_.store(exception); }
00443
00448 void metricsReportingInstanceName(std::string const& name)
00449 {
00450 instance_name_for_metrics_ = name;
00451 }
00452
00457 std::string printMode_();
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 std::mutex mutex_;
00468
00469 private:
00470
00471
00472 int request_port_;
00473 std::string request_addr_;
00474
00475
00476 struct sockaddr_in si_data_;
00477 int request_socket_;
00478 std::map<Fragment::sequence_id_t, Fragment::timestamp_t> requests_;
00479 std::atomic<bool> request_stop_requested_;
00480 std::chrono::steady_clock::time_point request_stop_timeout_;
00481 std::atomic<bool> request_received_;
00482 size_t end_of_run_timeout_ms_;
00483 std::mutex request_mutex_;
00484 boost::thread requestThread_;
00485
00486 RequestMode mode_;
00487 Fragment::timestamp_t windowOffset_;
00488 Fragment::timestamp_t windowWidth_;
00489 Fragment::timestamp_t staleTimeout_;
00490 Fragment::type_t expectedType_;
00491 size_t maxFragmentCount_;
00492 bool uniqueWindows_;
00493 bool missing_request_;
00494 std::chrono::steady_clock::time_point missing_request_time_;
00495 std::chrono::steady_clock::time_point last_window_send_time_;
00496
00497 bool last_window_send_time_set_;
00498 size_t missing_request_window_timeout_us_;
00499 size_t window_close_timeout_us_;
00500
00501 bool useDataThread_;
00502 size_t sleep_on_no_data_us_;
00503 std::atomic<bool> data_thread_running_;
00504 boost::thread dataThread_;
00505
00506 std::condition_variable requestCondition_;
00507 std::condition_variable dataCondition_;
00508 std::atomic<int> dataBufferDepthFragments_;
00509 std::atomic<size_t> dataBufferDepthBytes_;
00510 int maxDataBufferDepthFragments_;
00511 size_t maxDataBufferDepthBytes_;
00512
00513 bool useMonitoringThread_;
00514 boost::thread monitoringThread_;
00515 int64_t monitoringInterval_;
00516 std::chrono::steady_clock::time_point lastMonitoringCall_;
00517 bool isHardwareOK_;
00518
00519 FragmentPtrs dataBuffer_;
00520 FragmentPtrs newDataBuffer_;
00521 std::mutex dataBufferMutex_;
00522
00523 std::vector<artdaq::Fragment::fragment_id_t> fragment_ids_;
00524
00525
00526
00527
00528 int run_number_, subrun_number_;
00529
00530
00531
00532
00533 uint64_t timeout_;
00534
00535
00536
00537
00538
00539
00540
00541 uint64_t timestamp_;
00542
00543 std::atomic<bool> should_stop_, exception_, force_stop_;
00544 std::string latest_exception_report_;
00545 std::atomic<size_t> ev_counter_;
00546
00547 int board_id_;
00548 std::string instance_name_for_metrics_;
00549
00550
00551
00552
00553 int sleep_on_stop_us_;
00554
00555 protected:
00556
00557
00558
00559
00560
00561 virtual bool getNext_(FragmentPtrs& output) = 0;
00562
00563
00564
00565
00566
00567 virtual bool checkHWStatus_();
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579 virtual void start() = 0;
00580
00581
00582
00583 virtual void stopNoMutex() = 0;
00584
00585
00586
00587
00588
00589 virtual void stop() = 0;
00590
00591
00592
00593 virtual void pauseNoMutex();
00594
00595
00596
00597
00598 virtual void pause();
00599
00600
00601
00602
00603
00604 virtual void resume();
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614 virtual std::string report();
00615
00616 virtual std::string reportSpecific(std::string const&);
00617 };
00618 }
00619
00620 #endif