blob: f40a36ccd0942710d6c6e796a64bbaddbe2a6040 [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));
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700132}
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700133
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700134#ifdef NS3_MODULE
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700135void
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700136SyncLogic::StartApplication ()
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700137{
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700138 m_ccnxHandle->SetNode (GetNode ());
139 m_ccnxHandle->StartApplication ();
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700140
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700141 m_ccnxHandle->setInterestFilter (m_syncPrefix,
142 bind (&SyncLogic::respondSyncInterest, this, _1));
143
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700144 m_scheduler.schedule (TIME_SECONDS (0), // need to send first interests at exactly the same time
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700145 bind (&SyncLogic::sendSyncInterest, this),
146 REEXPRESSING_INTEREST);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700147}
148
149void
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700150SyncLogic::StopApplication ()
151{
Alexander Afanasyev434f1612012-04-21 21:19:15 -0700152 m_ccnxHandle->clearInterestFilter (m_syncPrefix);
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700153 m_ccnxHandle->StopApplication ();
Alexander Afanasyev40942f42012-04-21 20:53:16 -0700154 m_scheduler.cancel (REEXPRESSING_INTEREST);
155 m_scheduler.cancel (DELAYED_INTEREST_PROCESSING);
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700156}
157#endif
158
Zhenkai Zhueb1d8652012-12-23 15:25:39 -0800159void
160SyncLogic::stop()
161{
Yingdi Yu43e71612013-10-30 22:19:31 -0700162 m_handler->clearInterestFilter (Name(m_syncPrefix));
Zhenkai Zhueb1d8652012-12-23 15:25:39 -0800163 m_scheduler.cancel (REEXPRESSING_INTEREST);
164 m_scheduler.cancel (DELAYED_INTEREST_PROCESSING);
165}
166
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700167/**
168 * Two types of intersts
169 *
170 * Normal name: .../<hash>
171 * Recovery name: .../recovery/<hash>
172 */
173boost::tuple<DigestConstPtr, std::string>
174SyncLogic::convertNameToDigestAndType (const std::string &name)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700175{
Yingdi Yu43e71612013-10-30 22:19:31 -0700176 BOOST_ASSERT (name.find (m_syncPrefix.toUri()) == 0);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700177
Yingdi Yu43e71612013-10-30 22:19:31 -0700178 string hash = name.substr (m_syncPrefix.toUri().size (), name.size ()-m_syncPrefix.toUri().size ());
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700179 if (hash[0] == '/')
180 hash = hash.substr (1, hash.size ()-1);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700181 string interestType = "normal";
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700182
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700183 size_t pos = hash.find ('/');
184 if (pos != string::npos)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700185 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700186 interestType = hash.substr (0, pos);
187 hash = hash.substr (pos + 1);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700188 }
189
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700190 _LOG_TRACE (hash << ", " << interestType);
191
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700192 DigestPtr digest = make_shared<Digest> ();
193 istringstream is (hash);
194 is >> *digest;
195
196 return make_tuple (digest, interestType);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700197}
198
199void
Yingdi Yu43e71612013-10-30 22:19:31 -0700200SyncLogic::respondSyncInterest (ndn::Ptr<ndn::Interest> interest)
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700201{
Yingdi Yu43e71612013-10-30 22:19:31 -0700202 _LOG_DEBUG("respondSyncInterest: " << interest->getName().toUri());
203 string name = interest->getName().toUri();
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700204 try
205 {
206 _LOG_TRACE ("<< I " << name);
207
208 DigestConstPtr digest;
209 string type;
210 tie (digest, type) = convertNameToDigestAndType (name);
211
212 if (type == "normal") // kind of ineffective...
213 {
214 processSyncInterest (name, digest);
215 }
216 else if (type == "recovery")
217 {
218 processSyncRecoveryInterest (name, digest);
219 }
220 }
221 catch (Error::DigestCalculationError &e)
222 {
223 _LOG_TRACE ("Something fishy happened...");
224 // log error. ignoring it for now, later we should log it
225 return ;
226 }
227}
228
229void
Yingdi Yu43e71612013-10-30 22:19:31 -0700230SyncLogic::respondSyncData (Ptr<Data> data)
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700231{
Yingdi Yu43e71612013-10-30 22:19:31 -0700232 string name = data->getName().toUri();
233 const char *wireData = data->content().buf();
234 size_t len = data->content().size();
235
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700236 try
237 {
238 _LOG_TRACE ("<< D " << name);
239
240 DigestConstPtr digest;
241 string type;
242 tie (digest, type) = convertNameToDigestAndType (name);
243
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700244 if (type == "normal")
245 {
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700246 processSyncData (name, digest, wireData, len);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700247 }
248 else
249 {
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700250 // timer is always restarted when we schedule recovery
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700251 m_scheduler.cancel (REEXPRESSING_RECOVERY_INTEREST);
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700252 processSyncData (name, digest, wireData, len);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700253 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700254 }
255 catch (Error::DigestCalculationError &e)
256 {
257 _LOG_TRACE ("Something fishy happened...");
258 // log error. ignoring it for now, later we should log it
259 return;
260 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700261}
262
Yingdi Yu43e71612013-10-30 22:19:31 -0700263void
264SyncLogic::onSyncDataTimeout(Ptr<Closure> closure, Ptr<ndn::Interest> interest, int retry)
265{
266 if(retry > 0)
267 {
268 Ptr<Closure> newClosure = Ptr<Closure>(new Closure(closure->m_dataCallback,
269 boost::bind(&SyncLogic::onSyncDataTimeout,
270 this,
271 _1,
272 _2,
273 retry - 1),
274 closure->m_unverifiedCallback,
275 closure->m_stepCount)
276 );
277 m_handler->sendInterest(interest, newClosure);
278 }
279}
280
281void
282SyncLogic::onSyncDataUnverified()
283{}
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700284
285void
286SyncLogic::processSyncInterest (const std::string &name, DigestConstPtr digest, bool timedProcessing/*=false*/)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700287{
Yingdi Yu43e71612013-10-30 22:19:31 -0700288 _LOG_DEBUG("processSyncInterest");
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700289 DigestConstPtr rootDigest;
290 {
291 recursive_mutex::scoped_lock lock (m_stateMutex);
292 rootDigest = m_state->getDigest();
293 }
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700294
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700295 // Special case when state is not empty and we have received request with zero-root digest
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700296 if (digest->isZero () && !rootDigest->isZero ())
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700297 {
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700298
299 SyncStateMsg ssm;
300 {
301 recursive_mutex::scoped_lock lock (m_stateMutex);
302 ssm << (*m_state);
303 }
304 sendSyncData (name, digest, ssm);
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700305 return;
306 }
Alexander Afanasyev763855a2012-03-13 14:17:37 -0700307
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700308 if (*rootDigest == *digest)
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700309 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700310 _LOG_TRACE ("processSyncInterest (): Same state. Adding to PIT");
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700311 m_syncInterestTable.insert (digest, name, false);
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700312 return;
313 }
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700314
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700315 DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
316
317 if (stateInDiffLog != m_log.end ())
318 {
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700319 DiffStateConstPtr stateDiff = (*stateInDiffLog)->diff ();
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700320
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700321 sendSyncData (name, digest, stateDiff);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700322 return;
323 }
324
325 if (!timedProcessing)
326 {
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700327 bool exists = m_syncInterestTable.insert (digest, name, true);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700328 if (exists) // somebody else replied, so restart random-game timer
Alexander Afanasyev3a229132012-04-25 15:07:26 -0700329 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700330 _LOG_DEBUG ("Unknown digest, but somebody may have already replied, so restart our timer");
331 m_scheduler.cancel (DELAYED_INTEREST_PROCESSING);
Alexander Afanasyev3a229132012-04-25 15:07:26 -0700332 }
Alexander Afanasyev03793b42012-05-01 13:03:07 -0700333
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700334 uint32_t waitDelay = GET_RANDOM (m_rangeUniformRandom);
335 _LOG_DEBUG ("Digest is not in the log. Schedule processing after small delay: " << waitDelay << "ms");
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700336
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700337 m_scheduler.schedule (TIME_MILLISECONDS (waitDelay),
338 bind (&SyncLogic::processSyncInterest, this, name, digest, true),
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700339 DELAYED_INTEREST_PROCESSING);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700340 }
341 else
342 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700343 _LOG_TRACE (" (timed processing)");
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700344
345 m_recoveryRetransmissionInterval = m_defaultRecoveryRetransmitInterval;
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700346 sendSyncRecoveryInterests (digest);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700347 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800348}
349
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800350void
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700351SyncLogic::processSyncData (const std::string &name, DigestConstPtr digest, const char *wireData, size_t len)
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800352{
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700353 DiffStatePtr diffLog = make_shared<DiffState> ();
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700354 bool ownInterestSatisfied = false;
Alexander Afanasyeve4e2bf72012-03-12 12:44:54 -0700355
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700356 try
357 {
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700358
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700359 m_syncInterestTable.remove (name); // Remove satisfied interest from PIT
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700360
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700361 ownInterestSatisfied = (name == m_outstandingInterestName);
362
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700363 DiffState diff;
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700364 SyncStateMsg msg;
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700365 if (!msg.ParseFromArray(wireData, len) || !msg.IsInitialized())
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700366 {
367 //Throw
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700368 BOOST_THROW_EXCEPTION (Error::SyncStateMsgDecodingFailure () );
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700369 }
370 msg >> diff;
371
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700372 vector<MissingDataInfo> v;
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700373 BOOST_FOREACH (LeafConstPtr leaf, diff.getLeaves().get<ordered>())
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700374 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700375 DiffLeafConstPtr diffLeaf = dynamic_pointer_cast<const DiffLeaf> (leaf);
376 BOOST_ASSERT (diffLeaf != 0);
377
378 NameInfoConstPtr info = diffLeaf->getInfo();
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700379 if (diffLeaf->getOperation() == UPDATE)
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700380 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700381 SeqNo seq = diffLeaf->getSeq();
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700382
383 bool inserted = false;
384 bool updated = false;
385 SeqNo oldSeq;
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700386 {
387 recursive_mutex::scoped_lock lock (m_stateMutex);
388 tie (inserted, updated, oldSeq) = m_state->update (info, seq);
389 }
Chaoyi Bian89ee2dc2012-03-09 14:06:01 -0800390
Alexander Afanasyevd4adce52012-03-13 13:59:39 -0700391 if (inserted || updated)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700392 {
393 diffLog->update (info, seq);
Zhenkai Zhu68f04d52012-06-05 14:07:41 -0700394 if (!oldSeq.isValid())
395 {
396 oldSeq = SeqNo(seq.getSession(), 0);
397 }
398 else
399 {
400 ++oldSeq;
401 }
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700402 // there is no need for application to process update on forwarder node
403 if (info->toString() != forwarderPrefix)
404 {
405 MissingDataInfo mdi = {info->toString(), oldSeq, seq};
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700406 if (m_perBranch)
407 {
408 ostringstream interestName;
409 interestName << mdi.prefix << "/" << mdi.high.getSession() << "/" << mdi.high.getSeq();
410 m_onUpdateBranch(interestName.str());
411 }
412 else
413 {
414 v.push_back(mdi);
415 }
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700416 }
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700417 }
418 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700419 else if (diffLeaf->getOperation() == REMOVE)
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700420 {
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700421 recursive_mutex::scoped_lock lock (m_stateMutex);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700422 if (m_state->remove (info))
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700423 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700424 diffLog->remove (info);
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700425 if (!m_perBranch)
426 {
427 m_onRemove (info->toString ());
428 }
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700429 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700430 }
431 else
432 {
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700433 }
434 }
435
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700436 if (!v.empty())
437 {
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700438 if (!m_perBranch)
439 {
440 m_onUpdate(v);
441 }
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700442 }
443
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700444 insertToDiffLog (diffLog);
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700445 }
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700446 catch (Error::SyncStateMsgDecodingFailure &e)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700447 {
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700448 _LOG_TRACE ("Something really fishy happened during state decoding " <<
449 diagnostic_information (e));
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700450 diffLog.reset ();
451 // don't do anything
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700452 }
453
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700454 if ((diffLog != 0 && diffLog->getLeaves ().size () > 0) ||
455 ownInterestSatisfied)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700456 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700457 // Do it only if everything went fine and state changed
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700458
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700459 // this is kind of wrong
460 // 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 -0700461
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700462 // if state has changed, then it is safe to express a new interest
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700463 m_scheduler.cancel (REEXPRESSING_INTEREST);
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700464 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (0),
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700465 bind (&SyncLogic::sendSyncInterest, this),
466 REEXPRESSING_INTEREST);
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700467 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800468}
469
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800470void
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700471SyncLogic::processSyncRecoveryInterest (const std::string &name, DigestConstPtr digest)
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800472{
Yingdi Yu43e71612013-10-30 22:19:31 -0700473 _LOG_DEBUG("processSyncRecoveryInterest");
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700474 DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
475
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700476 if (stateInDiffLog == m_log.end ())
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700477 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700478 _LOG_TRACE ("Could not find " << *digest << " in digest log");
479 return;
480 }
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700481
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700482 SyncStateMsg ssm;
483 {
484 recursive_mutex::scoped_lock lock (m_stateMutex);
485 ssm << (*m_state);
486 }
487 sendSyncData (name, digest, ssm);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700488}
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700489
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700490void
491SyncLogic::satisfyPendingSyncInterests (DiffStateConstPtr diffLog)
492{
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700493 DiffStatePtr fullStateLog = make_shared<DiffState> ();
494 {
495 recursive_mutex::scoped_lock lock (m_stateMutex);
496 BOOST_FOREACH (LeafConstPtr leaf, m_state->getLeaves ()/*.get<timed> ()*/)
497 {
498 fullStateLog->update (leaf->getInfo (), leaf->getSeq ());
499 /// @todo Impose limit on how many state info should be send out
500 }
501 }
502
503 try
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800504 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700505 uint32_t counter = 0;
506 while (m_syncInterestTable.size () > 0)
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700507 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700508 Interest interest = m_syncInterestTable.pop ();
509
510 if (!interest.m_unknown)
511 {
512 _LOG_TRACE (">> D " << interest.m_name);
513 sendSyncData (interest.m_name, interest.m_digest, diffLog);
514 }
515 else
516 {
517 _LOG_TRACE (">> D (unknown)" << interest.m_name);
518 sendSyncData (interest.m_name, interest.m_digest, fullStateLog);
519 }
520 counter ++;
Alexander Afanasyevf07ab352012-03-13 12:57:46 -0700521 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700522 _LOG_DEBUG ("Satisfied " << counter << " pending interests");
Alexander Afanasyevf07ab352012-03-13 12:57:46 -0700523 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700524 catch (Error::InterestTableIsEmpty &e)
525 {
526 // ok. not really an error
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800527 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800528}
529
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800530void
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700531SyncLogic::insertToDiffLog (DiffStatePtr diffLog)
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700532{
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700533 diffLog->setDigest (m_state->getDigest());
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700534 if (m_log.size () > 0)
535 {
536 m_log.get<sequenced> ().front ()->setNext (diffLog);
537 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700538 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 -0700539 /// @todo Optimization
Alexander Afanasyev7df73332012-03-15 12:31:49 -0700540 m_log.get<sequenced> ().push_front (diffLog);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700541}
542
543void
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700544SyncLogic::addLocalNames (const string &prefix, uint32_t session, uint32_t seq)
545{
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700546 DiffStatePtr diff;
547 {
548 //cout << "Add local names" <<endl;
549 recursive_mutex::scoped_lock lock (m_stateMutex);
550 NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix);
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700551
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700552 _LOG_DEBUG ("addLocalNames (): old state " << *m_state->getDigest ());
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700553
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700554 SeqNo seqN (session, seq);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700555 m_state->update(info, seqN);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700556
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700557 _LOG_DEBUG ("addLocalNames (): new state " << *m_state->getDigest ());
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700558
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700559 diff = make_shared<DiffState>();
560 diff->update(info, seqN);
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700561 insertToDiffLog (diff);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700562 }
563
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700564 // _LOG_DEBUG ("PIT size: " << m_syncInterestTable.size ());
565 satisfyPendingSyncInterests (diff);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700566}
567
568void
Alexander Afanasyevd91497c2012-03-12 15:39:30 -0700569SyncLogic::remove(const string &prefix)
570{
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700571 DiffStatePtr diff;
572 {
573 recursive_mutex::scoped_lock lock (m_stateMutex);
574 NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700575 m_state->remove(info);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700576
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700577 // increment the sequence number for the forwarder node
578 NameInfoConstPtr forwarderInfo = StdNameInfo::FindOrCreate(forwarderPrefix);
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700579
Alexander Afanasyev7e1986f2012-10-04 10:21:10 -0700580 LeafContainer::iterator item = m_state->getLeaves ().find (forwarderInfo);
581 SeqNo seqNo (0);
582 if (item != m_state->getLeaves ().end ())
583 {
584 seqNo = (*item)->getSeq ();
585 ++seqNo;
586 }
587 m_state->update (forwarderInfo, seqNo);
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700588
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700589 diff = make_shared<DiffState>();
590 diff->remove(info);
Alexander Afanasyev7e1986f2012-10-04 10:21:10 -0700591 diff->update(forwarderInfo, seqNo);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700592
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700593 insertToDiffLog (diff);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700594 }
595
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700596 satisfyPendingSyncInterests (diff);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700597}
598
599void
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800600SyncLogic::sendSyncInterest ()
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800601{
Yingdi Yu43e71612013-10-30 22:19:31 -0700602 _LOG_DEBUG("sendSyncInterest");
Alexander Afanasyev172d2b72012-03-08 23:43:39 -0800603 ostringstream os;
Chaoyi Bian89ee2dc2012-03-09 14:06:01 -0800604
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700605 {
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700606 recursive_mutex::scoped_lock lock (m_stateMutex);
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700607
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700608 os << m_syncPrefix << "/" << *m_state->getDigest();
609 m_outstandingInterestName = os.str ();
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700610 _LOG_TRACE (">> I " << os.str ());
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700611 }
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700612
Yingdi Yu43e71612013-10-30 22:19:31 -0700613 _LOG_DEBUG("sendSyncInterest: " << os.str());
614
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700615 m_scheduler.cancel (REEXPRESSING_INTEREST);
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700616 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (m_syncInterestReexpress),
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700617 bind (&SyncLogic::sendSyncInterest, this),
618 REEXPRESSING_INTEREST);
Yingdi Yu43e71612013-10-30 22:19:31 -0700619
620 Ptr<ndn::Interest> interestPtr = Ptr<ndn::Interest>(new ndn::Interest(os.str()));
621 Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&SyncLogic::respondSyncData,
622 this,
623 _1),
624 boost::bind(&SyncLogic::onSyncDataTimeout,
625 this,
626 _1,
627 _2,
628 0),
629 boost::bind(&SyncLogic::onSyncDataUnverified,
630 this)));
631 m_handler->sendInterest(interestPtr, closure);
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800632}
633
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700634void
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700635SyncLogic::sendSyncRecoveryInterests (DigestConstPtr digest)
636{
637 ostringstream os;
638 os << m_syncPrefix << "/recovery/" << *digest;
639 _LOG_TRACE (">> I " << os.str ());
640
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700641 TimeDuration nextRetransmission = TIME_MILLISECONDS_WITH_JITTER (m_recoveryRetransmissionInterval);
642 m_recoveryRetransmissionInterval <<= 1;
643
644 m_scheduler.cancel (REEXPRESSING_RECOVERY_INTEREST);
645 if (m_recoveryRetransmissionInterval < 100*1000) // <100 seconds
646 {
647 m_scheduler.schedule (nextRetransmission,
648 bind (&SyncLogic::sendSyncRecoveryInterests, this, digest),
649 REEXPRESSING_RECOVERY_INTEREST);
650 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700651
Yingdi Yu43e71612013-10-30 22:19:31 -0700652 Ptr<ndn::Interest> interestPtr = Ptr<ndn::Interest>(new ndn::Interest(os.str()));
653 Ptr<Closure> closure = Ptr<Closure> (new Closure(boost::bind(&SyncLogic::respondSyncData,
654 this,
655 _1),
656 boost::bind(&SyncLogic::onSyncDataTimeout,
657 this,
658 _1,
659 _2,
660 0),
661 boost::bind(&SyncLogic::onSyncDataUnverified,
662 this)));
663 m_handler->sendInterest (interestPtr, closure);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700664}
665
666
667void
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700668SyncLogic::sendSyncData (const std::string &name, DigestConstPtr digest, StateConstPtr state)
669{
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700670 SyncStateMsg msg;
671 msg << (*state);
672 sendSyncData(name, digest, msg);
673}
674
675// pass in state msg instead of state, so that there is no need to lock the state until
676// this function returns
677void
678SyncLogic::sendSyncData (const std::string &name, DigestConstPtr digest, SyncStateMsg &ssm)
679{
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700680 _LOG_TRACE (">> D " << name);
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700681 int size = ssm.ByteSize();
682 char *wireData = new char[size];
683 ssm.SerializeToArray(wireData, size);
Yingdi Yu43e71612013-10-30 22:19:31 -0700684 Blob blob(wireData, size);
685 Name dataName(name);
686 Name signingIdentity = m_policyManager->inferSigningIdentity(dataName);
687 m_handler->publishDataByIdentity (dataName,
688 blob,
689 signingIdentity,
690 m_syncResponseFreshness); // in NS-3 it doesn't have any effect... yet
Chaoyi Bian6665d5a2012-06-07 14:16:44 -0700691 delete []wireData;
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700692
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700693 // checking if our own interest got satisfied
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700694 bool satisfiedOwnInterest = false;
695 {
696 recursive_mutex::scoped_lock lock (m_stateMutex);
697 satisfiedOwnInterest = (m_outstandingInterestName == name);
698 }
699
700 if (satisfiedOwnInterest)
701 {
702 _LOG_TRACE ("Satisfied our own Interest. Re-expressing (hopefully with a new digest)");
703
704 m_scheduler.cancel (REEXPRESSING_INTEREST);
705 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (0),
706 bind (&SyncLogic::sendSyncInterest, this),
707 REEXPRESSING_INTEREST);
708 }
709}
710
Zhenkai Zhue5660932012-06-04 15:25:20 -0700711string
712SyncLogic::getRootDigest()
713{
714 ostringstream os;
715 recursive_mutex::scoped_lock lock (m_stateMutex);
716 os << *m_state->getDigest();
717 return os.str();
718}
719
Alexander Afanasyev80237382012-10-04 10:20:47 -0700720size_t
721SyncLogic::getNumberOfBranches () const
722{
723 recursive_mutex::scoped_lock lock (m_stateMutex);
724 return m_state->getLeaves ().size ();
725}
726
Alexander Afanasyev5548c042012-10-04 19:10:09 -0700727void
728SyncLogic::printState () const
729{
730 recursive_mutex::scoped_lock lock (m_stateMutex);
731
732 BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
733 {
734 std::cout << *leaf << std::endl;
735 }
736}
737
Zhenkai Zhud5aec4b2012-10-09 12:01:19 -0700738std::map<std::string, bool>
739SyncLogic::getBranchPrefixes() const
740{
741 recursive_mutex::scoped_lock lock (m_stateMutex);
742
743 std::map<std::string, bool> m;
744
745 BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
746 {
747 std::string prefix = leaf->getInfo()->toString();
748 // do not return forwarder prefix
749 if (prefix != forwarderPrefix)
750 {
751 m.insert(pair<std::string, bool>(prefix, false));
752 }
753 }
754
755 return m;
756}
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700757
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800758}