blob: acb4d903fe1d91ae50aa509492970e6e9ac191f4 [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 Afanasyev4f9ea482012-03-15 11:57:29 -070031#include "sync-log.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;
41
Chaoyi Bianf007f922012-04-09 20:05:37 -070042INIT_LOGGER ("SyncLogic");
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070043
Alexander Afanasyev983b0e92012-04-26 12:44:18 -070044#ifdef NS3_MODULE
45#define GET_RANDOM(var) var.GetValue ()
46#else
47#define GET_RANDOM(var) var ()
48#endif
49
50#define TIME_SECONDS_WITH_JITTER(sec) \
51 (TIME_SECONDS (sec) + TIME_MILLISECONDS (GET_RANDOM (m_reexpressionJitter)))
52
Alexander Afanasyev42612262012-05-05 10:58:37 -070053#define TIME_MILLISECONDS_WITH_JITTER(ms) \
54 (TIME_MILLISECONDS (ms) + TIME_MILLISECONDS (GET_RANDOM (m_reexpressionJitter)))
Alexander Afanasyev983b0e92012-04-26 12:44:18 -070055
56
Chaoyi Bian44fff0c2012-03-07 21:07:22 -080057namespace Sync
58{
59
Alexander Afanasyev750d1872012-03-12 15:33:56 -070060SyncLogic::SyncLogic (const std::string &syncPrefix,
61 LogicUpdateCallback onUpdate,
Zhenkai Zhuce66e212012-03-12 22:27:19 -070062 LogicRemoveCallback onRemove)
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -070063 : m_state (new FullState)
64 , m_syncInterestTable (TIME_SECONDS (m_syncInterestReexpress))
65 , m_syncPrefix (syncPrefix)
Alexander Afanasyev750d1872012-03-12 15:33:56 -070066 , m_onUpdate (onUpdate)
Zhenkai Zhub9f19592012-10-16 14:27:38 -070067 , m_perBranch (false)
Alexander Afanasyev750d1872012-03-12 15:33:56 -070068 , m_onRemove (onRemove)
Zhenkai Zhu9587cd62012-10-17 11:58:37 -070069 , m_ccnxHandle(new CcnxWrapper ())
Alexander Afanasyeva76010b2012-05-24 21:31:49 -070070 , m_recoveryRetransmissionInterval (m_defaultRecoveryRetransmitInterval)
Alexander Afanasyev73f7f9a2012-04-09 15:45:47 -070071#ifndef NS3_MODULE
Alexander Afanasyev45fba082012-03-12 18:05:24 -070072 , m_randomGenerator (static_cast<unsigned int> (std::time (0)))
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -070073 , m_rangeUniformRandom (m_randomGenerator, uniform_int<> (200,1000))
74 , m_reexpressionJitter (m_randomGenerator, uniform_int<> (100,500))
Alexander Afanasyev73f7f9a2012-04-09 15:45:47 -070075#else
Alexander Afanasyev55608612012-04-30 13:24:50 -070076 , m_rangeUniformRandom (200,1000)
Alexander Afanasyeva76010b2012-05-24 21:31:49 -070077 , m_reexpressionJitter (10,500)
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -070078#endif
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -070079{
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -070080#ifndef NS3_MODULE
81 // In NS3 module these functions are moved to StartApplication method
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070082
Alexander Afanasyev1b449c42012-03-13 20:24:07 -070083 m_ccnxHandle->setInterestFilter (m_syncPrefix,
Alexander Afanasyev387ac952012-03-11 23:49:27 -070084 bind (&SyncLogic::respondSyncInterest, this, _1));
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -070085
Alexander Afanasyev983b0e92012-04-26 12:44:18 -070086 m_scheduler.schedule (TIME_SECONDS (0), // no need to add jitter
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -070087 bind (&SyncLogic::sendSyncInterest, this),
88 REEXPRESSING_INTEREST);
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -070089#endif
Chaoyi Bian44fff0c2012-03-07 21:07:22 -080090}
91
Zhenkai Zhub9f19592012-10-16 14:27:38 -070092SyncLogic::SyncLogic (const std::string &syncPrefix,
93 LogicPerBranchCallback onUpdateBranch)
94 : m_state (new FullState)
95 , m_syncInterestTable (TIME_SECONDS (m_syncInterestReexpress))
96 , m_syncPrefix (syncPrefix)
97 , m_onUpdateBranch (onUpdateBranch)
98 , m_perBranch(true)
Zhenkai Zhu9587cd62012-10-17 11:58:37 -070099 , m_ccnxHandle(new CcnxWrapper())
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700100 , m_recoveryRetransmissionInterval (m_defaultRecoveryRetransmitInterval)
101#ifndef NS3_MODULE
102 , m_randomGenerator (static_cast<unsigned int> (std::time (0)))
103 , m_rangeUniformRandom (m_randomGenerator, uniform_int<> (200,1000))
104 , m_reexpressionJitter (m_randomGenerator, uniform_int<> (100,500))
105#else
106 , m_rangeUniformRandom (200,1000)
107 , m_reexpressionJitter (10,500)
108#endif
109{
110#ifndef NS3_MODULE
111 // In NS3 module these functions are moved to StartApplication method
112
113 m_ccnxHandle->setInterestFilter (m_syncPrefix,
114 bind (&SyncLogic::respondSyncInterest, this, _1));
115
116 m_scheduler.schedule (TIME_SECONDS (0), // no need to add jitter
117 bind (&SyncLogic::sendSyncInterest, this),
118 REEXPRESSING_INTEREST);
119#endif
120}
121
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800122SyncLogic::~SyncLogic ()
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800123{
Alexander Afanasyev60126e02012-10-05 16:54:42 -0700124 m_ccnxHandle->clearInterestFilter (m_syncPrefix);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700125}
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700126
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700127#ifdef NS3_MODULE
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700128void
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700129SyncLogic::StartApplication ()
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700130{
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700131 m_ccnxHandle->SetNode (GetNode ());
132 m_ccnxHandle->StartApplication ();
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700133
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700134 m_ccnxHandle->setInterestFilter (m_syncPrefix,
135 bind (&SyncLogic::respondSyncInterest, this, _1));
136
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700137 m_scheduler.schedule (TIME_SECONDS (0), // need to send first interests at exactly the same time
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700138 bind (&SyncLogic::sendSyncInterest, this),
139 REEXPRESSING_INTEREST);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700140}
141
142void
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700143SyncLogic::StopApplication ()
144{
Alexander Afanasyev434f1612012-04-21 21:19:15 -0700145 m_ccnxHandle->clearInterestFilter (m_syncPrefix);
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700146 m_ccnxHandle->StopApplication ();
Alexander Afanasyev40942f42012-04-21 20:53:16 -0700147 m_scheduler.cancel (REEXPRESSING_INTEREST);
148 m_scheduler.cancel (DELAYED_INTEREST_PROCESSING);
Alexander Afanasyevb550d6a2012-04-09 15:03:16 -0700149}
150#endif
151
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700152/**
153 * Two types of intersts
154 *
155 * Normal name: .../<hash>
156 * Recovery name: .../recovery/<hash>
157 */
158boost::tuple<DigestConstPtr, std::string>
159SyncLogic::convertNameToDigestAndType (const std::string &name)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700160{
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700161 BOOST_ASSERT (name.find (m_syncPrefix) == 0);
162
163 string hash = name.substr (m_syncPrefix.size (), name.size ()-m_syncPrefix.size ());
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700164 if (hash[0] == '/')
165 hash = hash.substr (1, hash.size ()-1);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700166 string interestType = "normal";
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700167
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700168 size_t pos = hash.find ('/');
169 if (pos != string::npos)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700170 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700171 interestType = hash.substr (0, pos);
172 hash = hash.substr (pos + 1);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700173 }
174
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700175 _LOG_TRACE (hash << ", " << interestType);
176
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700177 DigestPtr digest = make_shared<Digest> ();
178 istringstream is (hash);
179 is >> *digest;
180
181 return make_tuple (digest, interestType);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700182}
183
184void
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700185SyncLogic::respondSyncInterest (const string &name)
186{
187 try
188 {
189 _LOG_TRACE ("<< I " << name);
190
191 DigestConstPtr digest;
192 string type;
193 tie (digest, type) = convertNameToDigestAndType (name);
194
195 if (type == "normal") // kind of ineffective...
196 {
197 processSyncInterest (name, digest);
198 }
199 else if (type == "recovery")
200 {
201 processSyncRecoveryInterest (name, digest);
202 }
203 }
204 catch (Error::DigestCalculationError &e)
205 {
206 _LOG_TRACE ("Something fishy happened...");
207 // log error. ignoring it for now, later we should log it
208 return ;
209 }
210}
211
212void
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700213SyncLogic::respondSyncData (const std::string &name, const char *wireData, size_t len)
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700214{
215 try
216 {
217 _LOG_TRACE ("<< D " << name);
218
219 DigestConstPtr digest;
220 string type;
221 tie (digest, type) = convertNameToDigestAndType (name);
222
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700223 if (type == "normal")
224 {
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700225 processSyncData (name, digest, wireData, len);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700226 }
227 else
228 {
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700229 // timer is always restarted when we schedule recovery
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700230 m_scheduler.cancel (REEXPRESSING_RECOVERY_INTEREST);
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700231 processSyncData (name, digest, wireData, len);
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700232 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700233 }
234 catch (Error::DigestCalculationError &e)
235 {
236 _LOG_TRACE ("Something fishy happened...");
237 // log error. ignoring it for now, later we should log it
238 return;
239 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700240}
241
242
243void
244SyncLogic::processSyncInterest (const std::string &name, DigestConstPtr digest, bool timedProcessing/*=false*/)
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700245{
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700246 DigestConstPtr rootDigest;
247 {
248 recursive_mutex::scoped_lock lock (m_stateMutex);
249 rootDigest = m_state->getDigest();
250 }
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700251
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700252 // Special case when state is not empty and we have received request with zero-root digest
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700253 if (digest->isZero () && !rootDigest->isZero ())
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700254 {
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700255
256 SyncStateMsg ssm;
257 {
258 recursive_mutex::scoped_lock lock (m_stateMutex);
259 ssm << (*m_state);
260 }
261 sendSyncData (name, digest, ssm);
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700262 return;
263 }
Alexander Afanasyev763855a2012-03-13 14:17:37 -0700264
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700265 if (*rootDigest == *digest)
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700266 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700267 _LOG_TRACE ("processSyncInterest (): Same state. Adding to PIT");
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700268 m_syncInterestTable.insert (digest, name, false);
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700269 return;
270 }
Alexander Afanasyevdd0eba72012-03-13 13:57:10 -0700271
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700272 DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
273
274 if (stateInDiffLog != m_log.end ())
275 {
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700276 DiffStateConstPtr stateDiff = (*stateInDiffLog)->diff ();
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700277
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700278 sendSyncData (name, digest, stateDiff);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700279 return;
280 }
281
282 if (!timedProcessing)
283 {
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700284 bool exists = m_syncInterestTable.insert (digest, name, true);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700285 if (exists) // somebody else replied, so restart random-game timer
Alexander Afanasyev3a229132012-04-25 15:07:26 -0700286 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700287 _LOG_DEBUG ("Unknown digest, but somebody may have already replied, so restart our timer");
288 m_scheduler.cancel (DELAYED_INTEREST_PROCESSING);
Alexander Afanasyev3a229132012-04-25 15:07:26 -0700289 }
Alexander Afanasyev03793b42012-05-01 13:03:07 -0700290
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700291 uint32_t waitDelay = GET_RANDOM (m_rangeUniformRandom);
292 _LOG_DEBUG ("Digest is not in the log. Schedule processing after small delay: " << waitDelay << "ms");
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700293
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700294 m_scheduler.schedule (TIME_MILLISECONDS (waitDelay),
295 bind (&SyncLogic::processSyncInterest, this, name, digest, true),
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700296 DELAYED_INTEREST_PROCESSING);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700297 }
298 else
299 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700300 _LOG_TRACE (" (timed processing)");
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700301
302 m_recoveryRetransmissionInterval = m_defaultRecoveryRetransmitInterval;
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700303 sendSyncRecoveryInterests (digest);
Alexander Afanasyev387ac952012-03-11 23:49:27 -0700304 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800305}
306
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800307void
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700308SyncLogic::processSyncData (const std::string &name, DigestConstPtr digest, const char *wireData, size_t len)
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800309{
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700310 DiffStatePtr diffLog = make_shared<DiffState> ();
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700311 bool ownInterestSatisfied = false;
Alexander Afanasyeve4e2bf72012-03-12 12:44:54 -0700312
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700313 try
314 {
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700315
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700316 m_syncInterestTable.remove (name); // Remove satisfied interest from PIT
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700317
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700318 ownInterestSatisfied = (name == m_outstandingInterestName);
319
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700320 DiffState diff;
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700321 SyncStateMsg msg;
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700322 if (!msg.ParseFromArray(wireData, len) || !msg.IsInitialized())
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700323 {
324 //Throw
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700325 BOOST_THROW_EXCEPTION (Error::SyncStateMsgDecodingFailure () );
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700326 }
327 msg >> diff;
328
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700329 vector<MissingDataInfo> v;
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700330 BOOST_FOREACH (LeafConstPtr leaf, diff.getLeaves().get<ordered>())
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700331 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700332 DiffLeafConstPtr diffLeaf = dynamic_pointer_cast<const DiffLeaf> (leaf);
333 BOOST_ASSERT (diffLeaf != 0);
334
335 NameInfoConstPtr info = diffLeaf->getInfo();
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700336 if (diffLeaf->getOperation() == UPDATE)
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700337 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700338 SeqNo seq = diffLeaf->getSeq();
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700339
340 bool inserted = false;
341 bool updated = false;
342 SeqNo oldSeq;
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700343 {
344 recursive_mutex::scoped_lock lock (m_stateMutex);
345 tie (inserted, updated, oldSeq) = m_state->update (info, seq);
346 }
Chaoyi Bian89ee2dc2012-03-09 14:06:01 -0800347
Alexander Afanasyevd4adce52012-03-13 13:59:39 -0700348 if (inserted || updated)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700349 {
350 diffLog->update (info, seq);
Zhenkai Zhu68f04d52012-06-05 14:07:41 -0700351 if (!oldSeq.isValid())
352 {
353 oldSeq = SeqNo(seq.getSession(), 0);
354 }
355 else
356 {
357 ++oldSeq;
358 }
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700359 // there is no need for application to process update on forwarder node
360 if (info->toString() != forwarderPrefix)
361 {
362 MissingDataInfo mdi = {info->toString(), oldSeq, seq};
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700363 if (m_perBranch)
364 {
365 ostringstream interestName;
366 interestName << mdi.prefix << "/" << mdi.high.getSession() << "/" << mdi.high.getSeq();
367 m_onUpdateBranch(interestName.str());
368 }
369 else
370 {
371 v.push_back(mdi);
372 }
Zhenkai Zhuba3c1d12012-10-03 23:26:35 -0700373 }
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700374 }
375 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700376 else if (diffLeaf->getOperation() == REMOVE)
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700377 {
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700378 recursive_mutex::scoped_lock lock (m_stateMutex);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700379 if (m_state->remove (info))
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700380 {
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700381 diffLog->remove (info);
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700382 if (!m_perBranch)
383 {
384 m_onRemove (info->toString ());
385 }
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700386 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700387 }
388 else
389 {
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700390 }
391 }
392
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700393 if (!v.empty())
394 {
Zhenkai Zhub9f19592012-10-16 14:27:38 -0700395 if (!m_perBranch)
396 {
397 m_onUpdate(v);
398 }
Zhenkai Zhu1cb29292012-05-31 22:54:34 -0700399 }
400
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700401 insertToDiffLog (diffLog);
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700402 }
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700403 catch (Error::SyncStateMsgDecodingFailure &e)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700404 {
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700405 _LOG_TRACE ("Something really fishy happened during state decoding " <<
406 diagnostic_information (e));
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700407 diffLog.reset ();
408 // don't do anything
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700409 }
410
Alexander Afanasyev2b6fbfb2012-05-24 10:57:14 -0700411 if ((diffLog != 0 && diffLog->getLeaves ().size () > 0) ||
412 ownInterestSatisfied)
Alexander Afanasyev750d1872012-03-12 15:33:56 -0700413 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700414 // Do it only if everything went fine and state changed
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700415
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700416 // this is kind of wrong
417 // 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 -0700418
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700419 // if state has changed, then it is safe to express a new interest
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700420 m_scheduler.cancel (REEXPRESSING_INTEREST);
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700421 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (0),
Alexander Afanasyevd4cca472012-03-13 14:25:46 -0700422 bind (&SyncLogic::sendSyncInterest, this),
423 REEXPRESSING_INTEREST);
Alexander Afanasyev04fd8a82012-03-12 15:40:48 -0700424 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800425}
426
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800427void
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700428SyncLogic::processSyncRecoveryInterest (const std::string &name, DigestConstPtr digest)
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800429{
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700430
431 DiffStateContainer::iterator stateInDiffLog = m_log.find (digest);
432
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700433 if (stateInDiffLog == m_log.end ())
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700434 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700435 _LOG_TRACE ("Could not find " << *digest << " in digest log");
436 return;
437 }
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700438
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700439 SyncStateMsg ssm;
440 {
441 recursive_mutex::scoped_lock lock (m_stateMutex);
442 ssm << (*m_state);
443 }
444 sendSyncData (name, digest, ssm);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700445}
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700446
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700447void
448SyncLogic::satisfyPendingSyncInterests (DiffStateConstPtr diffLog)
449{
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700450 DiffStatePtr fullStateLog = make_shared<DiffState> ();
451 {
452 recursive_mutex::scoped_lock lock (m_stateMutex);
453 BOOST_FOREACH (LeafConstPtr leaf, m_state->getLeaves ()/*.get<timed> ()*/)
454 {
455 fullStateLog->update (leaf->getInfo (), leaf->getSeq ());
456 /// @todo Impose limit on how many state info should be send out
457 }
458 }
459
460 try
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800461 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700462 uint32_t counter = 0;
463 while (m_syncInterestTable.size () > 0)
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700464 {
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700465 Interest interest = m_syncInterestTable.pop ();
466
467 if (!interest.m_unknown)
468 {
469 _LOG_TRACE (">> D " << interest.m_name);
470 sendSyncData (interest.m_name, interest.m_digest, diffLog);
471 }
472 else
473 {
474 _LOG_TRACE (">> D (unknown)" << interest.m_name);
475 sendSyncData (interest.m_name, interest.m_digest, fullStateLog);
476 }
477 counter ++;
Alexander Afanasyevf07ab352012-03-13 12:57:46 -0700478 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700479 _LOG_DEBUG ("Satisfied " << counter << " pending interests");
Alexander Afanasyevf07ab352012-03-13 12:57:46 -0700480 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700481 catch (Error::InterestTableIsEmpty &e)
482 {
483 // ok. not really an error
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800484 }
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800485}
486
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800487void
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700488SyncLogic::insertToDiffLog (DiffStatePtr diffLog)
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700489{
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700490 diffLog->setDigest (m_state->getDigest());
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700491 if (m_log.size () > 0)
492 {
493 m_log.get<sequenced> ().front ()->setNext (diffLog);
494 }
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700495 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 -0700496 /// @todo Optimization
Alexander Afanasyev7df73332012-03-15 12:31:49 -0700497 m_log.get<sequenced> ().push_front (diffLog);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700498}
499
500void
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700501SyncLogic::addLocalNames (const string &prefix, uint32_t session, uint32_t seq)
502{
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700503 DiffStatePtr diff;
504 {
505 //cout << "Add local names" <<endl;
506 recursive_mutex::scoped_lock lock (m_stateMutex);
507 NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix);
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700508
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700509 _LOG_DEBUG ("addLocalNames (): old state " << *m_state->getDigest ());
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700510
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700511 SeqNo seqN (session, seq);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700512 m_state->update(info, seqN);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700513
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700514 _LOG_DEBUG ("addLocalNames (): new state " << *m_state->getDigest ());
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700515
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700516 diff = make_shared<DiffState>();
517 diff->update(info, seqN);
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700518 insertToDiffLog (diff);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700519 }
520
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700521 // _LOG_DEBUG ("PIT size: " << m_syncInterestTable.size ());
522 satisfyPendingSyncInterests (diff);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700523}
524
525void
Alexander Afanasyevd91497c2012-03-12 15:39:30 -0700526SyncLogic::remove(const string &prefix)
527{
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700528 DiffStatePtr diff;
529 {
530 recursive_mutex::scoped_lock lock (m_stateMutex);
531 NameInfoConstPtr info = StdNameInfo::FindOrCreate(prefix);
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700532 m_state->remove(info);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700533
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700534 // increment the sequence number for the forwarder node
535 NameInfoConstPtr forwarderInfo = StdNameInfo::FindOrCreate(forwarderPrefix);
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700536
Alexander Afanasyev7e1986f2012-10-04 10:21:10 -0700537 LeafContainer::iterator item = m_state->getLeaves ().find (forwarderInfo);
538 SeqNo seqNo (0);
539 if (item != m_state->getLeaves ().end ())
540 {
541 seqNo = (*item)->getSeq ();
542 ++seqNo;
543 }
544 m_state->update (forwarderInfo, seqNo);
Zhenkai Zhua2e0b082012-09-26 10:34:15 -0700545
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700546 diff = make_shared<DiffState>();
547 diff->remove(info);
Alexander Afanasyev7e1986f2012-10-04 10:21:10 -0700548 diff->update(forwarderInfo, seqNo);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700549
Alexander Afanasyev235c6d72012-03-15 22:28:43 -0700550 insertToDiffLog (diff);
Alexander Afanasyev1b449c42012-03-13 20:24:07 -0700551 }
552
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700553 satisfyPendingSyncInterests (diff);
Zhenkai Zhu0efa37b2012-03-12 13:54:12 -0700554}
555
556void
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800557SyncLogic::sendSyncInterest ()
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800558{
Alexander Afanasyev172d2b72012-03-08 23:43:39 -0800559 ostringstream os;
Chaoyi Bian89ee2dc2012-03-09 14:06:01 -0800560
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700561 {
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700562 recursive_mutex::scoped_lock lock (m_stateMutex);
Alexander Afanasyev4f9ea482012-03-15 11:57:29 -0700563
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700564 os << m_syncPrefix << "/" << *m_state->getDigest();
565 m_outstandingInterestName = os.str ();
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700566 _LOG_TRACE (">> I " << os.str ());
Alexander Afanasyev860e6fe2012-03-15 17:30:31 -0700567 }
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700568
569 m_scheduler.cancel (REEXPRESSING_INTEREST);
Alexander Afanasyev983b0e92012-04-26 12:44:18 -0700570 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (m_syncInterestReexpress),
Alexander Afanasyevbf2b4362012-03-12 23:55:09 -0700571 bind (&SyncLogic::sendSyncInterest, this),
572 REEXPRESSING_INTEREST);
Alexander Afanasyev42612262012-05-05 10:58:37 -0700573
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700574 m_ccnxHandle->sendInterest (os.str (),
575 bind (&SyncLogic::respondSyncData, this, _1, _2, _3));
Chaoyi Bian44fff0c2012-03-07 21:07:22 -0800576}
577
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700578void
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700579SyncLogic::sendSyncRecoveryInterests (DigestConstPtr digest)
580{
581 ostringstream os;
582 os << m_syncPrefix << "/recovery/" << *digest;
583 _LOG_TRACE (">> I " << os.str ());
584
Alexander Afanasyeva76010b2012-05-24 21:31:49 -0700585 TimeDuration nextRetransmission = TIME_MILLISECONDS_WITH_JITTER (m_recoveryRetransmissionInterval);
586 m_recoveryRetransmissionInterval <<= 1;
587
588 m_scheduler.cancel (REEXPRESSING_RECOVERY_INTEREST);
589 if (m_recoveryRetransmissionInterval < 100*1000) // <100 seconds
590 {
591 m_scheduler.schedule (nextRetransmission,
592 bind (&SyncLogic::sendSyncRecoveryInterests, this, digest),
593 REEXPRESSING_RECOVERY_INTEREST);
594 }
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700595
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700596 m_ccnxHandle->sendInterest (os.str (),
597 bind (&SyncLogic::respondSyncData, this, _1, _2, _3));
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700598}
599
600
601void
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700602SyncLogic::sendSyncData (const std::string &name, DigestConstPtr digest, StateConstPtr state)
603{
Zhenkai Zhu2d3e2702012-10-15 14:18:05 -0700604 SyncStateMsg msg;
605 msg << (*state);
606 sendSyncData(name, digest, msg);
607}
608
609// pass in state msg instead of state, so that there is no need to lock the state until
610// this function returns
611void
612SyncLogic::sendSyncData (const std::string &name, DigestConstPtr digest, SyncStateMsg &ssm)
613{
Alexander Afanasyev46eb5262012-05-10 16:30:35 -0700614 _LOG_TRACE (">> D " << name);
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700615 int size = ssm.ByteSize();
616 char *wireData = new char[size];
617 ssm.SerializeToArray(wireData, size);
Zhenkai Zhu97e36bd2012-06-06 13:55:03 -0700618 m_ccnxHandle->publishRawData (name,
619 wireData,
Zhenkai Zhu3cfdcb92012-06-06 15:20:10 -0700620 size,
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700621 m_syncResponseFreshness); // in NS-3 it doesn't have any effect... yet
Chaoyi Bian6665d5a2012-06-07 14:16:44 -0700622 delete []wireData;
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700623
Alexander Afanasyev282a10b2012-05-09 12:56:38 -0700624 // checking if our own interest got satisfied
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700625 bool satisfiedOwnInterest = false;
626 {
627 recursive_mutex::scoped_lock lock (m_stateMutex);
628 satisfiedOwnInterest = (m_outstandingInterestName == name);
629 }
630
631 if (satisfiedOwnInterest)
632 {
633 _LOG_TRACE ("Satisfied our own Interest. Re-expressing (hopefully with a new digest)");
634
635 m_scheduler.cancel (REEXPRESSING_INTEREST);
636 m_scheduler.schedule (TIME_SECONDS_WITH_JITTER (0),
637 bind (&SyncLogic::sendSyncInterest, this),
638 REEXPRESSING_INTEREST);
639 }
640}
641
Zhenkai Zhue5660932012-06-04 15:25:20 -0700642string
643SyncLogic::getRootDigest()
644{
645 ostringstream os;
646 recursive_mutex::scoped_lock lock (m_stateMutex);
647 os << *m_state->getDigest();
648 return os.str();
649}
650
Alexander Afanasyev80237382012-10-04 10:20:47 -0700651size_t
652SyncLogic::getNumberOfBranches () const
653{
654 recursive_mutex::scoped_lock lock (m_stateMutex);
655 return m_state->getLeaves ().size ();
656}
657
Alexander Afanasyev5548c042012-10-04 19:10:09 -0700658void
659SyncLogic::printState () const
660{
661 recursive_mutex::scoped_lock lock (m_stateMutex);
662
663 BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
664 {
665 std::cout << *leaf << std::endl;
666 }
667}
668
Zhenkai Zhud5aec4b2012-10-09 12:01:19 -0700669std::map<std::string, bool>
670SyncLogic::getBranchPrefixes() const
671{
672 recursive_mutex::scoped_lock lock (m_stateMutex);
673
674 std::map<std::string, bool> m;
675
676 BOOST_FOREACH (const boost::shared_ptr<Sync::Leaf> leaf, m_state->getLeaves ())
677 {
678 std::string prefix = leaf->getInfo()->toString();
679 // do not return forwarder prefix
680 if (prefix != forwarderPrefix)
681 {
682 m.insert(pair<std::string, bool>(prefix, false));
683 }
684 }
685
686 return m;
687}
Alexander Afanasyevf3c03a92012-05-09 12:00:37 -0700688
Alexander Afanasyevc1030192012-03-08 22:21:28 -0800689}