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 <thread>
00016 #include <chrono>
00017 #include <array>
00018 #include <list>
00019
00020 #include "fhiclcpp/fwd.h"
00021 #include "fhiclcpp/ParameterSet.h"
00022 #include "artdaq-core/Data/Fragment.hh"
00023 #include "artdaq-core/Generators/FragmentGenerator.hh"
00024 #include "artdaq-utilities/Plugins/MetricManager.hh"
00025 #include "artdaq/DAQrate/detail/RequestMessage.hh"
00026 #include "artdaq/DAQdata/Globals.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
00124 explicit CommandableFragmentGenerator(const fhicl::ParameterSet& ps);
00125
00131 virtual ~CommandableFragmentGenerator();
00132
00138 bool getNext(FragmentPtrs& output) override final;
00139
00145 bool applyRequests(FragmentPtrs& output);
00146
00150 void setupRequestListener();
00151
00159 bool sendEmptyFragment(FragmentPtrs& frags, size_t sequenceId, std::string desc);
00160
00166 void sendEmptyFragments(FragmentPtrs& frags);
00167
00171 void startDataThread();
00172
00176 void startMonitoringThread();
00177
00181 void startRequestReceiverThread();
00182
00187 void getDataLoop();
00188
00193 bool dataBufferIsTooLarge();
00194
00198 void getDataBufferStats();
00199
00205 void checkDataBuffer();
00206
00210 void getMonitoringDataLoop();
00211
00215 void receiveRequestsLoop();
00216
00221 std::vector<Fragment::fragment_id_t> fragmentIDs() override
00222 {
00223 return fragment_ids_;
00224 }
00225
00226
00227
00228
00229
00244 void StartCmd(int run, uint64_t timeout, uint64_t timestamp);
00245
00255 void StopCmd(uint64_t timeout, uint64_t timestamp);
00256
00266 void PauseCmd(uint64_t timeout, uint64_t timestamp);
00267
00276 void ResumeCmd(uint64_t timeout, uint64_t timestamp);
00277
00288 std::string ReportCmd(std::string const& which = "");
00289
00294 virtual std::string metricsReportingInstanceName() const
00295 {
00296 return instance_name_for_metrics_;
00297 }
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00319 bool exception() const { return exception_.load(); }
00320
00321 protected:
00322
00323
00324
00325
00326
00327
00328
00329
00330
00335 int run_number() const { return run_number_; }
00340 int subrun_number() const { return subrun_number_; }
00345 uint64_t timeout() const { return timeout_; }
00350 uint64_t timestamp() const { return timestamp_; }
00351
00356 bool should_stop() const { return should_stop_.load(); }
00357
00362 bool check_stop();
00363
00368 int board_id() const { return board_id_; }
00369
00375 int fragment_id() const;
00376
00381 size_t ev_counter() const { return ev_counter_.load(); }
00382
00389 size_t ev_counter_inc(size_t step = 1, bool force = false);
00390
00395 void set_exception(bool exception) { exception_.store(exception); }
00396
00401 void metricsReportingInstanceName(std::string const& name)
00402 {
00403 instance_name_for_metrics_ = name;
00404 }
00405
00410 std::string printMode_();
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 std::mutex mutex_;
00421
00422 private:
00423
00424
00425 int request_port_;
00426 std::string request_addr_;
00427
00428
00429 struct sockaddr_in si_data_;
00430 int request_socket_;
00431 std::map<Fragment::sequence_id_t, Fragment::timestamp_t> requests_;
00432 std::atomic<bool> request_stop_requested_;
00433 std::chrono::steady_clock::time_point request_stop_timeout_;
00434 size_t end_of_run_timeout_ms_;
00435 std::mutex request_mutex_;
00436 std::thread requestThread_;
00437
00438 RequestMode mode_;
00439 Fragment::timestamp_t windowOffset_;
00440 Fragment::timestamp_t windowWidth_;
00441 Fragment::timestamp_t staleTimeout_;
00442 size_t maxFragmentCount_;
00443 bool uniqueWindows_;
00444
00445 bool useDataThread_;
00446 std::atomic<bool> data_thread_running_;
00447 std::thread dataThread_;
00448
00449 std::condition_variable requestCondition_;
00450 std::condition_variable dataCondition_;
00451 std::atomic<int> dataBufferDepthFragments_;
00452 std::atomic<size_t> dataBufferDepthBytes_;
00453 int maxDataBufferDepthFragments_;
00454 size_t maxDataBufferDepthBytes_;
00455
00456 bool useMonitoringThread_;
00457 std::thread monitoringThread_;
00458 int64_t monitoringInterval_;
00459 std::chrono::steady_clock::time_point lastMonitoringCall_;
00460 bool isHardwareOK_;
00461
00462 FragmentPtrs dataBuffer_;
00463 FragmentPtrs newDataBuffer_;
00464 std::mutex dataBufferMutex_;
00465
00466 std::vector<artdaq::Fragment::fragment_id_t> fragment_ids_;
00467
00468
00469
00470
00471 int run_number_, subrun_number_;
00472
00473
00474
00475
00476 uint64_t timeout_;
00477
00478
00479
00480
00481
00482
00483
00484 uint64_t timestamp_;
00485
00486 std::atomic<bool> should_stop_, exception_;
00487 std::string latest_exception_report_;
00488 std::atomic<size_t> ev_counter_;
00489
00490 int board_id_;
00491 std::string instance_name_for_metrics_;
00492
00493
00494
00495
00496 int sleep_on_stop_us_;
00497
00498
00499
00500
00501
00502 virtual bool getNext_(FragmentPtrs& output) = 0;
00503
00504
00505
00506
00507
00508 virtual bool checkHWStatus_();
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520 virtual void start() = 0;
00521
00522
00523
00524 virtual void stopNoMutex() = 0;
00525
00526
00527
00528
00529
00530 virtual void stop() = 0;
00531
00532
00533
00534 virtual void pauseNoMutex();
00535
00536
00537
00538
00539 virtual void pause();
00540
00541
00542
00543
00544
00545 virtual void resume();
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 virtual std::string report();
00556
00557 virtual std::string reportSpecific(std::string const&);
00558 };
00559 }
00560
00561 #endif