blob: acca1682410e90acb90b447fe90f1791b41c049e [file] [log] [blame]
Yingdi Yuf7ede412014-08-30 20:37:52 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012-2014 University of California, Los Angeles
4 *
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>
23 */
24
25#ifndef CHRONOSYNC_LOGIC_HPP
26#define CHRONOSYNC_LOGIC_HPP
27
28#include "boost-header.h"
29#include <memory>
30#include <map>
31
32#include <ndn-cxx/face.hpp>
33#include <ndn-cxx/util/scheduler.hpp>
34#include <ndn-cxx/security/key-chain.hpp>
Yingdi Yucd339022014-11-05 17:51:19 -080035#include <ndn-cxx/security/validator.hpp>
Yingdi Yuf7ede412014-08-30 20:37:52 -070036
37#include "interest-table.hpp"
38#include "diff-state-container.hpp"
39
40namespace chronosync {
41
42/**
43 * @brief The missing sequence numbers for a session
44 *
45 * This class is used to notify the clients of Logic
46 * the details of state changes.
47 *
48 * Instances of this class is usually used as elements of some containers
49 * such as std::vector, thus it is copyable.
50 */
51class MissingDataInfo
52{
53public:
54 /// @brief session name
55 Name session;
56 /// @brief the lowest one of missing sequence numbers
57 SeqNo low;
58 /// @brief the highest one of missing sequence numbers
59 SeqNo high;
60};
61
62/**
63 * @brief The callback function to handle state updates
64 *
65 * The parameter is a set of MissingDataInfo, of which each corresponds to
66 * a session that has changed its state.
67 */
68typedef function<void(const std::vector<MissingDataInfo>&)> UpdateCallback;
69
70/**
71 * @brief Logic of ChronoSync
72 */
73class Logic : noncopyable
74{
75public:
76 static const time::steady_clock::Duration DEFAULT_RESET_TIMER;
77 static const time::steady_clock::Duration DEFAULT_CANCEL_RESET_TIMER;
78 static const time::milliseconds DEFAULT_RESET_INTEREST_LIFETIME;
79 static const time::milliseconds DEFAULT_SYNC_INTEREST_LIFETIME;
80 static const time::milliseconds DEFAULT_SYNC_REPLY_FRESHNESS;
81
82 /**
83 * @brief Constructor
84 *
85 * @param syncPrefix The prefix of the sync group
86 * @param userPrefix The prefix of the user who owns the session
87 * @param onUpdate The callback function to handle state updates
Yingdi Yucd339022014-11-05 17:51:19 -080088 * @param validator The validator for packet validation
Yingdi Yuf7ede412014-08-30 20:37:52 -070089 * @param resetTimer The timer to periodically send Reset Interest
90 * @param syncReplyFreshness The FreshnessPeriod of sync reply
91 * @param resetInterestLifetime The lifetime of sync interest
92 * @param resetInterestLifetime The lifetime of Reset Interest
93 * @param cancelResetTimer The timer to exit from Reset state
94 */
95 Logic(ndn::Face& face,
96 const Name& syncPrefix,
97 const Name& userPrefix,
98 const UpdateCallback& onUpdate,
Yingdi Yucd339022014-11-05 17:51:19 -080099 const Name& signingId = DEFAULT_NAME,
100 ndn::shared_ptr<ndn::Validator> validator = DEFAULT_VALIDATOR,
Yingdi Yuf7ede412014-08-30 20:37:52 -0700101 const time::steady_clock::Duration& resetTimer = DEFAULT_RESET_TIMER,
102 const time::steady_clock::Duration& cancelResetTimer = DEFAULT_CANCEL_RESET_TIMER,
103 const time::milliseconds& resetInterestLifetime = DEFAULT_RESET_INTEREST_LIFETIME,
104 const time::milliseconds& syncInterestLifetime = DEFAULT_SYNC_INTEREST_LIFETIME,
105 const time::milliseconds& syncReplyFreshness = DEFAULT_SYNC_REPLY_FRESHNESS);
106
107 ~Logic();
108
109 /// @brief Reset the sync tree (and restart synchronization again)
110 void
111 reset();
112
113 /**
114 * @brief Set user prefix
115 *
116 * This method will also change the session name and trigger reset.
117 *
118 * @param userPrefix The prefix of user.
119 */
120 void
121 setUserPrefix(const Name& userPrefix);
122
123 /// @brief Get the name of the local session.
124 const Name&
125 getSessionName() const
126 {
127 return m_sessionName;
128 }
129
130 /// @brief Get current seqNo of the local session.
131 const SeqNo&
132 getSeqNo() const
133 {
134 return m_seqNo;
135 }
136
137 /**
138 * @brief Update the seqNo of the local session
139 *
140 * The method updates the existing seqNo with the supplied seqNo.
141 *
142 * @param seq The new seqNo.
143 */
144 void
145 updateSeqNo(const SeqNo& seq);
146
147 /// @brief Get root digest of current sync tree
148 ndn::ConstBufferPtr
149 getRootDigest() const;
150
151 /// @brief Get the name of all sessions
152 std::set<Name>
153 getSessionNames() const;
154
Yingdi Yu906c2ea2014-10-31 11:24:50 -0700155CHRONOSYNC_PUBLIC_WITH_TESTS_ELSE_PRIVATE:
Yingdi Yuf7ede412014-08-30 20:37:52 -0700156 void
157 printState(std::ostream& os) const;
158
159 ndn::Scheduler&
160 getScheduler()
161 {
162 return m_scheduler;
163 }
164
165 State&
166 getState()
167 {
168 return m_state;
169 }
170
171private:
172 /**
173 * @brief Callback to handle Sync Interest
174 *
175 * This method checks whether an incoming interest is a normal one or a reset
176 * and dispatches the incoming interest to corresponding processing methods.
177 *
178 * @param prefix The prefix of the sync group.
179 * @param interest The incoming sync interest.
180 */
181 void
182 onSyncInterest(const Name& prefix, const Interest& interest);
183
184 /**
185 * @brief Callback to handle Sync prefix registration failure
186 *
187 * This method does nothing for now.
188 *
189 * @param prefix The prefix of the sync group.
190 * @param msg The error message.
191 */
192 void
193 onSyncRegisterFailed(const Name& prefix, const std::string& msg);
194
195 /**
196 * @brief Callback to handle Sync Reply
197 *
198 * This method calls validator to validate Sync Reply.
199 * For now, validation is disabled, Logic::onSyncDataValidated is called
200 * directly.
201 *
202 * @param interest The Sync Interest
203 * @param data The reply to the Sync Interest
204 */
205 void
206 onSyncData(const Interest& interest, Data& data);
207
208 /**
209 * @brief Callback to handle reply to Reset Interest.
210 *
211 * This method does nothing, since reply to Reset Interest is not useful for now.
212 *
213 * @param interest The Reset Interest
214 * @param data The reply to the Reset Interest
215 */
216 void
217 onResetData(const Interest& interest, Data& data);
218
219 /**
220 * @brief Callback to handle Sync Interest timeout.
221 *
222 * This method does nothing, since Logic per se handles timeout explicitly.
223 *
224 * @param interest The Sync Interest
225 */
226 void
227 onSyncTimeout(const Interest& interest);
228
229 /**
230 * @brief Callback to invalid Sync Reply.
231 *
232 * This method does nothing but drops the invalid reply.
233 *
234 * @param data The invalid Sync Reply
235 */
236 void
237 onSyncDataValidationFailed(const shared_ptr<const Data>& data);
238
239 /**
240 * @brief Callback to valid Sync Reply.
241 *
242 * This method simply passes the valid reply to processSyncData.
243 *
244 * @param data The valid Sync Reply.
245 */
246 void
247 onSyncDataValidated(const shared_ptr<const Data>& data);
248
249 /**
250 * @brief Process normal Sync Interest
251 *
252 * This method extracts the digest from the incoming Sync Interest,
253 * compares it against current local digest, and process the Sync
254 * Interest according to the comparison result. See docs/design.rst
255 * for more details.
256 *
257 * @param interest The incoming interest
258 * @param isTimedProcessing True if the interest needs an immediate reply,
259 * otherwise hold the interest for a while before
260 * making a reply (to avoid unnecessary recovery)
261 */
262 void
263 processSyncInterest(const shared_ptr<const Interest>& interest,
264 bool isTimedProcessing = false);
265
266 /**
267 * @brief Process reset Sync Interest
268 *
269 * This method simply call Logic::reset()
270 *
271 * @param interest The incoming interest.
272 */
273 void
274 processResetInterest(const Interest& interest);
275
276 /**
277 * @brief Process Sync Reply.
278 *
279 * This method extracts state update information from Sync Reply and applies
280 * it to the Sync Tree and re-express Sync Interest.
281 *
282 * @param name The data name of the Sync Reply.
283 * @param digest The digest in the data name.
284 * @param syncReplyBlock The content of the Sync Reply.
285 */
286 void
287 processSyncData(const Name& name,
288 ndn::ConstBufferPtr digest,
289 const Block& syncReplyBlock);
290
291 /**
292 * @brief Insert state diff into log
293 *
294 * @param diff The diff .
295 * @param previousRoot The root digest before state changes.
296 */
297 void
298 insertToDiffLog(DiffStatePtr diff,
299 ndn::ConstBufferPtr previousRoot);
300
301 /**
302 * @brief Reply to all pending Sync Interests with a particular commit (or diff)
303 *
304 * @param commit The diff.
305 */
306 void
307 satisfyPendingSyncInterests(ConstDiffStatePtr commit);
308
309 /// @brief Helper method to send normal Sync Interest
310 void
311 sendSyncInterest();
312
313 /// @brief Helper method to send reset Sync Interest
314 void
315 sendResetInterest();
316
317 /// @brief Helper method to send Sync Reply
318 void
319 sendSyncData(const Name& name, const State& state);
320
321 /**
322 * @brief Unset reset status
323 *
324 * By invoking this method, one can add its own state into the Sync Tree, thus
325 * jumping out of the reset status
326 */
327 void
328 cancelReset();
329
330 void
331 printDigest(ndn::ConstBufferPtr digest);
332
Yingdi Yucd339022014-11-05 17:51:19 -0800333public:
334 static const ndn::Name DEFAULT_NAME;
335 static const ndn::shared_ptr<ndn::Validator> DEFAULT_VALIDATOR;
336
Yingdi Yuf7ede412014-08-30 20:37:52 -0700337private:
338
339 static const ndn::ConstBufferPtr EMPTY_DIGEST;
340 static const ndn::name::Component RESET_COMPONENT;
341
342 // Communication
343 ndn::Face& m_face;
344 Name m_syncPrefix;
345 const ndn::RegisteredPrefixId* m_syncRegisteredPrefixId;
346 Name m_syncReset;
347 Name m_userPrefix;
348
349 // State
350 Name m_sessionName;
351 SeqNo m_seqNo;
352 State m_state;
353 DiffStateContainer m_log;
354 InterestTable m_interestTable;
355 Name m_outstandingInterestName;
356 const ndn::PendingInterestId* m_outstandingInterestId;
357 bool m_isInReset;
358 bool m_needPeriodReset;
359
360 // Callback
361 UpdateCallback m_onUpdate;
362
363 // Event
364 ndn::Scheduler m_scheduler;
365 ndn::EventId m_delayedInterestProcessingId;
366 ndn::EventId m_reexpressingInterestId;
367 ndn::EventId m_resetInterestId;
368
369 // Timer
370 boost::mt19937 m_randomGenerator;
371 boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_rangeUniformRandom;
372 boost::variate_generator<boost::mt19937&, boost::uniform_int<> > m_reexpressionJitter;
373 /// @brief Timer to send next reset 0 for no reset
374 time::steady_clock::Duration m_resetTimer;
375 /// @brief Timer to cancel reset state
376 time::steady_clock::Duration m_cancelResetTimer;
377 /// @brief Lifetime of reset interest
378 time::milliseconds m_resetInterestLifetime;
379 /// @brief Lifetime of sync interest
380 time::milliseconds m_syncInterestLifetime;
381 /// @brief FreshnessPeriod of SyncReply
382 time::milliseconds m_syncReplyFreshness;
383
Yingdi Yucd339022014-11-05 17:51:19 -0800384 // Security
385 ndn::Name m_signingId;
Yingdi Yuf7ede412014-08-30 20:37:52 -0700386 ndn::KeyChain m_keyChain;
Yingdi Yucd339022014-11-05 17:51:19 -0800387 ndn::shared_ptr<ndn::Validator> m_validator;
Yingdi Yuf7ede412014-08-30 20:37:52 -0700388
389#ifdef _DEBUG
390 int m_instanceId;
391 static int m_instanceCounter;
392#endif
393};
394
395
396} // namespace chronosync
397
398#endif // CHRONOSYNC_LOGIC_HPP