blob: 05defbd658e066b689b1728c1dad85b12db1d733 [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
Yingdi Yuf7ede412014-08-30 20:37:52 -070040const uint8_t EMPTY_DIGEST_VALUE[] = {
41 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
Ashlesh Gawande08784d42017-09-06 23:40:21 -050047int Logic::s_instanceCounter = 0;
Yingdi Yuf7ede412014-08-30 20:37:52 -070048
Yingdi Yucd339022014-11-05 17:51:19 -080049const ndn::Name Logic::DEFAULT_NAME;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -080050const ndn::Name Logic::EMPTY_NAME;
Ashlesh Gawande08784d42017-09-06 23:40:21 -050051const std::shared_ptr<Validator> Logic::DEFAULT_VALIDATOR;
Yingdi Yuf7ede412014-08-30 20:37:52 -070052const time::steady_clock::Duration Logic::DEFAULT_RESET_TIMER = time::seconds(0);
53const time::steady_clock::Duration Logic::DEFAULT_CANCEL_RESET_TIMER = time::milliseconds(500);
54const time::milliseconds Logic::DEFAULT_RESET_INTEREST_LIFETIME(1000);
55const time::milliseconds Logic::DEFAULT_SYNC_INTEREST_LIFETIME(1000);
56const time::milliseconds Logic::DEFAULT_SYNC_REPLY_FRESHNESS(1000);
Sonu Mishra4d3a2e02017-01-18 20:27:51 -080057const time::milliseconds Logic::DEFAULT_RECOVERY_INTEREST_LIFETIME(1000);
Yingdi Yuf7ede412014-08-30 20:37:52 -070058
Ashlesh Gawande08784d42017-09-06 23:40:21 -050059const ConstBufferPtr Logic::EMPTY_DIGEST(new ndn::Buffer(EMPTY_DIGEST_VALUE, 32));
Yingdi Yuf7ede412014-08-30 20:37:52 -070060const ndn::name::Component Logic::RESET_COMPONENT("reset");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -080061const ndn::name::Component Logic::RECOVERY_COMPONENT("recovery");
Yingdi Yuf7ede412014-08-30 20:37:52 -070062
Alexander Afanasyev89036292018-02-13 17:19:50 -050063const size_t NDNLP_EXPECTED_OVERHEAD = 20;
64
65/**
66 * Get maximum packet limit
67 *
68 * By default, it returns `ndn::MAX_NDN_PACKET_SIZE`.
69 * The returned value can be customized using the environment variable `CHRONOSYNC_MAX_PACKET_SIZE`,
70 * but the returned value will be at least 500 and no more than `ndn::MAX_NDN_PACKET_SIZE`.
71 */
Davide Pesavento07684bc2021-02-07 20:09:28 -050072#ifndef CHRONOSYNC_WITH_TESTS
Alexander Afanasyev89036292018-02-13 17:19:50 -050073static
Davide Pesavento07684bc2021-02-07 20:09:28 -050074#endif // CHRONOSYNC_WITH_TESTS
Alexander Afanasyev89036292018-02-13 17:19:50 -050075size_t
76getMaxPacketLimit()
77{
78 static size_t limit = 0;
Davide Pesavento07684bc2021-02-07 20:09:28 -050079#ifndef CHRONOSYNC_WITH_TESTS
Alexander Afanasyev89036292018-02-13 17:19:50 -050080 if (limit != 0) {
81 return limit;
82 }
Davide Pesavento07684bc2021-02-07 20:09:28 -050083#endif // CHRONOSYNC_WITH_TESTS
Alexander Afanasyev89036292018-02-13 17:19:50 -050084
85 if (getenv("CHRONOSYNC_MAX_PACKET_SIZE") != nullptr) {
86 try {
87 limit = ndn::clamp<size_t>(boost::lexical_cast<size_t>(getenv("CHRONOSYNC_MAX_PACKET_SIZE")),
88 500, ndn::MAX_NDN_PACKET_SIZE);
89 }
90 catch (const boost::bad_lexical_cast&) {
91 limit = ndn::MAX_NDN_PACKET_SIZE;
92 }
93 }
94 else {
95 limit = ndn::MAX_NDN_PACKET_SIZE;
96 }
97
98 return limit;
99}
100
Yingdi Yuf7ede412014-08-30 20:37:52 -0700101Logic::Logic(ndn::Face& face,
102 const Name& syncPrefix,
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800103 const Name& defaultUserPrefix,
Yingdi Yuf7ede412014-08-30 20:37:52 -0700104 const UpdateCallback& onUpdate,
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800105 const Name& defaultSigningId,
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500106 std::shared_ptr<Validator> validator,
Yingdi Yuf7ede412014-08-30 20:37:52 -0700107 const time::steady_clock::Duration& resetTimer,
108 const time::steady_clock::Duration& cancelResetTimer,
109 const time::milliseconds& resetInterestLifetime,
110 const time::milliseconds& syncInterestLifetime,
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800111 const time::milliseconds& syncReplyFreshness,
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -0500112 const time::milliseconds& recoveryInterestLifetime,
113 const name::Component& session)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700114 : m_face(face)
115 , m_syncPrefix(syncPrefix)
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400116 , m_syncReset(Name(syncPrefix).append("reset"))
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800117 , m_defaultUserPrefix(defaultUserPrefix)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700118 , m_interestTable(m_face.getIoService())
Yingdi Yuf7ede412014-08-30 20:37:52 -0700119 , m_isInReset(false)
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400120 , m_needPeriodReset(resetTimer > time::nanoseconds::zero())
Yingdi Yuf7ede412014-08-30 20:37:52 -0700121 , m_onUpdate(onUpdate)
122 , m_scheduler(m_face.getIoService())
Ashlesh Gawande9a306fe2019-01-04 11:38:18 -0600123 , m_rng(ndn::random::getRandomNumberEngine())
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600124 , m_rangeUniformRandom(100, 500)
125 , m_reexpressionJitter(100, 500)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700126 , m_resetTimer(resetTimer)
127 , m_cancelResetTimer(cancelResetTimer)
128 , m_resetInterestLifetime(resetInterestLifetime)
129 , m_syncInterestLifetime(syncInterestLifetime)
130 , m_syncReplyFreshness(syncReplyFreshness)
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800131 , m_recoveryInterestLifetime(recoveryInterestLifetime)
Yingdi Yucd339022014-11-05 17:51:19 -0800132 , m_validator(validator)
Alexander Afanasyev90587b82018-02-11 20:36:53 -0500133 , m_instanceId(s_instanceCounter++)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700134{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500135 CHRONO_LOG_DBG(">> Logic::Logic");
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400136 addUserNode(m_defaultUserPrefix, defaultSigningId, session, false);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700137
Davide Pesavento07684bc2021-02-07 20:09:28 -0500138 CHRONO_LOG_DBG("Listen to: " << m_syncPrefix);
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700139 m_syncRegisteredPrefix = m_face.setInterestFilter(
140 ndn::InterestFilter(m_syncPrefix).allowLoopback(false),
141 bind(&Logic::onSyncInterest, this, _1, _2),
142 bind(&Logic::onSyncRegisterFailed, this, _1, _2));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700143
Qiuhan Dinge246b622014-12-03 21:57:48 -0800144 sendSyncInterest();
Davide Pesavento07684bc2021-02-07 20:09:28 -0500145 CHRONO_LOG_DBG("<< Logic::Logic");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700146}
147
148Logic::~Logic()
149{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500150 CHRONO_LOG_DBG(">> Logic::~Logic");
Yingdi Yu9d5679a2015-02-01 00:17:58 -0800151 m_interestTable.clear();
Nick Gordon0b3beab2018-03-02 13:03:28 -0600152 m_scheduler.cancelAllEvents();
Davide Pesavento07684bc2021-02-07 20:09:28 -0500153 CHRONO_LOG_DBG("<< Logic::~Logic");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700154}
155
156void
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800157Logic::reset(bool isOnInterest)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700158{
159 m_isInReset = true;
160
161 m_state.reset();
162 m_log.clear();
163
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800164 if (!isOnInterest)
165 sendResetInterest();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700166
Yingdi Yuf7ede412014-08-30 20:37:52 -0700167 sendSyncInterest();
168
Davide Pesaventod057cf12019-03-20 23:38:40 -0400169 m_delayedInterestProcessingId = m_scheduler.schedule(m_cancelResetTimer, [this] { cancelReset(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700170}
171
172void
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800173Logic::setDefaultUserPrefix(const Name& defaultUserPrefix)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700174{
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800175 if (defaultUserPrefix != EMPTY_NAME) {
176 if (m_nodeList.find(defaultUserPrefix) != m_nodeList.end()) {
177 m_defaultUserPrefix = defaultUserPrefix;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800178 }
179 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700180}
181
182void
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400183Logic::addUserNode(const Name& userPrefix, const Name& signingId, const name::Component& session, bool shouldSendReset)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700184{
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800185 if (userPrefix == EMPTY_NAME)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700186 return;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800187 if (m_defaultUserPrefix == EMPTY_NAME) {
188 m_defaultUserPrefix = userPrefix;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800189 }
190 if (m_nodeList.find(userPrefix) == m_nodeList.end()) {
191 m_nodeList[userPrefix].userPrefix = userPrefix;
192 m_nodeList[userPrefix].signingId = signingId;
193 Name sessionName = userPrefix;
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -0500194 if (!session.empty()) {
195 sessionName.append(session);
196 }
197 else {
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400198 sessionName.appendNumber(time::toUnixTimestamp(time::system_clock::now()).count());
Alexander Afanasyevbf5bc6c2018-02-19 11:26:09 -0500199 }
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800200 m_nodeList[userPrefix].sessionName = sessionName;
201 m_nodeList[userPrefix].seqNo = 0;
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400202 reset(!shouldSendReset);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800203 }
204}
Yingdi Yuf7ede412014-08-30 20:37:52 -0700205
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800206void
207Logic::removeUserNode(const Name& userPrefix)
208{
209 auto userNode = m_nodeList.find(userPrefix);
210 if (userNode != m_nodeList.end()) {
211 m_nodeList.erase(userNode);
212 if (m_defaultUserPrefix == userPrefix) {
213 if (!m_nodeList.empty()) {
214 m_defaultUserPrefix = m_nodeList.begin()->second.userPrefix;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800215 }
216 else {
217 m_defaultUserPrefix = EMPTY_NAME;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800218 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700219 }
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800220 reset(false);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800221 }
222}
Yingdi Yuf7ede412014-08-30 20:37:52 -0700223
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800224const Name&
225Logic::getSessionName(Name prefix)
226{
227 if (prefix == EMPTY_NAME)
228 prefix = m_defaultUserPrefix;
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500229
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800230 auto node = m_nodeList.find(prefix);
231 if (node != m_nodeList.end())
232 return node->second.sessionName;
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500233
234 NDN_THROW(Error("Nonexistent node: " + prefix.toUri()));
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800235}
Yingdi Yuf7ede412014-08-30 20:37:52 -0700236
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800237const SeqNo&
238Logic::getSeqNo(Name prefix)
239{
240 if (prefix == EMPTY_NAME)
241 prefix = m_defaultUserPrefix;
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500242
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800243 auto node = m_nodeList.find(prefix);
244 if (node != m_nodeList.end())
245 return node->second.seqNo;
Yingdi Yuf7ede412014-08-30 20:37:52 -0700246
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500247 NDN_THROW(Error("Nonexistent node: " + prefix.toUri()));
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800248}
249
250void
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800251Logic::updateSeqNo(const SeqNo& seqNo, const Name& updatePrefix)
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800252{
253 Name prefix;
254 if (updatePrefix == EMPTY_NAME) {
255 if (m_defaultUserPrefix == EMPTY_NAME)
256 return;
257 prefix = m_defaultUserPrefix;
258 }
259 else
260 prefix = updatePrefix;
261
262 auto it = m_nodeList.find(prefix);
263 if (it != m_nodeList.end()) {
264 NodeInfo& node = it->second;
Davide Pesavento07684bc2021-02-07 20:09:28 -0500265 CHRONO_LOG_DBG(">> Logic::updateSeqNo");
266 CHRONO_LOG_DBG("seqNo: " << seqNo << " m_seqNo: " << node.seqNo);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800267 if (seqNo < node.seqNo || seqNo == 0)
268 return;
269
270 node.seqNo = seqNo;
Davide Pesavento07684bc2021-02-07 20:09:28 -0500271 CHRONO_LOG_DBG("updateSeqNo: m_seqNo " << node.seqNo);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800272
273 if (!m_isInReset) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500274 CHRONO_LOG_DBG("updateSeqNo: not in Reset");
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500275 ConstBufferPtr previousRoot = m_state.getRootDigest();
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500276 printDigest(previousRoot);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800277
278 bool isInserted = false;
279 bool isUpdated = false;
280 SeqNo oldSeq;
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500281 std::tie(isInserted, isUpdated, oldSeq) = m_state.update(node.sessionName, node.seqNo);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800282
Davide Pesavento07684bc2021-02-07 20:09:28 -0500283 CHRONO_LOG_DBG("Insert: " << std::boolalpha << isInserted);
284 CHRONO_LOG_DBG("Updated: " << std::boolalpha << isUpdated);
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800285 if (isInserted || isUpdated) {
286 DiffStatePtr commit = make_shared<DiffState>();
287 commit->update(node.sessionName, node.seqNo);
288 commit->setRootDigest(m_state.getRootDigest());
289 insertToDiffLog(commit, previousRoot);
290
291 satisfyPendingSyncInterests(prefix, commit);
292 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700293 }
294 }
295}
296
297ConstBufferPtr
298Logic::getRootDigest() const
299{
300 return m_state.getRootDigest();
301}
302
303void
304Logic::printState(std::ostream& os) const
305{
Nick Gordon0b3beab2018-03-02 13:03:28 -0600306 for (const auto& leaf : m_state.getLeaves()) {
307 os << *leaf << "\n";
308 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700309}
310
311std::set<Name>
312Logic::getSessionNames() const
313{
314 std::set<Name> sessionNames;
Nick Gordon0b3beab2018-03-02 13:03:28 -0600315 for (const auto& leaf : m_state.getLeaves()) {
316 sessionNames.insert(leaf->getSessionName());
317 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700318 return sessionNames;
319}
320
321void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500322Logic::onSyncInterest(const Name&, const Interest& interest)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700323{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500324 CHRONO_LOG_DBG(">> Logic::onSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700325 Name name = interest.getName();
326
Davide Pesavento07684bc2021-02-07 20:09:28 -0500327 CHRONO_LOG_DBG("InterestName: " << name);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700328
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800329 if (name.size() >= 1 && RESET_COMPONENT == name.get(-1)) {
330 processResetInterest(interest);
331 }
332 else if (name.size() >= 2 && RECOVERY_COMPONENT == name.get(-2)) {
333 processRecoveryInterest(interest);
334 }
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500335 else {
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500336 processSyncInterest(interest);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700337 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700338
Davide Pesavento07684bc2021-02-07 20:09:28 -0500339 CHRONO_LOG_DBG("<< Logic::onSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700340}
341
342void
343Logic::onSyncRegisterFailed(const Name& prefix, const std::string& msg)
344{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500345 CHRONO_LOG_DBG(">> Logic::onSyncRegisterFailed");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700346}
347
348void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500349Logic::onSyncData(const Interest&, const Data& data)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700350{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500351 CHRONO_LOG_DBG(">> Logic::onSyncData");
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500352 if (m_validator != nullptr)
353 m_validator->validate(data,
354 bind(&Logic::onSyncDataValidated, this, _1),
355 bind(&Logic::onSyncDataValidationFailed, this, _1));
356 else
357 onSyncDataValidated(data);
Sonu Mishraf42aa2c2017-01-22 18:47:33 -0800358
Davide Pesavento07684bc2021-02-07 20:09:28 -0500359 CHRONO_LOG_DBG("<< Logic::onSyncData");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700360}
361
362void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500363Logic::onResetData(const Interest&, const Data&)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700364{
365 // This should not happened, drop the received data.
366}
367
368void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500369Logic::onSyncNack(const Interest&, const ndn::lp::Nack& nack)
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500370{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500371 CHRONO_LOG_DBG(">> Logic::onSyncNack");
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500372 if (nack.getReason() == ndn::lp::NackReason::NO_ROUTE) {
373 auto after = ndn::time::milliseconds(m_reexpressionJitter(m_rng));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500374 CHRONO_LOG_DBG("Schedule sync interest after: " << after);
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500375 m_scheduler.schedule(after, [this] { sendSyncInterest(); });
376 }
Davide Pesavento07684bc2021-02-07 20:09:28 -0500377 CHRONO_LOG_DBG("<< Logic::onSyncNack");
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500378}
379
380void
Yingdi Yuf7ede412014-08-30 20:37:52 -0700381Logic::onSyncTimeout(const Interest& interest)
382{
383 // It is OK. Others will handle the time out situation.
Davide Pesavento07684bc2021-02-07 20:09:28 -0500384 CHRONO_LOG_DBG(">> Logic::onSyncTimeout");
385 CHRONO_LOG_DBG("Interest: " << interest.getName());
386 CHRONO_LOG_DBG("<< Logic::onSyncTimeout");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700387}
388
389void
Davide Pesavento07684bc2021-02-07 20:09:28 -0500390Logic::onSyncDataValidationFailed(const Data&)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700391{
392 // SyncReply cannot be validated.
393}
394
395void
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500396Logic::onSyncDataValidated(const Data& data)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700397{
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500398 const auto& name = data.getName();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700399 ConstBufferPtr digest = make_shared<ndn::Buffer>(name.get(-1).value(), name.get(-1).value_size());
400
Alexander Afanasyevfcbf81d2018-02-19 10:25:46 -0500401 try {
402 auto contentBuffer = bzip2::decompress(reinterpret_cast<const char*>(data.getContent().value()),
403 data.getContent().value_size());
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500404 processSyncData(name, digest, Block(std::move(contentBuffer)));
Alexander Afanasyevfcbf81d2018-02-19 10:25:46 -0500405 }
406 catch (const std::ios_base::failure& error) {
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500407 NDN_LOG_WARN("Error decompressing content of " << name << " (" << error.what() << ")");
Alexander Afanasyevfcbf81d2018-02-19 10:25:46 -0500408 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700409}
410
411void
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500412Logic::processSyncInterest(const Interest& interest, bool isTimedProcessing/*=false*/)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700413{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500414 CHRONO_LOG_DBG(">> Logic::processSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700415
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500416 const auto& name = interest.getName();
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500417 ConstBufferPtr digest = make_shared<ndn::Buffer>(name.get(-1).value(), name.get(-1).value_size());
Yingdi Yuf7ede412014-08-30 20:37:52 -0700418 ConstBufferPtr rootDigest = m_state.getRootDigest();
419
420 // If the digest of the incoming interest is the same as root digest
421 // Put the interest into InterestTable
422 if (*rootDigest == *digest) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500423 CHRONO_LOG_DBG("Oh, we are in the same state");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700424 m_interestTable.insert(interest, digest, false);
425
426 if (!m_isInReset)
427 return;
428
429 if (!isTimedProcessing) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500430 CHRONO_LOG_DBG("Non timed processing in reset");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700431 // Still in reset, our own seq has not been put into state yet
432 // Do not hurry, some others may be also resetting and may send their reply
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600433 time::milliseconds after(m_rangeUniformRandom(m_rng));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500434 CHRONO_LOG_DBG("After: " << after);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400435 m_delayedInterestProcessingId = m_scheduler.schedule(after,
436 [=] { processSyncInterest(interest, true); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700437 }
438 else {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500439 CHRONO_LOG_DBG("Timed processing in reset");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700440 // Now we can get out of reset state by putting our own stuff into m_state.
441 cancelReset();
442 }
443
444 return;
445 }
446
447 // If the digest of incoming interest is an "empty" digest
Sonu Mishrae10acbc2017-01-18 14:14:05 -0800448 if (*digest == *EMPTY_DIGEST) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500449 CHRONO_LOG_DBG("Poor guy, he knows nothing");
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800450 sendSyncData(m_defaultUserPrefix, name, m_state);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700451 return;
452 }
453
Davide Pesavento27416442020-01-23 23:10:24 -0500454 auto stateIter = m_log.find(digest);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700455 // If the digest of incoming interest can be found from the log
456 if (stateIter != m_log.end()) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500457 CHRONO_LOG_DBG("It is ok, you are so close");
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800458 sendSyncData(m_defaultUserPrefix, name, *(*stateIter)->diff());
Yingdi Yuf7ede412014-08-30 20:37:52 -0700459 return;
460 }
461
462 if (!isTimedProcessing) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500463 CHRONO_LOG_DBG("Let's wait, just wait for a while");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700464 // Do not hurry, some incoming SyncReplies may help us to recognize the digest
Yingdi Yu53f5f042015-01-31 16:33:25 -0800465 m_interestTable.insert(interest, digest, true);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700466
467 m_delayedInterestProcessingId =
Davide Pesaventod057cf12019-03-20 23:38:40 -0400468 m_scheduler.schedule(time::milliseconds(m_rangeUniformRandom(m_rng)),
469 [=] { processSyncInterest(interest, true); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700470 }
471 else {
472 // OK, nobody is helping us, just tell the truth.
Davide Pesavento07684bc2021-02-07 20:09:28 -0500473 CHRONO_LOG_DBG("OK, nobody is helping us, let us try to recover");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700474 m_interestTable.erase(digest);
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800475 sendRecoveryInterest(digest);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700476 }
477
Davide Pesavento07684bc2021-02-07 20:09:28 -0500478 CHRONO_LOG_DBG("<< Logic::processSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700479}
480
481void
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400482Logic::processResetInterest(const Interest&)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700483{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500484 CHRONO_LOG_DBG(">> Logic::processResetInterest");
Qiuhan Dingfb8c9e02015-01-30 14:04:55 -0800485 reset(true);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700486}
487
488void
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400489Logic::processSyncData(const Name&, ConstBufferPtr digest, const Block& syncReply)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700490{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500491 CHRONO_LOG_DBG(">> Logic::processSyncData");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700492 DiffStatePtr commit = make_shared<DiffState>();
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500493 ConstBufferPtr previousRoot = m_state.getRootDigest();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700494
495 try {
496 m_interestTable.erase(digest); // Remove satisfied interest from PIT
497
498 State reply;
Davide Pesavento27416442020-01-23 23:10:24 -0500499 reply.wireDecode(syncReply);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700500
501 std::vector<MissingDataInfo> v;
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400502 for (const auto& leaf : reply.getLeaves().get<ordered>()) {
Davide Pesaventod057cf12019-03-20 23:38:40 -0400503 BOOST_ASSERT(leaf != nullptr);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700504
Davide Pesaventod057cf12019-03-20 23:38:40 -0400505 const Name& info = leaf->getSessionName();
506 SeqNo seq = leaf->getSeq();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700507
Davide Pesaventod057cf12019-03-20 23:38:40 -0400508 bool isInserted = false;
509 bool isUpdated = false;
510 SeqNo oldSeq;
511 std::tie(isInserted, isUpdated, oldSeq) = m_state.update(info, seq);
512 if (isInserted || isUpdated) {
513 commit->update(info, seq);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400514 oldSeq++;
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400515 v.push_back({info, oldSeq, seq});
Yingdi Yuf7ede412014-08-30 20:37:52 -0700516 }
Davide Pesaventod057cf12019-03-20 23:38:40 -0400517 }
Yingdi Yuf7ede412014-08-30 20:37:52 -0700518
519 if (!v.empty()) {
520 m_onUpdate(v);
521
522 commit->setRootDigest(m_state.getRootDigest());
523 insertToDiffLog(commit, previousRoot);
524 }
525 else {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500526 CHRONO_LOG_DBG("What? nothing new");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700527 }
528 }
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800529 catch (const State::Error&) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500530 CHRONO_LOG_DBG("Something really fishy happened during state decoding");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700531 commit.reset();
532 return;
533 }
534
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500535 if (static_cast<bool>(commit) && !commit->getLeaves().empty()) {
Yingdi Yuf7ede412014-08-30 20:37:52 -0700536 // state changed and it is safe to express a new interest
Junxiao Shic4902122019-02-08 15:13:50 -0700537 auto after = time::milliseconds(m_reexpressionJitter(m_rng));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500538 CHRONO_LOG_DBG("Reschedule sync interest after: " << after);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400539 m_reexpressingInterestId = m_scheduler.schedule(after, [this] { sendSyncInterest(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700540 }
541}
542
543void
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800544Logic::satisfyPendingSyncInterests(const Name& updatedPrefix, ConstDiffStatePtr commit)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700545{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500546 CHRONO_LOG_DBG(">> Logic::satisfyPendingSyncInterests");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700547 try {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500548 CHRONO_LOG_DBG("InterestTable size: " << m_interestTable.size());
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500549 auto it = m_interestTable.begin();
550 while (it != m_interestTable.end()) {
Yingdi Yuf7ede412014-08-30 20:37:52 -0700551 ConstUnsatisfiedInterestPtr request = *it;
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500552 ++it;
Yingdi Yuf7ede412014-08-30 20:37:52 -0700553 if (request->isUnknown)
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500554 sendSyncData(updatedPrefix, request->interest.getName(), m_state);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700555 else
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500556 sendSyncData(updatedPrefix, request->interest.getName(), *commit);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700557 }
558 m_interestTable.clear();
559 }
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800560 catch (const InterestTable::Error&) {
Yingdi Yuf7ede412014-08-30 20:37:52 -0700561 // ok. not really an error
562 }
Davide Pesavento07684bc2021-02-07 20:09:28 -0500563 CHRONO_LOG_DBG("<< Logic::satisfyPendingSyncInterests");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700564}
565
566void
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500567Logic::insertToDiffLog(DiffStatePtr commit, ConstBufferPtr previousRoot)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700568{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500569 CHRONO_LOG_DBG(">> Logic::insertToDiffLog");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700570 // Connect to the history
571 if (!m_log.empty())
572 (*m_log.find(previousRoot))->setNext(commit);
573
574 // Insert the commit
575 m_log.erase(commit->getRootDigest());
576 m_log.insert(commit);
Davide Pesavento07684bc2021-02-07 20:09:28 -0500577 CHRONO_LOG_DBG("<< Logic::insertToDiffLog");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700578}
579
580void
581Logic::sendResetInterest()
582{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500583 CHRONO_LOG_DBG(">> Logic::sendResetInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700584
585 if (m_needPeriodReset) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500586 CHRONO_LOG_DBG("Need Period Reset");
587 CHRONO_LOG_DBG("ResetTimer: " << m_resetTimer);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700588
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400589 m_resetInterestId = m_scheduler.schedule(m_resetTimer + time::milliseconds(m_reexpressionJitter(m_rng)),
Davide Pesaventod057cf12019-03-20 23:38:40 -0400590 [this] { sendResetInterest(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700591 }
592
593 Interest interest(m_syncReset);
594 interest.setMustBeFresh(true);
595 interest.setInterestLifetime(m_resetInterestLifetime);
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700596
597 // Assigning to m_pendingResetInterest cancels the previous reset Interest.
598 // This is harmless since no Data is expected.
599 m_pendingResetInterest = m_face.expressInterest(interest,
Nick Gordon0b3beab2018-03-02 13:03:28 -0600600 bind(&Logic::onResetData, this, _1, _2),
601 bind(&Logic::onSyncTimeout, this, _1), // Nack
602 bind(&Logic::onSyncTimeout, this, _1));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500603 CHRONO_LOG_DBG("<< Logic::sendResetInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700604}
605
606void
607Logic::sendSyncInterest()
608{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500609 CHRONO_LOG_DBG(">> Logic::sendSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700610
611 Name interestName;
612 interestName.append(m_syncPrefix)
613 .append(ndn::name::Component(*m_state.getRootDigest()));
614
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700615 m_pendingSyncInterestName = interestName;
Yingdi Yuf7ede412014-08-30 20:37:52 -0700616
617#ifdef _DEBUG
618 printDigest(m_state.getRootDigest());
619#endif
620
Davide Pesaventod057cf12019-03-20 23:38:40 -0400621 m_reexpressingInterestId = m_scheduler.schedule(m_syncInterestLifetime / 2 +
Davide Pesaventod7de2d42019-08-01 20:55:50 -0400622 time::milliseconds(m_reexpressionJitter(m_rng)),
Davide Pesaventod057cf12019-03-20 23:38:40 -0400623 [this] { sendSyncInterest(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700624
625 Interest interest(interestName);
626 interest.setMustBeFresh(true);
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500627 interest.setCanBePrefix(true);
Yingdi Yuf7ede412014-08-30 20:37:52 -0700628 interest.setInterestLifetime(m_syncInterestLifetime);
629
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700630 m_pendingSyncInterest = m_face.expressInterest(interest,
631 bind(&Logic::onSyncData, this, _1, _2),
Ashlesh Gawandea1ad6042019-10-07 15:56:11 -0500632 bind(&Logic::onSyncNack, this, _1, _2),
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700633 bind(&Logic::onSyncTimeout, this, _1));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700634
Davide Pesavento07684bc2021-02-07 20:09:28 -0500635 CHRONO_LOG_DBG("Send interest: " << interest.getName());
636 CHRONO_LOG_DBG("<< Logic::sendSyncInterest");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700637}
638
639void
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500640Logic::trimState(State& partialState, const State& state, size_t nExcludedStates)
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600641{
642 partialState.reset();
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500643
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600644 std::vector<ConstLeafPtr> leaves;
Davide Pesaventod6a09562020-04-02 02:48:46 -0400645 for (const auto& leaf : state.getLeaves()) {
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600646 leaves.push_back(leaf);
647 }
648
649 std::shuffle(leaves.begin(), leaves.end(), m_rng);
650
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500651 size_t statesToEncode = leaves.size() - std::min(leaves.size() - 1, nExcludedStates);
Davide Pesaventod6a09562020-04-02 02:48:46 -0400652 for (const auto& leaf : leaves) {
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500653 if (statesToEncode == 0) {
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600654 break;
655 }
Davide Pesaventod6a09562020-04-02 02:48:46 -0400656 partialState.update(leaf->getSessionName(), leaf->getSeq());
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500657 --statesToEncode;
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600658 }
659}
660
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500661Data
662Logic::encodeSyncReply(const Name& nodePrefix, const Name& name, const State& state)
663{
664 Data syncReply(name);
665 syncReply.setFreshnessPeriod(m_syncReplyFreshness);
666
667 auto finalizeReply = [this, &nodePrefix, &syncReply] (const State& state) {
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500668 auto contentBuffer = bzip2::compress(reinterpret_cast<const char*>(state.wireEncode().data()),
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500669 state.wireEncode().size());
670 syncReply.setContent(contentBuffer);
671
672 if (m_nodeList[nodePrefix].signingId.empty())
673 m_keyChain.sign(syncReply);
674 else
675 m_keyChain.sign(syncReply, security::signingByIdentity(m_nodeList[nodePrefix].signingId));
676 };
677
678 finalizeReply(state);
679
680 size_t nExcludedStates = 1;
681 while (syncReply.wireEncode().size() > getMaxPacketLimit() - NDNLP_EXPECTED_OVERHEAD) {
682 if (nExcludedStates == 1) {
683 // To show this debug message only once
Davide Pesavento07684bc2021-02-07 20:09:28 -0500684 NDN_LOG_DEBUG("Sync reply size exceeded maximum packet limit ("
685 << (getMaxPacketLimit() - NDNLP_EXPECTED_OVERHEAD) << ")");
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500686 }
687 State partialState;
688 trimState(partialState, state, nExcludedStates);
689 finalizeReply(partialState);
690
691 BOOST_ASSERT(state.getLeaves().size() != 0);
692 nExcludedStates *= 2;
693 }
694
695 return syncReply;
696}
697
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600698void
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800699Logic::sendSyncData(const Name& nodePrefix, const Name& name, const State& state)
Yingdi Yuf7ede412014-08-30 20:37:52 -0700700{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500701 CHRONO_LOG_DBG(">> Logic::sendSyncData");
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600702 if (m_nodeList.find(nodePrefix) == m_nodeList.end())
703 return;
704
Alexander Afanasyev6ee98ff2018-02-13 19:12:28 -0500705 m_face.put(encodeSyncReply(nodePrefix, name, state));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700706
707 // checking if our own interest got satisfied
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700708 if (m_pendingSyncInterestName == name) {
Yingdi Yuf7ede412014-08-30 20:37:52 -0700709 // remove outstanding interest
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700710 m_pendingSyncInterest.cancel();
Yingdi Yuf7ede412014-08-30 20:37:52 -0700711
712 // re-schedule sending Sync interest
Ashlesh Gawande4a9ecd52018-02-06 14:36:19 -0600713 time::milliseconds after(m_reexpressionJitter(m_rng));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500714 CHRONO_LOG_DBG("Satisfy our own interest");
715 CHRONO_LOG_DBG("Reschedule sync interest after " << after);
Davide Pesaventod057cf12019-03-20 23:38:40 -0400716 m_reexpressingInterestId = m_scheduler.schedule(after, [this] { sendSyncInterest(); });
Yingdi Yuf7ede412014-08-30 20:37:52 -0700717 }
Davide Pesavento07684bc2021-02-07 20:09:28 -0500718 CHRONO_LOG_DBG("<< Logic::sendSyncData");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700719}
720
721void
722Logic::cancelReset()
723{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500724 CHRONO_LOG_DBG(">> Logic::cancelReset");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700725 if (!m_isInReset)
726 return;
727
728 m_isInReset = false;
Qiuhan Ding8c095fd2014-11-19 17:38:32 -0800729 for (const auto& node : m_nodeList) {
730 updateSeqNo(node.second.seqNo, node.first);
731 }
Davide Pesavento07684bc2021-02-07 20:09:28 -0500732 CHRONO_LOG_DBG("<< Logic::cancelReset");
Yingdi Yuf7ede412014-08-30 20:37:52 -0700733}
734
735void
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500736Logic::printDigest(const ConstBufferPtr& digest) const
Yingdi Yuf7ede412014-08-30 20:37:52 -0700737{
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500738 CHRONO_LOG_DBG("Hash: " << ndn::toHex(*digest, false));
Yingdi Yuf7ede412014-08-30 20:37:52 -0700739}
740
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800741void
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500742Logic::sendRecoveryInterest(ConstBufferPtr digest)
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800743{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500744 CHRONO_LOG_DBG(">> Logic::sendRecoveryInterest");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800745
746 Name interestName;
747 interestName.append(m_syncPrefix)
748 .append(RECOVERY_COMPONENT)
749 .append(ndn::name::Component(*digest));
750
751 Interest interest(interestName);
752 interest.setMustBeFresh(true);
Ashlesh Gawande1d1092d2018-08-03 14:36:49 -0500753 interest.setCanBePrefix(true);
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800754 interest.setInterestLifetime(m_recoveryInterestLifetime);
755
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700756 m_pendingRecoveryInterests[interestName[-1].toUri()] = m_face.expressInterest(interest,
Nick Gordon0b3beab2018-03-02 13:03:28 -0600757 bind(&Logic::onRecoveryData, this, _1, _2),
758 bind(&Logic::onRecoveryTimeout, this, _1), // Nack
759 bind(&Logic::onRecoveryTimeout, this, _1));
Davide Pesavento07684bc2021-02-07 20:09:28 -0500760 CHRONO_LOG_DBG("interest: " << interest.getName());
761 CHRONO_LOG_DBG("<< Logic::sendRecoveryInterest");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800762}
763
764void
765Logic::processRecoveryInterest(const Interest& interest)
766{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500767 CHRONO_LOG_DBG(">> Logic::processRecoveryInterest");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800768
Davide Pesavento5f5101a2022-03-11 20:05:03 -0500769 const auto& name = interest.getName();
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800770 ConstBufferPtr digest = make_shared<ndn::Buffer>(name.get(-1).value(), name.get(-1).value_size());
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800771 ConstBufferPtr rootDigest = m_state.getRootDigest();
772
Davide Pesavento27416442020-01-23 23:10:24 -0500773 auto stateIter = m_log.find(digest);
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800774 if (stateIter != m_log.end() || *digest == *EMPTY_DIGEST || *rootDigest == *digest) {
Davide Pesavento07684bc2021-02-07 20:09:28 -0500775 CHRONO_LOG_DBG("I can help you recover");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800776 sendSyncData(m_defaultUserPrefix, name, m_state);
777 return;
778 }
Davide Pesavento27416442020-01-23 23:10:24 -0500779
Davide Pesavento07684bc2021-02-07 20:09:28 -0500780 CHRONO_LOG_DBG("<< Logic::processRecoveryInterest");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800781}
782
783void
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800784Logic::onRecoveryData(const Interest& interest, const Data& data)
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800785{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500786 CHRONO_LOG_DBG(">> Logic::onRecoveryData");
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700787 m_pendingRecoveryInterests.erase(interest.getName()[-1].toUri());
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500788 onSyncDataValidated(data);
Davide Pesavento07684bc2021-02-07 20:09:28 -0500789 CHRONO_LOG_DBG("<< Logic::onRecoveryData");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800790}
791
792void
793Logic::onRecoveryTimeout(const Interest& interest)
794{
Davide Pesavento07684bc2021-02-07 20:09:28 -0500795 CHRONO_LOG_DBG(">> Logic::onRecoveryTimeout");
Junxiao Shi8e4e76d2019-02-08 15:25:08 -0700796 m_pendingRecoveryInterests.erase(interest.getName()[-1].toUri());
Davide Pesavento07684bc2021-02-07 20:09:28 -0500797 CHRONO_LOG_DBG("Interest: " << interest.getName());
798 CHRONO_LOG_DBG("<< Logic::onRecoveryTimeout");
Sonu Mishra4d3a2e02017-01-18 20:27:51 -0800799}
800
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800801} // namespace chronosync