Line data Source code
1 : #ifndef artdaq_DAQrate_detail_RequestMessage_hh
2 : #define artdaq_DAQrate_detail_RequestMessage_hh
3 :
4 : #include "TRACE/tracemf.h" // Pre-empt TRACE/trace.h from Fragment.hh.
5 : #include "artdaq-core/Data/Fragment.hh"
6 : #define MAX_REQUEST_MESSAGE_SIZE 65000
7 :
8 : #include "artdaq/DAQdata/Globals.hh"
9 :
10 : #include <iostream>
11 : #include <vector>
12 :
13 : namespace artdaq {
14 : namespace detail {
15 : struct RequestPacket;
16 : struct RequestHeader;
17 : class RequestMessage;
18 :
19 : /**
20 : * \brief Mode used to indicate current run conditions to the request receiver
21 : */
22 : enum class RequestMessageMode : uint8_t
23 : {
24 : Normal = 0, ///< Normal running
25 : EndOfRun = 1, ///< End of Run mode (Used to end request processing on receiver)
26 : };
27 :
28 : /**
29 : * \brief Converts the RequestMessageMode to a string and sends it to the output stream
30 : * \param o Stream to send string to
31 : * \param m RequestMessageMode to convert to string
32 : * \return o with string sent to it
33 : */
34 0 : inline std::ostream& operator<<(std::ostream& o, RequestMessageMode m)
35 : {
36 0 : switch (m)
37 : {
38 0 : case RequestMessageMode::Normal:
39 0 : o << "Normal";
40 0 : break;
41 0 : case RequestMessageMode::EndOfRun:
42 0 : o << "EndOfRun";
43 0 : break;
44 : }
45 0 : return o;
46 : }
47 :
48 : } // namespace detail
49 : } // namespace artdaq
50 :
51 : /**
52 : * \brief The RequestPacket contains information about a single data request
53 : */
54 : struct artdaq::detail::RequestPacket
55 : {
56 : public:
57 : /** The magic bytes for the request packet */
58 : uint32_t header{0}; // TRIG, or 0x54524947
59 : Fragment::sequence_id_t sequence_id{Fragment::InvalidSequenceID}; ///< The sequence ID that responses to this request should use
60 : Fragment::timestamp_t timestamp{Fragment::InvalidTimestamp}; ///< The timestamp of the request
61 :
62 6 : RequestPacket() = default;
63 :
64 : /**
65 : * \brief Create a RequestPacket using the given sequence ID and timestmap
66 : * \param seq Sequence ID of RequestPacket
67 : * \param ts Timestamp of RequestPAcket
68 : */
69 6 : RequestPacket(const Fragment::sequence_id_t& seq, const Fragment::timestamp_t& ts)
70 6 : : header(0x54524947)
71 6 : , sequence_id(seq)
72 6 : , timestamp(ts)
73 6 : {}
74 :
75 : /**
76 : * \brief Check the magic bytes of the packet
77 : * \return Whether the correct magic bytes were found
78 : */
79 18 : bool isValid() const { return header == 0x54524947; }
80 : };
81 :
82 : /**
83 : * \brief Header of a RequestMessage. Contains magic bytes for validation and a count of expected RequestPackets
84 : */
85 : struct artdaq::detail::RequestHeader
86 : {
87 : /** The magic bytes for the request header */
88 : uint32_t header{0x48454452}; // HEDR, or 0x48454452
89 : uint32_t packet_count{0}; ///< The number of RequestPackets in this Request message
90 : int rank{my_rank}; ///< Rank of the sender
91 : uint32_t run_number{0}; ///< The Run with which this request should be associated
92 : RequestMessageMode mode{RequestMessageMode::Normal}; ///< Communicates additional information to the Request receiver
93 :
94 8 : RequestHeader() = default;
95 :
96 : /**
97 : * \brief Check the magic bytes of the packet
98 : * \return Whether the correct magic bytes were found
99 : */
100 16 : bool isValid() const { return header == 0x48454452; }
101 : };
102 :
103 : /**
104 : * \brief A RequestMessage consists of a RequestHeader and zero or more RequestPackets. They will usually be sent in two calls to send()
105 : */
106 : class artdaq::detail::RequestMessage
107 : {
108 : public:
109 : /**
110 : * \brief Default Constructor
111 : */
112 4 : RequestMessage()
113 4 : : header_()
114 4 : , packets_()
115 4 : {}
116 :
117 : /**
118 : * \brief Get the contents of the RequestMessage
119 : * \return Vector of bytes corresponding to the full RequestMessage (may span multiple packets)
120 : */
121 4 : std::vector<uint8_t> GetMessage()
122 : {
123 4 : auto size = sizeof(RequestHeader) + packets_.size() * sizeof(RequestPacket);
124 4 : header_.packet_count = packets_.size();
125 4 : assert(size < MAX_REQUEST_MESSAGE_SIZE);
126 4 : auto output = std::vector<uint8_t>(size);
127 4 : memcpy(&output[0], &header_, sizeof(RequestHeader));
128 4 : memcpy(&output[sizeof(RequestHeader)], &packets_[0], packets_.size() * sizeof(RequestPacket));
129 :
130 4 : return output;
131 : }
132 :
133 : /**
134 : * \brief Set the Request Message Mode for this request
135 : * \param mode Mode for this Request Message
136 : */
137 4 : void setMode(RequestMessageMode mode)
138 : {
139 4 : header_.mode = mode;
140 4 : }
141 :
142 : /**
143 : * \brief Set the rank in the header for this request. This will be the rank from which the request originates.
144 : * \param rank Rank for this Request Message
145 : */
146 4 : void setRank(int rank)
147 : {
148 4 : header_.rank = rank;
149 4 : }
150 :
151 : /**
152 : * \brief Set the run number in the header for this request.
153 : * This will be the Run for which the request is valid.
154 : * \param run Run number for this Request Message
155 : */
156 4 : void setRunNumber(int run)
157 : {
158 4 : header_.run_number = run;
159 4 : }
160 :
161 : /**
162 : * \brief Get the number of RequestPackets in the RequestMessage
163 : * \return The number of RequestPackets in the RequestMessage
164 : */
165 0 : size_t size() const { return packets_.size(); }
166 :
167 : /**
168 : * \brief Add a request for a sequence ID and timestamp combination
169 : * \param seq Sequence ID to request
170 : * \param time Timestamp of request
171 : */
172 6 : void addRequest(const Fragment::sequence_id_t& seq, const Fragment::timestamp_t& time)
173 : {
174 6 : packets_.emplace_back(RequestPacket(seq, time));
175 6 : }
176 :
177 : /**
178 : * @brief Get the maximum number of requests that can be sent in a single RequestMessage
179 : * @return The maximum number of reqeusts that fit in a single UDP datagram
180 : */
181 446 : static size_t max_request_count()
182 : {
183 446 : return (MAX_REQUEST_MESSAGE_SIZE - sizeof(RequestHeader)) / sizeof(RequestPacket);
184 : }
185 :
186 : private:
187 : RequestHeader header_;
188 : std::vector<RequestPacket> packets_;
189 : };
190 :
191 : #endif // artdaq_DAQrate_detail_RequestMessage
|