Skip to content

Commit d24584c

Browse files
Allow processing of AckNack submessages with count == 0 (#4639) (#4773)
* Refs #20729. Regression test. Signed-off-by: Miguel Company <[email protected]> * Refs #20729. Fix issue. Signed-off-by: Miguel Company <[email protected]> * Refs #20729. Update doxydoc. Signed-off-by: Miguel Company <[email protected]> * Refs #20729. Dont create timers if participant is nullptr. Signed-off-by: Miguel Company <[email protected]> --------- Signed-off-by: Miguel Company <[email protected]> (cherry picked from commit 66fc7c5) Co-authored-by: Miguel Company <[email protected]>
1 parent 2c0e715 commit d24584c

File tree

3 files changed

+73
-28
lines changed

3 files changed

+73
-28
lines changed

include/fastdds/rtps/writer/ReaderProxy.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -300,16 +300,19 @@ class ReaderProxy
300300
}
301301

302302
/**
303-
* Called when an ACKNACK is received to set a new value for the count of the last received ACKNACK.
303+
* Called when an ACKNACK is received to set a new value for the minimum count accepted for following received
304+
* ACKNACKs.
305+
*
304306
* @param acknack_count The count of the received ACKNACK.
305-
* @return true if internal count changed (i.e. new ACKNACK is accepted)
307+
* @return true if internal count changed (i.e. received ACKNACK is accepted)
306308
*/
307309
bool check_and_set_acknack_count(
308310
uint32_t acknack_count)
309311
{
310-
if (last_acknack_count_ < acknack_count)
312+
if (acknack_count >= next_expected_acknack_count_)
311313
{
312-
last_acknack_count_ = acknack_count;
314+
next_expected_acknack_count_ = acknack_count;
315+
++next_expected_acknack_count_;
313316
return true;
314317
}
315318

@@ -442,8 +445,8 @@ class ReaderProxy
442445
TimedEvent* initial_heartbeat_event_;
443446
//! Are timed events enabled?
444447
std::atomic_bool timers_enabled_;
445-
//! Last ack/nack count
446-
uint32_t last_acknack_count_;
448+
//! Next expected ack/nack count
449+
uint32_t next_expected_acknack_count_;
447450
//! Last NACKFRAG count.
448451
uint32_t last_nackfrag_count_;
449452

src/cpp/rtps/writer/ReaderProxy.cpp

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -57,23 +57,27 @@ ReaderProxy::ReaderProxy(
5757
, nack_supression_event_(nullptr)
5858
, initial_heartbeat_event_(nullptr)
5959
, timers_enabled_(false)
60-
, last_acknack_count_(0)
60+
, next_expected_acknack_count_(0)
6161
, last_nackfrag_count_(0)
6262
{
63-
nack_supression_event_ = new TimedEvent(writer_->getRTPSParticipant()->getEventResource(),
64-
[&]() -> bool
65-
{
66-
writer_->perform_nack_supression(guid());
67-
return false;
68-
},
69-
TimeConv::Time_t2MilliSecondsDouble(times.nackSupressionDuration));
63+
auto participant = writer_->getRTPSParticipant();
64+
if (nullptr != participant)
65+
{
66+
nack_supression_event_ = new TimedEvent(participant->getEventResource(),
67+
[&]() -> bool
68+
{
69+
writer_->perform_nack_supression(guid());
70+
return false;
71+
},
72+
TimeConv::Time_t2MilliSecondsDouble(times.nackSupressionDuration));
7073

71-
initial_heartbeat_event_ = new TimedEvent(writer_->getRTPSParticipant()->getEventResource(),
72-
[&]() -> bool
73-
{
74-
writer_->intraprocess_heartbeat(this);
75-
return false;
76-
}, 0);
74+
initial_heartbeat_event_ = new TimedEvent(participant->getEventResource(),
75+
[&]() -> bool
76+
{
77+
writer_->intraprocess_heartbeat(this);
78+
return false;
79+
}, 0);
80+
}
7781

7882
stop();
7983
}
@@ -135,7 +139,7 @@ void ReaderProxy::start(
135139
}
136140

137141
timers_enabled_.store(is_remote_and_reliable());
138-
if (is_local_reader())
142+
if (is_local_reader() && initial_heartbeat_event_)
139143
{
140144
initial_heartbeat_event_->restart_timer();
141145
}
@@ -166,32 +170,38 @@ void ReaderProxy::stop()
166170
disable_timers();
167171

168172
changes_for_reader_.clear();
169-
last_acknack_count_ = 0;
173+
next_expected_acknack_count_ = 0;
170174
last_nackfrag_count_ = 0;
171175
changes_low_mark_ = SequenceNumber_t();
172176
}
173177

174178
void ReaderProxy::disable_timers()
175179
{
176-
if (timers_enabled_.exchange(false))
180+
if (timers_enabled_.exchange(false) && nack_supression_event_)
177181
{
178182
nack_supression_event_->cancel_timer();
179183
}
180-
initial_heartbeat_event_->cancel_timer();
184+
if (initial_heartbeat_event_)
185+
{
186+
initial_heartbeat_event_->cancel_timer();
187+
}
181188
}
182189

183190
void ReaderProxy::update_nack_supression_interval(
184191
const Duration_t& interval)
185192
{
186-
nack_supression_event_->update_interval(interval);
193+
if (nack_supression_event_)
194+
{
195+
nack_supression_event_->update_interval(interval);
196+
}
187197
}
188198

189199
void ReaderProxy::add_change(
190200
const ChangeForReader_t& change,
191201
bool is_relevant,
192202
bool restart_nack_supression)
193203
{
194-
if (restart_nack_supression && timers_enabled_.load())
204+
if (restart_nack_supression && timers_enabled_.load() && nack_supression_event_)
195205
{
196206
nack_supression_event_->restart_timer();
197207
}
@@ -205,7 +215,7 @@ void ReaderProxy::add_change(
205215
bool restart_nack_supression,
206216
const std::chrono::time_point<std::chrono::steady_clock>& max_blocking_time)
207217
{
208-
if (restart_nack_supression && timers_enabled_)
218+
if (restart_nack_supression && timers_enabled_ && nack_supression_event_)
209219
{
210220
nack_supression_event_->restart_timer(max_blocking_time);
211221
}
@@ -459,7 +469,7 @@ void ReaderProxy::from_unsent_to_status(
459469
// It will use acked_changes_set().
460470
assert(is_reliable_);
461471

462-
if (restart_nack_supression && is_remote_and_reliable())
472+
if (restart_nack_supression && is_remote_and_reliable() && nack_supression_event_)
463473
{
464474
assert(timers_enabled_.load());
465475
nack_supression_event_->restart_timer();

test/unittest/rtps/writer/ReaderProxyTests.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,38 @@ TEST(ReaderProxyTests, has_been_delivered_test)
382382
expect_result({0, 3}, false, false);
383383
}
384384

385+
// Test expectations regarding acknack count.
386+
// Serves as a regression test for redmine issue #20729.
387+
TEST(ReaderProxyTests, acknack_count)
388+
{
389+
StatefulWriter writer_mock;
390+
WriterTimes w_times;
391+
RemoteLocatorsAllocationAttributes alloc;
392+
ReaderProxy rproxy(w_times, alloc, &writer_mock);
393+
394+
ReaderProxyData reader_attributes(0, 0);
395+
reader_attributes.m_qos.m_reliability.kind = RELIABLE_RELIABILITY_QOS;
396+
rproxy.start(reader_attributes);
397+
398+
// Check that the initial acknack count is 0.
399+
EXPECT_TRUE(rproxy.check_and_set_acknack_count(0u));
400+
// Check that it is not accepted twice.
401+
EXPECT_FALSE(rproxy.check_and_set_acknack_count(0u));
402+
// Check that it is accepted if it is incremented.
403+
EXPECT_TRUE(rproxy.check_and_set_acknack_count(1u));
404+
// Check that it is not accepted twice.
405+
EXPECT_FALSE(rproxy.check_and_set_acknack_count(1u));
406+
// Check that it is not accepted if it is decremented.
407+
EXPECT_FALSE(rproxy.check_and_set_acknack_count(0u));
408+
// Check that it is accepted if it has a big increment.
409+
EXPECT_TRUE(rproxy.check_and_set_acknack_count(100u));
410+
// Check that previous values are rejected.
411+
for (uint32_t i = 0; i <= 100u; ++i)
412+
{
413+
EXPECT_FALSE(rproxy.check_and_set_acknack_count(i));
414+
}
415+
}
416+
385417
} // namespace rtps
386418
} // namespace fastrtps
387419
} // namespace eprosima

0 commit comments

Comments
 (0)