Line data Source code
1 : #ifndef artdaq_ArtModules_TransferInterface_hh
2 : #define artdaq_ArtModules_TransferInterface_hh
3 :
4 : #include "TRACE/tracemf.h" // Pre-empt TRACE/trace.h from Fragment.hh.
5 : #include "artdaq-core/Data/Fragment.hh"
6 :
7 : #include "artdaq/DAQdata/Globals.hh" // my_rank
8 :
9 : #include "artdaq-core/Data/detail/RawFragmentHeader.hh"
10 :
11 : #include "fhiclcpp/types/Atom.h"
12 : #include "fhiclcpp/types/Comment.h"
13 : #include "fhiclcpp/types/ConfigurationTable.h"
14 : #include "fhiclcpp/types/Name.h"
15 :
16 : namespace fhicl {
17 : class ParameterSet;
18 : }
19 :
20 : #include "cetlib/compiler_macros.h" // EXTERN_C_FUNC_*
21 :
22 : #include <iostream>
23 : #include <limits>
24 : #include <memory>
25 : #include <sstream>
26 : #include <string>
27 :
28 : namespace artdaq {
29 : /**
30 : * \brief This interface defines the functions used to transfer data between artdaq applications.
31 : */
32 : class TransferInterface
33 : {
34 : public:
35 : /// <summary>
36 : /// Configuration of the TransferInterface. May be used for parameter validation
37 : /// </summary>
38 : struct Config
39 : {
40 : /// "source_rank" (Default: my_rank) : The rank that data is coming from
41 : fhicl::Atom<int> source_rank{fhicl::Name{"source_rank"}, fhicl::Comment{"The rank that data is coming from"}, my_rank};
42 : /// "destination_rank" (Default: my_rank) : The rank that data is going to
43 : fhicl::Atom<int> destination_rank{fhicl::Name{"destination_rank"}, fhicl::Comment{"The rank that data is going to"}, my_rank};
44 : /// "unique_label" (Default: "transfer_between_[source_rank]_and_[destination_rank]") : A label that uniquely identifies the TransferInterface instance
45 : fhicl::Atom<std::string> unique_label{fhicl::Name{"unique_label"}, fhicl::Comment{"A label that uniquely identifies the TransferInterface instance"}, "transfer_between_[source_rank]_and_[destination_rank]"};
46 : /// "buffer_count" (Default: 10) : How many Fragments can the TransferInterface handle simultaneously
47 : fhicl::Atom<size_t> buffer_count{fhicl::Name{"buffer_count"}, fhicl::Comment{"How many Fragments can the TransferInterface handle simultaneously"}, 10};
48 : /// "max_fragment_size_words" (Default: 1024) : The maximum Fragment size expected.May be used for static memory allocation, and will cause errors if larger Fragments are sent.
49 : fhicl::Atom<size_t> max_fragment_size{fhicl::Name{"max_fragment_size_words"}, fhicl::Comment{"The maximum Fragment size expected.May be used for static memory allocation, and will cause errors if larger Fragments are sent."}, 1024};
50 : };
51 : /// Used for ParameterSet validation (if desired)
52 : using Parameters = fhicl::WrappedTable<Config>;
53 :
54 : /// <summary>
55 : /// Return codes from receive operations
56 : /// </summary>
57 : enum ReceiveReturnCode : int
58 : {
59 : DATA_END = -2222, ///< Value that is to be returned when a Transfer plugin determines that no more data will be arriving.
60 : RECV_TIMEOUT = -1111, ///< Value to be returned upon receive timeout.
61 : NO_RANK_INFO = -1, ///< Will be returned from a successful receive that does not know the source rank (Transfer to OM art process)
62 : RECV_SUCCESS = 0 ///< For code clarity, things checking for successful receive should check retval >= NO_RANK_INFO
63 : };
64 :
65 : /**
66 : * \brief Used to determine if a TransferInterface is a Sender or Receiver
67 : */
68 : enum class Role
69 : {
70 : kSend, ///< This TransferInterface is a Sender
71 : kReceive ///< This TransferInterface is a Receiver
72 : };
73 :
74 : /**
75 : * \brief Returned from the send functions, this enumeration describes the possible return codes.
76 : * If an exception occurs, it will be thrown and should be handled normally.
77 : */
78 : enum class CopyStatus
79 : {
80 : kSuccess, ///< The send operation completed successfully
81 : kTimeout, ///< The send operation timed out
82 : kErrorNotRequiringException ///< Some error occurred, but no exception was thrown
83 : };
84 :
85 : /// <summary>
86 : /// Convert a CopyStatus variable to its string represenatation
87 : /// </summary>
88 : /// <param name="in">CopyStatus to convert</param>
89 : /// <returns>String representation of CopyStatus</returns>
90 0 : static std::string CopyStatusToString(CopyStatus in)
91 : {
92 0 : switch (in)
93 : {
94 0 : case CopyStatus::kSuccess:
95 0 : return "Success";
96 0 : case CopyStatus::kTimeout:
97 0 : return "Timeout";
98 0 : case CopyStatus::kErrorNotRequiringException:
99 0 : return "Error";
100 0 : default:
101 0 : return "UNKNOWN";
102 : }
103 : return "SWITCHERROR";
104 : }
105 :
106 : /**
107 : * \brief TransferInterface Constructor
108 : * \param ps ParameterSet used for configuring the TransferInterface. See artdaq::TransferInterface::Config
109 : * \param role Role of the TransferInterface (See TransferInterface::Role)
110 : */
111 : TransferInterface(const fhicl::ParameterSet& ps, Role role);
112 :
113 : /**
114 : * \brief Copy Constructor is deleted
115 : */
116 : TransferInterface(const TransferInterface&) = delete;
117 :
118 : /**
119 : * \brief Copy Assignment operator is deleted
120 : * \return TransferInterface Copy
121 : */
122 : TransferInterface& operator=(const TransferInterface&) = delete;
123 :
124 : /**
125 : * \brief Default virtual Destructor
126 : */
127 3 : virtual ~TransferInterface() = default;
128 :
129 : /**
130 : * \brief Receive a Fragment from the transport mechanism
131 : * \param[out] fragment Received Fragment
132 : * \param receive_timeout Timeout for receive
133 : * \return The rank the Fragment was received from (should be source_rank), or RECV_TIMEOUT
134 : */
135 : virtual int receiveFragment(artdaq::Fragment& fragment, size_t receive_timeout);
136 :
137 : /**
138 : * \brief Receive a Fragment Header from the transport mechanism
139 : * \param[out] header Received Fragment Header
140 : * \param receiveTimeout Timeout for receive
141 : * \return The rank the Fragment was received from (should be source_rank), or RECV_TIMEOUT
142 : */
143 : virtual int receiveFragmentHeader(detail::RawFragmentHeader& header, size_t receiveTimeout) = 0;
144 :
145 : /**
146 : * \brief Receive the body of a Fragment to the given destination pointer
147 : * \param destination Pointer to memory region where Fragment data should be stored
148 : * \param wordCount Number of words of Fragment data to receive
149 : * \return The rank the Fragment was received from (should be source_rank), or RECV_TIMEOUT
150 : *
151 : * The precondition for calling this function is that you have received a valid header, therefore it does
152 : * not have a , as the Fragment data should immediately be available.
153 : */
154 : virtual int receiveFragmentData(RawDataType* destination, size_t wordCount) = 0;
155 :
156 : /**
157 : * \brief Transfer a Fragment to the destination. May not necessarily be reliable, but will not block longer than send_timeout_usec.
158 : * \param fragment Fragment to transfer
159 : * \param send_timeout_usec Timeout for send, in microseconds
160 : * \return CopyStatus detailing result of transfer
161 : */
162 : virtual CopyStatus transfer_fragment_min_blocking_mode(artdaq::Fragment const& fragment, size_t send_timeout_usec) = 0;
163 :
164 : /**
165 : * \brief Transfer a Fragment to the destination. This should be reliable, if the underlying transport mechanism supports reliable sending
166 : * \param fragment Fragment to transfer
167 : * \return CopyStatus detailing result of copy
168 : */
169 : virtual CopyStatus transfer_fragment_reliable_mode(artdaq::Fragment&& fragment) = 0;
170 :
171 : /**
172 : * \brief Get the unique label of this TransferInterface instance
173 : * \return The unique label of this TransferInterface instance
174 : */
175 : std::string uniqueLabel() const { return unique_label_; }
176 :
177 : /**
178 : * \brief Get the source rank for this TransferInterface instance
179 : * \return The source rank for this Transferinterface instance
180 : */
181 143 : virtual int source_rank() const { return source_rank_; }
182 : /**
183 : * \brief Get the destination rank for this TransferInterface instance
184 : * \return The destination rank for this TransferInterface instance
185 : */
186 4 : virtual int destination_rank() const { return destination_rank_; }
187 :
188 : /**
189 : * \brief Determine whether the TransferInterface plugin is able to send/receive data
190 : * \return True if the TransferInterface plugin is currently able to send/receive data
191 : */
192 0 : virtual bool isRunning() { return false; }
193 :
194 : /**
195 : * \brief Flush any in-flight data. This should be used by the receiver after the receive loop has ended.
196 : */
197 : virtual void flush_buffers() = 0;
198 :
199 : /** \cond */
200 : #define GetTraceName() unique_label_ << (role_ == Role::kSend ? std::string("_SEND: ") : std::string("_RECV: "))
201 : /** \endcond */
202 :
203 : protected:
204 : TransferInterface(TransferInterface&&) = delete; ///< Move Constructor is deleted
205 : TransferInterface& operator=(TransferInterface&&) = delete; ///< Move Assignment Operator is deleted
206 :
207 : const Role role_; ///< Whether this instance of TransferInterface is a sender or receiver
208 :
209 : const int source_rank_; ///< Rank of source
210 : const int destination_rank_; ///< Rank of destination
211 : const std::string unique_label_; ///< Unique label of transfer (ideally the same on sender and receiver)
212 :
213 : size_t buffer_count_; ///< The number of Fragment transfers the TransferInterface can handle simultaneously
214 : const size_t max_fragment_size_words_; ///< The maximum size of the transferred Fragment objects, in artdaq::Fragment::RawDataType words
215 :
216 : protected:
217 : /**
218 : * \brief Get the TransferInterface::Role of this TransferInterface
219 : * \return The Role of this TransferInterface
220 : */
221 5 : Role role() const { return role_; }
222 : };
223 : } // namespace artdaq
224 :
225 : /** \cond */
226 :
227 : #ifndef EXTERN_C_FUNC_DECLARE_START
228 : #define EXTERN_C_FUNC_DECLARE_START extern "C" {
229 : #endif
230 :
231 : #define DEFINE_ARTDAQ_TRANSFER(klass) \
232 : EXTERN_C_FUNC_DECLARE_START \
233 : std::unique_ptr<artdaq::TransferInterface> make(fhicl::ParameterSet const& ps, artdaq::TransferInterface::Role role) \
234 : { \
235 : return std::unique_ptr<artdaq::TransferInterface>(new klass(ps, role)); \
236 : } \
237 : }
238 :
239 : /** \endcond */
240 :
241 : #endif /* artdaq_ArtModules_TransferInterface.hh */
242 :
243 : // Local Variables:
244 : // mode: c++
245 : // End:
|