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
00123 explicit CommandableFragmentGenerator(const fhicl::ParameterSet& ps);
00124
00130 virtual ~CommandableFragmentGenerator();
00131
00137 bool getNext(FragmentPtrs& output) override final;
00138
00144 bool applyRequests(FragmentPtrs& output);
00145
00149 void setupRequestListener();
00150
00158 bool sendEmptyFragment(FragmentPtrs& frags, size_t sequenceId, std::string desc);
00159
00165 void sendEmptyFragments(FragmentPtrs& frags);
00166
00170 void startDataThread();
00171
00175 void startMonitoringThread();
00176
00180 void startRequestReceiverThread();
00181
00186 void getDataLoop();
00187
00192 bool dataBufferIsTooLarge();
00193
00197 void getDataBufferStats();
00198
00204 void checkDataBuffer();
00205
00209 void getMonitoringDataLoop();
00210
00214 void receiveRequestsLoop();
00215
00220 std::vector<Fragment::fragment_id_t> fragmentIDs() override
00221 {
00222 return fragment_ids_;
00223 }
00224
00225
00226
00227
00228
00243 void StartCmd(int run, uint64_t timeout, uint64_t timestamp);
00244
00254 void StopCmd(uint64_t timeout, uint64_t timestamp);
00255
00265 void PauseCmd(uint64_t timeout, uint64_t timestamp);
00266
00275 void ResumeCmd(uint64_t timeout, uint64_t timestamp);
00276
00287 std::string ReportCmd(std::string const& which = "");
00288
00293 virtual std::string metricsReportingInstanceName() const
00294 {
00295 return instance_name_for_metrics_;
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00318 bool exception() const { return exception_.load(); }
00319
00320 protected:
00321
00322
00323
00324
00325
00326
00327
00328
00329
00334 int run_number() const { return run_number_; }
00339 int subrun_number() const { return subrun_number_; }
00344 uint64_t timeout() const { return timeout_; }
00349 uint64_t timestamp() const { return timestamp_; }
00350
00355 bool should_stop() const { return should_stop_.load(); }
00356
00361 bool check_stop();
00362
00367 int board_id() const { return board_id_; }
00368
00374 int fragment_id() const;
00375
00380 size_t ev_counter() const { return ev_counter_.load(); }
00381
00388 size_t ev_counter_inc(size_t step = 1, bool force = false);
00389
00394 void set_exception(bool exception) { exception_.store(exception); }
00395
00400 void metricsReportingInstanceName(std::string const& name)
00401 {
00402 instance_name_for_metrics_ = name;
00403 }
00404
00409 std::string printMode_();
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419 std::mutex mutex_;
00420
00421 private:
00422
00423
00424 int request_port_;
00425 std::string request_addr_;
00426
00427
00428 struct sockaddr_in si_data_;
00429 int request_socket_;
00430 std::map<Fragment::sequence_id_t, Fragment::timestamp_t> requests_;
00431 std::mutex request_mutex_;
00432 std::thread requestThread_;
00433
00434 RequestMode mode_;
00435 Fragment::timestamp_t windowOffset_;
00436 Fragment::timestamp_t windowWidth_;
00437 Fragment::timestamp_t staleTimeout_;
00438 size_t maxFragmentCount_;
00439 bool uniqueWindows_;
00440
00441 bool useDataThread_;
00442 std::thread dataThread_;
00443
00444 std::condition_variable requestCondition_;
00445 std::condition_variable dataCondition_;
00446 std::atomic<int> dataBufferDepthFragments_;
00447 std::atomic<size_t> dataBufferDepthBytes_;
00448 int maxDataBufferDepthFragments_;
00449 size_t maxDataBufferDepthBytes_;
00450
00451 bool useMonitoringThread_;
00452 std::thread monitoringThread_;
00453 int64_t monitoringInterval_;
00454 std::chrono::steady_clock::time_point lastMonitoringCall_;
00455 bool isHardwareOK_;
00456
00457 FragmentPtrs dataBuffer_;
00458 FragmentPtrs newDataBuffer_;
00459 std::mutex dataBufferMutex_;
00460
00461 std::vector<artdaq::Fragment::fragment_id_t> fragment_ids_;
00462
00463
00464
00465
00466 int run_number_, subrun_number_;
00467
00468
00469
00470
00471 uint64_t timeout_;
00472
00473
00474
00475
00476
00477
00478
00479 uint64_t timestamp_;
00480
00481 std::atomic<bool> should_stop_, exception_;
00482 std::string latest_exception_report_;
00483 std::atomic<size_t> ev_counter_;
00484
00485 int board_id_;
00486 std::string instance_name_for_metrics_;
00487
00488
00489
00490
00491 int sleep_on_stop_us_;
00492
00493
00494
00495
00496
00497 virtual bool getNext_(FragmentPtrs& output) = 0;
00498
00499
00500
00501
00502
00503 virtual bool checkHWStatus_();
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 virtual void start() = 0;
00516
00517
00518
00519 virtual void stopNoMutex() = 0;
00520
00521
00522
00523
00524
00525 virtual void stop() = 0;
00526
00527
00528
00529 virtual void pauseNoMutex();
00530
00531
00532
00533
00534 virtual void pause();
00535
00536
00537
00538
00539
00540 virtual void resume();
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550 virtual std::string report();
00551
00552 virtual std::string reportSpecific(std::string const&);
00553 };
00554 }
00555
00556 #endif