DUNE-DAQ
DUNE Trigger and Data Acquisition software
Toggle main menu visibility
Loading...
Searching...
No Matches
dunedaq
sourcecode
iomanager
include
iomanager
network
detail
NetworkReceiverModel.hxx
Go to the documentation of this file.
1
#include "
iomanager/Receiver.hpp
"
2
#include "
iomanager/network/NetworkIssues.hpp
"
3
#include "
iomanager/network/NetworkManager.hpp
"
4
5
#include "
ipm/Subscriber.hpp
"
6
#include "
logging/Logging.hpp
"
7
#include "
serialization/Serialization.hpp
"
8
#include "
utilities/Issues.hpp
"
9
10
#include <atomic>
11
#include <memory>
12
#include <optional>
13
#include <string>
14
#include <thread>
15
#include <typeinfo>
16
#include <utility>
17
18
namespace
dunedaq::iomanager
{
19
20
template
<
typename
Datatype>
21
inline
NetworkReceiverModel<Datatype>::NetworkReceiverModel
(
ConnectionId
const
& conn_id)
22
:
ReceiverConcept
<Datatype>(conn_id)
23
{
24
TLOG
() <<
"NetworkReceiverModel created with DT! ID: "
<< conn_id.
uid
<<
" Addr: "
<<
static_cast<
void
*
>
(
this
);
25
try
{
26
get_receiver
(std::chrono::milliseconds(1000));
27
}
catch
(
ConnectionNotFound
const
& ex) {
28
TLOG
() <<
"Initial connection attempt failed: "
<< ex;
29
}
30
}
31
32
template
<
typename
Datatype>
33
inline
NetworkReceiverModel<Datatype>::NetworkReceiverModel
(
NetworkReceiverModel
&& other)
34
:
ReceiverConcept
<Datatype>(other.
m_conn
.uid)
35
,
m_callback
(
std
::move(other.
m_callback
))
36
,
m_event_loop_runner
(
std
::move(other.
m_event_loop_runner
))
37
,
m_network_receiver_ptr
(
std
::move(other.
m_network_receiver_ptr
))
38
{
39
}
40
41
template
<
typename
Datatype>
42
inline
Datatype
43
NetworkReceiverModel<Datatype>::receive
(
Receiver::timeout_t
timeout)
44
{
45
try
{
46
return
read_network<Datatype>
(timeout);
47
}
catch
(ipm::ReceiveTimeoutExpired& ex) {
48
throw
TimeoutExpired
(
ERS_HERE
, this->
id
().uid,
"receive"
, timeout.count(), ex);
49
}
50
}
51
52
template
<
typename
Datatype>
53
inline
void
54
NetworkReceiverModel<Datatype>::remove_callback
()
55
{
56
std::lock_guard<std::mutex> lk(
m_callback_mutex
);
57
if
(
m_event_loop_runner
!=
nullptr
&&
m_event_loop_runner
->joinable()) {
58
m_event_loop_runner
->request_stop();
59
m_event_loop_runner
->join();
60
}
else
if
(
m_event_loop_runner
!=
nullptr
) {
61
TLOG
() <<
"Event loop can't be closed!"
;
62
}
63
m_event_loop_runner
.reset(
nullptr
);
64
// remove function.
65
}
66
67
template
<
typename
Datatype>
68
inline
void
69
NetworkReceiverModel<Datatype>::subscribe
(std::string topic)
70
{
71
if
(
NetworkManager::get
().is_pubsub_connection(this->
m_conn
)) {
72
std::dynamic_pointer_cast<ipm::Subscriber>(
m_network_receiver_ptr
)->subscribe(topic);
73
}
74
}
75
76
template
<
typename
Datatype>
77
inline
void
78
NetworkReceiverModel<Datatype>::unsubscribe
(std::string topic)
79
{
80
if
(
NetworkManager::get
().is_pubsub_connection(this->
m_conn
)) {
81
std::dynamic_pointer_cast<ipm::Subscriber>(
m_network_receiver_ptr
)->unsubscribe(topic);
82
}
83
}
84
85
template
<
typename
Datatype>
86
inline
void
87
NetworkReceiverModel<Datatype>::get_receiver
(
Receiver::timeout_t
timeout)
88
{
89
// get network resources
90
auto
start = std::chrono::steady_clock::now();
91
while
(
m_network_receiver_ptr
==
nullptr
&&
92
std::chrono::duration_cast<Receiver::timeout_t>(std::chrono::steady_clock::now() - start) < timeout) {
93
94
try
{
95
m_network_receiver_ptr
=
NetworkManager::get
().
get_receiver
(this->
id
());
96
}
catch
(
ConnectionNotFound
const
& ex) {
97
m_network_receiver_ptr
=
nullptr
;
98
std::this_thread::sleep_for(std::chrono::milliseconds(10));
99
}
100
}
101
}
102
103
template
<
typename
Datatype>
104
template
<
typename
MessageType>
105
inline
typename
std::enable_if<serialization::is_serializable<MessageType>::value, MessageType>
::type
106
NetworkReceiverModel<Datatype>::read_network
(
Receiver::timeout_t
const
& timeout)
107
{
108
std::lock_guard<std::mutex> lk(
m_receive_mutex
);
109
get_receiver
(timeout);
110
111
if
(
m_network_receiver_ptr
==
nullptr
) {
112
throw
ConnectionInstanceNotFound(
ERS_HERE
, this->
id
().uid);
113
}
114
115
auto
response =
m_network_receiver_ptr
->receive(timeout);
116
if
(response.data.size() > 0) {
117
return
serialization::deserialize<MessageType>(response.data);
118
}
119
120
throw
TimeoutExpired
(
ERS_HERE
, this->
id
().uid,
"network receive"
, timeout.count());
121
return
MessageType();
122
}
123
124
template
<
typename
Datatype>
125
template
<
typename
MessageType>
126
inline
typename
std::enable_if<!serialization::is_serializable<MessageType>::value, MessageType>
::type
127
NetworkReceiverModel<Datatype>::read_network
(
Receiver::timeout_t
const
&)
128
{
129
throw
NetworkMessageNotSerializable(
ERS_HERE
,
typeid
(MessageType).name());
// NOLINT(runtime/rtti)
130
return
MessageType();
131
}
132
133
template
<
typename
Datatype>
134
template
<
typename
MessageType>
135
inline
typename
std::enable_if<serialization::is_serializable<MessageType>::value, std::optional<MessageType>>
::type
136
NetworkReceiverModel<Datatype>::try_read_network
(
Receiver::timeout_t
const
& timeout)
137
{
138
std::lock_guard<std::mutex> lk(
m_receive_mutex
);
139
get_receiver
(timeout);
140
if
(
m_network_receiver_ptr
==
nullptr
) {
141
TLOG_DEBUG
(5) << ConnectionInstanceNotFound(
ERS_HERE
, this->
id
().uid);
142
return
std::nullopt;
143
}
144
145
ipm::Receiver::Response
res;
146
res =
m_network_receiver_ptr
->receive(timeout,
ipm::Receiver::s_any_size
,
true
);
147
148
if
(res.
data
.size() > 0) {
149
return
std::make_optional<MessageType>(serialization::deserialize<MessageType>(res.
data
));
150
}
151
152
return
std::nullopt;
153
}
154
155
template
<
typename
Datatype>
156
template
<
typename
MessageType>
157
inline
typename
std::enable_if<!serialization::is_serializable<MessageType>::value, std::optional<MessageType>>
::type
158
NetworkReceiverModel<Datatype>::try_read_network
(
Receiver::timeout_t
const
&)
159
{
160
ers::error
(NetworkMessageNotSerializable(
ERS_HERE
,
typeid
(MessageType).name()));
// NOLINT(runtime/rtti)
161
return
std::nullopt;
162
}
163
164
template
<
typename
Datatype>
165
template
<
typename
MessageType>
166
inline
typename
std::enable_if<serialization::is_serializable<MessageType>::value,
void
>
::type
167
NetworkReceiverModel<Datatype>::add_callback_impl
(std::function<
void
(MessageType&)> callback)
168
{
169
remove_callback
();
170
{
171
// This ensures that add_callback_impl and remove_callback are not processing concurrently
172
std::lock_guard<std::mutex> lk(
m_callback_mutex
);
173
}
174
TLOG
() <<
"Registering callback."
;
175
m_callback
= callback;
176
// start event loop (thread that calls when receive happens). remove_callback() is called in the destructor, so this
177
// will never go out-of-scope while this is running
178
m_event_loop_runner
= std::make_unique<std::jthread>([&](std::stop_token token) {
179
std::optional<Datatype> message;
180
while
(!token.stop_requested() || message) {
181
try
{
182
// 0 timeout when we are trying to stop
183
message =
try_read_network<Datatype>
(token.stop_requested() ? std::chrono::milliseconds(0)
184
: std::chrono::milliseconds(20));
185
if
(message) {
186
m_callback
(*message);
187
}
188
}
catch
(
const
ers::Issue
&) {
189
// Intentionally ignoring any ers::Issues that might have been raised
190
;
191
}
192
}
193
});
194
auto
handle =
m_event_loop_runner
->native_handle();
195
std::string name =
"N_"
+ this->
id
().uid;
196
name.resize(15);
197
auto
rc = pthread_setname_np(handle, name.c_str());
198
if
(rc != 0) {
199
std::ostringstream s;
200
s <<
"The name "
<< name <<
" provided for the thread is too long."
;
201
ers::warning
(utilities::ThreadingIssue(
ERS_HERE
, s.str()));
202
}
203
}
204
205
template
<
typename
Datatype>
206
template
<
typename
MessageType>
207
inline
typename
std::enable_if<!serialization::is_serializable<MessageType>::value,
void
>
::type
208
NetworkReceiverModel<Datatype>::add_callback_impl
(std::function<
void
(MessageType&)>)
209
{
210
throw
NetworkMessageNotSerializable(
ERS_HERE
,
typeid
(MessageType).name());
// NOLINT(runtime/rtti)
211
}
212
213
}
// namespace dunedaq::iomanager
ERS_HERE
#define ERS_HERE
Definition
LocalContext.hpp:141
NetworkIssues.hpp
NetworkManager.hpp
Serialization.hpp
Subscriber.hpp
type
type
Definition
TriggerActivity_serialization.hpp:48
dunedaq::iomanager::NetworkManager::get
static NetworkManager & get()
Definition
NetworkManager.cpp:32
dunedaq::iomanager::NetworkManager::get_receiver
std::shared_ptr< ipm::Receiver > get_receiver(ConnectionId const &conn_id)
Definition
NetworkManager.cpp:151
dunedaq::iomanager::NetworkReceiverModel::get_receiver
void get_receiver(Receiver::timeout_t timeout)
Definition
NetworkReceiverModel.hxx:87
dunedaq::iomanager::NetworkReceiverModel::subscribe
void subscribe(std::string topic) override
Definition
NetworkReceiverModel.hxx:69
dunedaq::iomanager::NetworkReceiverModel::add_callback_impl
std::enable_if< serialization::is_serializable< MessageType >::value, void >::type add_callback_impl(std::function< void(MessageType &)> callback)
Definition
NetworkReceiverModel.hxx:167
dunedaq::iomanager::NetworkReceiverModel::m_callback
std::function< void(Datatype &)> m_callback
Definition
NetworkReceiverModel.hpp:74
dunedaq::iomanager::NetworkReceiverModel::read_network
std::enable_if< serialization::is_serializable< MessageType >::value, MessageType >::type read_network(Receiver::timeout_t const &timeout)
Definition
NetworkReceiverModel.hxx:106
dunedaq::iomanager::NetworkReceiverModel::NetworkReceiverModel
NetworkReceiverModel(ConnectionId const &conn_id)
Definition
NetworkReceiverModel.hxx:21
dunedaq::iomanager::NetworkReceiverModel::m_event_loop_runner
std::unique_ptr< std::jthread > m_event_loop_runner
Definition
NetworkReceiverModel.hpp:75
dunedaq::iomanager::NetworkReceiverModel::m_receive_mutex
std::mutex m_receive_mutex
Definition
NetworkReceiverModel.hpp:78
dunedaq::iomanager::NetworkReceiverModel::unsubscribe
void unsubscribe(std::string topic) override
Definition
NetworkReceiverModel.hxx:78
dunedaq::iomanager::NetworkReceiverModel::m_network_receiver_ptr
std::shared_ptr< ipm::Receiver > m_network_receiver_ptr
Definition
NetworkReceiverModel.hpp:76
dunedaq::iomanager::NetworkReceiverModel::try_read_network
std::enable_if< serialization::is_serializable< MessageType >::value, std::optional< MessageType > >::type try_read_network(Receiver::timeout_t const &timeout)
Definition
NetworkReceiverModel.hxx:136
dunedaq::iomanager::NetworkReceiverModel::m_callback_mutex
std::mutex m_callback_mutex
Definition
NetworkReceiverModel.hpp:77
dunedaq::iomanager::NetworkReceiverModel::remove_callback
void remove_callback() override
Definition
NetworkReceiverModel.hxx:54
dunedaq::iomanager::NetworkReceiverModel::receive
Datatype receive(Receiver::timeout_t timeout) override
Definition
NetworkReceiverModel.hxx:43
dunedaq::iomanager::ReceiverConcept::ReceiverConcept
ReceiverConcept(ConnectionId const &conn_id)
Definition
Receiver.hpp:50
dunedaq::iomanager::Receiver::m_conn
ConnectionId m_conn
Definition
Receiver.hpp:42
dunedaq::iomanager::Receiver::timeout_t
std::chrono::milliseconds timeout_t
Definition
Receiver.hpp:27
dunedaq::iomanager::Receiver::id
ConnectionId id() const
Definition
Receiver.hpp:39
dunedaq::ipm::Receiver::s_any_size
static constexpr message_size_t s_any_size
Definition
Receiver.hpp:88
ers::Issue
Base class for any user define issue.
Definition
Issue.hpp:80
Receiver.hpp
Logging.hpp
TLOG_DEBUG
#define TLOG_DEBUG(lvl,...)
Definition
Logging.hpp:112
TLOG
#define TLOG(...)
Definition
macro.hpp:22
dunedaq::iomanager
Definition
IOManager.hxx:19
dunedaq::TimeoutExpired
TimeoutExpired
Definition
CommonIssues.hpp:26
dunedaq::ConnectionNotFound
ConnectionNotFound
Definition
NetworkIssues.hpp:28
ers::warning
void warning(const Issue &issue)
Definition
ers.hpp:126
ers::error
void error(const Issue &issue)
Definition
ers.hpp:92
std
Definition
SchemaUtils.hpp:118
dunedaq::iomanager::ConnectionId
Definition
SchemaUtils.hpp:26
dunedaq::iomanager::ConnectionId::uid
std::string uid
Definition
SchemaUtils.hpp:27
dunedaq::ipm::Receiver::Response
Definition
Receiver.hpp:104
dunedaq::ipm::Receiver::Response::data
std::vector< char > data
Definition
Receiver.hpp:106
Issues.hpp
Generated on
for DUNE-DAQ by
1.17.0