/src/Fast-DDS/src/cpp/fastdds/publisher/PublisherImpl.cpp
Line | Count | Source |
1 | | // Copyright 2019 Proyectos y Sistemas de Mantenimiento SL (eProsima). |
2 | | // |
3 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
4 | | // you may not use this file except in compliance with the License. |
5 | | // You may obtain a copy of the License at |
6 | | // |
7 | | // http://www.apache.org/licenses/LICENSE-2.0 |
8 | | // |
9 | | // Unless required by applicable law or agreed to in writing, software |
10 | | // distributed under the License is distributed on an "AS IS" BASIS, |
11 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 | | // See the License for the specific language governing permissions and |
13 | | // limitations under the License. |
14 | | |
15 | | /* |
16 | | * PublisherImpl.cpp |
17 | | * |
18 | | */ |
19 | | |
20 | | #include <fastdds/publisher/PublisherImpl.hpp> |
21 | | |
22 | | #include <functional> |
23 | | |
24 | | #include <fastdds/dds/domain/DomainParticipantListener.hpp> |
25 | | #include <fastdds/dds/log/Log.hpp> |
26 | | #include <fastdds/dds/publisher/DataWriter.hpp> |
27 | | #include <fastdds/dds/publisher/Publisher.hpp> |
28 | | #include <fastdds/dds/publisher/PublisherListener.hpp> |
29 | | #include <fastdds/dds/publisher/qos/DataWriterQos.hpp> |
30 | | #include <fastdds/dds/topic/TypeSupport.hpp> |
31 | | #include <fastdds/domain/DomainParticipantImpl.hpp> |
32 | | #include <fastdds/publisher/DataWriterImpl.hpp> |
33 | | #include <fastdds/rtps/participant/RTPSParticipant.hpp> |
34 | | #include <fastdds/topic/TopicDescriptionImpl.hpp> |
35 | | #include <fastdds/utils/QosConverters.hpp> |
36 | | |
37 | | #include <rtps/network/utils/netmask_filter.hpp> |
38 | | #ifdef FASTDDS_STATISTICS |
39 | | #include <statistics/types/monitorservice_types.hpp> |
40 | | #endif //FASTDDS_STATISTICS |
41 | | #include <xmlparser/attributes/PublisherAttributes.hpp> |
42 | | #include <xmlparser/XMLProfileManager.h> |
43 | | |
44 | | namespace eprosima { |
45 | | namespace fastdds { |
46 | | namespace dds { |
47 | | |
48 | | using xmlparser::XMLProfileManager; |
49 | | using xmlparser::XMLP_ret; |
50 | | using rtps::InstanceHandle_t; |
51 | | |
52 | | PublisherImpl::PublisherImpl( |
53 | | DomainParticipantImpl* p, |
54 | | const PublisherQos& qos, |
55 | | PublisherListener* listen) |
56 | 0 | : participant_(p) |
57 | 0 | , qos_(&qos == &PUBLISHER_QOS_DEFAULT ? participant_->get_default_publisher_qos() : qos) |
58 | 0 | , listener_(listen) |
59 | 0 | , publisher_listener_(this) |
60 | 0 | , user_publisher_(nullptr) |
61 | 0 | , rtps_participant_(p->get_rtps_participant()) |
62 | 0 | , default_datawriter_qos_(DATAWRITER_QOS_DEFAULT) |
63 | 0 | { |
64 | 0 | xmlparser::PublisherAttributes pub_attr; |
65 | 0 | XMLProfileManager::getDefaultPublisherAttributes(pub_attr); |
66 | 0 | utils::set_qos_from_attributes(default_datawriter_qos_, pub_attr); |
67 | 0 | } |
68 | | |
69 | | ReturnCode_t PublisherImpl::enable() |
70 | 0 | { |
71 | 0 | if (qos_.entity_factory().autoenable_created_entities) |
72 | 0 | { |
73 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
74 | 0 | for (auto topic_writers : writers_) |
75 | 0 | { |
76 | 0 | for (DataWriterImpl* dw : topic_writers.second) |
77 | 0 | { |
78 | 0 | dw->user_datawriter_->enable(); |
79 | 0 | } |
80 | 0 | } |
81 | 0 | } |
82 | |
|
83 | 0 | return RETCODE_OK; |
84 | 0 | } |
85 | | |
86 | | void PublisherImpl::disable() |
87 | 0 | { |
88 | 0 | set_listener(nullptr); |
89 | 0 | user_publisher_->set_listener(nullptr); |
90 | 0 | { |
91 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
92 | 0 | for (auto it = writers_.begin(); it != writers_.end(); ++it) |
93 | 0 | { |
94 | 0 | for (DataWriterImpl* dw : it->second) |
95 | 0 | { |
96 | 0 | dw->disable(); |
97 | 0 | } |
98 | 0 | } |
99 | 0 | } |
100 | 0 | } |
101 | | |
102 | | PublisherImpl::~PublisherImpl() |
103 | 0 | { |
104 | 0 | { |
105 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
106 | 0 | for (auto it = writers_.begin(); it != writers_.end(); ++it) |
107 | 0 | { |
108 | 0 | for (DataWriterImpl* dw : it->second) |
109 | 0 | { |
110 | 0 | delete dw; |
111 | 0 | } |
112 | 0 | } |
113 | 0 | writers_.clear(); |
114 | 0 | } |
115 | |
|
116 | 0 | delete user_publisher_; |
117 | 0 | } |
118 | | |
119 | | const PublisherQos& PublisherImpl::get_qos() const |
120 | 0 | { |
121 | 0 | return qos_; |
122 | 0 | } |
123 | | |
124 | | ReturnCode_t PublisherImpl::set_qos( |
125 | | const PublisherQos& qos) |
126 | 0 | { |
127 | 0 | bool enabled = user_publisher_->is_enabled(); |
128 | |
|
129 | 0 | const PublisherQos& qos_to_set = (&qos == &PUBLISHER_QOS_DEFAULT) ? |
130 | 0 | participant_->get_default_publisher_qos() : qos; |
131 | |
|
132 | 0 | if (&qos != &PUBLISHER_QOS_DEFAULT) |
133 | 0 | { |
134 | 0 | ReturnCode_t ret_val = check_qos(qos_to_set); |
135 | 0 | if (RETCODE_OK != ret_val) |
136 | 0 | { |
137 | 0 | return ret_val; |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | 0 | if (enabled && !can_qos_be_updated(qos_, qos_to_set)) |
142 | 0 | { |
143 | 0 | return RETCODE_IMMUTABLE_POLICY; |
144 | 0 | } |
145 | 0 | set_qos(qos_, qos_to_set, !enabled); |
146 | |
|
147 | 0 | if (enabled) |
148 | 0 | { |
149 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
150 | 0 | for (auto topic_writers : writers_) |
151 | 0 | { |
152 | 0 | for (auto writer : topic_writers.second) |
153 | 0 | { |
154 | 0 | writer->publisher_qos_updated(); |
155 | 0 | } |
156 | 0 | } |
157 | 0 | } |
158 | |
|
159 | 0 | return RETCODE_OK; |
160 | 0 | } |
161 | | |
162 | | const PublisherListener* PublisherImpl::get_listener() const |
163 | 0 | { |
164 | 0 | return listener_; |
165 | 0 | } |
166 | | |
167 | | ReturnCode_t PublisherImpl::set_listener( |
168 | | PublisherListener* listener) |
169 | 0 | { |
170 | 0 | listener_ = listener; |
171 | 0 | return RETCODE_OK; |
172 | 0 | } |
173 | | |
174 | | void PublisherImpl::PublisherWriterListener::on_publication_matched( |
175 | | DataWriter* writer, |
176 | | const PublicationMatchedStatus& info) |
177 | 0 | { |
178 | 0 | if (publisher_->listener_ != nullptr) |
179 | 0 | { |
180 | 0 | publisher_->listener_->on_publication_matched(writer, info); |
181 | 0 | } |
182 | 0 | } |
183 | | |
184 | | void PublisherImpl::PublisherWriterListener::on_liveliness_lost( |
185 | | DataWriter* writer, |
186 | | const LivelinessLostStatus& status) |
187 | 0 | { |
188 | 0 | if (publisher_->listener_ != nullptr) |
189 | 0 | { |
190 | 0 | publisher_->listener_->on_liveliness_lost(writer, status); |
191 | 0 | } |
192 | 0 | } |
193 | | |
194 | | void PublisherImpl::PublisherWriterListener::on_offered_deadline_missed( |
195 | | DataWriter* writer, |
196 | | const OfferedDeadlineMissedStatus& status) |
197 | 0 | { |
198 | 0 | if (publisher_->listener_ != nullptr) |
199 | 0 | { |
200 | 0 | publisher_->listener_->on_offered_deadline_missed(writer, status); |
201 | 0 | } |
202 | 0 | } |
203 | | |
204 | | DataWriterImpl* PublisherImpl::create_datawriter_impl( |
205 | | const TypeSupport& type, |
206 | | Topic* topic, |
207 | | const DataWriterQos& qos, |
208 | | DataWriterListener* listener, |
209 | | std::shared_ptr<fastdds::rtps::IPayloadPool> payload_pool) |
210 | 0 | { |
211 | 0 | return new DataWriterImpl(this, type, topic, qos, listener, payload_pool); |
212 | 0 | } |
213 | | |
214 | | DataWriter* PublisherImpl::create_datawriter( |
215 | | Topic* topic, |
216 | | const DataWriterQos& qos, |
217 | | DataWriterListener* listener, |
218 | | const StatusMask& mask, |
219 | | std::shared_ptr<fastdds::rtps::IPayloadPool> payload_pool) |
220 | 0 | { |
221 | 0 | EPROSIMA_LOG_INFO(PUBLISHER, "CREATING WRITER IN TOPIC: " << topic->get_name()); |
222 | | //Look for the correct type registration |
223 | 0 | TypeSupport type_support = participant_->find_type(topic->get_type_name()); |
224 | | |
225 | | /// Preconditions |
226 | | // Check the type was registered. |
227 | 0 | if (type_support.empty()) |
228 | 0 | { |
229 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, "Type: " << topic->get_type_name() << " Not Registered"); |
230 | 0 | return nullptr; |
231 | 0 | } |
232 | | |
233 | 0 | if (RETCODE_OK != DataWriterImpl::check_qos_including_resource_limits(qos, type_support)) |
234 | 0 | { |
235 | 0 | return nullptr; |
236 | 0 | } |
237 | | |
238 | | // Check netmask filtering preconditions |
239 | 0 | if (nullptr != rtps_participant_) |
240 | 0 | { |
241 | 0 | std::vector<fastdds::rtps::TransportNetmaskFilterInfo> netmask_filter_info = |
242 | 0 | rtps_participant_->get_netmask_filter_info(); |
243 | 0 | std::string error_msg; |
244 | 0 | if (!fastdds::rtps::network::netmask_filter::check_preconditions(netmask_filter_info, |
245 | 0 | qos.endpoint().ignore_non_matching_locators, |
246 | 0 | error_msg) || |
247 | 0 | !fastdds::rtps::network::netmask_filter::check_preconditions(netmask_filter_info, |
248 | 0 | qos.endpoint().external_unicast_locators, error_msg)) |
249 | 0 | { |
250 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, |
251 | 0 | "Failed to create writer -> " << error_msg); |
252 | 0 | return nullptr; |
253 | 0 | } |
254 | 0 | } |
255 | | |
256 | 0 | DataWriterImpl* impl = create_datawriter_impl(type_support, topic, qos, listener, payload_pool); |
257 | 0 | return create_datawriter(topic, impl, mask); |
258 | 0 | } |
259 | | |
260 | | DataWriter* PublisherImpl::create_datawriter( |
261 | | Topic* topic, |
262 | | DataWriterImpl* impl, |
263 | | const StatusMask& mask) |
264 | 0 | { |
265 | 0 | topic->get_impl()->reference(); |
266 | |
|
267 | 0 | DataWriter* writer = new DataWriter(impl, mask); |
268 | 0 | impl->user_datawriter_ = writer; |
269 | |
|
270 | 0 | { |
271 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
272 | 0 | writers_[topic->get_name()].push_back(impl); |
273 | 0 | } |
274 | |
|
275 | 0 | if (user_publisher_->is_enabled() && qos_.entity_factory().autoenable_created_entities) |
276 | 0 | { |
277 | 0 | if (RETCODE_OK != writer->enable()) |
278 | 0 | { |
279 | 0 | delete_datawriter(writer); |
280 | 0 | return nullptr; |
281 | 0 | } |
282 | 0 | } |
283 | | |
284 | 0 | return writer; |
285 | 0 | } |
286 | | |
287 | | DataWriter* PublisherImpl::create_datawriter_with_profile( |
288 | | Topic* topic, |
289 | | const std::string& profile_name, |
290 | | DataWriterListener* listener, |
291 | | const StatusMask& mask, |
292 | | std::shared_ptr<fastdds::rtps::IPayloadPool> payload_pool) |
293 | 0 | { |
294 | | // TODO (ILG): Change when we have full XML support for DDS QoS profiles |
295 | 0 | xmlparser::PublisherAttributes attr; |
296 | 0 | if (XMLP_ret::XML_OK == XMLProfileManager::fillPublisherAttributes(profile_name, attr)) |
297 | 0 | { |
298 | 0 | DataWriterQos qos = default_datawriter_qos_; |
299 | 0 | utils::set_qos_from_attributes(qos, attr); |
300 | 0 | return create_datawriter(topic, qos, listener, mask, payload_pool); |
301 | 0 | } |
302 | | |
303 | 0 | return nullptr; |
304 | 0 | } |
305 | | |
306 | | ReturnCode_t PublisherImpl::delete_datawriter( |
307 | | const DataWriter* writer) |
308 | 0 | { |
309 | 0 | if (user_publisher_ != writer->get_publisher()) |
310 | 0 | { |
311 | 0 | return RETCODE_PRECONDITION_NOT_MET; |
312 | 0 | } |
313 | 0 | std::unique_lock<std::mutex> lock(mtx_writers_); |
314 | 0 | auto vit = writers_.find(writer->get_topic()->get_name()); |
315 | 0 | if (vit != writers_.end()) |
316 | 0 | { |
317 | 0 | auto dw_it = std::find(vit->second.begin(), vit->second.end(), writer->impl_); |
318 | 0 | if (dw_it != vit->second.end()) |
319 | 0 | { |
320 | | //First extract the writer from the maps to free the mutex |
321 | 0 | DataWriterImpl* writer_impl = *dw_it; |
322 | 0 | ReturnCode_t ret_code = writer_impl->check_delete_preconditions(); |
323 | 0 | if (RETCODE_OK != ret_code) |
324 | 0 | { |
325 | 0 | return ret_code; |
326 | 0 | } |
327 | 0 | writer_impl->set_listener(nullptr); |
328 | 0 | vit->second.erase(dw_it); |
329 | 0 | if (vit->second.empty()) |
330 | 0 | { |
331 | 0 | writers_.erase(vit); |
332 | 0 | } |
333 | 0 | lock.unlock(); |
334 | | |
335 | | //Now we can delete it |
336 | 0 | writer_impl->get_topic()->get_impl()->dereference(); |
337 | 0 | delete (writer_impl); |
338 | 0 | return RETCODE_OK; |
339 | 0 | } |
340 | 0 | } |
341 | 0 | return RETCODE_ERROR; |
342 | 0 | } |
343 | | |
344 | | DataWriter* PublisherImpl::lookup_datawriter( |
345 | | const std::string& topic_name) const |
346 | 0 | { |
347 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
348 | 0 | auto it = writers_.find(topic_name); |
349 | 0 | if (it != writers_.end() && it->second.size() > 0) |
350 | 0 | { |
351 | 0 | return it->second.front()->user_datawriter_; |
352 | 0 | } |
353 | 0 | return nullptr; |
354 | 0 | } |
355 | | |
356 | | bool PublisherImpl::get_datawriters( |
357 | | std::vector<DataWriter*>& writers) const |
358 | 0 | { |
359 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
360 | 0 | for (auto vit : writers_) |
361 | 0 | { |
362 | 0 | for (DataWriterImpl* dw : vit.second) |
363 | 0 | { |
364 | 0 | writers.push_back(dw->user_datawriter_); |
365 | 0 | } |
366 | 0 | } |
367 | 0 | return true; |
368 | 0 | } |
369 | | |
370 | | bool PublisherImpl::has_datawriters() const |
371 | 0 | { |
372 | 0 | if (writers_.empty()) |
373 | 0 | { |
374 | 0 | return false; |
375 | 0 | } |
376 | 0 | return true; |
377 | 0 | } |
378 | | |
379 | | bool PublisherImpl::contains_entity( |
380 | | const fastdds::rtps::InstanceHandle_t& handle) const |
381 | 0 | { |
382 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
383 | 0 | for (auto vit : writers_) |
384 | 0 | { |
385 | 0 | for (DataWriterImpl* dw : vit.second) |
386 | 0 | { |
387 | 0 | InstanceHandle_t h(dw->guid()); |
388 | 0 | if (h == handle) |
389 | 0 | { |
390 | 0 | return true; |
391 | 0 | } |
392 | 0 | } |
393 | 0 | } |
394 | 0 | return false; |
395 | 0 | } |
396 | | |
397 | | /* TODO |
398 | | bool PublisherImpl::suspend_publications() |
399 | | { |
400 | | EPROSIMA_LOG_ERROR(PUBLISHER, "Operation not implemented"); |
401 | | return false; |
402 | | } |
403 | | */ |
404 | | |
405 | | /* TODO |
406 | | bool PublisherImpl::resume_publications() |
407 | | { |
408 | | EPROSIMA_LOG_ERROR(PUBLISHER, "Operation not implemented"); |
409 | | return false; |
410 | | } |
411 | | */ |
412 | | |
413 | | /* TODO |
414 | | bool PublisherImpl::begin_coherent_changes() |
415 | | { |
416 | | EPROSIMA_LOG_ERROR(PUBLISHER, "Operation not implemented"); |
417 | | return false; |
418 | | } |
419 | | */ |
420 | | |
421 | | /* TODO |
422 | | bool PublisherImpl::end_coherent_changes() |
423 | | { |
424 | | EPROSIMA_LOG_ERROR(PUBLISHER, "Operation not implemented"); |
425 | | return false; |
426 | | } |
427 | | */ |
428 | | |
429 | | |
430 | | ReturnCode_t PublisherImpl::set_default_datawriter_qos( |
431 | | const DataWriterQos& qos) |
432 | 0 | { |
433 | 0 | if (&qos == &DATAWRITER_QOS_DEFAULT) |
434 | 0 | { |
435 | 0 | reset_default_datawriter_qos(); |
436 | 0 | return RETCODE_OK; |
437 | 0 | } |
438 | | |
439 | 0 | ReturnCode_t ret_val = DataWriterImpl::check_qos(qos); |
440 | 0 | if (RETCODE_OK != ret_val) |
441 | 0 | { |
442 | 0 | return ret_val; |
443 | 0 | } |
444 | 0 | DataWriterImpl::set_qos(default_datawriter_qos_, qos, true); |
445 | 0 | return RETCODE_OK; |
446 | 0 | } |
447 | | |
448 | | void PublisherImpl::reset_default_datawriter_qos() |
449 | 0 | { |
450 | | // TODO (ILG): Change when we have full XML support for DDS QoS profiles |
451 | 0 | DataWriterImpl::set_qos(default_datawriter_qos_, DATAWRITER_QOS_DEFAULT, true); |
452 | 0 | xmlparser::PublisherAttributes attr; |
453 | 0 | XMLProfileManager::getDefaultPublisherAttributes(attr); |
454 | 0 | utils::set_qos_from_attributes(default_datawriter_qos_, attr); |
455 | 0 | } |
456 | | |
457 | | const DataWriterQos& PublisherImpl::get_default_datawriter_qos() const |
458 | 0 | { |
459 | 0 | return default_datawriter_qos_; |
460 | 0 | } |
461 | | |
462 | | ReturnCode_t PublisherImpl::get_datawriter_qos_from_profile( |
463 | | const std::string& profile_name, |
464 | | DataWriterQos& qos) const |
465 | 0 | { |
466 | 0 | std::string _topic_name; |
467 | 0 | return get_datawriter_qos_from_profile(profile_name, qos, _topic_name); |
468 | 0 | } |
469 | | |
470 | | ReturnCode_t PublisherImpl::get_datawriter_qos_from_profile( |
471 | | const std::string& profile_name, |
472 | | DataWriterQos& qos, |
473 | | std::string& topic_name) const |
474 | 0 | { |
475 | 0 | xmlparser::PublisherAttributes attr; |
476 | 0 | if (XMLP_ret::XML_OK == XMLProfileManager::fillPublisherAttributes(profile_name, attr, false)) |
477 | 0 | { |
478 | 0 | qos = default_datawriter_qos_; |
479 | 0 | utils::set_qos_from_attributes(qos, attr); |
480 | 0 | topic_name = attr.topic.getTopicName(); |
481 | 0 | return RETCODE_OK; |
482 | 0 | } |
483 | | |
484 | 0 | return RETCODE_BAD_PARAMETER; |
485 | 0 | } |
486 | | |
487 | | ReturnCode_t PublisherImpl::get_datawriter_qos_from_xml( |
488 | | const std::string& xml, |
489 | | DataWriterQos& qos) const |
490 | 0 | { |
491 | 0 | std::string _topic_name; |
492 | 0 | return get_datawriter_qos_from_xml(xml, qos, _topic_name); |
493 | 0 | } |
494 | | |
495 | | ReturnCode_t PublisherImpl::get_datawriter_qos_from_xml( |
496 | | const std::string& xml, |
497 | | DataWriterQos& qos, |
498 | | std::string& topic_name) const |
499 | 0 | { |
500 | 0 | xmlparser::PublisherAttributes attr; |
501 | 0 | if (XMLP_ret::XML_OK == XMLProfileManager::fill_publisher_attributes_from_xml(xml, attr, false)) |
502 | 0 | { |
503 | 0 | qos = default_datawriter_qos_; |
504 | 0 | utils::set_qos_from_attributes(qos, attr); |
505 | 0 | topic_name = attr.topic.getTopicName(); |
506 | 0 | return RETCODE_OK; |
507 | 0 | } |
508 | | |
509 | 0 | return RETCODE_BAD_PARAMETER; |
510 | 0 | } |
511 | | |
512 | | ReturnCode_t PublisherImpl::get_datawriter_qos_from_xml( |
513 | | const std::string& xml, |
514 | | DataWriterQos& qos, |
515 | | const std::string& profile_name) const |
516 | 0 | { |
517 | 0 | std::string _topic_name; |
518 | 0 | return get_datawriter_qos_from_xml(xml, qos, _topic_name, profile_name); |
519 | 0 | } |
520 | | |
521 | | ReturnCode_t PublisherImpl::get_datawriter_qos_from_xml( |
522 | | const std::string& xml, |
523 | | DataWriterQos& qos, |
524 | | std::string& topic_name, |
525 | | const std::string& profile_name) const |
526 | 0 | { |
527 | 0 | if (profile_name.empty()) |
528 | 0 | { |
529 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, "Provided profile name must be non-empty"); |
530 | 0 | return RETCODE_BAD_PARAMETER; |
531 | 0 | } |
532 | | |
533 | 0 | xmlparser::PublisherAttributes attr; |
534 | 0 | if (XMLP_ret::XML_OK == XMLProfileManager::fill_publisher_attributes_from_xml(xml, attr, true, profile_name)) |
535 | 0 | { |
536 | 0 | qos = default_datawriter_qos_; |
537 | 0 | utils::set_qos_from_attributes(qos, attr); |
538 | 0 | topic_name = attr.topic.getTopicName(); |
539 | 0 | return RETCODE_OK; |
540 | 0 | } |
541 | | |
542 | 0 | return RETCODE_BAD_PARAMETER; |
543 | 0 | } |
544 | | |
545 | | ReturnCode_t PublisherImpl::get_default_datawriter_qos_from_xml( |
546 | | const std::string& xml, |
547 | | DataWriterQos& qos) const |
548 | 0 | { |
549 | 0 | std::string _topic_name; |
550 | 0 | return get_default_datawriter_qos_from_xml(xml, qos, _topic_name); |
551 | 0 | } |
552 | | |
553 | | ReturnCode_t PublisherImpl::get_default_datawriter_qos_from_xml( |
554 | | const std::string& xml, |
555 | | DataWriterQos& qos, |
556 | | std::string& topic_name) const |
557 | 0 | { |
558 | 0 | xmlparser::PublisherAttributes attr; |
559 | 0 | if (XMLP_ret::XML_OK == XMLProfileManager::fill_default_publisher_attributes_from_xml(xml, attr, true)) |
560 | 0 | { |
561 | 0 | qos = default_datawriter_qos_; |
562 | 0 | utils::set_qos_from_attributes(qos, attr); |
563 | 0 | topic_name = attr.topic.getTopicName(); |
564 | 0 | return RETCODE_OK; |
565 | 0 | } |
566 | | |
567 | 0 | return RETCODE_BAD_PARAMETER; |
568 | 0 | } |
569 | | |
570 | | ReturnCode_t PublisherImpl::copy_from_topic_qos( |
571 | | DataWriterQos& writer_qos, |
572 | | const TopicQos& topic_qos) |
573 | 0 | { |
574 | 0 | writer_qos.durability(topic_qos.durability()); |
575 | 0 | writer_qos.durability_service(topic_qos.durability_service()); |
576 | 0 | writer_qos.deadline(topic_qos.deadline()); |
577 | 0 | writer_qos.latency_budget(topic_qos.latency_budget()); |
578 | 0 | writer_qos.liveliness(topic_qos.liveliness()); |
579 | 0 | writer_qos.reliability(topic_qos.reliability()); |
580 | 0 | writer_qos.destination_order(topic_qos.destination_order()); |
581 | 0 | writer_qos.history(topic_qos.history()); |
582 | 0 | writer_qos.resource_limits(topic_qos.resource_limits()); |
583 | 0 | writer_qos.transport_priority(topic_qos.transport_priority()); |
584 | 0 | writer_qos.lifespan(topic_qos.lifespan()); |
585 | 0 | writer_qos.ownership(topic_qos.ownership()); |
586 | 0 | writer_qos.representation(topic_qos.representation()); |
587 | 0 | return RETCODE_OK; |
588 | 0 | } |
589 | | |
590 | | ReturnCode_t PublisherImpl::wait_for_acknowledgments( |
591 | | const dds::Duration_t& max_wait) |
592 | 0 | { |
593 | 0 | dds::Duration_t current = max_wait; |
594 | 0 | dds::Duration_t begin, end; |
595 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
596 | 0 | for (auto& vit : writers_) |
597 | 0 | { |
598 | 0 | for (DataWriterImpl* dw : vit.second) |
599 | 0 | { |
600 | 0 | participant_->get_current_time(begin); |
601 | 0 | if (RETCODE_OK != dw->wait_for_acknowledgments(current)) |
602 | 0 | { |
603 | 0 | return RETCODE_ERROR; |
604 | 0 | } |
605 | | // Check ellapsed time and decrement |
606 | 0 | participant_->get_current_time(end); |
607 | 0 | current = current - (end - begin); |
608 | 0 | if (current < fastdds::dds::c_TimeZero) |
609 | 0 | { |
610 | 0 | return RETCODE_TIMEOUT; |
611 | 0 | } |
612 | 0 | } |
613 | 0 | } |
614 | 0 | return RETCODE_OK; |
615 | 0 | } |
616 | | |
617 | | const DomainParticipant* PublisherImpl::get_participant() const |
618 | 0 | { |
619 | 0 | return const_cast<const DomainParticipantImpl*>(participant_)->get_participant(); |
620 | 0 | } |
621 | | |
622 | | const Publisher* PublisherImpl::get_publisher() const |
623 | 0 | { |
624 | 0 | return user_publisher_; |
625 | 0 | } |
626 | | |
627 | | ReturnCode_t PublisherImpl::delete_contained_entities() |
628 | 0 | { |
629 | | // Let's be optimistic |
630 | 0 | ReturnCode_t result = RETCODE_OK; |
631 | |
|
632 | 0 | bool can_be_deleted = true; |
633 | |
|
634 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
635 | 0 | for (auto writer: writers_) |
636 | 0 | { |
637 | 0 | for (DataWriterImpl* dw: writer.second) |
638 | 0 | { |
639 | 0 | can_be_deleted = dw->check_delete_preconditions() == RETCODE_OK; |
640 | 0 | if (!can_be_deleted) |
641 | 0 | { |
642 | 0 | return RETCODE_PRECONDITION_NOT_MET; |
643 | 0 | } |
644 | 0 | } |
645 | 0 | } |
646 | | |
647 | | // We traverse the map trying to delete all writers; |
648 | 0 | auto writer_iterator = writers_.begin(); |
649 | 0 | while (writer_iterator != writers_.end()) |
650 | 0 | { |
651 | | //First extract the writer from the maps to free the mutex |
652 | 0 | auto it = writer_iterator->second.begin(); |
653 | 0 | DataWriterImpl* writer_impl = *it; |
654 | 0 | ReturnCode_t ret_code = writer_impl->check_delete_preconditions(); |
655 | 0 | if (RETCODE_OK != ret_code) |
656 | 0 | { |
657 | 0 | return RETCODE_ERROR; |
658 | 0 | } |
659 | 0 | writer_impl->set_listener(nullptr); |
660 | 0 | it = writer_iterator->second.erase(it); |
661 | 0 | if (writer_iterator->second.empty()) |
662 | 0 | { |
663 | 0 | writer_iterator = writers_.erase(writer_iterator); |
664 | 0 | } |
665 | |
|
666 | 0 | writer_impl->get_topic()->get_impl()->dereference(); |
667 | 0 | delete (writer_impl); |
668 | 0 | } |
669 | 0 | return result; |
670 | 0 | } |
671 | | |
672 | | bool PublisherImpl::can_be_deleted() |
673 | 0 | { |
674 | 0 | bool can_be_deleted = true; |
675 | |
|
676 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
677 | 0 | for (auto topic_writers : writers_) |
678 | 0 | { |
679 | 0 | for (DataWriterImpl* dw : topic_writers.second) |
680 | 0 | { |
681 | 0 | can_be_deleted = can_be_deleted && (dw->check_delete_preconditions() == RETCODE_OK); |
682 | 0 | if (!can_be_deleted) |
683 | 0 | { |
684 | 0 | return can_be_deleted; |
685 | 0 | } |
686 | 0 | } |
687 | |
|
688 | 0 | } |
689 | | |
690 | 0 | return can_be_deleted; |
691 | 0 | } |
692 | | |
693 | | bool PublisherImpl::can_be_deleted( |
694 | | DataWriter* writer) const |
695 | 0 | { |
696 | 0 | if (!writer) |
697 | 0 | { |
698 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, "DataWriter is nullptr."); |
699 | 0 | return false; |
700 | 0 | } |
701 | | |
702 | 0 | if (user_publisher_ != writer->get_publisher()) |
703 | 0 | { |
704 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, "DataWriter does not belong to this Publisher."); |
705 | 0 | return false; |
706 | 0 | } |
707 | | |
708 | 0 | std::lock_guard<std::mutex> lock(mtx_writers_); |
709 | 0 | auto it = writers_.find(writer->get_topic()->get_name()); |
710 | |
|
711 | 0 | if (it != writers_.end()) |
712 | 0 | { |
713 | 0 | auto dw_it = std::find(it->second.begin(), it->second.end(), writer->impl_); |
714 | |
|
715 | 0 | if (dw_it == it->second.end()) |
716 | 0 | { |
717 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, "DataWriter implementation not found."); |
718 | 0 | return false; |
719 | 0 | } |
720 | | |
721 | 0 | return (*dw_it)->check_delete_preconditions() == RETCODE_OK; |
722 | 0 | } |
723 | | |
724 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, "DataWriter not found."); |
725 | 0 | return false; |
726 | 0 | } |
727 | | |
728 | | const InstanceHandle_t& PublisherImpl::get_instance_handle() const |
729 | 0 | { |
730 | 0 | return handle_; |
731 | 0 | } |
732 | | |
733 | | bool PublisherImpl::type_in_use( |
734 | | const std::string& type_name) const |
735 | 0 | { |
736 | 0 | for (auto it : writers_) |
737 | 0 | { |
738 | 0 | for (DataWriterImpl* writer : it.second) |
739 | 0 | { |
740 | 0 | if (writer->get_topic()->get_type_name() == type_name) |
741 | 0 | { |
742 | 0 | return true; // Is in use |
743 | 0 | } |
744 | 0 | } |
745 | 0 | } |
746 | 0 | return false; |
747 | 0 | } |
748 | | |
749 | | void PublisherImpl::set_qos( |
750 | | PublisherQos& to, |
751 | | const PublisherQos& from, |
752 | | bool first_time) |
753 | 0 | { |
754 | 0 | if (first_time && !(to.presentation() == from.presentation())) |
755 | 0 | { |
756 | 0 | to.presentation(from.presentation()); |
757 | 0 | } |
758 | 0 | if (!(to.partition() == from.partition())) |
759 | 0 | { |
760 | 0 | to.partition() = from.partition(); |
761 | 0 | } |
762 | 0 | if (!(to.group_data() == from.group_data())) |
763 | 0 | { |
764 | 0 | to.group_data() = from.group_data(); |
765 | 0 | } |
766 | 0 | if (!(to.entity_factory() == from.entity_factory())) |
767 | 0 | { |
768 | 0 | to.entity_factory() = from.entity_factory(); |
769 | 0 | } |
770 | 0 | } |
771 | | |
772 | | ReturnCode_t PublisherImpl::check_qos( |
773 | | const PublisherQos& qos) |
774 | 0 | { |
775 | 0 | (void) qos; |
776 | 0 | return RETCODE_OK; |
777 | 0 | } |
778 | | |
779 | | bool PublisherImpl::can_qos_be_updated( |
780 | | const PublisherQos& to, |
781 | | const PublisherQos& from) |
782 | 0 | { |
783 | 0 | (void) to; |
784 | 0 | (void) from; |
785 | 0 | return true; |
786 | 0 | } |
787 | | |
788 | | PublisherListener* PublisherImpl::get_listener_for( |
789 | | const StatusMask& status) |
790 | 0 | { |
791 | 0 | if (listener_ != nullptr && |
792 | 0 | user_publisher_->get_status_mask().is_active(status)) |
793 | 0 | { |
794 | 0 | return listener_; |
795 | 0 | } |
796 | 0 | return participant_->get_listener_for(status); |
797 | 0 | } |
798 | | |
799 | | #ifdef FASTDDS_STATISTICS |
800 | | bool PublisherImpl::get_monitoring_status( |
801 | | statistics::MonitorServiceData& status, |
802 | | const fastdds::rtps::GUID_t& entity_guid) |
803 | 0 | { |
804 | 0 | bool ret = false; |
805 | 0 | std::vector<DataWriter*> writers; |
806 | 0 | if (get_datawriters(writers)) |
807 | 0 | { |
808 | 0 | for (auto& writer : writers) |
809 | 0 | { |
810 | 0 | if (writer->guid() == entity_guid) |
811 | 0 | { |
812 | 0 | switch (status._d()) |
813 | 0 | { |
814 | 0 | case statistics::StatusKind::INCOMPATIBLE_QOS: |
815 | 0 | { |
816 | 0 | OfferedIncompatibleQosStatus incompatible_qos_status; |
817 | 0 | writer->get_offered_incompatible_qos_status(incompatible_qos_status); |
818 | 0 | status.incompatible_qos_status().total_count(incompatible_qos_status.total_count); |
819 | 0 | status.incompatible_qos_status().last_policy_id(incompatible_qos_status.last_policy_id); |
820 | 0 | for (auto& qos : incompatible_qos_status.policies) |
821 | 0 | { |
822 | 0 | statistics::QosPolicyCount_s count; |
823 | 0 | count.count(qos.count); |
824 | 0 | count.policy_id(qos.policy_id); |
825 | 0 | status.incompatible_qos_status().policies().push_back(count); |
826 | 0 | } |
827 | 0 | ret = true; |
828 | 0 | break; |
829 | 0 | } |
830 | | //! TODO |
831 | | /*case statistics::StatusKind::INCONSISTENT_TOPIC: |
832 | | { |
833 | | writer->get_inconsistent_topic_status(); |
834 | | ret = true; |
835 | | break; |
836 | | }*/ |
837 | 0 | case statistics::StatusKind::LIVELINESS_LOST: |
838 | 0 | { |
839 | 0 | LivelinessLostStatus liveliness_lost_status; |
840 | 0 | writer->get_liveliness_lost_status(liveliness_lost_status); |
841 | 0 | status.liveliness_lost_status().total_count(liveliness_lost_status.total_count); |
842 | 0 | ret = true; |
843 | 0 | break; |
844 | 0 | } |
845 | 0 | case statistics::StatusKind::DEADLINE_MISSED: |
846 | 0 | { |
847 | 0 | DeadlineMissedStatus deadline_missed_status; |
848 | 0 | writer->get_offered_deadline_missed_status(deadline_missed_status); |
849 | 0 | status.deadline_missed_status().total_count(deadline_missed_status.total_count); |
850 | 0 | std::memcpy( |
851 | 0 | status.deadline_missed_status().last_instance_handle().data(), |
852 | 0 | deadline_missed_status.last_instance_handle.value, |
853 | 0 | 16); |
854 | 0 | ret = true; |
855 | 0 | break; |
856 | 0 | } |
857 | 0 | default: |
858 | 0 | { |
859 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, "Queried status not available for this entity " << status._d()); |
860 | 0 | break; |
861 | 0 | } |
862 | 0 | } |
863 | | |
864 | 0 | break; |
865 | 0 | } |
866 | 0 | } |
867 | 0 | } |
868 | 0 | else |
869 | 0 | { |
870 | 0 | EPROSIMA_LOG_ERROR(PUBLISHER, "Could not retrieve datawriters"); |
871 | 0 | } |
872 | | |
873 | | |
874 | 0 | return ret; |
875 | 0 | } |
876 | | |
877 | | #endif //FASTDDS_STATISTICS |
878 | | |
879 | | } // dds |
880 | | } // fastdds |
881 | | } // eprosima |