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
00022 #include "artdaq/DAQdata/Globals.hh"
00023 #include "artdaq-core/Data/Fragment.hh"
00024 #include "artdaq-core/Generators/FragmentGenerator.hh"
00025 #include "artdaq-utilities/Plugins/MetricManager.hh"
00026 #include "artdaq/DAQrate/RequestReceiver.hh"
00027
00028 namespace artdaq
00029 {
00033 enum class RequestMode
00034 {
00035 Single,
00036 Buffer,
00037 Window,
00038 Ignored
00039 };
00040
00083 class CommandableFragmentGenerator : public FragmentGenerator
00084 {
00085 public:
00086
00092 CommandableFragmentGenerator();
00093
00128 explicit CommandableFragmentGenerator(const fhicl::ParameterSet& ps);
00129
00135 virtual ~CommandableFragmentGenerator();
00136
00137
00144 void joinThreads();
00145
00151 bool getNext(FragmentPtrs& output) override final;
00152
00153
00159 void applyRequestsIgnoredMode(artdaq::FragmentPtrs& frags);
00160
00166 void applyRequestsSingleMode(artdaq::FragmentPtrs& frags);
00167
00173 void applyRequestsBufferMode(artdaq::FragmentPtrs& frags);
00174
00180 void applyRequestsWindowMode(artdaq::FragmentPtrs& frags);
00181
00187 bool applyRequests(FragmentPtrs& output);
00188
00196 bool sendEmptyFragment(FragmentPtrs& frags, size_t sequenceId, std::string desc);
00197
00204 void sendEmptyFragments(FragmentPtrs& frags, std::map<Fragment::sequence_id_t, Fragment::timestamp_t>& requests);
00205
00209 void startDataThread();
00210
00214 void startMonitoringThread();
00215
00220 void getDataLoop();
00221
00226 bool waitForDataBufferReady();
00227
00232 bool dataBufferIsTooLarge();
00233
00237 void getDataBufferStats();
00238
00244 void checkDataBuffer();
00245
00249 void getMonitoringDataLoop();
00250
00255 std::vector<Fragment::fragment_id_t> fragmentIDs() override
00256 {
00257 return fragment_ids_;
00258 }
00259
00260
00261
00262
00263
00278 void StartCmd(int run, uint64_t timeout, uint64_t timestamp);
00279
00289 void StopCmd(uint64_t timeout, uint64_t timestamp);
00290
00300 void PauseCmd(uint64_t timeout, uint64_t timestamp);
00301
00310 void ResumeCmd(uint64_t timeout, uint64_t timestamp);
00311
00322 std::string ReportCmd(std::string const& which = "");
00323
00328 virtual std::string metricsReportingInstanceName() const
00329 {
00330 return instance_name_for_metrics_;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00353 bool exception() const { return exception_.load(); }
00354
00355 protected:
00356
00357
00358
00359
00360
00361
00362
00363
00364
00369 int run_number() const { return run_number_; }
00374 int subrun_number() const { return subrun_number_; }
00379 uint64_t timeout() const { return timeout_; }
00384 uint64_t timestamp() const { return timestamp_; }
00385
00390 bool should_stop() const { return should_stop_.load(); }
00391
00396 bool check_stop();
00397
00402 int board_id() const { return board_id_; }
00403
00409 int fragment_id() const;
00410
00415 size_t ev_counter() const { return ev_counter_.load(); }
00416
00423 size_t ev_counter_inc(size_t step = 1, bool force = false);
00424
00429 void set_exception(bool exception) { exception_.store(exception); }
00430
00435 void metricsReportingInstanceName(std::string const& name)
00436 {
00437 instance_name_for_metrics_ = name;
00438 }
00439
00444 std::string printMode_();
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 std::mutex mutex_;
00455
00456 private:
00457
00458
00459
00460
00461 struct sockaddr_in si_data_;
00462 std::unique_ptr<RequestReceiver> requestReceiver_;
00463
00464 RequestMode mode_;
00465 Fragment::timestamp_t windowOffset_;
00466 Fragment::timestamp_t windowWidth_;
00467 Fragment::timestamp_t staleTimeout_;
00468 Fragment::type_t expectedType_;
00469 size_t maxFragmentCount_;
00470 bool uniqueWindows_;
00471 bool missing_request_;
00472 std::chrono::steady_clock::time_point missing_request_time_;
00473 std::chrono::steady_clock::time_point last_window_send_time_;
00474 bool last_window_send_time_set_;
00475 std::set<Fragment::sequence_id_t> windows_sent_ooo_;
00476 size_t missing_request_window_timeout_us_;
00477 size_t window_close_timeout_us_;
00478
00479 bool useDataThread_;
00480 size_t sleep_on_no_data_us_;
00481 std::atomic<bool> data_thread_running_;
00482 boost::thread dataThread_;
00483
00484 std::condition_variable dataCondition_;
00485 std::atomic<int> dataBufferDepthFragments_;
00486 std::atomic<size_t> dataBufferDepthBytes_;
00487 int maxDataBufferDepthFragments_;
00488 size_t maxDataBufferDepthBytes_;
00489
00490 bool useMonitoringThread_;
00491 boost::thread monitoringThread_;
00492 int64_t monitoringInterval_;
00493 std::chrono::steady_clock::time_point lastMonitoringCall_;
00494 bool isHardwareOK_;
00495
00496 FragmentPtrs dataBuffer_;
00497 FragmentPtrs newDataBuffer_;
00498 std::mutex dataBufferMutex_;
00499
00500 std::vector<artdaq::Fragment::fragment_id_t> fragment_ids_;
00501
00502
00503
00504
00505 int run_number_, subrun_number_;
00506
00507
00508
00509
00510 uint64_t timeout_;
00511
00512
00513
00514
00515
00516
00517
00518 uint64_t timestamp_;
00519
00520 std::atomic<bool> should_stop_, exception_, force_stop_;
00521 std::string latest_exception_report_;
00522 std::atomic<size_t> ev_counter_;
00523
00524 int board_id_;
00525 std::string instance_name_for_metrics_;
00526
00527
00528
00529
00530 int sleep_on_stop_us_;
00531
00532 protected:
00533
00534
00535
00536
00537
00538 virtual bool getNext_(FragmentPtrs& output) = 0;
00539
00540
00541
00542
00543
00544 virtual bool checkHWStatus_();
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556 virtual void start() = 0;
00557
00558
00559
00560 virtual void stopNoMutex() = 0;
00561
00562
00563
00564
00565
00566 virtual void stop() = 0;
00567
00568
00569
00570 virtual void pauseNoMutex();
00571
00572
00573
00574
00575 virtual void pause();
00576
00577
00578
00579
00580
00581 virtual void resume();
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591 virtual std::string report();
00592
00593 virtual std::string reportSpecific(std::string const&);
00594 };
00595 }
00596
00597 #endif