blob: b34673954f654c0d70476f6b5a6481c62836f8eb [file] [log] [blame]
Zhenkai Zhu8d935c82012-03-06 10:44:12 -08001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
3 * Copyright (c) 2012 University of California, Los Angeles
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation;
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 *
18 * Author: Zhenkai Zhu <zhenkai@cs.ucla.edu>
Chaoyi Bian3e1eb162012-04-03 16:59:32 -070019 * Chaoyi Bian <bcy@pku.edu.cn>
Zhenkai Zhu8d935c82012-03-06 10:44:12 -080020 * Alexander Afanasyev <alexander.afanasyev@ucla.edu>
21 */
Chaoyi Bian44fff0c2012-03-07 21:07:22 -080022
Alexander Afanasyevb6cf56e2012-05-29 19:33:49 -070023#ifdef NS3_MODULE
Alexander Afanasyev0ac399e2012-04-27 13:28:28 -070024#include <ns3/ccnx-pit.h>
25#include <ns3/ccnx.h>
Alexander Afanasyevb6cf56e2012-05-29 19:33:49 -070026#endif
Alexander Afanasyev0ac399e2012-04-27 13:28:28 -070027
Chaoyi Bian11f294f2012-03-08 14:28:06 -080028#include "sync-logic.h"
Chaoyi Bian89ee2dc2012-03-09 14:06:01 -080029#include "sync-diff-leaf.h"
30#include "sync-full-leaf.h"
Alexander Afanasyevce001692013-07-14 11:34:41 -070031#include "sync-logging.h"
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -070032#include "sync-state.h"
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070033
Chaoyi Bian89ee2dc2012-03-09 14:06:01 -080034#include <boost/make_shared.hpp>
35#include <boost/foreach.hpp>
Alexander Afanasyev387ac952012-03-11 23:49:27 -070036#include <boost/lexical_cast.hpp>
Zhenkai Zhua5d06d72012-03-09 15:16:24 -080037#include <vector>
Chaoyi Bian44fff0c2012-03-07 21:07:22 -080038
39using namespace std;
40using namespace boost;
Yingdi Yu43e71612013-10-30 22:19:31 -070041using namespace ndn;
Chaoyi Bian44fff0c2012-03-07 21:07:22 -080042
Chaoyi Bianf007f922012-04-09 20:05:37 -070043INIT_LOGGER ("SyncLogic");
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070044
Alexander Afanasyev983b0e92012-04-26 12:44:18 -070045#ifdef NS3_MODULE
46#define GET_RANDOM(var) var.GetValue ()
47#else
48#define GET_RANDOM(var) var ()
49#endif
50
51#define TIME_SECONDS_WITH_JITTER(sec) \
52 (TIME_SECONDS (sec) + TIME_MILLISECONDS (GET_RANDOM (m_reexpressionJitter)))
53
Alexander Afanasyev42612262012-05-05 10:58:37 -070054#define TIME_MILLISECONDS_WITH_JITTER(ms) \
55 (TIME_MILLISECONDS (ms) + TIME_MILLISECONDS (GET_RANDOM (m_reexpressionJitter)))
Alexander Afanasyev983b0e92012-04-26 12:44:18 -070056
57
Chaoyi Bian44fff0c2012-03-07 21:07:22 -080058namespace Sync
59{
60
Yingdi Yu43e71612013-10-30 22:19:31 -070061 SyncLogic::SyncLogic (const Name& syncPrefix,
62 Ptr<SyncPolicyManager> syncPolicyManager,
Yingdi Yu8600a092013-11-01 16:12:31 -070063 Ptr<Wrapper> handler,
Yingdi Yu43e71612013-10-30 22:19:31 -070064 LogicUpdateCallback onUpdate,
65 LogicRemoveCallback onRemove)
66 : m_state (new FullState)
67 , m_syncInterestTable (TIME_SECONDS (m_syncInterestReexpress))
68 , m_syncPrefix (syncPrefix)
69 , m_onUpdate (onUpdate)
70 , m_onRemove (onRemove)
71 , m_perBranch (false)
72 , m_policyManager(syncPolicyManager)
Yingdi Yu8600a092013-11-01 16:12:31 -070073 , m_handler (handler)
Alexander Afanasyev73f7f9a2012-04-09 15:45:47 -070074#ifndef NS3_MODULE
Yingdi Yu43e71612013-10-30 22:19:31 -070075 , m_randomGenerator (static_cast<unsigned int> (std::time (0)))
76 , m_rangeUniformRandom (m_randomGenerator, uniform_int<> (200,1000))
77 , m_reexpressionJitter (m_randomGenerator, uniform_int<> (100,500))
Alexander Afanasyev73f7f9a2012-04-09 15:45:47 -070078#else
Yingdi Yu43e71612013-10-30 22:19:31 -070079 , m_rangeUniformRandom (200,1000)
80 , m_reexpressionJitter (10,500)
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -070081#endif
Yingdi Yu43e71612013-10-30 22:19:31 -070082 , m_recoveryRetransmissionInterval (m_defaultRecoveryRetransmitInterval)
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -070083{
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -070084#ifndef NS3_MODULE
85 // In NS3 module these functions are moved to StartApplication method
Yingdi Yu43e71612013-10-30 22:19:31 -070086
Yingdi Yu43e71612013-10-30 22:19:31 -070087 m_handler->setInterestFilter (m_syncPrefix,
88 bind (&SyncLogic::respondSyncInterest, this, _1));
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -070089
Alexander Afanasyev983b0e92012-04-26 12:44:18 -070090 m_scheduler.schedule (TIME_SECONDS (0), // no need to add jitter
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070091 bind (&SyncLogic::sendSyncInterest, this),
92 REEXPRESSING_INTEREST);
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -070093#endif
Chaoyi Bian44fff0c2012-03-07 21:07:22 -080094}
95
Yingdi Yu43e71612013-10-30 22:19:31 -070096SyncLogic::SyncLogic (const Name& syncPrefix,
97 Ptr<SyncPolicyManager> syncPolicyManager,
Yingdi Yu8600a092013-11-01 16:12:31 -070098 Ptr<Wrapper> handler,
Zhenkai Zhub9f19592012-10-16 14:27:38 -070099 LogicPerBranchCallback onUpdateBranch)
100 : m_state (new FullState)
101 , m_syncInterestTable (TIME_SECONDS (m_syncInterestReexpress))
102 , m_syncPrefix (syncPrefix)
103 , m_onUpdateBranch (onUpdateBranch)
104 , m_perBranch(true)
Yingdi Yu43e71612013-10-30 22:19:31 -0700105 , m_policyManager(syncPolicyManager)
Yingdi Yu8600a092013-11-01 16:12:31 -0700106 , m_handler (handler)
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700107#ifndef NS3_MODULE
108 , m_randomGenerator (static_cast<unsigned int> (std::time (0)))
109 , m_rangeUniformRandom (m_randomGenerator, uniform_int<> (200,1000))
110 , m_reexpressionJitter (m_randomGenerator, uniform_int<> (100,500))
111#else
112 , m_rangeUniformRandom (200,1000)
113 , m_reexpressionJitter (10,500)
114#endif
Alexander Afanasyevce001692013-07-14 11:34:41 -0700115 , m_recoveryRetransmissionInterval (m_defaultRecoveryRetransmitInterval)
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700116{
117#ifndef NS3_MODULE
118 // In NS3 module these functions are moved to StartApplication method
119
Yingdi Yu43e71612013-10-30 22:19:31 -0700120 m_handler->setInterestFilter (m_syncPrefix,
Yingdi Yu8600a092013-11-01 16:12:31 -0700121 bind (&SyncLogic::respondSyncInterest, this, _1));
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700122
123 m_scheduler.schedule (TIME_SECONDS (0), // no need to add jitter
124 bind (&SyncLogic::sendSyncInterest, this),
125 REEXPRESSING_INTEREST);
126#endif
127}
128
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800129SyncLogic::~SyncLogic ()
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800130{
Yingdi Yu43e71612013-10-30 22:19:31 -0700131 m_handler->clearInterestFilter (Name(m_syncPrefix));
Yingdi Yu479e1172013-11-06 16:36:19 -0800132 m_handler->shutdown();
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700133}
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700134
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700135#ifdef NS3_MODULE
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700136void
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700137SyncLogic::StartApplication ()
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700138{
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700139 m_ccnxHandle->SetNode (GetNode ());
140 m_ccnxHandle->StartApplication ();
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700141
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700142 m_ccnxHandle->setInterestFilter (m_syncPrefix,
143 bind (&SyncLogic::respondSyncInterest, this, _1));
144
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700145 m_scheduler.schedule (TIME_SECONDS (0), // need to send first interests at exactly the same time
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700146 bind (&SyncLogic::sendSyncInterest, this),
147 REEXPRESSING_INTEREST);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700148}
149
150void
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700151SyncLogic::StopApplication ()
152{
Alexander Afanasyev434f1612012-04-21 21:19:15 -0700153 m_ccnxHandle->clearInterestFilter (m_syncPrefix);
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700154 m_ccnxHandle->StopApplication ();
Alexander Afanasyev40942f42012-04-21 20:53:16 -0700155 m_scheduler.cancel (REEXPRESSING_INTEREST);
156 m_scheduler.cancel (DELAYED_INTEREST_PROCESSING);
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700157}
158#endif
159
Zhenkai Zhueb1d8652012-12-23 15:25:39 -0800160void
161SyncLogic::stop()
162{
Yingdi Yu43e71612013-10-30 22:19:31 -0700163 m_handler->clearInterestFilter (Name(m_syncPrefix));
Zhenkai Zhueb1d8652012-12-23 15:25:39 -0800164 m_scheduler.cancel (REEXPRESSING_INTEREST);
165 m_scheduler.cancel (DELAYED_INTEREST_PROCESSING);
166}
167
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700168/**
169 * Two types of intersts
170 *
171 * Normal name: .../<hash>
172 * Recovery name: .../recovery/<hash>
173 */
174boost::tuple<DigestConstPtr, std::string>
175SyncLogic::convertNameToDigestAndType (const std::string &name)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700176{
Yingdi Yu43e71612013-10-30 22:19:31 -0700177 BOOST_ASSERT (name.find (m_syncPrefix.toUri()) == 0);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700178
Yingdi Yu43e71612013-10-30 22:19:31 -0700179 string hash = name.substr (m_syncPrefix.toUri().size (), name.size ()-m_syncPrefix.toUri().size ());
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700180 if (hash[0] == '/')
181 hash = hash.substr (1, hash.size ()-1);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700182 string interestType = "normal";
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700183
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700184 size_t pos = hash.find ('/');
185 if (pos != string::npos)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700186 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700187 interestType = hash.substr (0, pos);
188 hash = hash.substr (pos + 1);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700189 }
190
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700191 _LOG_TRACE (hash << ", " << interestType);
192
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700193 DigestPtr digest = make_shared<Digest> ();
194 istringstream is (hash);
195 is >> *digest;
196
197 return make_tuple (digest, interestType);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700198}
199
200void
Yingdi Yu43e71612013-10-30 22:19:31 -0700201SyncLogic::respondSyncInterest (ndn::Ptr<ndn::Interest> interest)
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700202{
Yingdi Yu43e71612013-10-30 22:19:31 -0700203 _LOG_DEBUG("respondSyncInterest: " << interest->getName().toUri());
204 string name = interest->getName().toUri();
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700205 try
206 {
207 _LOG_TRACE ("<< I " << name);
208
209 DigestConstPtr digest;
210 string type;
211 tie (digest, type) = convertNameToDigestAndType (name);
212
213 if (type == "normal") // kind of ineffective...
214 {
215 processSyncInterest (name, digest);
216 }
217 else if (type == "recovery")
218 {
219 processSyncRecoveryInterest (name, digest);
220 }
221 }
222 catch (Error::DigestCalculationError &e)
223 {
224 _LOG_TRACE ("Something fishy happened...");
225 // log error. ignoring it for now, later we should log it
226 return ;
227 }
228}
229
230void
Yingdi Yu43e71612013-10-30 22:19:31 -0700231SyncLogic::respondSyncData (Ptr<Data> data)
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700232{
Yingdi Yu43e71612013-10-30 22:19:31 -0700233 string name = data->getName().toUri();
234 const char *wireData = data->content().buf();
235 size_t len = data->content().size();
236
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700237 try
238 {
239 _LOG_TRACE ("<< D " << name);
240
241 DigestConstPtr digest;
242 string type;
243 tie (digest, type) = convertNameToDigestAndType (name);
244
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700245 if (type == "normal")
246 {
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700247 processSyncData (name, digest, wireData, len);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700248 }
249 else
250 {
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700251 // timer is always restarted when we schedule recovery
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700252 m_scheduler.cancel (REEXPRESSING_RECOVERY_INTEREST);
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700253 processSyncData (name, digest, wireData, len);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700254 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700255 }
256 catch (Error::DigestCalculationError &e)
257 {
258 _LOG_TRACE ("Something fishy happened...");
259 // log error. ignoring it for now, later we should log it
260 return;
261 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700262}
263
Yingdi Yu43e71612013-10-30 22:19:31 -0700264void
265SyncLogic::onSyncDataTimeout(Ptr<Closure> closure, Ptr<ndn::Interest> interest, int retry)
266{
267 if(retry > 0)
268 {
269 Ptr<Closure> newClosure = Ptr<Closure>(new Closure(closure->m_dataCallback,
270 boost::bind(&SyncLogic::onSyncDataTimeout,
271 this,
272 _1,
273 _2,
274 retry - 1),
275 closure->m_unverifiedCallback,
276 closure->m_stepCount)
277 );
278 m_handler->sendInterest(interest, newClosure);
279 }
280}
281
282void
283SyncLogic::onSyncDataUnverified()
284{}
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700285
286void
287SyncLogic::processSyncInterest (const std::string &name, DigestConstPtr digest, bool timedProcessing/*=false*/)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700288{
Yingdi Yu43e71612013-10-30 22:19:31 -0700289 _LOG_DEBUG("processSyncInterest");
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700290 DigestConstPtr rootDigest;
291 {
292 recursive_mutex::scoped_lock lock (m_stateMutex);
293 rootDigest = m_state->getDigest();
294 }
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700295
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700296 // Special case when state is not empty and we have received request with zero-root digest
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700297 if (digest->isZero () && !rootDigest->isZero ())
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700298 {
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700299
300 SyncStateMsg ssm;
301 {
302 recursive_mutex::scoped_lock lock (m_stateMutex);
303 ssm << (*m_state);
304 }
305 sendSyncData (name, digest, ssm);
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700306 return;
307 }
Alexander Afanasyev763855a2012-03-13 14:17:37 -0700308
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700309 if (*rootDigest == *digest)
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700310 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700311 _LOG_TRACE ("processSyncInterest (): Same state. Adding to PIT");
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700312 m_syncInterestTable.insert (digest, name, false);
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700313 return;
314 }
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700315
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700316 DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
317
318 if (stateInDiffLog != m_log.end ())
319 {
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700320 DiffStateConstPtr stateDiff = (*stateInDiffLog)->diff ();
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700321
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700322 sendSyncData (name, digest, stateDiff);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700323 return;
324 }
325
326 if (!timedProcessing)
327 {
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700328 bool exists = m_syncInterestTable.insert (digest, name, true);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700329 if (exists) // somebody else replied, so restart random-game timer
Alexander Afanasyev3a229132012-04-25 15:07:26 -0700330 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700331 _LOG_DEBUG ("Unknown digest, but somebody may have already replied, so restart our timer");
332 m_scheduler.cancel (DELAYED_INTEREST_PROCESSING);
Alexander Afanasyev3a229132012-04-25 15:07:26 -0700333 }
Alexander Afanasyev03793b42012-05-01 13:03:07 -0700334
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700335 uint32_t waitDelay = GET_RANDOM (m_rangeUniformRandom);
336 _LOG_DEBUG ("Digest is not in the log. Schedule processing after small delay: " << waitDelay << "ms");
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700337
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700338 m_scheduler.schedule (TIME_MILLISECONDS (waitDelay),
339 bind (&SyncLogic::processSyncInterest, this, name, digest, true),
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700340 DELAYED_INTEREST_PROCESSING);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700341 }
342 else
343 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700344 _LOG_TRACE (" (timed processing)");
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700345
346 m_recoveryRetransmissionInterval = m_defaultRecoveryRetransmitInterval;
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700347 sendSyncRecoveryInterests (digest);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700348 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800349}
350
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800351void
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700352SyncLogic::processSyncData (const std::string &name, DigestConstPtr digest, const char *wireData, size_t len)
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800353{
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700354 DiffStatePtr diffLog = make_shared<DiffState> ();
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700355 bool ownInterestSatisfied = false;
Alexander Afanasyeve4e2bf72012-03-12 12:44:54 -0700356
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700357 try
358 {
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700359
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700360 m_syncInterestTable.remove (name); // Remove satisfied interest from PIT
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700361
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700362 ownInterestSatisfied = (name == m_outstandingInterestName);
363
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700364 DiffState diff;
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700365 SyncStateMsg msg;
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700366 if (!msg.ParseFromArray(wireData, len) || !msg.IsInitialized())
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700367 {
368 //Throw
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700369 BOOST_THROW_EXCEPTION (Error::SyncStateMsgDecodingFailure () );
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700370 }
371 msg >> diff;
372
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700373 vector<MissingDataInfo> v;
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700374 BOOST_FOREACH (LeafConstPtr leaf, diff.getLeaves().get<ordered>())
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700375 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700376 DiffLeafConstPtr diffLeaf = dynamic_pointer_cast<const DiffLeaf> (leaf);
377 BOOST_ASSERT (diffLeaf != 0);
378
379 NameInfoConstPtr info = diffLeaf->getInfo();
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700380 if (diffLeaf->getOperation() == UPDATE)
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700381 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700382 SeqNo seq = diffLeaf->getSeq();
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700383
384 bool inserted = false;
385 bool updated = false;
386 SeqNo oldSeq;
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700387 {
388 recursive_mutex::scoped_lock lock (m_stateMutex);
389 tie (inserted, updated, oldSeq) = m_state->update (info, seq);
390 }
Chaoyi Bian89ee2dc2012-03-09 14:06:01 -0800391
Alexander Afanasyevd4adce52012-03-13 13:59:39 -0700392 if (inserted || updated)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700393 {
394 diffLog->update (info, seq);
Zhenkai Zhu68f04d52012-06-05 14:07:41 -0700395 if (!oldSeq.isValid())
396 {
397 oldSeq = SeqNo(seq.getSession(), 0);
398 }
399 else
400 {
401 ++oldSeq;
402 }
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700403 // there is no need for application to process update on forwarder node
404 if (info->toString() != forwarderPrefix)
405 {
406 MissingDataInfo mdi = {info->toString(), oldSeq, seq};
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700407 if (m_perBranch)
408 {
409 ostringstream interestName;
410 interestName << mdi.prefix << "/" << mdi.high.getSession() << "/" << mdi.high.getSeq();
411 m_onUpdateBranch(interestName.str());
412 }
413 else
414 {
415 v.push_back(mdi);
416 }
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700417 }
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700418 }
419 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700420 else if (diffLeaf->getOperation() == REMOVE)
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700421 {
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700422 recursive_mutex::scoped_lock lock (m_stateMutex);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700423 if (m_state->remove (info))
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700424 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700425 diffLog->remove (info);
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700426 if (!m_perBranch)
427 {
428 m_onRemove (info->toString ());
429 }
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700430 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700431 }
432 else
433 {
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700434 }
435 }
436
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700437 if (!v.empty())
438 {
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700439 if (!m_perBranch)
440 {
441 m_onUpdate(v);
442 }
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700443 }
444
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700445 insertToDiffLog (diffLog);
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700446 }
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700447 catch (Error::SyncStateMsgDecodingFailure &e)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700448 {
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700449 _LOG_TRACE ("Something really fishy happened during state decoding " <<
450 diagnostic_information (e));
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700451 diffLog.reset ();
452 // don't do anything
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700453 }
454
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700455 if ((diffLog != 0 && diffLog->getLeaves ().size () > 0) ||
456 ownInterestSatisfied)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700457 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700458 // Do it only if everything went fine and state changed
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700459
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700460 // this is kind of wrong
461 // satisfyPendingSyncInterests (diffLog); // if there are interests in PIT, there is a point to satisfy them using new state
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700462
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700463 // if state has changed, then it is safe to express a new interest
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700464 m_scheduler.cancel (REEXPRESSING_INTEREST);
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700465 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (0),
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700466 bind (&SyncLogic::sendSyncInterest, this),
467 REEXPRESSING_INTEREST);
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700468 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800469}
470
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800471void
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700472SyncLogic::processSyncRecoveryInterest (const std::string &name, DigestConstPtr digest)
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800473{
Yingdi Yu43e71612013-10-30 22:19:31 -0700474 _LOG_DEBUG("processSyncRecoveryInterest");
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700475 DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
476
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700477 if (stateInDiffLog == m_log.end ())
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700478 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700479 _LOG_TRACE ("Could not find " << *digest << " in digest log");
480 return;
481 }
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700482
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700483 SyncStateMsg ssm;
484 {
485 recursive_mutex::scoped_lock lock (m_stateMutex);
486 ssm << (*m_state);
487 }
488 sendSyncData (name, digest, ssm);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700489}
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700490
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700491void
492SyncLogic::satisfyPendingSyncInterests (DiffStateConstPtr diffLog)
493{
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700494 DiffStatePtr fullStateLog = make_shared<DiffState> ();
495 {
496 recursive_mutex::scoped_lock lock (m_stateMutex);
497 BOOST_FOREACH (LeafConstPtr leaf, m_state->getLeaves ()/*.get<timed> ()*/)
498 {
499 fullStateLog->update (leaf->getInfo (), leaf->getSeq ());
500 /// @todo Impose limit on how many state info should be send out
501 }
502 }
503
504 try
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800505 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700506 uint32_t counter = 0;
507 while (m_syncInterestTable.size () > 0)
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700508 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700509 Interest interest = m_syncInterestTable.pop ();
510
511 if (!interest.m_unknown)
512 {
513 _LOG_TRACE (">> D " << interest.m_name);
514 sendSyncData (interest.m_name, interest.m_digest, diffLog);
515 }
516 else
517 {
518 _LOG_TRACE (">> D (unknown)" << interest.m_name);
519 sendSyncData (interest.m_name, interest.m_digest, fullStateLog);
520 }
521 counter ++;
Alexander Afanasyevf07ab352012-03-13 12:57:46 -0700522 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700523 _LOG_DEBUG ("Satisfied " << counter << " pending interests");
Alexander Afanasyevf07ab352012-03-13 12:57:46 -0700524 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700525 catch (Error::InterestTableIsEmpty &e)
526 {
527 // ok. not really an error
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800528 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800529}
530
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800531void
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700532SyncLogic::insertToDiffLog (DiffStatePtr diffLog)
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700533{
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700534 diffLog->setDigest (m_state->getDigest());
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700535 if (m_log.size () > 0)
536 {
537 m_log.get<sequenced> ().front ()->setNext (diffLog);
538 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700539 m_log.erase (m_state->getDigest()); // remove diff state with the same digest. next pointers are still valid
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700540 /// @todo Optimization
Alexander Afanasyev7df73332012-03-15 12:31:49 -0700541 m_log.get<sequenced> ().push_front (diffLog);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700542}
543
544void
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700545SyncLogic::addLocalNames (const string &prefix, uint32_t session, uint32_t seq)
546{
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700547 DiffStatePtr diff;
548 {
549 //cout << "Add local names" <<endl;
550 recursive_mutex::scoped_lock lock (m_stateMutex);
551 NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix);
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700552
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700553 _LOG_DEBUG ("addLocalNames (): old state " << *m_state->getDigest ());
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700554
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700555 SeqNo seqN (session, seq);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700556 m_state->update(info, seqN);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700557
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700558 _LOG_DEBUG ("addLocalNames (): new state " << *m_state->getDigest ());
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700559
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700560 diff = make_shared<DiffState>();
561 diff->update(info, seqN);
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700562 insertToDiffLog (diff);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700563 }
564
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700565 // _LOG_DEBUG ("PIT size: " << m_syncInterestTable.size ());
566 satisfyPendingSyncInterests (diff);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700567}
568
569void
Alexander Afanasyevd91497c2012-03-12 15:39:30 -0700570SyncLogic::remove(const string &prefix)
571{
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700572 DiffStatePtr diff;
573 {
574 recursive_mutex::scoped_lock lock (m_stateMutex);
575 NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700576 m_state->remove(info);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700577
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700578 // increment the sequence number for the forwarder node
579 NameInfoConstPtr forwarderInfo = StdNameInfo::FindOrCreate(forwarderPrefix);
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700580
Alexander Afanasyev7e1986f2012-10-04 10:21:10 -0700581 LeafContainer::iterator item = m_state->getLeaves ().find (forwarderInfo);
582 SeqNo seqNo (0);
583 if (item != m_state->getLeaves ().end ())
584 {
585 seqNo = (*item)->getSeq ();
586 ++seqNo;
587 }
588 m_state->update (forwarderInfo, seqNo);
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700589
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700590 diff = make_shared<DiffState>();
591 diff->remove(info);
Alexander Afanasyev7e1986f2012-10-04 10:21:10 -0700592 diff->update(forwarderInfo, seqNo);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700593
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700594 insertToDiffLog (diff);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700595 }
596
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700597 satisfyPendingSyncInterests (diff);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700598}
599
600void
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800601SyncLogic::sendSyncInterest ()
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800602{
Yingdi Yu43e71612013-10-30 22:19:31 -0700603 _LOG_DEBUG("sendSyncInterest");
Alexander Afanasyev172d2b72012-03-08 23:43:39 -0800604 ostringstream os;
Chaoyi Bian89ee2dc2012-03-09 14:06:01 -0800605
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700606 {
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700607 recursive_mutex::scoped_lock lock (m_stateMutex);
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700608
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700609 os << m_syncPrefix << "/" << *m_state->getDigest();
610 m_outstandingInterestName = os.str ();
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700611 _LOG_TRACE (">> I " << os.str ());
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700612 }
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700613
Yingdi Yu43e71612013-10-30 22:19:31 -0700614 _LOG_DEBUG("sendSyncInterest: " << os.str());
615
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700616 m_scheduler.cancel (REEXPRESSING_INTEREST);
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700617 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (m_syncInterestReexpress),
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700618 bind (&SyncLogic::sendSyncInterest, this),
619 REEXPRESSING_INTEREST);
Yingdi Yu43e71612013-10-30 22:19:31 -0700620
621 Ptr<ndn::Interest> interestPtr = Ptr<ndn::Interest>(new ndn::Interest(os.str()));
622 Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&SyncLogic::respondSyncData,
623 this,
624 _1),
625 boost::bind(&SyncLogic::onSyncDataTimeout,
626 this,
627 _1,
628 _2,
629 0),
630 boost::bind(&SyncLogic::onSyncDataUnverified,
631 this)));
632 m_handler->sendInterest(interestPtr, closure);
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800633}
634
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700635void
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700636SyncLogic::sendSyncRecoveryInterests (DigestConstPtr digest)
637{
638 ostringstream os;
639 os << m_syncPrefix << "/recovery/" << *digest;
640 _LOG_TRACE (">> I " << os.str ());
641
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700642 TimeDuration nextRetransmission = TIME_MILLISECONDS_WITH_JITTER (m_recoveryRetransmissionInterval);
643 m_recoveryRetransmissionInterval <<= 1;
644
645 m_scheduler.cancel (REEXPRESSING_RECOVERY_INTEREST);
646 if (m_recoveryRetransmissionInterval < 100*1000) // <100 seconds
647 {
648 m_scheduler.schedule (nextRetransmission,
649 bind (&SyncLogic::sendSyncRecoveryInterests, this, digest),
650 REEXPRESSING_RECOVERY_INTEREST);
651 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700652
Yingdi Yu43e71612013-10-30 22:19:31 -0700653 Ptr<ndn::Interest> interestPtr = Ptr<ndn::Interest>(new ndn::Interest(os.str()));
654 Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&SyncLogic::respondSyncData,
655 this,
656 _1),
657 boost::bind(&SyncLogic::onSyncDataTimeout,
658 this,
659 _1,
660 _2,
661 0),
662 boost::bind(&SyncLogic::onSyncDataUnverified,
663 this)));
664 m_handler->sendInterest (interestPtr, closure);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700665}
666
667
668void
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700669SyncLogic::sendSyncData (const std::string &name, DigestConstPtr digest, StateConstPtr state)
670{
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700671 SyncStateMsg msg;
672 msg << (*state);
673 sendSyncData(name, digest, msg);
674}
675
676// pass in state msg instead of state, so that there is no need to lock the state until
677// this function returns
678void
679SyncLogic::sendSyncData (const std::string &name, DigestConstPtr digest, SyncStateMsg &ssm)
680{
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700681 _LOG_TRACE (">> D " << name);
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700682 int size = ssm.ByteSize();
683 char *wireData = new char[size];
684 ssm.SerializeToArray(wireData, size);
Yingdi Yu43e71612013-10-30 22:19:31 -0700685 Blob blob(wireData, size);
686 Name dataName(name);
687 Name signingIdentity = m_policyManager->inferSigningIdentity(dataName);
688 m_handler->publishDataByIdentity (dataName,
689 blob,
690 signingIdentity,
691 m_syncResponseFreshness); // in NS-3 it doesn't have any effect... yet
Chaoyi Bian6665d5a2012-06-07 14:16:44 -0700692 delete []wireData;
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700693
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700694 // checking if our own interest got satisfied
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700695 bool satisfiedOwnInterest = false;
696 {
697 recursive_mutex::scoped_lock lock (m_stateMutex);
698 satisfiedOwnInterest = (m_outstandingInterestName == name);
699 }
700
701 if (satisfiedOwnInterest)
702 {
703 _LOG_TRACE ("Satisfied our own Interest. Re-expressing (hopefully with a new digest)");
704
705 m_scheduler.cancel (REEXPRESSING_INTEREST);
706 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (0),
707 bind (&SyncLogic::sendSyncInterest, this),
708 REEXPRESSING_INTEREST);
709 }
710}
711
Zhenkai Zhue5660932012-06-04 15:25:20 -0700712string
713SyncLogic::getRootDigest()
714{
715 ostringstream os;
716 recursive_mutex::scoped_lock lock (m_stateMutex);
717 os << *m_state->getDigest();
718 return os.str();
719}
720
Alexander Afanasyev80237382012-10-04 10:20:47 -0700721size_t
722SyncLogic::getNumberOfBranches () const
723{
724 recursive_mutex::scoped_lock lock (m_stateMutex);
725 return m_state->getLeaves ().size ();
726}
727
Alexander Afanasyev5548c042012-10-04 19:10:09 -0700728void
729SyncLogic::printState () const
730{
731 recursive_mutex::scoped_lock lock (m_stateMutex);
732
733 BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
734 {
735 std::cout << *leaf << std::endl;
736 }
737}
738
Zhenkai Zhud5aec4b2012-10-09 12:01:19 -0700739std::map<std::string, bool>
740SyncLogic::getBranchPrefixes() const
741{
742 recursive_mutex::scoped_lock lock (m_stateMutex);
743
744 std::map<std::string, bool> m;
745
746 BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
747 {
748 std::string prefix = leaf->getInfo()->toString();
749 // do not return forwarder prefix
750 if (prefix != forwarderPrefix)
751 {
752 m.insert(pair<std::string, bool>(prefix, false));
753 }
754 }
755
756 return m;
757}
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700758
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800759}