blob: c2ca8f8f14ad0d8624b830edf58d9058d3009d79 [file] [log] [blame]
Yingdi Yuf7ede412014-08-30 20:37:52 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Davide Pesavento44ec2072022-03-07 13:32:04 -05003 * Copyright (c) 2012-2022 University of California, Los Angeles
Yingdi Yuf7ede412014-08-30 20:37:52 -07004 *
5 * This file is part of ChronoSync, synchronization library for distributed realtime
6 * applications for NDN.
7 *
8 * ChronoSync is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation, either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * ChronoSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
20 * @author Chaoyi Bian <bcy@pku.edu.cn>
21 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
22 * @author Yingdi Yu <yingdi@cs.ucla.edu>
Sonu Mishra0dadc572016-12-12 23:59:41 -080023 * @author Sonu Mishra <https://www.linkedin.com/in/mishrasonu>
Yingdi Yuf7ede412014-08-30 20:37:52 -070024 */
25
26#include "logic.hpp"
Davide Pesavento07684bc2021-02-07 20:09:28 -050027#include "detail/bzip2-helper.hpp"
Yingdi Yuf7ede412014-08-30 20:37:52 -070028
Alexander Afanasyev89036292018-02-13 17:19:50 -050029#include <ndn-cxx/util/backports.hpp>
Davide Pesaventoe7dc7762020-12-22 20:47:52 -050030#include <ndn-cxx/util/exception.hpp>
Davide Pesavento07684bc2021-02-07 20:09:28 -050031#include <ndn-cxx/util/logger.hpp>
Ashlesh Gawande687cf922017-05-30 15:04:16 -050032#include <ndn-cxx/util/string-helper.hpp>
33
Davide Pesavento07684bc2021-02-07 20:09:28 -050034NDN_LOG_INIT(sync.Logic);
Yingdi Yuf7ede412014-08-30 20:37:52 -070035
Davide Pesavento07684bc2021-02-07 20:09:28 -050036#define CHRONO_LOG_DBG(v) NDN_LOG_DEBUG("Instance" << m_instanceId << ": " << v)
Yingdi Yuf7ede412014-08-30 20:37:52 -070037
38namespace chronosync {
39
Davide Pesavento8663ed12022-07-23 03:04:27 -040040const std::vector<uint8_t> EMPTY_DIGEST{
Yingdi Yuf7ede412014-08-30 20:37:52 -070041 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
42 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
43 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
44 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
45};
46
Davide Pesavento55492d52022-09-19 18:38:02 -040047const name::Component RESET_COMPONENT{"reset"};
48const name::Component RECOVERY_COMPONENT{"recovery"};
Alexander Afanasyev89036292018-02-13 17:19:50 -050049const size_t NDNLP_EXPECTED_OVERHEAD = 20;
50
51/**
52 * Get maximum packet limit
53 *
54 * By default, it returns `ndn::MAX_NDN_PACKET_SIZE`.
55 * The returned value can be customized using the environment variable `CHRONOSYNC_MAX_PACKET_SIZE`,
56 * but the returned value will be at least 500 and no more than `ndn::MAX_NDN_PACKET_SIZE`.
57 */
Davide Pesavento07684bc2021-02-07 20:09:28 -050058#ifndef CHRONOSYNC_WITH_TESTS
Alexander Afanasyev89036292018-02-13 17:19:50 -050059static
Davide Pesavento07684bc2021-02-07 20:09:28 -050060#endif // CHRONOSYNC_WITH_TESTS
Alexander Afanasyev89036292018-02-13 17:19:50 -050061size_t
62getMaxPacketLimit()
63{
64 static size_t limit = 0;
Davide Pesavento07684bc2021-02-07 20:09:28 -050065#ifndef CHRONOSYNC_WITH_TESTS
Alexander Afanasyev89036292018-02-13 17:19:50 -050066 if (limit != 0) {
67 return limit;
68 }
Davide Pesavento07684bc2021-02-07 20:09:28 -050069#endif // CHRONOSYNC_WITH_TESTS
Alexander Afanasyev89036292018-02-13 17:19:50 -050070
71 if (getenv("CHRONOSYNC_MAX_PACKET_SIZE") != nullptr) {
72 try {
Davide Pesavento8663ed12022-07-23 03:04:27 -040073 limit = std::clamp<size_t>(boost::lexical_cast<size_t>(getenv("CHRONOSYNC_MAX_PACKET_SIZE")),
Alexander Afanasyev89036292018-02-13 17:19:50 -050074 500, ndn::MAX_NDN_PACKET_SIZE);
75 }
76 catch (const boost::bad_lexical_cast&) {
77 limit = ndn::MAX_NDN_PACKET_SIZE;
78 }
79 }
80 else {
81 limit = ndn::MAX_NDN_PACKET_SIZE;
82 }
83
84 return limit;
85}
86
Yingdi Yuf7ede412014-08-30 20:37:52 -070087Logic::Logic(ndn::Face& face,
88 const Name& syncPrefix,
Qiuhan Ding8c095fd2014-11-19 17:38:32 -080089 const Name& defaultUserPrefix,
Yingdi Yuf7ede412014-08-30 20:37:52 -070090 const UpdateCallback& onUpdate,
Qiuhan Ding8c095fd2014-11-19 17:38:32 -080091 const Name& defaultSigningId,
Ashlesh Gawande08784d42017-09-06 23:40:21 -050092 std::shared_ptr<Validator> validator,
Davide Pesavento8663ed12022-07-23 03:04:27 -040093 const time::steady_clock::duration& resetTimer,
94 const time::steady_clock::duration& cancelResetTimer,
Yingdi Yuf7ede412014-08-30 20:37:52 -070095 const time::milliseconds& resetInterestLifetime,
96 const time::milliseconds& syncInterestLifetime,
Sonu Mishra4d3a2e02017-01-18 20:27:51 -080097 const time::milliseconds& syncReplyFreshness,
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -050098 const time::milliseconds& recoveryInterestLifetime,
99 const name::Component& session)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700100 : m_face(face)
101 , m_syncPrefix(syncPrefix)
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400102 , m_syncReset(Name(syncPrefix).append("reset"))
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800103 , m_defaultUserPrefix(defaultUserPrefix)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700104 , m_interestTable(m_face.getIoService())
Yingdi Yuf7ede412014-08-30 20:37:52 -0700105 , m_isInReset(false)
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400106 , m_needPeriodReset(resetTimer > time::nanoseconds::zero())
Yingdi Yuf7ede412014-08-30 20:37:52 -0700107 , m_onUpdate(onUpdate)
108 , m_scheduler(m_face.getIoService())
Ashlesh Gawande9a306fe2019-01-04 11:38:18 -0600109 , m_rng(ndn::random::getRandomNumberEngine())
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600110 , m_rangeUniformRandom(100, 500)
111 , m_reexpressionJitter(100, 500)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700112 , m_resetTimer(resetTimer)
113 , m_cancelResetTimer(cancelResetTimer)
114 , m_resetInterestLifetime(resetInterestLifetime)
115 , m_syncInterestLifetime(syncInterestLifetime)
116 , m_syncReplyFreshness(syncReplyFreshness)
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800117 , m_recoveryInterestLifetime(recoveryInterestLifetime)
Davide Pesavento8663ed12022-07-23 03:04:27 -0400118 , m_validator(std::move(validator))
Alexander Afanasyev90587b82018-02-11 20:36:53 -0500119 , m_instanceId(s_instanceCounter++)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700120{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500121 CHRONO_LOG_DBG(">> Logic::Logic");
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400122 addUserNode(m_defaultUserPrefix, defaultSigningId, session, false);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700123
Davide Pesavento07684bc2021-02-07 20:09:28 -0500124 CHRONO_LOG_DBG("Listen to: " << m_syncPrefix);
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700125 m_syncRegisteredPrefix = m_face.setInterestFilter(
126 ndn::InterestFilter(m_syncPrefix).allowLoopback(false),
127 bind(&Logic::onSyncInterest, this, _1, _2),
128 bind(&Logic::onSyncRegisterFailed, this, _1, _2));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700129
Qiuhan Dinge246b622014-12-03 21:57:48 -0800130 sendSyncInterest();
Davide Pesavento07684bc2021-02-07 20:09:28 -0500131 CHRONO_LOG_DBG("<< Logic::Logic");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700132}
133
134Logic::~Logic()
135{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500136 CHRONO_LOG_DBG(">> Logic::~Logic");
Yingdi Yu9d5679a2015-02-01 00:17:58 -0800137 m_interestTable.clear();
Nick Gordon0b3beab2018-03-02 13:03:28 -0600138 m_scheduler.cancelAllEvents();
Davide Pesavento07684bc2021-02-07 20:09:28 -0500139 CHRONO_LOG_DBG("<< Logic::~Logic");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700140}
141
142void
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800143Logic::reset(bool isOnInterest)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700144{
145 m_isInReset = true;
146
147 m_state.reset();
148 m_log.clear();
149
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800150 if (!isOnInterest)
151 sendResetInterest();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700152
Yingdi Yuf7ede412014-08-30 20:37:52 -0700153 sendSyncInterest();
154
Davide Pesaventod057cf12019-03-20 23:38:40 -0400155 m_delayedInterestProcessingId = m_scheduler.schedule(m_cancelResetTimer, [this] { cancelReset(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700156}
157
158void
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800159Logic::setDefaultUserPrefix(const Name& defaultUserPrefix)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700160{
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800161 if (defaultUserPrefix != EMPTY_NAME) {
162 if (m_nodeList.find(defaultUserPrefix) != m_nodeList.end()) {
163 m_defaultUserPrefix = defaultUserPrefix;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800164 }
165 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700166}
167
168void
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400169Logic::addUserNode(const Name& userPrefix, const Name& signingId, const name::Component& session, bool shouldSendReset)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700170{
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800171 if (userPrefix == EMPTY_NAME)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700172 return;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800173 if (m_defaultUserPrefix == EMPTY_NAME) {
174 m_defaultUserPrefix = userPrefix;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800175 }
176 if (m_nodeList.find(userPrefix) == m_nodeList.end()) {
177 m_nodeList[userPrefix].userPrefix = userPrefix;
178 m_nodeList[userPrefix].signingId = signingId;
179 Name sessionName = userPrefix;
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -0500180 if (!session.empty()) {
181 sessionName.append(session);
182 }
183 else {
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400184 sessionName.appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -0500185 }
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800186 m_nodeList[userPrefix].sessionName = sessionName;
187 m_nodeList[userPrefix].seqNo = 0;
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400188 reset(!shouldSendReset);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800189 }
190}
Yingdi Yuf7ede412014-08-30 20:37:52 -0700191
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800192void
193Logic::removeUserNode(const Name& userPrefix)
194{
195 auto userNode = m_nodeList.find(userPrefix);
196 if (userNode != m_nodeList.end()) {
197 m_nodeList.erase(userNode);
198 if (m_defaultUserPrefix == userPrefix) {
199 if (!m_nodeList.empty()) {
200 m_defaultUserPrefix = m_nodeList.begin()->second.userPrefix;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800201 }
202 else {
203 m_defaultUserPrefix = EMPTY_NAME;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800204 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700205 }
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800206 reset(false);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800207 }
208}
Yingdi Yuf7ede412014-08-30 20:37:52 -0700209
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800210const Name&
211Logic::getSessionName(Name prefix)
212{
213 if (prefix == EMPTY_NAME)
214 prefix = m_defaultUserPrefix;
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500215
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800216 auto node = m_nodeList.find(prefix);
217 if (node != m_nodeList.end())
218 return node->second.sessionName;
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500219
220 NDN_THROW(Error("Nonexistent node: " + prefix.toUri()));
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800221}
Yingdi Yuf7ede412014-08-30 20:37:52 -0700222
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800223const SeqNo&
224Logic::getSeqNo(Name prefix)
225{
226 if (prefix == EMPTY_NAME)
227 prefix = m_defaultUserPrefix;
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500228
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800229 auto node = m_nodeList.find(prefix);
230 if (node != m_nodeList.end())
231 return node->second.seqNo;
Yingdi Yuf7ede412014-08-30 20:37:52 -0700232
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500233 NDN_THROW(Error("Nonexistent node: " + prefix.toUri()));
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800234}
235
236void
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800237Logic::updateSeqNo(const SeqNo& seqNo, const Name& updatePrefix)
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800238{
239 Name prefix;
240 if (updatePrefix == EMPTY_NAME) {
241 if (m_defaultUserPrefix == EMPTY_NAME)
242 return;
243 prefix = m_defaultUserPrefix;
244 }
245 else
246 prefix = updatePrefix;
247
248 auto it = m_nodeList.find(prefix);
249 if (it != m_nodeList.end()) {
250 NodeInfo& node = it->second;
Davide Pesavento07684bc2021-02-07 20:09:28 -0500251 CHRONO_LOG_DBG(">> Logic::updateSeqNo");
252 CHRONO_LOG_DBG("seqNo: " << seqNo << " m_seqNo: " << node.seqNo);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800253 if (seqNo < node.seqNo || seqNo == 0)
254 return;
255
256 node.seqNo = seqNo;
Davide Pesavento07684bc2021-02-07 20:09:28 -0500257 CHRONO_LOG_DBG("updateSeqNo: m_seqNo " << node.seqNo);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800258
259 if (!m_isInReset) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500260 CHRONO_LOG_DBG("updateSeqNo: not in Reset");
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500261 ConstBufferPtr previousRoot = m_state.getRootDigest();
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500262 printDigest(previousRoot);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800263
Davide Pesavento8663ed12022-07-23 03:04:27 -0400264 auto [isInserted, isUpdated, oldSeq] = m_state.update(node.sessionName, node.seqNo);
Davide Pesavento07684bc2021-02-07 20:09:28 -0500265 CHRONO_LOG_DBG("Insert: " << std::boolalpha << isInserted);
266 CHRONO_LOG_DBG("Updated: " << std::boolalpha << isUpdated);
Davide Pesavento8663ed12022-07-23 03:04:27 -0400267 (void)oldSeq; // silence "unused variable" warning with gcc 7
268
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800269 if (isInserted || isUpdated) {
270 DiffStatePtr commit = make_shared<DiffState>();
271 commit->update(node.sessionName, node.seqNo);
272 commit->setRootDigest(m_state.getRootDigest());
273 insertToDiffLog(commit, previousRoot);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800274 satisfyPendingSyncInterests(prefix, commit);
275 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700276 }
277 }
278}
279
280ConstBufferPtr
281Logic::getRootDigest() const
282{
283 return m_state.getRootDigest();
284}
285
286void
287Logic::printState(std::ostream& os) const
288{
Nick Gordon0b3beab2018-03-02 13:03:28 -0600289 for (const auto& leaf : m_state.getLeaves()) {
290 os << *leaf << "\n";
291 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700292}
293
294std::set<Name>
295Logic::getSessionNames() const
296{
297 std::set<Name> sessionNames;
Nick Gordon0b3beab2018-03-02 13:03:28 -0600298 for (const auto& leaf : m_state.getLeaves()) {
299 sessionNames.insert(leaf->getSessionName());
300 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700301 return sessionNames;
302}
303
304void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500305Logic::onSyncInterest(const Name&, const Interest& interest)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700306{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500307 CHRONO_LOG_DBG(">> Logic::onSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700308 Name name = interest.getName();
309
Davide Pesavento07684bc2021-02-07 20:09:28 -0500310 CHRONO_LOG_DBG("InterestName: " << name);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700311
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800312 if (name.size() >= 1 && RESET_COMPONENT == name.get(-1)) {
313 processResetInterest(interest);
314 }
315 else if (name.size() >= 2 && RECOVERY_COMPONENT == name.get(-2)) {
316 processRecoveryInterest(interest);
317 }
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500318 else {
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500319 processSyncInterest(interest);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700320 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700321
Davide Pesavento07684bc2021-02-07 20:09:28 -0500322 CHRONO_LOG_DBG("<< Logic::onSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700323}
324
325void
326Logic::onSyncRegisterFailed(const Name& prefix, const std::string& msg)
327{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500328 CHRONO_LOG_DBG(">> Logic::onSyncRegisterFailed");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700329}
330
331void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500332Logic::onSyncData(const Interest&, const Data& data)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700333{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500334 CHRONO_LOG_DBG(">> Logic::onSyncData");
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500335 if (m_validator != nullptr)
336 m_validator->validate(data,
337 bind(&Logic::onSyncDataValidated, this, _1),
338 bind(&Logic::onSyncDataValidationFailed, this, _1));
339 else
340 onSyncDataValidated(data);
Sonu Mishraf42aa2c2017-01-22 18:47:33 -0800341
Davide Pesavento07684bc2021-02-07 20:09:28 -0500342 CHRONO_LOG_DBG("<< Logic::onSyncData");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700343}
344
345void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500346Logic::onResetData(const Interest&, const Data&)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700347{
348 // This should not happened, drop the received data.
349}
350
351void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500352Logic::onSyncNack(const Interest&, const ndn::lp::Nack& nack)
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500353{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500354 CHRONO_LOG_DBG(">> Logic::onSyncNack");
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500355 if (nack.getReason() == ndn::lp::NackReason::NO_ROUTE) {
356 auto after = ndn::time::milliseconds(m_reexpressionJitter(m_rng));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500357 CHRONO_LOG_DBG("Schedule sync interest after: " << after);
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500358 m_scheduler.schedule(after, [this] { sendSyncInterest(); });
359 }
Davide Pesavento07684bc2021-02-07 20:09:28 -0500360 CHRONO_LOG_DBG("<< Logic::onSyncNack");
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500361}
362
363void
Yingdi Yuf7ede412014-08-30 20:37:52 -0700364Logic::onSyncTimeout(const Interest& interest)
365{
366 // It is OK. Others will handle the time out situation.
Davide Pesavento07684bc2021-02-07 20:09:28 -0500367 CHRONO_LOG_DBG(">> Logic::onSyncTimeout");
368 CHRONO_LOG_DBG("Interest: " << interest.getName());
369 CHRONO_LOG_DBG("<< Logic::onSyncTimeout");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700370}
371
372void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500373Logic::onSyncDataValidationFailed(const Data&)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700374{
375 // SyncReply cannot be validated.
376}
377
378void
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500379Logic::onSyncDataValidated(const Data& data)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700380{
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500381 const auto& name = data.getName();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700382 ConstBufferPtr digest = make_shared<ndn::Buffer>(name.get(-1).value(), name.get(-1).value_size());
383
Alexander Afanasyevfcbf81d2018-02-19 10:25:46 -0500384 try {
385 auto contentBuffer = bzip2::decompress(reinterpret_cast<const char*>(data.getContent().value()),
386 data.getContent().value_size());
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500387 processSyncData(name, digest, Block(std::move(contentBuffer)));
Alexander Afanasyevfcbf81d2018-02-19 10:25:46 -0500388 }
389 catch (const std::ios_base::failure& error) {
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500390 NDN_LOG_WARN("Error decompressing content of " << name << " (" << error.what() << ")");
Alexander Afanasyevfcbf81d2018-02-19 10:25:46 -0500391 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700392}
393
394void
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500395Logic::processSyncInterest(const Interest& interest, bool isTimedProcessing/*=false*/)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700396{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500397 CHRONO_LOG_DBG(">> Logic::processSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700398
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500399 const auto& name = interest.getName();
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500400 ConstBufferPtr digest = make_shared<ndn::Buffer>(name.get(-1).value(), name.get(-1).value_size());
Yingdi Yuf7ede412014-08-30 20:37:52 -0700401 ConstBufferPtr rootDigest = m_state.getRootDigest();
402
403 // If the digest of the incoming interest is the same as root digest
404 // Put the interest into InterestTable
405 if (*rootDigest == *digest) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500406 CHRONO_LOG_DBG("Oh, we are in the same state");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700407 m_interestTable.insert(interest, digest, false);
408
409 if (!m_isInReset)
410 return;
411
412 if (!isTimedProcessing) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500413 CHRONO_LOG_DBG("Non timed processing in reset");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700414 // Still in reset, our own seq has not been put into state yet
415 // Do not hurry, some others may be also resetting and may send their reply
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600416 time::milliseconds after(m_rangeUniformRandom(m_rng));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500417 CHRONO_LOG_DBG("After: " << after);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400418 m_delayedInterestProcessingId = m_scheduler.schedule(after,
419 [=] { processSyncInterest(interest, true); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700420 }
421 else {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500422 CHRONO_LOG_DBG("Timed processing in reset");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700423 // Now we can get out of reset state by putting our own stuff into m_state.
424 cancelReset();
425 }
426
427 return;
428 }
429
430 // If the digest of incoming interest is an "empty" digest
Davide Pesavento8663ed12022-07-23 03:04:27 -0400431 if (*digest == EMPTY_DIGEST) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500432 CHRONO_LOG_DBG("Poor guy, he knows nothing");
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800433 sendSyncData(m_defaultUserPrefix, name, m_state);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700434 return;
435 }
436
Davide Pesavento27416442020-01-23 23:10:24 -0500437 auto stateIter = m_log.find(digest);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700438 // If the digest of incoming interest can be found from the log
439 if (stateIter != m_log.end()) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500440 CHRONO_LOG_DBG("It is ok, you are so close");
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800441 sendSyncData(m_defaultUserPrefix, name, *(*stateIter)->diff());
Yingdi Yuf7ede412014-08-30 20:37:52 -0700442 return;
443 }
444
445 if (!isTimedProcessing) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500446 CHRONO_LOG_DBG("Let's wait, just wait for a while");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700447 // Do not hurry, some incoming SyncReplies may help us to recognize the digest
Yingdi Yu53f5f042015-01-31 16:33:25 -0800448 m_interestTable.insert(interest, digest, true);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700449
450 m_delayedInterestProcessingId =
Davide Pesaventod057cf12019-03-20 23:38:40 -0400451 m_scheduler.schedule(time::milliseconds(m_rangeUniformRandom(m_rng)),
452 [=] { processSyncInterest(interest, true); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700453 }
454 else {
455 // OK, nobody is helping us, just tell the truth.
Davide Pesavento07684bc2021-02-07 20:09:28 -0500456 CHRONO_LOG_DBG("OK, nobody is helping us, let us try to recover");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700457 m_interestTable.erase(digest);
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800458 sendRecoveryInterest(digest);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700459 }
460
Davide Pesavento07684bc2021-02-07 20:09:28 -0500461 CHRONO_LOG_DBG("<< Logic::processSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700462}
463
464void
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400465Logic::processResetInterest(const Interest&)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700466{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500467 CHRONO_LOG_DBG(">> Logic::processResetInterest");
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800468 reset(true);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700469}
470
471void
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400472Logic::processSyncData(const Name&, ConstBufferPtr digest, const Block& syncReply)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700473{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500474 CHRONO_LOG_DBG(">> Logic::processSyncData");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700475 DiffStatePtr commit = make_shared<DiffState>();
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500476 ConstBufferPtr previousRoot = m_state.getRootDigest();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700477
478 try {
479 m_interestTable.erase(digest); // Remove satisfied interest from PIT
480
481 State reply;
Davide Pesavento27416442020-01-23 23:10:24 -0500482 reply.wireDecode(syncReply);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700483
484 std::vector<MissingDataInfo> v;
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400485 for (const auto& leaf : reply.getLeaves().get<ordered>()) {
Davide Pesaventod057cf12019-03-20 23:38:40 -0400486 BOOST_ASSERT(leaf != nullptr);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700487
Davide Pesaventod057cf12019-03-20 23:38:40 -0400488 const Name& info = leaf->getSessionName();
489 SeqNo seq = leaf->getSeq();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700490
Davide Pesavento8663ed12022-07-23 03:04:27 -0400491 auto [isInserted, isUpdated, oldSeq] = m_state.update(info, seq);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400492 if (isInserted || isUpdated) {
493 commit->update(info, seq);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400494 oldSeq++;
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400495 v.push_back({info, oldSeq, seq});
Yingdi Yuf7ede412014-08-30 20:37:52 -0700496 }
Davide Pesaventod057cf12019-03-20 23:38:40 -0400497 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700498
499 if (!v.empty()) {
500 m_onUpdate(v);
501
502 commit->setRootDigest(m_state.getRootDigest());
503 insertToDiffLog(commit, previousRoot);
504 }
505 else {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500506 CHRONO_LOG_DBG("What? nothing new");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700507 }
508 }
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800509 catch (const State::Error&) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500510 CHRONO_LOG_DBG("Something really fishy happened during state decoding");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700511 commit.reset();
512 return;
513 }
514
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500515 if (static_cast<bool>(commit) && !commit->getLeaves().empty()) {
Yingdi Yuf7ede412014-08-30 20:37:52 -0700516 // state changed and it is safe to express a new interest
Junxiao Shic4902122019-02-08 15:13:50 -0700517 auto after = time::milliseconds(m_reexpressionJitter(m_rng));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500518 CHRONO_LOG_DBG("Reschedule sync interest after: " << after);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400519 m_reexpressingInterestId = m_scheduler.schedule(after, [this] { sendSyncInterest(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700520 }
521}
522
523void
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800524Logic::satisfyPendingSyncInterests(const Name& updatedPrefix, ConstDiffStatePtr commit)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700525{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500526 CHRONO_LOG_DBG(">> Logic::satisfyPendingSyncInterests");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700527 try {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500528 CHRONO_LOG_DBG("InterestTable size: " << m_interestTable.size());
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500529 auto it = m_interestTable.begin();
530 while (it != m_interestTable.end()) {
Yingdi Yuf7ede412014-08-30 20:37:52 -0700531 ConstUnsatisfiedInterestPtr request = *it;
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500532 ++it;
Yingdi Yuf7ede412014-08-30 20:37:52 -0700533 if (request->isUnknown)
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500534 sendSyncData(updatedPrefix, request->interest.getName(), m_state);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700535 else
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500536 sendSyncData(updatedPrefix, request->interest.getName(), *commit);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700537 }
538 m_interestTable.clear();
539 }
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800540 catch (const InterestTable::Error&) {
Yingdi Yuf7ede412014-08-30 20:37:52 -0700541 // ok. not really an error
542 }
Davide Pesavento07684bc2021-02-07 20:09:28 -0500543 CHRONO_LOG_DBG("<< Logic::satisfyPendingSyncInterests");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700544}
545
546void
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500547Logic::insertToDiffLog(DiffStatePtr commit, ConstBufferPtr previousRoot)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700548{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500549 CHRONO_LOG_DBG(">> Logic::insertToDiffLog");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700550 // Connect to the history
551 if (!m_log.empty())
552 (*m_log.find(previousRoot))->setNext(commit);
553
554 // Insert the commit
555 m_log.erase(commit->getRootDigest());
556 m_log.insert(commit);
Davide Pesavento07684bc2021-02-07 20:09:28 -0500557 CHRONO_LOG_DBG("<< Logic::insertToDiffLog");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700558}
559
560void
561Logic::sendResetInterest()
562{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500563 CHRONO_LOG_DBG(">> Logic::sendResetInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700564
565 if (m_needPeriodReset) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500566 CHRONO_LOG_DBG("Need Period Reset");
567 CHRONO_LOG_DBG("ResetTimer: " << m_resetTimer);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700568
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400569 m_resetInterestId = m_scheduler.schedule(m_resetTimer + time::milliseconds(m_reexpressionJitter(m_rng)),
Davide Pesaventod057cf12019-03-20 23:38:40 -0400570 [this] { sendResetInterest(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700571 }
572
573 Interest interest(m_syncReset);
574 interest.setMustBeFresh(true);
575 interest.setInterestLifetime(m_resetInterestLifetime);
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700576
577 // Assigning to m_pendingResetInterest cancels the previous reset Interest.
578 // This is harmless since no Data is expected.
579 m_pendingResetInterest = m_face.expressInterest(interest,
Nick Gordon0b3beab2018-03-02 13:03:28 -0600580 bind(&Logic::onResetData, this, _1, _2),
581 bind(&Logic::onSyncTimeout, this, _1), // Nack
582 bind(&Logic::onSyncTimeout, this, _1));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500583 CHRONO_LOG_DBG("<< Logic::sendResetInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700584}
585
586void
587Logic::sendSyncInterest()
588{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500589 CHRONO_LOG_DBG(">> Logic::sendSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700590
591 Name interestName;
592 interestName.append(m_syncPrefix)
Davide Pesavento8663ed12022-07-23 03:04:27 -0400593 .append(name::Component(*m_state.getRootDigest()));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700594
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700595 m_pendingSyncInterestName = interestName;
Yingdi Yuf7ede412014-08-30 20:37:52 -0700596
597#ifdef _DEBUG
598 printDigest(m_state.getRootDigest());
599#endif
600
Davide Pesaventod057cf12019-03-20 23:38:40 -0400601 m_reexpressingInterestId = m_scheduler.schedule(m_syncInterestLifetime / 2 +
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400602 time::milliseconds(m_reexpressionJitter(m_rng)),
Davide Pesaventod057cf12019-03-20 23:38:40 -0400603 [this] { sendSyncInterest(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700604
605 Interest interest(interestName);
606 interest.setMustBeFresh(true);
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500607 interest.setCanBePrefix(true);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700608 interest.setInterestLifetime(m_syncInterestLifetime);
609
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700610 m_pendingSyncInterest = m_face.expressInterest(interest,
611 bind(&Logic::onSyncData, this, _1, _2),
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500612 bind(&Logic::onSyncNack, this, _1, _2),
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700613 bind(&Logic::onSyncTimeout, this, _1));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700614
Davide Pesavento07684bc2021-02-07 20:09:28 -0500615 CHRONO_LOG_DBG("Send interest: " << interest.getName());
616 CHRONO_LOG_DBG("<< Logic::sendSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700617}
618
619void
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500620Logic::trimState(State& partialState, const State& state, size_t nExcludedStates)
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600621{
622 partialState.reset();
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500623
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600624 std::vector<ConstLeafPtr> leaves;
Davide Pesaventod6a09562020-04-02 02:48:46 -0400625 for (const auto& leaf : state.getLeaves()) {
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600626 leaves.push_back(leaf);
627 }
628
629 std::shuffle(leaves.begin(), leaves.end(), m_rng);
630
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500631 size_t statesToEncode = leaves.size() - std::min(leaves.size() - 1, nExcludedStates);
Davide Pesaventod6a09562020-04-02 02:48:46 -0400632 for (const auto& leaf : leaves) {
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500633 if (statesToEncode == 0) {
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600634 break;
635 }
Davide Pesaventod6a09562020-04-02 02:48:46 -0400636 partialState.update(leaf->getSessionName(), leaf->getSeq());
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500637 --statesToEncode;
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600638 }
639}
640
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500641Data
642Logic::encodeSyncReply(const Name& nodePrefix, const Name& name, const State& state)
643{
644 Data syncReply(name);
645 syncReply.setFreshnessPeriod(m_syncReplyFreshness);
646
647 auto finalizeReply = [this, &nodePrefix, &syncReply] (const State& state) {
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500648 auto contentBuffer = bzip2::compress(reinterpret_cast<const char*>(state.wireEncode().data()),
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500649 state.wireEncode().size());
650 syncReply.setContent(contentBuffer);
651
652 if (m_nodeList[nodePrefix].signingId.empty())
653 m_keyChain.sign(syncReply);
654 else
655 m_keyChain.sign(syncReply, security::signingByIdentity(m_nodeList[nodePrefix].signingId));
656 };
657
658 finalizeReply(state);
659
660 size_t nExcludedStates = 1;
661 while (syncReply.wireEncode().size() > getMaxPacketLimit() - NDNLP_EXPECTED_OVERHEAD) {
662 if (nExcludedStates == 1) {
663 // To show this debug message only once
Davide Pesavento07684bc2021-02-07 20:09:28 -0500664 NDN_LOG_DEBUG("Sync reply size exceeded maximum packet limit ("
665 << (getMaxPacketLimit() - NDNLP_EXPECTED_OVERHEAD) << ")");
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500666 }
667 State partialState;
668 trimState(partialState, state, nExcludedStates);
669 finalizeReply(partialState);
670
Davide Pesavento8663ed12022-07-23 03:04:27 -0400671 BOOST_ASSERT(!state.getLeaves().empty());
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500672 nExcludedStates *= 2;
673 }
674
675 return syncReply;
676}
677
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600678void
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800679Logic::sendSyncData(const Name& nodePrefix, const Name& name, const State& state)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700680{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500681 CHRONO_LOG_DBG(">> Logic::sendSyncData");
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600682 if (m_nodeList.find(nodePrefix) == m_nodeList.end())
683 return;
684
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500685 m_face.put(encodeSyncReply(nodePrefix, name, state));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700686
687 // checking if our own interest got satisfied
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700688 if (m_pendingSyncInterestName == name) {
Yingdi Yuf7ede412014-08-30 20:37:52 -0700689 // remove outstanding interest
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700690 m_pendingSyncInterest.cancel();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700691
692 // re-schedule sending Sync interest
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600693 time::milliseconds after(m_reexpressionJitter(m_rng));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500694 CHRONO_LOG_DBG("Satisfy our own interest");
695 CHRONO_LOG_DBG("Reschedule sync interest after " << after);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400696 m_reexpressingInterestId = m_scheduler.schedule(after, [this] { sendSyncInterest(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700697 }
Davide Pesavento07684bc2021-02-07 20:09:28 -0500698 CHRONO_LOG_DBG("<< Logic::sendSyncData");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700699}
700
701void
702Logic::cancelReset()
703{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500704 CHRONO_LOG_DBG(">> Logic::cancelReset");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700705 if (!m_isInReset)
706 return;
707
708 m_isInReset = false;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800709 for (const auto& node : m_nodeList) {
710 updateSeqNo(node.second.seqNo, node.first);
711 }
Davide Pesavento07684bc2021-02-07 20:09:28 -0500712 CHRONO_LOG_DBG("<< Logic::cancelReset");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700713}
714
715void
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500716Logic::printDigest(const ConstBufferPtr& digest) const
Yingdi Yuf7ede412014-08-30 20:37:52 -0700717{
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500718 CHRONO_LOG_DBG("Hash: " << ndn::toHex(*digest, false));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700719}
720
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800721void
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500722Logic::sendRecoveryInterest(ConstBufferPtr digest)
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800723{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500724 CHRONO_LOG_DBG(">> Logic::sendRecoveryInterest");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800725
726 Name interestName;
727 interestName.append(m_syncPrefix)
728 .append(RECOVERY_COMPONENT)
Davide Pesavento8663ed12022-07-23 03:04:27 -0400729 .append(name::Component(*digest));
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800730
731 Interest interest(interestName);
732 interest.setMustBeFresh(true);
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500733 interest.setCanBePrefix(true);
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800734 interest.setInterestLifetime(m_recoveryInterestLifetime);
735
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700736 m_pendingRecoveryInterests[interestName[-1].toUri()] = m_face.expressInterest(interest,
Nick Gordon0b3beab2018-03-02 13:03:28 -0600737 bind(&Logic::onRecoveryData, this, _1, _2),
738 bind(&Logic::onRecoveryTimeout, this, _1), // Nack
739 bind(&Logic::onRecoveryTimeout, this, _1));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500740 CHRONO_LOG_DBG("interest: " << interest.getName());
741 CHRONO_LOG_DBG("<< Logic::sendRecoveryInterest");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800742}
743
744void
745Logic::processRecoveryInterest(const Interest& interest)
746{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500747 CHRONO_LOG_DBG(">> Logic::processRecoveryInterest");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800748
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500749 const auto& name = interest.getName();
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800750 ConstBufferPtr digest = make_shared<ndn::Buffer>(name.get(-1).value(), name.get(-1).value_size());
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800751 ConstBufferPtr rootDigest = m_state.getRootDigest();
752
Davide Pesavento27416442020-01-23 23:10:24 -0500753 auto stateIter = m_log.find(digest);
Davide Pesavento8663ed12022-07-23 03:04:27 -0400754 if (stateIter != m_log.end() || *digest == EMPTY_DIGEST || *rootDigest == *digest) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500755 CHRONO_LOG_DBG("I can help you recover");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800756 sendSyncData(m_defaultUserPrefix, name, m_state);
757 return;
758 }
Davide Pesavento27416442020-01-23 23:10:24 -0500759
Davide Pesavento07684bc2021-02-07 20:09:28 -0500760 CHRONO_LOG_DBG("<< Logic::processRecoveryInterest");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800761}
762
763void
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800764Logic::onRecoveryData(const Interest& interest, const Data& data)
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800765{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500766 CHRONO_LOG_DBG(">> Logic::onRecoveryData");
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700767 m_pendingRecoveryInterests.erase(interest.getName()[-1].toUri());
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500768 onSyncDataValidated(data);
Davide Pesavento07684bc2021-02-07 20:09:28 -0500769 CHRONO_LOG_DBG("<< Logic::onRecoveryData");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800770}
771
772void
773Logic::onRecoveryTimeout(const Interest& interest)
774{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500775 CHRONO_LOG_DBG(">> Logic::onRecoveryTimeout");
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700776 m_pendingRecoveryInterests.erase(interest.getName()[-1].toUri());
Davide Pesavento07684bc2021-02-07 20:09:28 -0500777 CHRONO_LOG_DBG("Interest: " << interest.getName());
778 CHRONO_LOG_DBG("<< Logic::onRecoveryTimeout");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800779}
780
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800781} // namespace chronosync