blob: d660b66b2f37e0ff55f60c2c9fa6bcd79f795b80 [file] [log] [blame]
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
Junxiao Shifadcde52022-02-28 00:38:45 +00003 * Copyright (c) 2014-2022, The University of Memphis
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -05004 *
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -06005 * This file is part of PSync.
6 * See AUTHORS.md for complete list of PSync authors and contributors.
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -05007 *
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -06008 * PSync is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU Lesser General Public License as published by the Free Software Foundation,
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050010 * either version 3 of the License, or (at your option) any later version.
11 *
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -060012 * PSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050013 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -060014 * PURPOSE. See the GNU Lesser General Public License for more details.
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050015 *
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -060016 * You should have received a copy of the GNU Lesser General Public License along with
17 * PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050018 **/
19
20#ifndef PSYNC_FULL_PRODUCER_HPP
21#define PSYNC_FULL_PRODUCER_HPP
22
Ashlesh Gawande78b94ad2018-12-13 15:29:19 -060023#include "PSync/producer-base.hpp"
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050024
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050025#include <random>
Davide Pesaventod1437842019-03-19 14:05:21 -040026#include <set>
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050027
Ashlesh Gawande40970d62018-11-01 11:24:17 -050028#include <ndn-cxx/util/segment-fetcher.hpp>
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050029
30namespace psync {
31
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050032/**
33 * @brief Full sync logic to synchronize with other nodes
34 * where all nodes wants to get all names prefixes synced.
35 *
36 * Application should call publishName whenever it wants to
37 * let consumers know that new data is available for the userPrefix.
38 * Multiple userPrefixes can be added by using addUserNode.
39 * Currently, fetching and publishing of data needs to be handled by the application.
40 */
41class FullProducer : public ProducerBase
42{
43public:
44 /**
45 * @brief constructor
46 *
47 * Registers syncPrefix in NFD and sends a sync interest
48 *
49 * @param expectedNumEntries expected entries in IBF
50 * @param face application's face
51 * @param syncPrefix The prefix of the sync group
52 * @param userPrefix The prefix of the first user in the group
53 * @param onUpdateCallBack The call back to be called when there is new data
54 * @param syncInterestLifetime lifetime of the sync interest
55 * @param syncReplyFreshness freshness of sync data
Ashlesh Gawanded51690a2019-11-11 22:51:06 -060056 * @param ibltCompression Compression scheme to use for IBF
57 * @param contentCompression Compression scheme to use for Data content
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050058 */
59 FullProducer(size_t expectedNumEntries,
60 ndn::Face& face,
61 const ndn::Name& syncPrefix,
62 const ndn::Name& userPrefix,
63 const UpdateCallback& onUpdateCallBack,
Davide Pesaventoeeca59e2021-01-15 16:06:06 -050064 ndn::time::milliseconds syncInterestLifetime = SYNC_INTEREST_LIFETIME,
Ashlesh Gawanded51690a2019-11-11 22:51:06 -060065 ndn::time::milliseconds syncReplyFreshness = SYNC_REPLY_FRESHNESS,
Ashlesh Gawandee23b53b2020-02-16 13:47:38 -080066 CompressionScheme ibltCompression = CompressionScheme::DEFAULT,
67 CompressionScheme contentCompression = CompressionScheme::DEFAULT);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050068
69 ~FullProducer();
70
71 /**
72 * @brief Publish name to let others know
73 *
74 * addUserNode needs to be called before this to add the prefix
75 * if not already added via the constructor.
76 * If seq is null then the seq of prefix is incremented by 1 else
77 * the supplied sequence is set in the IBF.
78 *
79 * @param prefix the prefix to be updated
80 * @param seq the sequence number of the prefix
81 */
82 void
Davide Pesaventoc407dee2022-07-21 23:56:05 -040083 publishName(const ndn::Name& prefix, std::optional<uint64_t> seq = std::nullopt);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050084
Ashlesh Gawande584e1202019-05-19 16:15:33 -070085PSYNC_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050086 /**
87 * @brief Send sync interest for full synchronization
88 *
89 * Forms the interest name: /<sync-prefix>/<own-IBF>
90 * Cancels any pending sync interest we sent earlier on the face
91 * Sends the sync interest
92 */
93 void
94 sendSyncInterest();
95
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050096 /**
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050097 * @brief Process sync interest from other parties
98 *
99 * Get differences b/w our IBF and IBF in the sync interest.
100 * If we cannot get the differences successfully then send an application nack.
101 *
102 * If we have some things in our IBF that the other side does not have, reply with the content or
103 * If no. of different items is greater than threshold or equals zero then send a nack.
104 * Otherwise add the sync interest into a map with interest name as key and PendingEntryInfoFull
105 * as value.
106 *
Ashlesh Gawande40970d62018-11-01 11:24:17 -0500107 * @param prefixName prefix for sync group which we registered
108 * @param interest the interest we got
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500109 */
110 void
Ashlesh Gawande40970d62018-11-01 11:24:17 -0500111 onSyncInterest(const ndn::Name& prefixName, const ndn::Interest& interest);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500112
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500113 /**
114 * @brief Send sync data
115 *
116 * Check if the data will satisfy our own pending interest,
117 * remove it first if it does, and then renew the sync interest
118 * Otherwise just send the data
119 *
120 * @param name name to be set as data name
121 * @param block the content of the data
122 */
123 void
124 sendSyncData(const ndn::Name& name, const ndn::Block& block);
125
126 /**
127 * @brief Process sync data
128 *
129 * Call deletePendingInterests to delete any pending sync interest with
130 * interest name would have been satisfied once NFD got the data.
131 *
132 * For each prefix/seq in data content check that we don't already have the
133 * prefix/seq and updateSeq(prefix, seq)
134 *
135 * Notify the application about the updates
136 * sendSyncInterest because the last one was satisfied by the incoming data
137 *
138 * @param interest interest for which we got the data
Ashlesh Gawande40970d62018-11-01 11:24:17 -0500139 * @param bufferPtr sync data content
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500140 */
141 void
Ashlesh Gawande40970d62018-11-01 11:24:17 -0500142 onSyncData(const ndn::Interest& interest, const ndn::ConstBufferPtr& bufferPtr);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500143
Ashlesh Gawanded51690a2019-11-11 22:51:06 -0600144private:
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500145 /**
146 * @brief Satisfy pending sync interests
147 *
148 * For pending sync interests SI, if IBF of SI has any difference from our own IBF:
149 * send data back.
150 * If we can't decode differences from the stored IBF, then delete it.
151 */
152 void
153 satisfyPendingInterests();
154
155 /**
156 * @brief Delete pending sync interests that match given name
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500157 */
158 void
159 deletePendingInterests(const ndn::Name& interestName);
160
161 /**
162 * @brief Check if hash(prefix + 1) is in negative
163 *
164 * Sometimes what happens is that interest from other side
165 * gets to us before the data
166 */
167 bool
168 isFutureHash(const ndn::Name& prefix, const std::set<uint32_t>& negative);
169
Junxiao Shifadcde52022-02-28 00:38:45 +0000170#ifdef PSYNC_WITH_TESTS
171public:
172 size_t nIbfDecodeFailuresAboveThreshold = 0;
173 size_t nIbfDecodeFailuresBelowThreshold = 0;
174#endif // PSYNC_WITH_TESTS
175
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500176private:
Davide Pesaventodb789562020-12-19 23:01:08 -0500177 struct PendingEntryInfo
178 {
179 detail::IBLT iblt;
180 ndn::scheduler::ScopedEventId expirationEvent;
181 };
182
183 std::map<ndn::Name, PendingEntryInfo> m_pendingEntries;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500184 ndn::time::milliseconds m_syncInterestLifetime;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500185 UpdateCallback m_onUpdate;
Davide Pesaventod1437842019-03-19 14:05:21 -0400186 ndn::scheduler::ScopedEventId m_scheduledSyncInterestId;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500187 std::uniform_int_distribution<> m_jitter;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500188 ndn::Name m_outstandingInterestName;
Junxiao Shie5fdcc32019-01-23 16:48:54 +0000189 ndn::ScopedRegisteredPrefixHandle m_registeredPrefix;
Ashlesh Gawande40970d62018-11-01 11:24:17 -0500190 std::shared_ptr<ndn::util::SegmentFetcher> m_fetcher;
Alexander Afanasyev16d493e2022-04-23 22:37:19 -0400191 uint64_t m_incomingFace = 0;
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500192};
193
194} // namespace psync
195
Ashlesh Gawande0cf4b602019-01-18 15:58:17 -0600196#endif // PSYNC_FULL_PRODUCER_HPP