Coverage Report

Created: 2026-10-28 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/Fast-DDS/src/cpp/rtps/writer/StatefulWriter.cpp
Line
Count
Source
1
// Copyright 2016 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
 * @file StatefulWriter.cpp
17
 *
18
 */
19
20
#include "StatefulWriter.hpp"
21
22
#include <algorithm>
23
#include <mutex>
24
#include <stdexcept>
25
#include <vector>
26
27
#include <fastdds/dds/log/Log.hpp>
28
#include <fastdds/rtps/builtin/data/SubscriptionBuiltinTopicData.hpp>
29
#include <fastdds/rtps/common/VendorId_t.hpp>
30
#include <fastdds/rtps/history/WriterHistory.hpp>
31
#include <fastdds/rtps/history/WriterHistory.hpp>
32
#include <fastdds/rtps/interfaces/IReaderDataFilter.hpp>
33
#include <rtps/messages/RTPSMessageCreator.hpp>
34
#include <fastdds/rtps/participant/RTPSParticipant.hpp>
35
#include <fastdds/rtps/reader/ReaderDiscoveryStatus.hpp>
36
#include <fastdds/rtps/reader/RTPSReader.hpp>
37
#include <fastdds/rtps/writer/WriterListener.hpp>
38
39
#include <rtps/builtin/BuiltinProtocols.h>
40
#include <rtps/builtin/liveliness/WLP.hpp>
41
#include <rtps/DataSharing/DataSharingNotifier.hpp>
42
#include <rtps/DataSharing/DataSharingPayloadPool.hpp>
43
#include <rtps/DataSharing/WriterPool.hpp>
44
#include <rtps/history/BasicPayloadPool.hpp>
45
#include <rtps/history/CacheChangePool.h>
46
#include <rtps/messages/RTPSGapBuilder.hpp>
47
#include <rtps/messages/RTPSMessageGroup.hpp>
48
#include <rtps/network/utils/external_locators.hpp>
49
#include <rtps/participant/RTPSParticipantImpl.hpp>
50
#include <rtps/reader/BaseReader.hpp>
51
#include <rtps/reader/LocalReaderPointer.hpp>
52
#include <rtps/resources/ResourceEvent.h>
53
#include <rtps/resources/TimedEvent.h>
54
#include <rtps/domain/RTPSDomainImpl.hpp>
55
#include <rtps/writer/BaseWriter.hpp>
56
#include <rtps/writer/ReaderProxy.hpp>
57
#include <rtps/writer/StatefulWriterListener.hpp>
58
#include <utils/TimeConversion.hpp>
59
60
#ifdef FASTDDS_STATISTICS
61
#include <statistics/types/monitorservice_types.hpp>
62
#endif // ifdef FASTDDS_STATISTICS
63
64
#include "../builtin/discovery/database/DiscoveryDataBase.hpp"
65
66
#include "../flowcontrol/FlowController.hpp"
67
68
namespace eprosima {
69
namespace fastdds {
70
namespace rtps {
71
72
/**
73
 * Loops over all the readers in the vector, applying the given routine.
74
 * The loop continues until the result of the routine is true for any reader
75
 * or all readers have been processed.
76
 * The returned value is true if the routine returned true at any point,
77
 * or false otherwise.
78
 */
79
template<typename T>
80
static bool for_matched_readers(
81
        ResourceLimitedVector<ReaderProxy*>& reader_vector_1,
82
        T fun)
83
0
{
84
0
    for (ReaderProxy* remote_reader : reader_vector_1)
85
0
    {
86
0
        if (fun(remote_reader))
87
0
        {
88
0
            return true;
89
0
        }
90
0
    }
91
92
0
    return false;
93
0
}
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::unsent_change_added_to_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::unsent_change_added_to_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::change_removed_by_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::change_removed_by_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_add_edp(eprosima::fastdds::rtps::ReaderProxyData const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_add_edp(eprosima::fastdds::rtps::ReaderProxyData const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_is_matched(eprosima::fastdds::rtps::GUID_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_is_matched(eprosima::fastdds::rtps::GUID_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_lookup(eprosima::fastdds::rtps::GUID_t&, eprosima::fastdds::rtps::ReaderProxy**)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_lookup(eprosima::fastdds::rtps::GUID_t&, eprosima::fastdds::rtps::ReaderProxy**)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::all_readers_updated()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::all_readers_updated()::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::wait_for_all_acked(eprosima::fastdds::dds::Time_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::wait_for_all_acked(eprosima::fastdds::dds::Time_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::check_acked_status()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::check_acked_status()::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::update_times(eprosima::fastdds::rtps::WriterTimes const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::update_times(eprosima::fastdds::rtps::WriterTimes const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_1>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_1)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::perform_nack_supression(eprosima::fastdds::rtps::GUID_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::perform_nack_supression(eprosima::fastdds::rtps::GUID_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::process_acknack(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::BitmapRange<eprosima::fastdds::rtps::SequenceNumber_t, eprosima::fastdds::rtps::SequenceNumberDiff, 256u> const&, bool, bool&, std::__1::array<unsigned char, 2ul>)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::process_acknack(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::BitmapRange<eprosima::fastdds::rtps::SequenceNumber_t, eprosima::fastdds::rtps::SequenceNumberDiff, 256u> const&, bool, bool&, std::__1::array<unsigned char, 2ul>)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::process_nack_frag(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::rtps::SequenceNumber_t const&, eprosima::fastdds::BitmapRange<unsigned int, eprosima::fastdds::DiffFunction<unsigned int>, 256u> const&, bool&, std::__1::array<unsigned char, 2ul>)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::process_nack_frag(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::rtps::SequenceNumber_t const&, eprosima::fastdds::BitmapRange<unsigned int, eprosima::fastdds::DiffFunction<unsigned int>, 256u> const&, bool&, std::__1::array<unsigned char, 2ul>)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::ack_timer_expired()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::ack_timer_expired()::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::get_connections(std::__1::vector<eprosima::fastdds::statistics::Connection, std::__1::allocator<eprosima::fastdds::statistics::Connection> >&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::get_connections(std::__1::vector<eprosima::fastdds::statistics::Connection, std::__1::allocator<eprosima::fastdds::statistics::Connection> >&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::get_connections(std::__1::vector<eprosima::fastdds::statistics::Connection, std::__1::allocator<eprosima::fastdds::statistics::Connection> >&)::$_1>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::get_connections(std::__1::vector<eprosima::fastdds::statistics::Connection, std::__1::allocator<eprosima::fastdds::statistics::Connection> >&)::$_1)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::get_connections(std::__1::vector<eprosima::fastdds::statistics::Connection, std::__1::allocator<eprosima::fastdds::statistics::Connection> >&)::$_2>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::get_connections(std::__1::vector<eprosima::fastdds::statistics::Connection, std::__1::allocator<eprosima::fastdds::statistics::Connection> >&)::$_2)
94
95
template<typename T>
96
static bool for_matched_readers(
97
        ResourceLimitedVector<ReaderProxy*>& reader_vector_1,
98
        ResourceLimitedVector<ReaderProxy*>& reader_vector_2,
99
        T fun)
100
0
{
101
0
    if (for_matched_readers(reader_vector_1, fun))
102
0
    {
103
0
        return true;
104
0
    }
105
0
    return for_matched_readers(reader_vector_2, fun);
106
0
}
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::unsent_change_added_to_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::unsent_change_added_to_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::change_removed_by_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::change_removed_by_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_add_edp(eprosima::fastdds::rtps::ReaderProxyData const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_add_edp(eprosima::fastdds::rtps::ReaderProxyData const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_is_matched(eprosima::fastdds::rtps::GUID_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_is_matched(eprosima::fastdds::rtps::GUID_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_lookup(eprosima::fastdds::rtps::GUID_t&, eprosima::fastdds::rtps::ReaderProxy**)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_lookup(eprosima::fastdds::rtps::GUID_t&, eprosima::fastdds::rtps::ReaderProxy**)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::all_readers_updated()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::all_readers_updated()::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::wait_for_all_acked(eprosima::fastdds::dds::Time_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::wait_for_all_acked(eprosima::fastdds::dds::Time_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::check_acked_status()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::check_acked_status()::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::update_times(eprosima::fastdds::rtps::WriterTimes const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::update_times(eprosima::fastdds::rtps::WriterTimes const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_1>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_1)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::perform_nack_supression(eprosima::fastdds::rtps::GUID_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::perform_nack_supression(eprosima::fastdds::rtps::GUID_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::process_acknack(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::BitmapRange<eprosima::fastdds::rtps::SequenceNumber_t, eprosima::fastdds::rtps::SequenceNumberDiff, 256u> const&, bool, bool&, std::__1::array<unsigned char, 2ul>)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::process_acknack(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::BitmapRange<eprosima::fastdds::rtps::SequenceNumber_t, eprosima::fastdds::rtps::SequenceNumberDiff, 256u> const&, bool, bool&, std::__1::array<unsigned char, 2ul>)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::process_nack_frag(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::rtps::SequenceNumber_t const&, eprosima::fastdds::BitmapRange<unsigned int, eprosima::fastdds::DiffFunction<unsigned int>, 256u> const&, bool&, std::__1::array<unsigned char, 2ul>)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::process_nack_frag(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::rtps::SequenceNumber_t const&, eprosima::fastdds::BitmapRange<unsigned int, eprosima::fastdds::DiffFunction<unsigned int>, 256u> const&, bool&, std::__1::array<unsigned char, 2ul>)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::ack_timer_expired()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::ack_timer_expired()::$_0)
107
108
template<typename T>
109
static bool for_matched_readers(
110
        ResourceLimitedVector<ReaderProxy*>& reader_vector_1,
111
        ResourceLimitedVector<ReaderProxy*>& reader_vector_2,
112
        ResourceLimitedVector<ReaderProxy*>& reader_vector_3,
113
        T fun)
114
0
{
115
0
    if (for_matched_readers(reader_vector_1, reader_vector_2, fun))
116
0
    {
117
0
        return true;
118
0
    }
119
0
    return for_matched_readers(reader_vector_3, fun);
120
0
}
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::unsent_change_added_to_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::unsent_change_added_to_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::change_removed_by_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::change_removed_by_history(eprosima::fastdds::rtps::CacheChange_t*, std::__1::chrono::time_point<std::__1::chrono::steady_clock, std::__1::chrono::duration<long long, std::__1::ratio<1l, 1000000000l> > > const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_add_edp(eprosima::fastdds::rtps::ReaderProxyData const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_add_edp(eprosima::fastdds::rtps::ReaderProxyData const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_is_matched(eprosima::fastdds::rtps::GUID_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_is_matched(eprosima::fastdds::rtps::GUID_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_reader_lookup(eprosima::fastdds::rtps::GUID_t&, eprosima::fastdds::rtps::ReaderProxy**)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::matched_reader_lookup(eprosima::fastdds::rtps::GUID_t&, eprosima::fastdds::rtps::ReaderProxy**)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::all_readers_updated()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::all_readers_updated()::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::wait_for_all_acked(eprosima::fastdds::dds::Time_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::wait_for_all_acked(eprosima::fastdds::dds::Time_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::check_acked_status()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::check_acked_status()::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::update_times(eprosima::fastdds::rtps::WriterTimes const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::update_times(eprosima::fastdds::rtps::WriterTimes const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_1>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::send_periodic_heartbeat(bool, bool)::$_1)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::perform_nack_supression(eprosima::fastdds::rtps::GUID_t const&)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::perform_nack_supression(eprosima::fastdds::rtps::GUID_t const&)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::process_acknack(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::BitmapRange<eprosima::fastdds::rtps::SequenceNumber_t, eprosima::fastdds::rtps::SequenceNumberDiff, 256u> const&, bool, bool&, std::__1::array<unsigned char, 2ul>)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::process_acknack(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::BitmapRange<eprosima::fastdds::rtps::SequenceNumber_t, eprosima::fastdds::rtps::SequenceNumberDiff, 256u> const&, bool, bool&, std::__1::array<unsigned char, 2ul>)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::process_nack_frag(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::rtps::SequenceNumber_t const&, eprosima::fastdds::BitmapRange<unsigned int, eprosima::fastdds::DiffFunction<unsigned int>, 256u> const&, bool&, std::__1::array<unsigned char, 2ul>)::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::process_nack_frag(eprosima::fastdds::rtps::GUID_t const&, eprosima::fastdds::rtps::GUID_t const&, unsigned int, eprosima::fastdds::rtps::SequenceNumber_t const&, eprosima::fastdds::BitmapRange<unsigned int, eprosima::fastdds::DiffFunction<unsigned int>, 256u> const&, bool&, std::__1::array<unsigned char, 2ul>)::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::ack_timer_expired()::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > >&, eprosima::fastdds::rtps::StatefulWriter::ack_timer_expired()::$_0)
121
122
/**
123
 * Loops over all the readers in the vector, applying the given routine.
124
 * The loop continues until the result of the routine is true for any reader
125
 * or all readers have been processes.
126
 * The returned value is true if the routine returned true at any point,
127
 * or false otherwise.
128
 *
129
 * const version
130
 */
131
template<typename T>
132
static bool for_matched_readers(
133
        const ResourceLimitedVector<ReaderProxy*>& reader_vector_1,
134
        T fun)
135
0
{
136
0
    for (const ReaderProxy* remote_reader : reader_vector_1)
137
0
    {
138
0
        if (fun(remote_reader))
139
0
        {
140
0
            return true;
141
0
        }
142
0
    }
143
144
0
    return false;
145
0
}
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::is_acked_by_all_nts(eprosima::fastdds::rtps::SequenceNumber_t) const::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::rtps::StatefulWriter::is_acked_by_all_nts(eprosima::fastdds::rtps::SequenceNumber_t) const::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_readers_guids(std::__1::vector<eprosima::fastdds::rtps::GUID_t, std::__1::allocator<eprosima::fastdds::rtps::GUID_t> >&) const::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::rtps::StatefulWriter::matched_readers_guids(std::__1::vector<eprosima::fastdds::rtps::GUID_t, std::__1::allocator<eprosima::fastdds::rtps::GUID_t> >&) const::$_0)
146
147
template<typename T>
148
static bool for_matched_readers(
149
        const ResourceLimitedVector<ReaderProxy*>& reader_vector_1,
150
        const ResourceLimitedVector<ReaderProxy*>& reader_vector_2,
151
        T fun)
152
0
{
153
0
    if (for_matched_readers(reader_vector_1, fun))
154
0
    {
155
0
        return true;
156
0
    }
157
0
    return for_matched_readers(reader_vector_2, fun);
158
0
}
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::is_acked_by_all_nts(eprosima::fastdds::rtps::SequenceNumber_t) const::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::rtps::StatefulWriter::is_acked_by_all_nts(eprosima::fastdds::rtps::SequenceNumber_t) const::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_readers_guids(std::__1::vector<eprosima::fastdds::rtps::GUID_t, std::__1::allocator<eprosima::fastdds::rtps::GUID_t> >&) const::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::rtps::StatefulWriter::matched_readers_guids(std::__1::vector<eprosima::fastdds::rtps::GUID_t, std::__1::allocator<eprosima::fastdds::rtps::GUID_t> >&) const::$_0)
159
160
template<typename T>
161
static bool for_matched_readers(
162
        const ResourceLimitedVector<ReaderProxy*>& reader_vector_1,
163
        const ResourceLimitedVector<ReaderProxy*>& reader_vector_2,
164
        const ResourceLimitedVector<ReaderProxy*>& reader_vector_3,
165
        T fun)
166
0
{
167
0
    if (for_matched_readers(reader_vector_1, reader_vector_2, fun))
168
0
    {
169
0
        return true;
170
0
    }
171
0
    return for_matched_readers(reader_vector_3, fun);
172
0
}
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::is_acked_by_all_nts(eprosima::fastdds::rtps::SequenceNumber_t) const::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::rtps::StatefulWriter::is_acked_by_all_nts(eprosima::fastdds::rtps::SequenceNumber_t) const::$_0)
Unexecuted instantiation: StatefulWriter.cpp:bool eprosima::fastdds::rtps::for_matched_readers<eprosima::fastdds::rtps::StatefulWriter::matched_readers_guids(std::__1::vector<eprosima::fastdds::rtps::GUID_t, std::__1::allocator<eprosima::fastdds::rtps::GUID_t> >&) const::$_0>(eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::ResourceLimitedVector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::integral_constant<bool, false>, eprosima::fastdds::ResourceLimitedContainerConfig, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*>, std::__1::vector<eprosima::fastdds::rtps::ReaderProxy*, std::__1::allocator<eprosima::fastdds::rtps::ReaderProxy*> > > const&, eprosima::fastdds::rtps::StatefulWriter::matched_readers_guids(std::__1::vector<eprosima::fastdds::rtps::GUID_t, std::__1::allocator<eprosima::fastdds::rtps::GUID_t> >&) const::$_0)
173
174
using namespace std::chrono;
175
176
StatefulWriter::StatefulWriter(
177
        RTPSParticipantImpl* pimpl,
178
        const GUID_t& guid,
179
        const WriterAttributes& att,
180
        FlowController* flow_controller,
181
        WriterHistory* history,
182
        WriterListener* listener,
183
        StatefulWriterListener* stateful_listener)
184
0
    : BaseWriter(pimpl, guid, att, flow_controller, history, listener)
185
0
    , periodic_hb_event_(nullptr)
186
0
    , nack_response_event_(nullptr)
187
0
    , ack_event_(nullptr)
188
0
    , heartbeat_count_(0)
189
0
    , times_(att.times)
190
0
    , matched_remote_readers_(att.matched_readers_allocation)
191
0
    , matched_readers_pool_(att.matched_readers_allocation)
192
0
    , next_all_acked_notify_sequence_(0, 1)
193
0
    , all_acked_(false)
194
0
    , may_remove_change_cond_()
195
0
    , may_remove_change_(0)
196
0
    , disable_heartbeat_piggyback_(att.disable_heartbeat_piggyback)
197
0
    , disable_positive_acks_(att.disable_positive_acks)
198
0
    , keep_duration_(att.keep_duration)
199
0
    , last_sequence_number_()
200
0
    , biggest_removed_sequence_number_()
201
0
    , matched_local_readers_(att.matched_readers_allocation)
202
0
    , matched_datasharing_readers_(att.matched_readers_allocation)
203
0
    , locator_selector_general_(*this, att.matched_readers_allocation)
204
0
    , locator_selector_async_(*this, att.matched_readers_allocation)
205
0
    , stateful_writer_listener_(stateful_listener)
206
0
{
207
0
    init(pimpl, att);
208
0
}
209
210
void StatefulWriter::init(
211
        RTPSParticipantImpl* pimpl,
212
        const WriterAttributes& att)
213
0
{
214
0
    const RTPSParticipantAttributes& part_att = pimpl->get_attributes();
215
216
0
    auto push_mode = PropertyPolicyHelper::find_property(att.endpoint.properties, "fastdds.push_mode");
217
0
    push_mode_ = !((nullptr != push_mode) && ("false" == *push_mode));
218
219
0
    periodic_hb_event_ = new TimedEvent(
220
0
        pimpl->getEventResource(),
221
0
        [&]() -> bool
222
0
        {
223
0
            return send_periodic_heartbeat();
224
0
        },
225
0
        fastdds::rtps::TimeConv::Time_t2MilliSecondsDouble(times_.heartbeat_period));
226
227
0
    nack_response_event_ = new TimedEvent(
228
0
        pimpl->getEventResource(),
229
0
        [&]() -> bool
230
0
        {
231
0
            perform_nack_response();
232
0
            return false;
233
0
        },
234
0
        fastdds::rtps::TimeConv::Time_t2MilliSecondsDouble(times_.nack_response_delay));
235
236
0
    if (disable_positive_acks_)
237
0
    {
238
0
        ack_event_ = new TimedEvent(
239
0
            pimpl->getEventResource(),
240
0
            [&]() -> bool
241
0
            {
242
0
                return ack_timer_expired();
243
0
            },
244
0
            att.keep_duration.to_ns() * 1e-6);             // in milliseconds
245
0
    }
246
247
0
    for (size_t n = 0; n < att.matched_readers_allocation.initial; ++n)
248
0
    {
249
0
        ReaderProxy* new_proxy = new ReaderProxy(
250
0
            times_, part_att.allocation.locators, this, stateful_writer_listener_);
251
0
        matched_readers_pool_.push_back(new_proxy);
252
0
    }
253
0
}
254
255
StatefulWriter::~StatefulWriter()
256
0
{
257
0
    EPROSIMA_LOG_INFO(RTPS_WRITER, "StatefulWriter destructor");
258
0
}
259
260
void StatefulWriter::local_actions_on_writer_removed()
261
0
{
262
0
    EPROSIMA_LOG_INFO(RTPS_WRITER, "StatefulWriter local_actions_on_writer_removed");
263
264
    // Disable timed events, because their callbacks use cache changes
265
0
    if (disable_positive_acks_)
266
0
    {
267
0
        delete(ack_event_);
268
0
        ack_event_ = nullptr;
269
0
    }
270
271
0
    if (nack_response_event_ != nullptr)
272
0
    {
273
0
        delete(nack_response_event_);
274
0
        nack_response_event_ = nullptr;
275
0
    }
276
277
    // This must be the next action, as it frees CacheChange_t from the async thread.
278
0
    BaseWriter::local_actions_on_writer_removed();
279
280
    // Stop all active proxies and pass them to the pool
281
0
    {
282
0
        std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
283
0
        while (!matched_remote_readers_.empty())
284
0
        {
285
0
            ReaderProxy* remote_reader = matched_remote_readers_.back();
286
0
            matched_remote_readers_.pop_back();
287
0
            remote_reader->stop();
288
0
            matched_readers_pool_.push_back(remote_reader);
289
0
        }
290
0
        while (!matched_local_readers_.empty())
291
0
        {
292
0
            ReaderProxy* remote_reader = matched_local_readers_.back();
293
0
            matched_local_readers_.pop_back();
294
0
            remote_reader->stop();
295
0
            matched_readers_pool_.push_back(remote_reader);
296
0
        }
297
0
        while (!matched_datasharing_readers_.empty())
298
0
        {
299
0
            ReaderProxy* remote_reader = matched_datasharing_readers_.back();
300
0
            matched_datasharing_readers_.pop_back();
301
0
            remote_reader->stop();
302
0
            matched_readers_pool_.push_back(remote_reader);
303
0
        }
304
0
    }
305
306
    // PeriodicHeartbeatEvent must be released after releasing all proxies
307
    // because proxy's NackSuppressionEvent could restart this event.
308
0
    if (periodic_hb_event_ != nullptr)
309
0
    {
310
0
        delete(periodic_hb_event_);
311
0
        periodic_hb_event_ = nullptr;
312
0
    }
313
314
    // Delete all proxies in the pool
315
0
    for (ReaderProxy* remote_reader : matched_readers_pool_)
316
0
    {
317
0
        delete(remote_reader);
318
0
    }
319
0
}
320
321
/*
322
 * CHANGE-RELATED METHODS
323
 */
324
void StatefulWriter::prepare_datasharing_delivery(
325
        CacheChange_t* change)
326
0
{
327
0
    auto pool = std::dynamic_pointer_cast<WriterPool>(history_->get_payload_pool());
328
0
    assert (pool != nullptr);
329
330
0
    pool->add_to_shared_history(change);
331
0
    EPROSIMA_LOG_INFO(RTPS_WRITER, "Notifying readers of cache change with SN " << change->sequenceNumber);
332
0
}
333
334
void StatefulWriter::unsent_change_added_to_history(
335
        CacheChange_t* change,
336
        const std::chrono::time_point<std::chrono::steady_clock>& max_blocking_time)
337
0
{
338
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
339
0
    auto payload_length = change->serializedPayload.length;
340
341
0
    if (liveliness_lease_duration_ < dds::c_TimeInfinite)
342
0
    {
343
0
        mp_RTPSParticipant->wlp()->assert_liveliness(
344
0
            getGuid(),
345
0
            liveliness_kind_,
346
0
            liveliness_lease_duration_);
347
0
    }
348
349
    // Prepare the metadata for datasharing
350
0
    if (is_datasharing_compatible())
351
0
    {
352
0
        prepare_datasharing_delivery(change);
353
0
    }
354
355
    // Now for the rest of readers
356
0
    if (!matched_remote_readers_.empty() || !matched_datasharing_readers_.empty() || !matched_local_readers_.empty())
357
0
    {
358
0
        bool should_be_sent = false;
359
0
        for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
360
0
                [this, &should_be_sent, &change, &max_blocking_time](ReaderProxy* reader)
361
0
                {
362
0
                    ChangeForReader_t changeForReader(change);
363
0
                    bool is_relevant = reader->rtps_is_relevant(change);
364
365
0
                    if (push_mode_ || !reader->is_reliable() || reader->is_local_reader())
366
0
                    {
367
                        //ChangeForReader_t construct sets status to UNSENT.
368
0
                        should_be_sent |= is_relevant;
369
0
                    }
370
0
                    else
371
0
                    {
372
0
                        changeForReader.setStatus(UNACKNOWLEDGED);
373
0
                    }
374
0
                    reader->add_change(changeForReader, is_relevant, false, max_blocking_time);
375
376
0
                    return false;
377
0
                }
378
0
                );
379
380
0
        if (disable_positive_acks_)
381
0
        {
382
0
            Time_t expiration_ts = change->sourceTimestamp + keep_duration_;
383
0
            Time_t current_ts;
384
0
            Time_t::now(current_ts);
385
0
            assert(expiration_ts >= current_ts);
386
0
            auto interval = (expiration_ts - current_ts).to_duration_t();
387
388
0
            ack_event_->update_interval(interval);
389
0
            ack_event_->restart_timer(max_blocking_time);
390
0
        }
391
392
        // After adding the CacheChange_t to flowcontroller, its pointer cannot be used because it may be removed
393
        // internally before exiting the call. For example if the writer matched with a best-effort reader.
394
0
        if (should_be_sent)
395
0
        {
396
0
            flow_controller_->add_new_sample(this, change, max_blocking_time);
397
0
        }
398
0
        else
399
0
        {
400
0
            periodic_hb_event_->restart_timer(max_blocking_time);
401
0
        }
402
0
    }
403
0
    else
404
0
    {
405
0
        EPROSIMA_LOG_INFO(RTPS_WRITER, "No reader proxy to add change.");
406
0
        check_acked_status();
407
0
    }
408
409
    // Throughput should be notified even if no matches are available
410
0
    on_publish_throughput(payload_length);
411
0
}
412
413
bool StatefulWriter::intraprocess_delivery(
414
        CacheChange_t* change,
415
        ReaderProxy* reader_proxy)
416
0
{
417
0
    LocalReaderPointer::Instance local_reader = reader_proxy->local_reader();
418
0
    if (local_reader)
419
0
    {
420
0
        if (change->write_params.related_sample_identity() != SampleIdentity::unknown())
421
0
        {
422
0
            change->write_params.sample_identity(change->write_params.related_sample_identity());
423
0
        }
424
0
        return local_reader->process_data_msg(change);
425
0
    }
426
0
    return false;
427
0
}
428
429
bool StatefulWriter::intraprocess_gap(
430
        ReaderProxy* reader_proxy,
431
        const SequenceNumber_t& first_seq,
432
        const SequenceNumber_t& last_seq)
433
0
{
434
0
    LocalReaderPointer::Instance local_reader = reader_proxy->local_reader();
435
0
    if (local_reader)
436
0
    {
437
0
        return local_reader->process_gap_msg(
438
0
            m_guid, first_seq, SequenceNumberSet_t(last_seq), c_VendorId_eProsima);
439
0
    }
440
441
0
    return false;
442
0
}
443
444
bool StatefulWriter::intraprocess_heartbeat(
445
        ReaderProxy* reader_proxy,
446
        bool liveliness,
447
        bool gap_preceded)
448
0
{
449
0
    bool returned_value = false;
450
0
    std::unique_lock<RecursiveTimedMutex> lockW(mp_mutex);
451
0
    LocalReaderPointer::Instance local_reader = reader_proxy->local_reader();
452
0
    lockW.unlock();
453
454
0
    if (local_reader)
455
0
    {
456
0
        lockW.lock();
457
0
        SequenceNumber_t first_seq = get_seq_num_min();
458
0
        SequenceNumber_t last_seq = get_seq_num_max();
459
460
0
        if (first_seq == c_SequenceNumber_Unknown || last_seq == c_SequenceNumber_Unknown)
461
0
        {
462
0
            if (liveliness)
463
0
            {
464
0
                first_seq = next_sequence_number();
465
0
                last_seq = first_seq - 1;
466
0
            }
467
0
        }
468
469
0
        if ((first_seq != c_SequenceNumber_Unknown && last_seq != c_SequenceNumber_Unknown) &&
470
0
                (liveliness || gap_preceded || reader_proxy->has_changes()))
471
0
        {
472
0
            increment_hb_count();
473
0
            Count_t hb_count = heartbeat_count_;
474
0
            lockW.unlock();
475
0
            returned_value = local_reader->process_heartbeat_msg(
476
0
                m_guid, hb_count, first_seq, last_seq, true, liveliness, c_VendorId_eProsima);
477
0
        }
478
0
    }
479
480
0
    return returned_value;
481
0
}
482
483
bool StatefulWriter::change_removed_by_history(
484
        CacheChange_t* a_change,
485
        const std::chrono::time_point<std::chrono::steady_clock>& max_blocking_time)
486
0
{
487
0
    bool ret_value = false;
488
0
    SequenceNumber_t sequence_number = a_change->sequenceNumber;
489
490
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
491
0
    EPROSIMA_LOG_INFO(RTPS_WRITER, "Change " << sequence_number << " to be removed.");
492
493
0
    if (flow_controller_->remove_change(a_change, max_blocking_time))
494
0
    {
495
496
        // Take note of biggest removed sequence number to improve sending of gaps
497
0
        if (sequence_number > biggest_removed_sequence_number_)
498
0
        {
499
0
            biggest_removed_sequence_number_ = sequence_number;
500
0
        }
501
502
        // Flush pending irrelevant GAPs for any remote reader before the change is erased from history
503
0
        for (ReaderProxy* reader : matched_remote_readers_)
504
0
        {
505
0
            if (SequenceNumber_t::unknown() != reader->first_irrelevant_removed() &&
506
0
                    reader->first_irrelevant_removed() <= sequence_number)
507
0
            {
508
0
                try
509
0
                {
510
0
                    RTPSMessageGroup group(mp_RTPSParticipant, this, reader->message_sender());
511
0
                    send_heartbeat_nts_(1u, group, true);  // Final Heartbeat
512
0
                    add_gaps_for_removed_irrelevants(*reader, group);
513
0
                }
514
0
                catch (const RTPSMessageGroup::timeout&)
515
0
                {
516
0
                    EPROSIMA_LOG_ERROR(RTPS_WRITER, "Max blocking time reached");
517
0
                }
518
0
            }
519
0
        }
520
521
        // Invalidate CacheChange pointer in ReaderProxies.
522
0
        for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
523
0
                [sequence_number](ReaderProxy* reader)
524
0
                {
525
0
                    reader->change_has_been_removed(sequence_number);
526
0
                    return false;
527
0
                }
528
0
                );
529
530
        // remove from datasharing pool history
531
0
        if (is_datasharing_compatible())
532
0
        {
533
0
            auto pool = std::dynamic_pointer_cast<WriterPool>(history_->get_payload_pool());
534
0
            assert (pool != nullptr);
535
536
0
            pool->remove_from_shared_history(a_change);
537
0
            EPROSIMA_LOG_INFO(RTPS_WRITER, "Removing shared cache change with SN " << a_change->sequenceNumber);
538
0
        }
539
540
0
        may_remove_change_ = 2;
541
0
        may_remove_change_cond_.notify_one();
542
543
0
        ret_value = true;
544
0
    }
545
546
0
    return ret_value;
547
0
}
548
549
void StatefulWriter::send_heartbeat_to_all_readers(
550
        bool force_separating)
551
0
{
552
    // This method is only called from send_periodic_heartbeat
553
554
0
    if (separate_sending_enabled_ || force_separating)
555
0
    {
556
0
        for (ReaderProxy* reader : matched_remote_readers_)
557
0
        {
558
0
            send_heartbeat_to_nts(*reader);
559
0
        }
560
0
    }
561
0
    else
562
0
    {
563
0
        for (ReaderProxy* reader : matched_local_readers_)
564
0
        {
565
0
            intraprocess_heartbeat(reader);
566
0
        }
567
568
0
        for (ReaderProxy* reader : matched_datasharing_readers_)
569
0
        {
570
0
            reader->datasharing_notify();
571
0
        }
572
573
0
        if (there_are_remote_readers_)
574
0
        {
575
0
            RTPSMessageGroup group(mp_RTPSParticipant, this, &locator_selector_general_);
576
0
            select_all_readers_nts(group, locator_selector_general_);
577
578
0
            assert(
579
0
                (SequenceNumber_t::unknown() == get_seq_num_min() &&
580
0
                SequenceNumber_t::unknown() == get_seq_num_max()) ||
581
0
                (SequenceNumber_t::unknown() != get_seq_num_min() &&
582
0
                SequenceNumber_t::unknown() != get_seq_num_max()));
583
584
0
            send_heartbeat_nts_(locator_selector_general_.all_remote_readers.size(), group, disable_positive_acks_);
585
586
0
            add_gaps_for_holes_in_history(group);
587
0
        }
588
0
    }
589
0
}
590
591
void StatefulWriter::deliver_sample_to_intraprocesses(
592
        CacheChange_t* change)
593
0
{
594
0
    for (ReaderProxy* remoteReader : matched_local_readers_)
595
0
    {
596
0
        SequenceNumber_t gap_seq;
597
0
        FragmentNumber_t dummy = 0;
598
0
        bool dumb = false;
599
0
        if (remoteReader->change_is_unsent(change->sequenceNumber, dummy, gap_seq, get_seq_num_min(), dumb))
600
0
        {
601
            // If there is a hole (removed from history or not relevants) between previous sample and this one,
602
            // send it a personal GAP.
603
0
            if (SequenceNumber_t::unknown() != gap_seq)
604
0
            {
605
                // Force the heartbeat. The reader may have no pending changes but still needs the HB to apply the GAP
606
0
                intraprocess_heartbeat(remoteReader, false, true);
607
0
                intraprocess_gap(remoteReader, gap_seq, change->sequenceNumber);
608
0
                remoteReader->acked_changes_set(change->sequenceNumber);
609
0
            }
610
0
            bool delivered = intraprocess_delivery(change, remoteReader);
611
0
            if (!remoteReader->is_reliable())
612
0
            {
613
0
                remoteReader->acked_changes_set(change->sequenceNumber + 1);
614
0
            }
615
0
            else
616
0
            {
617
0
                intraprocess_heartbeat(remoteReader, false);
618
0
                remoteReader->from_unsent_to_status(
619
0
                    change->sequenceNumber,
620
0
                    delivered ? ACKNOWLEDGED : UNACKNOWLEDGED,
621
0
                    false,
622
0
                    delivered);
623
0
            }
624
0
        }
625
0
    }
626
0
}
627
628
void StatefulWriter::deliver_sample_to_datasharing(
629
        CacheChange_t* change)
630
0
{
631
0
    for (ReaderProxy* remoteReader : matched_datasharing_readers_)
632
0
    {
633
0
        SequenceNumber_t gap_seq;
634
0
        FragmentNumber_t dummy = 0;
635
0
        bool dumb = false;
636
0
        if (remoteReader->change_is_unsent(change->sequenceNumber, dummy, gap_seq, get_seq_num_min(), dumb))
637
0
        {
638
0
            if (!remoteReader->is_reliable())
639
0
            {
640
0
                remoteReader->acked_changes_set(change->sequenceNumber + 1);
641
0
            }
642
0
            else
643
0
            {
644
0
                remoteReader->from_unsent_to_status(
645
0
                    change->sequenceNumber,
646
0
                    UNACKNOWLEDGED,
647
0
                    false);
648
0
            }
649
0
            remoteReader->datasharing_notify();
650
0
        }
651
0
    }
652
0
}
653
654
DeliveryRetCode StatefulWriter::deliver_sample_to_network(
655
        CacheChange_t* change,
656
        RTPSMessageGroup& group,
657
        LocatorSelectorSender& locator_selector, // Object locked by FlowControllerImpl
658
        const std::chrono::time_point<std::chrono::steady_clock>& max_blocking_time)
659
0
{
660
0
    NetworkFactory& network = mp_RTPSParticipant->network_factory();
661
0
    DeliveryRetCode ret_code = DeliveryRetCode::DELIVERED;
662
0
    uint32_t n_fragments = change->getFragmentCount();
663
0
    FragmentNumber_t min_unsent_fragment = 0;
664
0
    bool need_reactivate_periodic_heartbeat = false;
665
666
0
    while (DeliveryRetCode::DELIVERED == ret_code &&
667
0
            min_unsent_fragment != n_fragments + 1)
668
0
    {
669
0
        SequenceNumber_t gap_seq_for_all = SequenceNumber_t::unknown();
670
0
        locator_selector.locator_selector.reset(false);
671
0
        auto first_relevant_reader = matched_remote_readers_.begin();
672
0
        bool inline_qos = false;
673
0
        bool should_be_sent = false;
674
0
        min_unsent_fragment = n_fragments + 1;
675
676
0
        for (auto remote_reader = first_relevant_reader; remote_reader != matched_remote_readers_.end();
677
0
                ++remote_reader)
678
0
        {
679
0
            SequenceNumber_t gap_seq;
680
0
            FragmentNumber_t next_unsent_frag = 0;
681
682
0
            if (SequenceNumber_t::unknown() != (*remote_reader)->first_irrelevant_removed())
683
0
            {
684
                // Send GAP with irrelevant changes that are not in history.
685
0
                group.sender(this, (*remote_reader)->message_sender());
686
0
                send_heartbeat_nts_(1u, group, disable_positive_acks_);
687
0
                add_gaps_for_removed_irrelevants(**remote_reader, group);
688
0
                group.sender(this, &locator_selector);             // This makes the flush_and_reset().
689
0
            }
690
691
0
            if ((*remote_reader)->change_is_unsent(change->sequenceNumber, next_unsent_frag, gap_seq, get_seq_num_min(),
692
0
                    need_reactivate_periodic_heartbeat) &&
693
0
                    (0 == n_fragments || min_unsent_fragment >= next_unsent_frag))
694
0
            {
695
0
                if (min_unsent_fragment > next_unsent_frag)
696
0
                {
697
0
                    locator_selector.locator_selector.reset(false);
698
0
                    first_relevant_reader = remote_reader;
699
0
                    min_unsent_fragment = next_unsent_frag;
700
0
                }
701
702
0
                (*remote_reader)->active(true);
703
0
                locator_selector.locator_selector.enable((*remote_reader)->guid());
704
0
                should_be_sent = true;
705
0
                inline_qos |= (*remote_reader)->expects_inline_qos();
706
707
                // If there is a hole (removed from history or not relevants) between previous sample and this one,
708
                // send it a personal GAP.
709
0
                if (SequenceNumber_t::unknown() != gap_seq)
710
0
                {
711
0
                    if (SequenceNumber_t::unknown() == gap_seq_for_all)     // Calculate if the hole is for all readers
712
0
                    {
713
0
                        History::const_iterator chit = history_->find_change_nts(change);
714
715
0
                        if (chit == history_->changesBegin())
716
0
                        {
717
0
                            gap_seq_for_all = gap_seq;
718
0
                        }
719
0
                        else
720
0
                        {
721
0
                            SequenceNumber_t prev = (*std::prev(chit))->sequenceNumber + 1;
722
723
0
                            if (prev == gap_seq)
724
0
                            {
725
0
                                gap_seq_for_all = gap_seq;
726
0
                            }
727
0
                        }
728
0
                    }
729
730
0
                    if (gap_seq_for_all != gap_seq)     // If it is an individual GAP, sent it to repective reader.
731
0
                    {
732
0
                        group.sender(this, (*remote_reader)->message_sender());
733
0
                        send_heartbeat_nts_(1u, group, disable_positive_acks_);
734
0
                        group.add_gap(gap_seq, SequenceNumberSet_t(change->sequenceNumber),
735
0
                                (*remote_reader)->guid());
736
0
                        group.sender(this, &locator_selector);     // This makes the flush_and_reset().
737
0
                    }
738
0
                }
739
0
            }
740
0
            else
741
0
            {
742
0
                (*remote_reader)->active(false);
743
0
            }
744
0
        }
745
746
0
        bool should_send_global_gap = SequenceNumber_t::unknown() != gap_seq_for_all;
747
748
0
        if (locator_selector.locator_selector.state_has_changed() &&
749
0
                ((should_be_sent && !separate_sending_enabled_) || should_send_global_gap))
750
0
        {
751
0
            group.flush_and_reset();
752
0
            network.select_locators(locator_selector.locator_selector);
753
0
            compute_selected_guids(locator_selector);
754
0
        }
755
756
0
        if (should_send_global_gap) // Send GAP for all readers
757
0
        {
758
0
            send_heartbeat_nts_(locator_selector.all_remote_readers.size(), group, disable_positive_acks_);
759
0
            group.add_gap(gap_seq_for_all, SequenceNumberSet_t(change->sequenceNumber));
760
0
        }
761
762
0
        try
763
0
        {
764
0
            if (should_be_sent)
765
0
            {
766
0
                if (!separate_sending_enabled_)
767
0
                {
768
0
                    size_t num_locators = locator_selector.locator_selector.selected_size();
769
0
                    if (num_locators > 0)
770
0
                    {
771
0
                        if (0 < n_fragments)
772
0
                        {
773
0
                            if (min_unsent_fragment != n_fragments + 1)
774
0
                            {
775
0
                                if (group.add_data_frag(*change, min_unsent_fragment, inline_qos))
776
0
                                {
777
0
                                    for (auto remote_reader = first_relevant_reader;
778
0
                                            remote_reader != matched_remote_readers_.end();
779
0
                                            ++remote_reader)
780
0
                                    {
781
0
                                        if ((*remote_reader)->active())
782
0
                                        {
783
0
                                            bool allFragmentsSent = false;
784
0
                                            (*remote_reader)->mark_fragment_as_sent_for_change(
785
0
                                                change->sequenceNumber,
786
0
                                                min_unsent_fragment,
787
0
                                                allFragmentsSent);
788
789
0
                                            if (allFragmentsSent)
790
0
                                            {
791
0
                                                if (!(*remote_reader)->is_reliable())
792
0
                                                {
793
0
                                                    (*remote_reader)->acked_changes_set(change->sequenceNumber + 1);
794
0
                                                }
795
0
                                                else
796
0
                                                {
797
0
                                                    (*remote_reader)->from_unsent_to_status(
798
0
                                                        change->sequenceNumber,
799
0
                                                        UNDERWAY,
800
0
                                                        true);
801
0
                                                }
802
0
                                            }
803
0
                                        }
804
0
                                    }
805
0
                                    add_statistics_sent_submessage(change, num_locators);
806
0
                                }
807
0
                                else
808
0
                                {
809
0
                                    ret_code = DeliveryRetCode::NOT_DELIVERED;
810
0
                                }
811
0
                            }
812
0
                        }
813
0
                        else
814
0
                        {
815
0
                            if (group.add_data(*change, inline_qos))
816
0
                            {
817
0
                                for (auto remote_reader = first_relevant_reader;
818
0
                                        remote_reader != matched_remote_readers_.end();
819
0
                                        ++remote_reader)
820
0
                                {
821
0
                                    if ((*remote_reader)->active())
822
0
                                    {
823
0
                                        if (!(*remote_reader)->is_reliable())
824
0
                                        {
825
0
                                            (*remote_reader)->acked_changes_set(change->sequenceNumber + 1);
826
0
                                        }
827
0
                                        else
828
0
                                        {
829
0
                                            (*remote_reader)->from_unsent_to_status(
830
0
                                                change->sequenceNumber,
831
0
                                                UNDERWAY,
832
0
                                                true);
833
0
                                        }
834
0
                                    }
835
0
                                }
836
0
                                add_statistics_sent_submessage(change, num_locators);
837
0
                            }
838
0
                            else
839
0
                            {
840
0
                                ret_code = DeliveryRetCode::NOT_DELIVERED;
841
0
                            }
842
0
                        }
843
844
0
                        send_heartbeat_piggyback_nts_(group, locator_selector);
845
0
                    }
846
0
                }
847
0
                else
848
0
                {
849
0
                    for (auto remote_reader = first_relevant_reader;
850
0
                            remote_reader != matched_remote_readers_.end();
851
0
                            ++remote_reader)
852
0
                    {
853
0
                        if ((*remote_reader)->active())
854
0
                        {
855
0
                            group.sender(this, (*remote_reader)->message_sender());
856
857
0
                            if (0 < n_fragments)
858
0
                            {
859
0
                                if (min_unsent_fragment != n_fragments + 1)
860
0
                                {
861
0
                                    if (group.add_data_frag(*change, min_unsent_fragment, inline_qos))
862
0
                                    {
863
0
                                        bool allFragmentsSent = false;
864
0
                                        (*remote_reader)->mark_fragment_as_sent_for_change(
865
0
                                            change->sequenceNumber,
866
0
                                            min_unsent_fragment,
867
0
                                            allFragmentsSent);
868
869
0
                                        if (allFragmentsSent)
870
0
                                        {
871
0
                                            if (!(*remote_reader)->is_reliable())
872
0
                                            {
873
0
                                                (*remote_reader)->acked_changes_set(change->sequenceNumber + 1);
874
0
                                            }
875
0
                                            else
876
0
                                            {
877
0
                                                (*remote_reader)->from_unsent_to_status(
878
0
                                                    change->sequenceNumber,
879
0
                                                    UNDERWAY,
880
0
                                                    true);
881
0
                                            }
882
0
                                        }
883
0
                                        add_statistics_sent_submessage(change, (*remote_reader)->locators_size());
884
0
                                    }
885
0
                                    else
886
0
                                    {
887
0
                                        ret_code = DeliveryRetCode::NOT_DELIVERED;
888
0
                                    }
889
0
                                }
890
0
                            }
891
0
                            else
892
0
                            {
893
0
                                if (group.add_data(*change, (*remote_reader)->expects_inline_qos()))
894
0
                                {
895
0
                                    if (!(*remote_reader)->is_reliable())
896
0
                                    {
897
0
                                        (*remote_reader)->acked_changes_set(change->sequenceNumber + 1);
898
0
                                    }
899
0
                                    else
900
0
                                    {
901
0
                                        (*remote_reader)->from_unsent_to_status(
902
0
                                            change->sequenceNumber,
903
0
                                            UNDERWAY,
904
0
                                            true);
905
0
                                    }
906
0
                                    add_statistics_sent_submessage(change, (*remote_reader)->locators_size());
907
0
                                }
908
0
                                else
909
0
                                {
910
0
                                    EPROSIMA_LOG_ERROR(RTPS_WRITER, "Error sending change " << change->sequenceNumber);
911
0
                                    ret_code = DeliveryRetCode::NOT_DELIVERED;
912
0
                                }
913
0
                            }
914
915
0
                            send_heartbeat_nts_(1u, group, false);
916
0
                        }
917
0
                    }
918
0
                }
919
920
0
                on_sample_datas(change->write_params.sample_identity(), change->writer_info.num_sent_submessages);
921
0
                on_data_sent();
922
0
            }
923
0
        }
924
0
        catch (const RTPSMessageGroup::timeout&)
925
0
        {
926
0
            EPROSIMA_LOG_ERROR(RTPS_WRITER, "Max blocking time reached");
927
0
            ret_code = DeliveryRetCode::NOT_DELIVERED;
928
0
        }
929
0
        catch (const RTPSMessageGroup::limit_exceeded&)
930
0
        {
931
0
            ret_code = DeliveryRetCode::EXCEEDED_LIMIT;
932
0
        }
933
934
0
        if (disable_positive_acks_ && last_sequence_number_ == SequenceNumber_t())
935
0
        {
936
0
            last_sequence_number_ = change->sequenceNumber;
937
0
            if ( !(ack_event_->getRemainingTimeMilliSec() > 0))
938
0
            {
939
                // Restart ack_timer
940
0
                Time_t expiration_ts = change->sourceTimestamp + keep_duration_;
941
0
                Time_t current_ts;
942
0
                Time_t::now(current_ts);
943
0
                assert(expiration_ts >= current_ts);
944
0
                auto interval = (expiration_ts - current_ts).to_duration_t();
945
946
0
                ack_event_->update_interval(interval);
947
0
                ack_event_->restart_timer(max_blocking_time);
948
0
            }
949
0
        }
950
951
        // Restore in case a exception was launched by RTPSMessageGroup.
952
0
        group.sender(this, &locator_selector);
953
954
0
    }
955
956
0
    if (need_reactivate_periodic_heartbeat)
957
0
    {
958
0
        periodic_hb_event_->restart_timer(max_blocking_time);
959
0
    }
960
961
0
    return ret_code;
962
0
}
963
964
/*
965
 * MATCHED_READER-RELATED METHODS
966
 */
967
void StatefulWriter::update_reader_info(
968
        LocatorSelectorSender& locator_selector,
969
        bool create_sender_resources)
970
0
{
971
0
    update_cached_info_nts(locator_selector);
972
0
    compute_selected_guids(locator_selector);
973
974
0
    if (create_sender_resources)
975
0
    {
976
0
        RTPSParticipantImpl* part = get_participant_impl();
977
0
        locator_selector.locator_selector.for_each([part](const Locator_t& loc)
978
0
                {
979
0
                    part->createSenderResources(loc);
980
0
                });
981
0
    }
982
983
    // Check if we have local or remote readers
984
0
    there_are_remote_readers_ = !matched_remote_readers_.empty();
985
0
    there_are_local_readers_ = !matched_local_readers_.empty();
986
0
    there_are_datasharing_readers_ = !matched_datasharing_readers_.empty();
987
0
}
988
989
void StatefulWriter::select_all_readers_nts(
990
        RTPSMessageGroup& group,
991
        LocatorSelectorSender& locator_selector)
992
0
{
993
0
    locator_selector.locator_selector.reset(true);
994
0
    if (locator_selector.locator_selector.state_has_changed())
995
0
    {
996
0
        group.flush_and_reset();
997
0
        mp_RTPSParticipant->network_factory().select_locators(locator_selector.locator_selector);
998
0
        compute_selected_guids(locator_selector);
999
0
    }
1000
0
}
1001
1002
bool StatefulWriter::matched_reader_add_edp(
1003
        const ReaderProxyData& rdata)
1004
0
{
1005
0
    using network::external_locators::filter_remote_locators;
1006
1007
0
    if (rdata.guid == c_Guid_Unknown)
1008
0
    {
1009
0
        EPROSIMA_LOG_ERROR(RTPS_WRITER, "Reliable Writer need GUID_t of matched readers");
1010
0
        return false;
1011
0
    }
1012
1013
0
    std::unique_lock<RecursiveTimedMutex> guard(mp_mutex);
1014
0
    std::unique_lock<LocatorSelectorSender> guard_locator_selector_general(locator_selector_general_);
1015
0
    std::unique_lock<LocatorSelectorSender> guard_locator_selector_async(locator_selector_async_);
1016
1017
    // Check if it is already matched.
1018
0
    if (for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1019
0
            [this, &rdata](ReaderProxy* reader)
1020
0
            {
1021
0
                if (reader->guid() == rdata.guid)
1022
0
                {
1023
0
                    EPROSIMA_LOG_INFO(RTPS_WRITER, "Attempting to add existing reader, updating information.");
1024
0
                    if (reader->update(rdata))
1025
0
                    {
1026
0
                        filter_remote_locators(*reader->general_locator_selector_entry(),
1027
0
                        m_att.external_unicast_locators, m_att.ignore_non_matching_locators);
1028
0
                        filter_remote_locators(*reader->async_locator_selector_entry(),
1029
0
                        m_att.external_unicast_locators, m_att.ignore_non_matching_locators);
1030
0
                        mp_RTPSParticipant->createSenderResources(rdata.remote_locators, m_att);
1031
0
                        update_reader_info(locator_selector_general_, true);
1032
0
                        update_reader_info(locator_selector_async_, true);
1033
0
                    }
1034
0
                    return true;
1035
0
                }
1036
0
                return false;
1037
0
            }))
1038
0
    {
1039
0
        if (nullptr != listener_)
1040
0
        {
1041
            // call the listener without locks taken
1042
0
            guard_locator_selector_async.unlock();
1043
0
            guard_locator_selector_general.unlock();
1044
0
            guard.unlock();
1045
1046
0
            listener_->on_reader_discovery(this, ReaderDiscoveryStatus::CHANGED_QOS_READER, rdata.guid, &rdata);
1047
0
        }
1048
1049
0
#ifdef FASTDDS_STATISTICS
1050
        // notify monitor service so that the connectionlist for this entity
1051
        // could be updated
1052
0
        if (nullptr != mp_RTPSParticipant->get_connections_observer() && !m_guid.is_builtin())
1053
0
        {
1054
0
            mp_RTPSParticipant->get_connections_observer()->on_local_entity_connections_change(m_guid);
1055
0
        }
1056
0
#endif //FASTDDS_STATISTICS
1057
1058
0
        return false;
1059
0
    }
1060
1061
    // Get a reader proxy from the inactive pool (or create a new one if necessary and allowed)
1062
0
    ReaderProxy* rp = nullptr;
1063
0
    if (matched_readers_pool_.empty())
1064
0
    {
1065
0
        size_t max_readers = matched_readers_pool_.max_size();
1066
0
        if (get_matched_readers_size() + matched_readers_pool_.size() < max_readers)
1067
0
        {
1068
0
            const RTPSParticipantAttributes& part_att = mp_RTPSParticipant->get_attributes();
1069
0
            rp = new ReaderProxy(times_, part_att.allocation.locators, this, stateful_writer_listener_);
1070
0
        }
1071
0
        else
1072
0
        {
1073
0
            EPROSIMA_LOG_WARNING(RTPS_WRITER, "Maximum number of reader proxies (" << max_readers
1074
0
                                                                                   << ") reached for writer "
1075
0
                                                                                   << m_guid);
1076
0
            return false;
1077
0
        }
1078
0
    }
1079
0
    else
1080
0
    {
1081
0
        rp = matched_readers_pool_.back();
1082
0
        matched_readers_pool_.pop_back();
1083
0
    }
1084
1085
    // Add info of new datareader.
1086
0
    rp->start(rdata, is_datasharing_compatible_with(rdata.data_sharing));
1087
0
    filter_remote_locators(*rp->general_locator_selector_entry(),
1088
0
            m_att.external_unicast_locators, m_att.ignore_non_matching_locators);
1089
0
    filter_remote_locators(*rp->async_locator_selector_entry(),
1090
0
            m_att.external_unicast_locators, m_att.ignore_non_matching_locators);
1091
0
    locator_selector_general_.locator_selector.add_entry(rp->general_locator_selector_entry());
1092
0
    locator_selector_async_.locator_selector.add_entry(rp->async_locator_selector_entry());
1093
1094
0
    if (rp->is_local_reader())
1095
0
    {
1096
0
        matched_local_readers_.push_back(rp);
1097
0
        EPROSIMA_LOG_INFO(RTPS_WRITER, "Adding reader " << rdata.guid << " to " << this->m_guid.entityId
1098
0
                                                        << " as local reader");
1099
0
    }
1100
0
    else
1101
0
    {
1102
0
        if (rp->is_datasharing_reader())
1103
0
        {
1104
0
            matched_datasharing_readers_.push_back(rp);
1105
0
            EPROSIMA_LOG_INFO(RTPS_WRITER, "Adding reader " << rdata.guid << " to " << this->m_guid.entityId
1106
0
                                                            << " as data sharing");
1107
0
        }
1108
0
        else
1109
0
        {
1110
0
            matched_remote_readers_.push_back(rp);
1111
0
            EPROSIMA_LOG_INFO(RTPS_WRITER, "Adding reader " << rdata.guid << " to " << this->m_guid.entityId
1112
0
                                                            << " as remote reader");
1113
0
        }
1114
0
    }
1115
1116
0
    mp_RTPSParticipant->createSenderResources(rdata.remote_locators, m_att);
1117
0
    update_reader_info(locator_selector_general_, true);
1118
0
    update_reader_info(locator_selector_async_, true);
1119
1120
0
    if (rp->is_datasharing_reader())
1121
0
    {
1122
0
        if (nullptr != listener_)
1123
0
        {
1124
            // call the listener without locks taken
1125
0
            guard_locator_selector_async.unlock();
1126
0
            guard_locator_selector_general.unlock();
1127
0
            guard.unlock();
1128
1129
0
            listener_->on_reader_discovery(this, ReaderDiscoveryStatus::DISCOVERED_READER, rdata.guid, &rdata);
1130
0
        }
1131
1132
0
#ifdef FASTDDS_STATISTICS
1133
        // notify monitor service so that the connectionlist for this entity
1134
        // could be updated
1135
0
        if (nullptr != mp_RTPSParticipant->get_connections_observer() && !m_guid.is_builtin())
1136
0
        {
1137
0
            mp_RTPSParticipant->get_connections_observer()->on_local_entity_connections_change(m_guid);
1138
0
        }
1139
0
#endif //FASTDDS_STATISTICS
1140
1141
0
        return true;
1142
0
    }
1143
1144
0
    bool is_reliable = rp->is_reliable();
1145
0
    if (is_reliable)
1146
0
    {
1147
0
        SequenceNumber_t min_seq = get_seq_num_min();
1148
0
        SequenceNumber_t last_seq = get_seq_num_max();
1149
0
        RTPSMessageGroup group(mp_RTPSParticipant, this, rp->message_sender());
1150
1151
        // Force the intraprocess Heartbeat in case a VOLATILE local reader has no pending changes, but it
1152
        // still needs the range to apply the positioning GAP.
1153
0
        if (rp->is_local_reader())
1154
0
        {
1155
0
            intraprocess_heartbeat(rp, false, true);
1156
0
        }
1157
0
        else
1158
0
        {
1159
0
            send_heartbeat_nts_(1u, group, disable_positive_acks_);
1160
0
        }
1161
1162
        // History not empty
1163
0
        if (min_seq != SequenceNumber_t::unknown())
1164
0
        {
1165
0
            (void)last_seq;
1166
0
            assert(last_seq != SequenceNumber_t::unknown());
1167
0
            assert(min_seq <= last_seq);
1168
1169
0
            try
1170
0
            {
1171
                // Late-joiner
1172
0
                if (TRANSIENT_LOCAL <= rp->durability_kind() &&
1173
0
                        TRANSIENT_LOCAL <= m_att.durabilityKind)
1174
0
                {
1175
0
                    for (History::iterator cit = history_->changesBegin(); cit != history_->changesEnd(); ++cit)
1176
0
                    {
1177
                        // Holes are managed when deliver_sample(), sending GAP messages.
1178
0
                        if (rp->rtps_is_relevant(*cit))
1179
0
                        {
1180
0
                            ChangeForReader_t changeForReader(*cit);
1181
1182
                            // If it is local, maintain in UNSENT status and add to flow controller.
1183
0
                            if (rp->is_local_reader())
1184
0
                            {
1185
0
                                flow_controller_->add_old_sample(this, *cit);
1186
0
                            }
1187
                            // In other case, set as UNACKNOWLEDGED and expects the reader request them.
1188
0
                            else
1189
0
                            {
1190
0
                                changeForReader.setStatus(UNACKNOWLEDGED);
1191
0
                            }
1192
1193
0
                            rp->add_change(changeForReader, true, false);
1194
0
                        }
1195
0
                    }
1196
0
                }
1197
0
                else
1198
0
                {
1199
0
                    if (rp->is_local_reader())
1200
0
                    {
1201
0
                        intraprocess_gap(rp, min_seq, history_->next_sequence_number());
1202
0
                    }
1203
0
                    else
1204
0
                    {
1205
                        // Send a GAP of the whole history.
1206
0
                        group.add_gap(min_seq, SequenceNumberSet_t(history_->next_sequence_number()), rp->guid());
1207
0
                    }
1208
0
                }
1209
1210
                // Always activate heartbeat period. We need a confirmation of the reader.
1211
                // The state has to be updated.
1212
0
                periodic_hb_event_->restart_timer(std::chrono::steady_clock::now() + std::chrono::hours(24));
1213
0
            }
1214
0
            catch (const RTPSMessageGroup::timeout&)
1215
0
            {
1216
0
                EPROSIMA_LOG_ERROR(RTPS_WRITER, "Max blocking time reached");
1217
0
            }
1218
0
        }
1219
1220
0
        if (!rp->is_local_reader())
1221
0
        {
1222
0
            group.flush_and_reset();
1223
0
        }
1224
0
    }
1225
0
    else
1226
0
    {
1227
        // Acknowledged all for best-effort reader.
1228
0
        rp->acked_changes_set(history_->next_sequence_number());
1229
0
    }
1230
1231
0
    EPROSIMA_LOG_INFO(RTPS_WRITER, "Reader Proxy " << rp->guid() << " added to " << this->m_guid.entityId << " with "
1232
0
                                                   << rdata.remote_locators.unicast.size() << "(u)-"
1233
0
                                                   << rdata.remote_locators.multicast.size()
1234
0
                                                   << "(m) locators");
1235
1236
0
    if (nullptr != listener_)
1237
0
    {
1238
        // call the listener without locks taken
1239
0
        guard_locator_selector_async.unlock();
1240
0
        guard_locator_selector_general.unlock();
1241
0
        guard.unlock();
1242
1243
0
        listener_->on_reader_discovery(this, ReaderDiscoveryStatus::DISCOVERED_READER, rdata.guid, &rdata);
1244
0
    }
1245
1246
0
#ifdef FASTDDS_STATISTICS
1247
    // notify monitor service so that the connectionlist for this entity
1248
    // could be updated
1249
0
    if (nullptr != mp_RTPSParticipant->get_connections_observer() && !m_guid.is_builtin())
1250
0
    {
1251
0
        mp_RTPSParticipant->get_connections_observer()->on_local_entity_connections_change(m_guid);
1252
0
    }
1253
0
#endif //FASTDDS_STATISTICS
1254
1255
0
    return true;
1256
0
}
1257
1258
bool StatefulWriter::matched_reader_remove(
1259
        const GUID_t& reader_guid)
1260
0
{
1261
0
    ReaderProxy* rproxy = nullptr;
1262
0
    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
1263
1264
0
    {
1265
0
        std::lock_guard<LocatorSelectorSender> guard_locator_selector_general(locator_selector_general_);
1266
0
        std::lock_guard<LocatorSelectorSender> guard_locator_selector_async(locator_selector_async_);
1267
1268
0
        for (ReaderProxyIterator it = matched_local_readers_.begin();
1269
0
                it != matched_local_readers_.end(); ++it)
1270
0
        {
1271
0
            if ((*it)->guid() == reader_guid)
1272
0
            {
1273
0
                EPROSIMA_LOG_INFO(RTPS_WRITER, "Reader Proxy removed: " << reader_guid);
1274
0
                rproxy = std::move(*it);
1275
0
                it = matched_local_readers_.erase(it);
1276
0
                break;
1277
0
            }
1278
0
        }
1279
1280
0
        if (rproxy == nullptr)
1281
0
        {
1282
0
            for (ReaderProxyIterator it = matched_datasharing_readers_.begin();
1283
0
                    it != matched_datasharing_readers_.end(); ++it)
1284
0
            {
1285
0
                if ((*it)->guid() == reader_guid)
1286
0
                {
1287
0
                    EPROSIMA_LOG_INFO(RTPS_WRITER, "Reader Proxy removed: " << reader_guid);
1288
0
                    rproxy = std::move(*it);
1289
0
                    it = matched_datasharing_readers_.erase(it);
1290
0
                    break;
1291
0
                }
1292
0
            }
1293
0
        }
1294
1295
0
        if (rproxy == nullptr)
1296
0
        {
1297
0
            for (ReaderProxyIterator it = matched_remote_readers_.begin();
1298
0
                    it != matched_remote_readers_.end(); ++it)
1299
0
            {
1300
0
                if ((*it)->guid() == reader_guid)
1301
0
                {
1302
0
                    EPROSIMA_LOG_INFO(RTPS_WRITER, "Reader Proxy removed: " << reader_guid);
1303
0
                    rproxy = std::move(*it);
1304
0
                    it = matched_remote_readers_.erase(it);
1305
0
                    break;
1306
0
                }
1307
0
            }
1308
0
        }
1309
1310
0
        locator_selector_general_.locator_selector.remove_entry(reader_guid);
1311
0
        locator_selector_async_.locator_selector.remove_entry(reader_guid);
1312
0
        update_reader_info(locator_selector_general_, false);
1313
0
        update_reader_info(locator_selector_async_, false);
1314
0
    }
1315
1316
0
    if (get_matched_readers_size() == 0)
1317
0
    {
1318
0
        periodic_hb_event_->cancel_timer();
1319
0
    }
1320
1321
0
    if (rproxy != nullptr)
1322
0
    {
1323
0
        rproxy->stop();
1324
0
        matched_readers_pool_.push_back(rproxy);
1325
1326
0
        check_acked_status();
1327
1328
0
        if (nullptr != listener_)
1329
0
        {
1330
            // listener is called without locks taken
1331
0
            lock.unlock();
1332
0
            listener_->on_reader_discovery(this, ReaderDiscoveryStatus::REMOVED_READER, reader_guid, nullptr);
1333
0
        }
1334
1335
0
#ifdef FASTDDS_STATISTICS
1336
        // notify monitor service so that the connectionlist for this entity
1337
        // could be updated
1338
0
        if (nullptr != mp_RTPSParticipant->get_connections_observer() && !m_guid.is_builtin())
1339
0
        {
1340
0
            mp_RTPSParticipant->get_connections_observer()->on_local_entity_connections_change(m_guid);
1341
0
        }
1342
0
#endif //FASTDDS_STATISTICS
1343
1344
0
        return true;
1345
0
    }
1346
1347
0
    EPROSIMA_LOG_INFO(RTPS_HISTORY, "Reader Proxy doesn't exist in this writer");
1348
0
    return false;
1349
0
}
1350
1351
bool StatefulWriter::matched_reader_is_matched(
1352
        const GUID_t& reader_guid)
1353
0
{
1354
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1355
0
    return for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1356
0
                   [&reader_guid](ReaderProxy* reader)
1357
0
                   {
1358
0
                       return (reader->guid() == reader_guid);
1359
0
                   }
1360
0
                   );
1361
0
}
1362
1363
bool StatefulWriter::matched_reader_lookup(
1364
        GUID_t& readerGuid,
1365
        ReaderProxy** RP)
1366
0
{
1367
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1368
0
    return for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1369
0
                   [&readerGuid, RP](ReaderProxy* reader)
1370
0
                   {
1371
0
                       if (reader->guid() == readerGuid)
1372
0
                       {
1373
0
                           *RP = reader;
1374
0
                           return true;
1375
0
                       }
1376
0
                       return false;
1377
0
                   }
1378
0
                   );
1379
0
}
1380
1381
bool StatefulWriter::has_been_fully_delivered(
1382
        const SequenceNumber_t& seq_num) const
1383
0
{
1384
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1385
0
    bool found = false;
1386
    // Sequence number has not been generated by this WriterHistory.
1387
0
    if (seq_num >= history_->next_sequence_number())
1388
0
    {
1389
0
        return false;
1390
0
    }
1391
0
    for (auto reader : matched_remote_readers_)
1392
0
    {
1393
0
        bool ret_code = reader->has_been_delivered(seq_num, found);
1394
0
        if (found && !ret_code)
1395
0
        {
1396
            // The change has not been fully delivered if it is pending delivery on at least one ReaderProxy.
1397
0
            return false;
1398
0
        }
1399
0
    }
1400
0
    return true;
1401
0
}
1402
1403
bool StatefulWriter::is_acked_by_all(
1404
        const SequenceNumber_t& seq_num) const
1405
0
{
1406
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1407
0
    return is_acked_by_all_nts(seq_num);
1408
0
}
1409
1410
bool StatefulWriter::is_acked_by_all_nts(
1411
        const SequenceNumber_t seq) const
1412
0
{
1413
0
    assert(history_->next_sequence_number() > seq);
1414
0
    return (seq < next_all_acked_notify_sequence_) ||
1415
0
           !for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1416
0
                   [seq](const ReaderProxy* reader)
1417
0
                   {
1418
0
                       return !(reader->change_is_acked(seq));
1419
0
                   });
1420
0
}
1421
1422
bool StatefulWriter::all_readers_updated()
1423
0
{
1424
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1425
1426
0
    return !for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1427
0
                   [](const ReaderProxy* reader)
1428
0
                   {
1429
0
                       return (reader->has_changes());
1430
0
                   }
1431
0
                   );
1432
0
}
1433
1434
bool StatefulWriter::wait_for_all_acked(
1435
        const dds::Duration_t& max_wait)
1436
0
{
1437
0
    send_periodic_heartbeat();
1438
1439
0
    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
1440
0
    std::unique_lock<std::mutex> all_acked_lock(all_acked_mutex_);
1441
1442
0
    all_acked_ = !for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1443
0
                    [](const ReaderProxy* reader)
1444
0
                    {
1445
0
                        return reader->has_changes();
1446
0
                    }
1447
0
                    );
1448
0
    lock.unlock();
1449
1450
0
    if (!all_acked_)
1451
0
    {
1452
0
        std::chrono::microseconds max_w(fastdds::rtps::TimeConv::Duration_t2MicroSecondsInt64(max_wait));
1453
0
        all_acked_cond_.wait_for(all_acked_lock, max_w, [&]()
1454
0
                {
1455
0
                    return all_acked_;
1456
0
                });
1457
0
    }
1458
1459
0
    return all_acked_;
1460
0
}
1461
1462
void StatefulWriter::rebuild_status_after_load()
1463
0
{
1464
0
    SequenceNumber_t min_seq = get_seq_num_min();
1465
0
    if (min_seq != SequenceNumber_t::unknown())
1466
0
    {
1467
0
        biggest_removed_sequence_number_ = min_seq - 1;
1468
0
        may_remove_change_ = 1;
1469
0
    }
1470
1471
0
    SequenceNumber_t next_seq = history_->next_sequence_number();
1472
0
    next_all_acked_notify_sequence_ = next_seq;
1473
0
    min_readers_low_mark_ = next_seq - 1;
1474
0
    all_acked_ = true;
1475
0
}
1476
1477
void StatefulWriter::check_acked_status()
1478
0
{
1479
0
    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
1480
1481
0
    bool all_acked = true;
1482
0
    bool has_min_low_mark = false;
1483
    // #8945 If no readers matched, notify all old changes.
1484
0
    SequenceNumber_t min_low_mark = history_->next_sequence_number() - 1;
1485
1486
0
    for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1487
0
            [&all_acked, &has_min_low_mark, &min_low_mark](ReaderProxy* reader)
1488
0
            {
1489
0
                SequenceNumber_t reader_low_mark = reader->changes_low_mark();
1490
0
                if (reader_low_mark < min_low_mark || !has_min_low_mark)
1491
0
                {
1492
0
                    has_min_low_mark = true;
1493
0
                    min_low_mark = reader_low_mark;
1494
0
                }
1495
1496
0
                if (reader->has_changes())
1497
0
                {
1498
0
                    all_acked = false;
1499
0
                }
1500
1501
0
                return false;
1502
0
            }
1503
0
            );
1504
1505
0
    if (all_acked)
1506
0
    {
1507
0
        min_low_mark = history_->next_sequence_number() - 1;
1508
0
    }
1509
1510
0
    bool something_changed = all_acked;
1511
0
    SequenceNumber_t min_seq = get_seq_num_min();
1512
0
    if (min_seq != SequenceNumber_t::unknown())
1513
0
    {
1514
        // In the case where we haven't received an acknack from a recently matched reader,
1515
        // min_low_mark will be zero, and no change will be notified as received by all
1516
0
        if (next_all_acked_notify_sequence_ <= min_low_mark)
1517
0
        {
1518
0
            if ((listener_ != nullptr) && (min_low_mark >= get_seq_num_min()))
1519
0
            {
1520
                // We will inform backwards about the changes received by all readers, starting
1521
                // on min_low_mark down until next_all_acked_notify_sequence_. This way we can
1522
                // safely proceed with the traversal, in case a change is removed from the history
1523
                // inside the callback
1524
0
                History::iterator history_end = history_->changesEnd();
1525
0
                History::iterator cit =
1526
0
                        std::lower_bound(history_->changesBegin(), history_end, min_low_mark,
1527
0
                                [](
1528
0
                                    const CacheChange_t* change,
1529
0
                                    const SequenceNumber_t& seq)
1530
0
                                {
1531
0
                                    return change->sequenceNumber < seq;
1532
0
                                });
1533
0
                if (cit != history_end && (*cit)->sequenceNumber == min_low_mark)
1534
0
                {
1535
0
                    ++cit;
1536
0
                }
1537
1538
0
                SequenceNumber_t seq{};
1539
0
                SequenceNumber_t end_seq = min_seq > next_all_acked_notify_sequence_ ?
1540
0
                        min_seq : next_all_acked_notify_sequence_;
1541
1542
                // The iterator starts pointing to the change inmediately after min_low_mark
1543
0
                --cit;
1544
1545
0
                do
1546
0
                {
1547
                    // Avoid notifying changes before next_all_acked_notify_sequence_
1548
0
                    CacheChange_t* change = *cit;
1549
0
                    seq = change->sequenceNumber;
1550
0
                    if (seq < next_all_acked_notify_sequence_)
1551
0
                    {
1552
0
                        break;
1553
0
                    }
1554
1555
                    // Change iterator before it possibly becomes invalidated
1556
0
                    if (cit != history_->changesBegin())
1557
0
                    {
1558
0
                        --cit;
1559
0
                    }
1560
1561
                    // Notify reception of change (may remove that change on VOLATILE writers)
1562
0
                    listener_->on_writer_change_received_by_all(this, change);
1563
1564
                    // Stop if we got to either next_all_acked_notify_sequence_ or the first change
1565
0
                }
1566
0
                while (seq > end_seq);
1567
0
            }
1568
1569
0
            next_all_acked_notify_sequence_ = min_low_mark + 1;
1570
0
        }
1571
1572
0
        if (min_low_mark >= get_seq_num_min())
1573
0
        {
1574
            // get_seq_num_min() returns SequenceNumber_t::unknown() when the history is empty.
1575
            // Thus, it is set to 2 to indicate that all samples have been removed.
1576
0
            may_remove_change_ = (get_seq_num_min() == SequenceNumber_t::unknown()) ? 2 : 1;
1577
0
        }
1578
1579
0
        min_readers_low_mark_ = min_low_mark;
1580
0
        something_changed = true;
1581
0
    }
1582
1583
0
    if (all_acked)
1584
0
    {
1585
0
        std::unique_lock<std::mutex> all_acked_lock(all_acked_mutex_);
1586
0
        SequenceNumber_t next_seq = history_->next_sequence_number();
1587
0
        next_all_acked_notify_sequence_ = next_seq;
1588
0
        min_readers_low_mark_ = next_seq - 1;
1589
0
        all_acked_ = true;
1590
0
        all_acked_cond_.notify_all();
1591
0
    }
1592
1593
0
    if (something_changed)
1594
0
    {
1595
0
        may_remove_change_cond_.notify_one();
1596
0
    }
1597
0
}
1598
1599
bool StatefulWriter::try_remove_change(
1600
        const std::chrono::steady_clock::time_point& max_blocking_time_point,
1601
        std::unique_lock<RecursiveTimedMutex>& lock)
1602
0
{
1603
0
    EPROSIMA_LOG_INFO(RTPS_WRITER, "Starting process try remove change for writer " << getGuid());
1604
1605
0
    SequenceNumber_t min_low_mark;
1606
1607
0
    {
1608
0
        std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1609
0
        min_low_mark = next_all_acked_notify_sequence_ - 1;
1610
0
    }
1611
1612
0
    SequenceNumber_t calc = min_low_mark < get_seq_num_min() ? SequenceNumber_t() :
1613
0
            (min_low_mark - get_seq_num_min()) + 1;
1614
0
    unsigned int may_remove_change = 1;
1615
1616
0
    if (calc <= SequenceNumber_t())
1617
0
    {
1618
0
        may_remove_change_ = 0;
1619
0
        may_remove_change_cond_.wait_until(lock, max_blocking_time_point,
1620
0
                [&]()
1621
0
                {
1622
0
                    return may_remove_change_ > 0;
1623
0
                });
1624
0
        may_remove_change = may_remove_change_;
1625
0
    }
1626
1627
    // Some changes acked
1628
0
    if (may_remove_change == 1)
1629
0
    {
1630
0
        return history_->remove_min_change();
1631
0
    }
1632
    // Waiting a change was removed.
1633
0
    else if (may_remove_change == 2)
1634
0
    {
1635
0
        return true;
1636
0
    }
1637
1638
0
    return false;
1639
0
}
1640
1641
bool StatefulWriter::wait_for_acknowledgement(
1642
        const SequenceNumber_t& seq,
1643
        const std::chrono::steady_clock::time_point& max_blocking_time_point,
1644
        std::unique_lock<RecursiveTimedMutex>& lock)
1645
0
{
1646
0
    return may_remove_change_cond_.wait_until(lock, max_blocking_time_point,
1647
0
                   [this, &seq]()
1648
0
                   {
1649
0
                       return is_acked_by_all_nts(seq);
1650
0
                   });
1651
0
}
1652
1653
/*
1654
 * PARAMETER_RELATED METHODS
1655
 */
1656
void StatefulWriter::update_attributes(
1657
        const WriterAttributes& att)
1658
0
{
1659
0
    BaseWriter::update_attributes(att);
1660
1661
0
    this->update_times(att.times);
1662
0
    if (this->get_disable_positive_acks())
1663
0
    {
1664
0
        this->update_positive_acks_times(att);
1665
0
    }
1666
0
}
1667
1668
bool StatefulWriter::matched_readers_guids(
1669
        std::vector<GUID_t>& guids) const
1670
0
{
1671
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1672
0
    guids.clear();
1673
0
    guids.reserve(matched_local_readers_.size() + matched_datasharing_readers_.size() +
1674
0
            matched_remote_readers_.size());
1675
0
    for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1676
0
            [&guids](const ReaderProxy* reader)
1677
0
            {
1678
0
                guids.emplace_back(reader->guid());
1679
0
                return false;
1680
0
            }
1681
0
            );
1682
1683
0
    return true;
1684
0
}
1685
1686
void StatefulWriter::update_positive_acks_times(
1687
        const WriterAttributes& att)
1688
0
{
1689
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1690
0
    keep_duration_ = att.keep_duration;
1691
    // Restart ack timer with new duration
1692
0
    ack_event_->update_interval(keep_duration_);
1693
0
    ack_event_->restart_timer();
1694
0
}
1695
1696
void StatefulWriter::update_times(
1697
        const WriterTimes& times)
1698
0
{
1699
0
    std::lock_guard<RecursiveTimedMutex> guard(mp_mutex);
1700
0
    if (times_.heartbeat_period != times.heartbeat_period)
1701
0
    {
1702
0
        periodic_hb_event_->update_interval(times.heartbeat_period);
1703
0
    }
1704
0
    if (times_.nack_response_delay != times.nack_response_delay)
1705
0
    {
1706
0
        if (nack_response_event_ != nullptr)
1707
0
        {
1708
0
            nack_response_event_->update_interval(times.nack_response_delay);
1709
0
        }
1710
0
    }
1711
0
    if (times_.nack_supression_duration != times.nack_supression_duration)
1712
0
    {
1713
0
        for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1714
0
                [&times](ReaderProxy* reader)
1715
0
                {
1716
0
                    reader->update_nack_supression_interval(times.nack_supression_duration);
1717
0
                    return false;
1718
0
                }
1719
0
                );
1720
1721
0
        for (ReaderProxy* it : matched_readers_pool_)
1722
0
        {
1723
0
            it->update_nack_supression_interval(times.nack_supression_duration);
1724
0
        }
1725
0
    }
1726
0
    times_ = times;
1727
0
}
1728
1729
SequenceNumber_t StatefulWriter::next_sequence_number() const
1730
0
{
1731
0
    return history_->next_sequence_number();
1732
0
}
1733
1734
bool StatefulWriter::send_periodic_heartbeat(
1735
        bool final,
1736
        bool liveliness)
1737
0
{
1738
0
    std::lock_guard<RecursiveTimedMutex> guardW(mp_mutex);
1739
0
    std::lock_guard<LocatorSelectorSender> guard_locator_selector_general(locator_selector_general_);
1740
1741
0
    bool unacked_changes {false};
1742
0
    bool irrelevants_removed {false};
1743
0
    if (!liveliness)
1744
0
    {
1745
0
        SequenceNumber_t first_seq_to_check_acknowledge = get_seq_num_min();
1746
0
        if (SequenceNumber_t::unknown() == first_seq_to_check_acknowledge)
1747
0
        {
1748
0
            first_seq_to_check_acknowledge = history_->next_sequence_number() - 1;
1749
0
        }
1750
1751
0
        for_matched_readers(matched_local_readers_, matched_datasharing_readers_,
1752
0
                matched_remote_readers_,
1753
0
                [first_seq_to_check_acknowledge, &unacked_changes, &irrelevants_removed](ReaderProxy* reader)
1754
0
                {
1755
0
                    if (!unacked_changes)
1756
0
                    {
1757
0
                        unacked_changes = reader->has_unacknowledged(first_seq_to_check_acknowledge);
1758
0
                    }
1759
1760
0
                    if (!irrelevants_removed)
1761
0
                    {
1762
0
                        irrelevants_removed = SequenceNumber_t::unknown() != reader->first_irrelevant_removed();
1763
0
                    }
1764
1765
0
                    return unacked_changes && irrelevants_removed;
1766
0
                }
1767
0
                );
1768
1769
0
        if (unacked_changes)
1770
0
        {
1771
0
            try
1772
0
            {
1773
                //TODO if separating, here sends periodic for all readers, instead of ones needed it.
1774
0
                send_heartbeat_to_all_readers(irrelevants_removed);
1775
0
            }
1776
0
            catch (const RTPSMessageGroup::timeout&)
1777
0
            {
1778
0
                EPROSIMA_LOG_ERROR(RTPS_WRITER, "Max blocking time reached");
1779
0
            }
1780
0
        }
1781
0
    }
1782
0
    else if (separate_sending_enabled_)
1783
0
    {
1784
        // Send individual liveliness heartbeat to each reader
1785
0
        for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1786
0
                [this, &liveliness, &unacked_changes](ReaderProxy* reader)
1787
0
                {
1788
0
                    send_heartbeat_to_nts(*reader, liveliness);
1789
0
                    unacked_changes = true;
1790
0
                    return false;
1791
0
                }
1792
0
                );
1793
0
    }
1794
0
    else
1795
0
    {
1796
        // This is a liveliness heartbeat, we don't care about checking sequence numbers
1797
0
        try
1798
0
        {
1799
0
            for (ReaderProxy* reader : matched_local_readers_)
1800
0
            {
1801
0
                intraprocess_heartbeat(reader, true);
1802
0
                unacked_changes = true;
1803
0
            }
1804
1805
0
            for (ReaderProxy* reader : matched_datasharing_readers_)
1806
0
            {
1807
0
                auto pool = std::dynamic_pointer_cast<WriterPool>(history_->get_payload_pool());
1808
0
                assert(pool);
1809
0
                pool->assert_liveliness();
1810
0
                reader->datasharing_notify();
1811
0
                unacked_changes = true;
1812
0
            }
1813
1814
0
            if (there_are_remote_readers_)
1815
0
            {
1816
0
                unacked_changes = true;
1817
0
                RTPSMessageGroup group(mp_RTPSParticipant, this, &locator_selector_general_);
1818
0
                send_heartbeat_nts_(locator_selector_general_.all_remote_readers.size(), group, final, liveliness);
1819
0
            }
1820
0
        }
1821
0
        catch (const RTPSMessageGroup::timeout&)
1822
0
        {
1823
0
            EPROSIMA_LOG_ERROR(RTPS_WRITER, "Max blocking time reached");
1824
0
        }
1825
0
    }
1826
1827
0
    return unacked_changes;
1828
0
}
1829
1830
void StatefulWriter::send_heartbeat_to_nts(
1831
        ReaderProxy& remoteReaderProxy,
1832
        bool liveliness,
1833
        bool force /* = false */)
1834
0
{
1835
0
    SequenceNumber_t first_seq_to_check_acknowledge = get_seq_num_min();
1836
0
    if (SequenceNumber_t::unknown() == first_seq_to_check_acknowledge)
1837
0
    {
1838
0
        first_seq_to_check_acknowledge = history_->next_sequence_number() - 1;
1839
0
    }
1840
0
    if (remoteReaderProxy.is_reliable() &&
1841
0
            (force || liveliness || remoteReaderProxy.has_unacknowledged(first_seq_to_check_acknowledge)))
1842
0
    {
1843
0
        if (remoteReaderProxy.is_local_reader())
1844
0
        {
1845
0
            intraprocess_heartbeat(&remoteReaderProxy, liveliness);
1846
0
        }
1847
0
        else if (remoteReaderProxy.is_datasharing_reader())
1848
0
        {
1849
0
            remoteReaderProxy.datasharing_notify();
1850
0
        }
1851
0
        else
1852
0
        {
1853
0
            try
1854
0
            {
1855
0
                RTPSMessageGroup group(mp_RTPSParticipant, this, remoteReaderProxy.message_sender());
1856
1857
0
                send_heartbeat_nts_(1u, group, disable_positive_acks_, liveliness);
1858
1859
0
                SequenceNumber_t firstSeq = get_seq_num_min();
1860
0
                SequenceNumber_t lastSeq = get_seq_num_max();
1861
1862
0
                if (firstSeq != c_SequenceNumber_Unknown && lastSeq != c_SequenceNumber_Unknown)
1863
0
                {
1864
0
                    assert(firstSeq <= lastSeq);
1865
0
                    if (!liveliness)
1866
0
                    {
1867
0
                        add_gaps_for_removed_irrelevants(remoteReaderProxy, group);
1868
0
                        add_gaps_for_holes_in_history(group);
1869
0
                    }
1870
0
                }
1871
0
            }
1872
0
            catch (const RTPSMessageGroup::timeout&)
1873
0
            {
1874
0
                EPROSIMA_LOG_ERROR(RTPS_WRITER, "Max blocking time reached");
1875
0
            }
1876
0
        }
1877
0
    }
1878
0
}
1879
1880
void StatefulWriter::send_heartbeat_nts_(
1881
        size_t number_of_readers,
1882
        RTPSMessageGroup& message_group,
1883
        bool final,
1884
        bool liveliness)
1885
0
{
1886
0
    if (!number_of_readers)
1887
0
    {
1888
0
        return;
1889
0
    }
1890
1891
0
    SequenceNumber_t firstSeq = get_seq_num_min();
1892
0
    SequenceNumber_t lastSeq = get_seq_num_max();
1893
1894
0
    if (firstSeq == c_SequenceNumber_Unknown || lastSeq == c_SequenceNumber_Unknown)
1895
0
    {
1896
0
        assert(firstSeq == c_SequenceNumber_Unknown && lastSeq == c_SequenceNumber_Unknown);
1897
1898
0
        if (number_of_readers == 1 || liveliness)
1899
0
        {
1900
0
            firstSeq = next_sequence_number();
1901
0
            lastSeq = firstSeq - 1;
1902
0
        }
1903
0
        else
1904
0
        {
1905
0
            return;
1906
0
        }
1907
0
    }
1908
0
    else
1909
0
    {
1910
0
        assert(firstSeq <= lastSeq);
1911
0
    }
1912
1913
0
    increment_hb_count();
1914
0
    message_group.add_heartbeat(firstSeq, lastSeq, heartbeat_count_, final, liveliness);
1915
1916
0
    EPROSIMA_LOG_INFO(RTPS_WRITER,
1917
0
            getGuid().entityId << " Sending Heartbeat (" << firstSeq << " - " << lastSeq << ")" );
1918
0
}
1919
1920
void StatefulWriter::send_heartbeat_piggyback_nts_(
1921
        RTPSMessageGroup& message_group,
1922
        LocatorSelectorSender& locator_selector)
1923
0
{
1924
0
    if (!disable_heartbeat_piggyback_)
1925
0
    {
1926
0
        if (history_->isFull() || next_all_acked_notify_sequence_ < get_seq_num_min())
1927
0
        {
1928
0
            select_all_readers_nts(message_group, locator_selector);
1929
0
            size_t number_of_readers = locator_selector.all_remote_readers.size();
1930
0
            send_heartbeat_nts_(number_of_readers, message_group, disable_positive_acks_);
1931
0
        }
1932
0
        else
1933
0
        {
1934
0
            if (last_num_exceeded_send_buffer_size_ != message_group.num_exceeded_send_buffer_size())
1935
0
            {
1936
0
                last_num_exceeded_send_buffer_size_ = message_group.num_exceeded_send_buffer_size();
1937
0
                select_all_readers_nts(message_group, locator_selector);
1938
0
                size_t number_of_readers = locator_selector.all_remote_readers.size();
1939
0
                send_heartbeat_nts_(number_of_readers, message_group, disable_positive_acks_);
1940
0
            }
1941
0
        }
1942
0
    }
1943
0
}
1944
1945
void StatefulWriter::perform_nack_response()
1946
0
{
1947
0
    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
1948
1949
0
    uint32_t changes_to_resend = 0;
1950
0
    for (ReaderProxy* reader : matched_remote_readers_)
1951
0
    {
1952
0
        changes_to_resend += reader->perform_acknack_response([&](ChangeForReader_t& change)
1953
0
                        {
1954
                            // This labmda is called if the ChangeForReader_t pass from REQUESTED to UNSENT.
1955
0
                            assert(nullptr != change.getChange());
1956
0
                            flow_controller_->add_old_sample(this, change.getChange());
1957
0
                        }
1958
0
                        );
1959
0
    }
1960
1961
0
    lock.unlock();
1962
1963
    // Notify the statistics module
1964
0
    on_resent_data(changes_to_resend);
1965
0
}
1966
1967
void StatefulWriter::perform_nack_supression(
1968
        const GUID_t& reader_guid)
1969
0
{
1970
0
    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
1971
1972
0
    for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
1973
0
            [this, &reader_guid](ReaderProxy* reader)
1974
0
            {
1975
0
                if (reader->guid() == reader_guid)
1976
0
                {
1977
0
                    reader->perform_nack_supression();
1978
0
                    periodic_hb_event_->restart_timer();
1979
0
                    return true;
1980
0
                }
1981
0
                return false;
1982
0
            }
1983
0
            );
1984
0
}
1985
1986
bool StatefulWriter::process_acknack(
1987
        const GUID_t& writer_guid,
1988
        const GUID_t& reader_guid,
1989
        uint32_t ack_count,
1990
        const SequenceNumberSet_t& sn_set,
1991
        bool final_flag,
1992
        bool& result,
1993
        fastdds::rtps::VendorId_t /*origin_vendor_id*/)
1994
0
{
1995
0
    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
1996
0
    result = (m_guid == writer_guid);
1997
1998
0
    if (result)
1999
0
    {
2000
0
        SequenceNumber_t received_sequence_number = sn_set.empty() ? sn_set.base() : sn_set.max();
2001
0
        if (received_sequence_number <= next_sequence_number())
2002
0
        {
2003
0
            for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
2004
0
                    [&](ReaderProxy* remote_reader)
2005
0
                    {
2006
0
                        if (remote_reader->guid() == reader_guid)
2007
0
                        {
2008
0
                            if (remote_reader->check_and_set_acknack_count(ack_count))
2009
0
                            {
2010
                                // Sequence numbers before Base are set as Acknowledged.
2011
0
                                remote_reader->acked_changes_set(sn_set.base());
2012
0
                                if (sn_set.base() > SequenceNumber_t(0, 0))
2013
0
                                {
2014
                                    // Prepare GAP for requested  samples that are not in history or are irrelevants.
2015
0
                                    RTPSMessageGroup group(mp_RTPSParticipant, this, remote_reader->message_sender());
2016
2017
                                    // A VOLATILE reader may be requesting changes below the position we assumed for it when
2018
                                    // it matched if its one-shot positioning GAP was lost.
2019
                                    // Here we re-send a GAP covering [base, low_mark] on every ACKNACK that reveals the
2020
                                    // reader is still behind. Base is computed as the maximum of the requested base and
2021
                                    // the lowest sequence number in history to avoid GAPs for changes already removed
2022
0
                                    SequenceNumber_t assumed_low_mark = remote_reader->changes_low_mark();
2023
0
                                    SequenceNumber_t gap_from = std::max(sn_set.base(), get_seq_num_min());
2024
0
                                    if (gap_from <= assumed_low_mark)
2025
0
                                    {
2026
0
                                        send_heartbeat_nts_(1u, group, true);
2027
0
                                        group.add_gap(gap_from, SequenceNumberSet_t(assumed_low_mark + 1),
2028
0
                                        remote_reader->guid());
2029
0
                                    }
2030
2031
0
                                    RTPSGapBuilder gap_builder(group);
2032
2033
0
                                    if (remote_reader->requested_changes_set(sn_set, gap_builder, get_seq_num_min()))
2034
0
                                    {
2035
0
                                        nack_response_event_->restart_timer();
2036
0
                                    }
2037
0
                                    else if (!final_flag)
2038
0
                                    {
2039
0
                                        periodic_hb_event_->restart_timer();
2040
0
                                    }
2041
2042
0
                                    gap_builder.flush();
2043
0
                                }
2044
0
                                else if (sn_set.empty() && !final_flag)
2045
0
                                {
2046
                                    // This is the preemptive acknack.
2047
0
                                    if (remote_reader->process_initial_acknack([&](ChangeForReader_t& change_reader)
2048
0
                                    {
2049
0
                                        assert(nullptr != change_reader.getChange());
2050
0
                                        flow_controller_->add_old_sample(this, change_reader.getChange());
2051
0
                                    }))
2052
0
                                    {
2053
0
                                        if (remote_reader->is_remote_and_reliable())
2054
0
                                        {
2055
                                            // Send heartbeat if requested
2056
0
                                            send_heartbeat_to_nts(*remote_reader, false, true);
2057
0
                                            periodic_hb_event_->restart_timer();
2058
0
                                        }
2059
0
                                    }
2060
2061
0
                                    if (remote_reader->is_local_reader() && !remote_reader->is_datasharing_reader())
2062
0
                                    {
2063
0
                                        intraprocess_heartbeat(remote_reader);
2064
0
                                    }
2065
0
                                }
2066
2067
                                // Check if all CacheChange are acknowledge, because a user could be waiting
2068
                                // for this, or some CacheChanges could be removed if we are VOLATILE
2069
0
                                check_acked_status();
2070
0
                            }
2071
0
                            return true;
2072
0
                        }
2073
2074
0
                        return false;
2075
0
                    }
2076
0
                    );
2077
0
        }
2078
0
        else
2079
0
        {
2080
0
            print_inconsistent_acknack(writer_guid, reader_guid, sn_set.base(), received_sequence_number,
2081
0
                    next_sequence_number());
2082
0
        }
2083
0
    }
2084
2085
0
    return result;
2086
0
}
2087
2088
bool StatefulWriter::process_nack_frag(
2089
        const GUID_t& writer_guid,
2090
        const GUID_t& reader_guid,
2091
        uint32_t ack_count,
2092
        const SequenceNumber_t& seq_num,
2093
        const FragmentNumberSet_t& fragments_state,
2094
        bool& result,
2095
        fastdds::rtps::VendorId_t /*origin_vendor_id*/)
2096
0
{
2097
0
    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
2098
0
    result = false;
2099
0
    if (m_guid == writer_guid)
2100
0
    {
2101
0
        result = true;
2102
0
        for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
2103
0
                [this, &reader_guid, &ack_count, &seq_num, &fragments_state](ReaderProxy* reader)
2104
0
                {
2105
0
                    if (reader->guid() == reader_guid)
2106
0
                    {
2107
0
                        if (reader->process_nack_frag(reader_guid, ack_count, seq_num, fragments_state))
2108
0
                        {
2109
0
                            nack_response_event_->restart_timer();
2110
0
                        }
2111
0
                        return true;
2112
0
                    }
2113
0
                    return false;
2114
0
                }
2115
0
                );
2116
0
    }
2117
2118
0
    return result;
2119
0
}
2120
2121
bool StatefulWriter::ack_timer_expired()
2122
0
{
2123
0
    std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
2124
2125
    // The timer has expired so the earliest non-acked change must be marked as acknowledged
2126
    // This will be done in the first while iteration, as we start with a negative interval
2127
2128
0
    Time_t expiration_ts;
2129
0
    Time_t current_ts;
2130
0
    Time_t::now(current_ts);
2131
2132
    // On the other hand, we've seen in the tests that if samples are sent very quickly with little
2133
    // time between consecutive samples, the timer interval could end up being negative
2134
    // In this case, we keep marking changes as acknowledged until the timer is able to keep up, hence the while
2135
    // loop
2136
2137
0
    do
2138
0
    {
2139
0
        bool acks_flag = false;
2140
0
        for_matched_readers(matched_local_readers_, matched_datasharing_readers_, matched_remote_readers_,
2141
0
                [this, &acks_flag](ReaderProxy* reader)
2142
0
                {
2143
0
                    if (reader->disable_positive_acks())
2144
0
                    {
2145
0
                        reader->acked_changes_set(last_sequence_number_ + 1);
2146
0
                        acks_flag = true;
2147
0
                    }
2148
0
                    return false;
2149
0
                }
2150
0
                );
2151
0
        if (acks_flag)
2152
0
        {
2153
0
            check_acked_status();
2154
0
        }
2155
2156
0
        CacheChange_t* change;
2157
2158
        // Skip removed changes until reaching the last change
2159
0
        do
2160
0
        {
2161
0
            last_sequence_number_++;
2162
0
        }
2163
0
        while (!history_->get_change(last_sequence_number_, getGuid(), &change) &&
2164
0
                last_sequence_number_ < next_sequence_number());
2165
2166
0
        if (!history_->get_change(
2167
0
                    last_sequence_number_,
2168
0
                    getGuid(),
2169
0
                    &change))
2170
0
        {
2171
            // Stop ack_timer
2172
0
            return false;
2173
0
        }
2174
2175
0
        Time_t::now(current_ts);
2176
0
        expiration_ts = change->sourceTimestamp + keep_duration_;
2177
0
    }
2178
0
    while (expiration_ts < current_ts);
2179
2180
0
    auto interval = (expiration_ts - current_ts).to_duration_t();
2181
0
    ack_event_->update_interval(interval);
2182
0
    return true;
2183
0
}
2184
2185
void StatefulWriter::print_inconsistent_acknack(
2186
        const GUID_t& writer_guid,
2187
        const GUID_t& reader_guid,
2188
        const SequenceNumber_t& min_requested_sequence_number,
2189
        const SequenceNumber_t& max_requested_sequence_number,
2190
        const SequenceNumber_t& next_sequence_number)
2191
0
{
2192
0
    EPROSIMA_LOG_WARNING(RTPS_WRITER, "Inconsistent acknack received. Local Writer "
2193
0
            << writer_guid << " next SequenceNumber " << next_sequence_number << ". Remote Reader "
2194
0
            << reader_guid << " requested range is  [" << min_requested_sequence_number
2195
0
            << ", " << max_requested_sequence_number << "].");
2196
    // This is necessary to avoid Warning of unused variable in case warning log level is disable
2197
0
    static_cast<void>(writer_guid);
2198
0
    static_cast<void>(reader_guid);
2199
0
    static_cast<void>(min_requested_sequence_number);
2200
0
    static_cast<void>(max_requested_sequence_number);
2201
0
    static_cast<void>(next_sequence_number);
2202
0
}
2203
2204
void StatefulWriter::reader_data_filter(
2205
        fastdds::rtps::IReaderDataFilter* reader_data_filter)
2206
0
{
2207
0
    reader_data_filter_ = reader_data_filter;
2208
0
}
2209
2210
const fastdds::rtps::IReaderDataFilter* StatefulWriter::reader_data_filter() const
2211
0
{
2212
0
    return reader_data_filter_;
2213
0
}
2214
2215
DeliveryRetCode StatefulWriter::deliver_sample_nts(
2216
        CacheChange_t* cache_change,
2217
        RTPSMessageGroup& group,
2218
        LocatorSelectorSender& locator_selector, // Object locked by FlowControllerImpl
2219
        const std::chrono::time_point<std::chrono::steady_clock>& max_blocking_time)
2220
0
{
2221
0
    DeliveryRetCode ret_code = DeliveryRetCode::DELIVERED;
2222
2223
0
    if (there_are_local_readers_)
2224
0
    {
2225
0
        deliver_sample_to_intraprocesses(cache_change);
2226
0
    }
2227
2228
    // Process datasharing then
2229
0
    if (there_are_datasharing_readers_)
2230
0
    {
2231
0
        deliver_sample_to_datasharing(cache_change);
2232
0
    }
2233
2234
0
    if (there_are_remote_readers_)
2235
0
    {
2236
0
        ret_code = deliver_sample_to_network(cache_change, group, locator_selector, max_blocking_time);
2237
0
    }
2238
2239
0
    check_acked_status();
2240
2241
0
    return ret_code;
2242
0
}
2243
2244
#ifdef FASTDDS_STATISTICS
2245
2246
bool StatefulWriter::get_connections(
2247
        fastdds::statistics::rtps::ConnectionList& connection_list)
2248
0
{
2249
0
    connection_list.reserve(matched_local_readers_.size() +
2250
0
            matched_datasharing_readers_.size() +
2251
0
            matched_remote_readers_.size());
2252
2253
0
    fastdds::statistics::Connection connection;
2254
2255
0
    {
2256
0
        std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
2257
2258
        //! intraprocess
2259
0
        for_matched_readers(matched_local_readers_, [&connection, &connection_list](ReaderProxy*& reader)
2260
0
                {
2261
0
                    connection.guid(fastdds::statistics::to_statistics_type(reader->guid()));
2262
0
                    connection.mode(fastdds::statistics::ConnectionMode::INTRAPROCESS);
2263
0
                    connection_list.push_back(connection);
2264
2265
0
                    return false;
2266
0
                });
2267
0
    }
2268
2269
0
    {
2270
0
        std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
2271
2272
        //! datasharing
2273
0
        for_matched_readers(matched_datasharing_readers_, [&connection, &connection_list](ReaderProxy*& reader)
2274
0
                {
2275
0
                    connection.guid(fastdds::statistics::to_statistics_type(reader->guid()));
2276
0
                    connection.mode(fastdds::statistics::ConnectionMode::DATA_SHARING);
2277
0
                    connection_list.push_back(connection);
2278
2279
0
                    return false;
2280
0
                });
2281
0
    }
2282
2283
0
    {
2284
0
        std::unique_lock<RecursiveTimedMutex> lock(mp_mutex);
2285
2286
        //! remote
2287
0
        for_matched_readers(matched_remote_readers_, [&connection, &connection_list](ReaderProxy*& reader)
2288
0
                {
2289
                    //! Announced locators is, for the moment,
2290
                    //! equal to the used_locators
2291
0
                    LocatorSelectorEntry* loc_selector_entry = reader->general_locator_selector_entry();
2292
2293
0
                    connection.announced_locators().reserve(reader->locators_size());
2294
0
                    connection.used_locators().reserve(reader->locators_size());
2295
2296
0
                    std::vector<fastdds::statistics::detail::Locator_s> statistics_locators;
2297
0
                    std::for_each(loc_selector_entry->multicast.begin(), loc_selector_entry->multicast.end(),
2298
0
                    [&statistics_locators](const Locator_t& locator)
2299
0
                    {
2300
0
                        statistics_locators.push_back(fastdds::statistics::to_statistics_type(locator));
2301
0
                    });
2302
2303
0
                    std::for_each(loc_selector_entry->unicast.begin(), loc_selector_entry->unicast.end(),
2304
0
                    [&statistics_locators](const Locator_t& locator)
2305
0
                    {
2306
0
                        statistics_locators.push_back(fastdds::statistics::to_statistics_type(locator));
2307
0
                    });
2308
2309
0
                    connection.guid(fastdds::statistics::to_statistics_type(reader->guid()));
2310
0
                    connection.mode(fastdds::statistics::ConnectionMode::TRANSPORT);
2311
0
                    connection.announced_locators(statistics_locators);
2312
0
                    connection.used_locators(statistics_locators);
2313
0
                    connection_list.push_back(connection);
2314
2315
0
                    return false;
2316
0
                });
2317
0
    }
2318
2319
0
    return true;
2320
2321
0
}
2322
2323
#endif // ifdef FASTDDS_STATISTICS
2324
2325
void StatefulWriter::add_gaps_for_removed_irrelevants(
2326
        ReaderProxy& remoteReaderProxy,
2327
        RTPSMessageGroup& group)
2328
0
{
2329
0
    if (SequenceNumber_t::unknown() != remoteReaderProxy.first_irrelevant_removed())
2330
0
    {
2331
0
        group.add_gap(remoteReaderProxy.first_irrelevant_removed(),
2332
0
                SequenceNumberSet_t(remoteReaderProxy.last_irrelevant_removed() + 1),
2333
0
                remoteReaderProxy.guid());
2334
0
        remoteReaderProxy.reset_irrelevant_removed();
2335
0
    }
2336
0
}
2337
2338
void StatefulWriter::add_gaps_for_holes_in_history(
2339
        RTPSMessageGroup& group)
2340
0
{
2341
0
    SequenceNumber_t firstSeq = get_seq_num_min();
2342
0
    SequenceNumber_t lastSeq = get_seq_num_max();
2343
2344
0
    if (SequenceNumber_t::unknown() != firstSeq &&
2345
0
            lastSeq.to64long() - firstSeq.to64long() + 1 != history_->getHistorySize())
2346
0
    {
2347
0
        RTPSGapBuilder gaps(group);
2348
        // There are holes in the history.
2349
0
        History::const_iterator cit = history_->changesBegin();
2350
0
        SequenceNumber_t prev = (*cit)->sequenceNumber + 1;
2351
0
        ++cit;
2352
0
        while (cit != history_->changesEnd())
2353
0
        {
2354
0
            while (prev != (*cit)->sequenceNumber)
2355
0
            {
2356
0
                gaps.add(prev);
2357
0
                ++prev;
2358
0
            }
2359
0
            ++prev;
2360
0
            ++cit;
2361
0
        }
2362
0
        gaps.flush();
2363
0
    }
2364
0
}
2365
2366
}  // namespace rtps
2367
}  // namespace fastdds
2368
}  // namespace eprosima