blob: e73116842924b44aab2ec0358c34e57bc01b1fef [file] [log] [blame]
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -05001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/*
3 * Copyright (c) 2014-2018, The University of Memphis
4 *
5 * This file is part of PSync.
6 * See AUTHORS.md for complete list of PSync authors and contributors.
7 *
8 * PSync is free software: you can redistribute it and/or modify it under the terms
9 * of the GNU General Public License as published by the Free Software Foundation,
10 * either version 3 of the License, or (at your option) any later version.
11 *
12 * PSync is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
13 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 * PURPOSE. See the GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along with
17 * PSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 **/
19
20#include "producer-base.hpp"
21
22#include <ndn-cxx/util/logger.hpp>
23#include <boost/algorithm/string.hpp>
24
25#include <cstring>
26#include <limits>
27#include <functional>
28
29namespace psync {
30
31NDN_LOG_INIT(psync.ProducerBase);
32
33ProducerBase::ProducerBase(size_t expectedNumEntries,
34 ndn::Face& face,
35 const ndn::Name& syncPrefix,
36 const ndn::Name& userPrefix,
37 ndn::time::milliseconds syncReplyFreshness,
38 ndn::time::milliseconds helloReplyFreshness)
39 : m_iblt(expectedNumEntries)
40 , m_expectedNumEntries(expectedNumEntries)
41 , m_threshold(expectedNumEntries/2)
42 , m_face(face)
43 , m_scheduler(m_face.getIoService())
44 , m_syncPrefix(syncPrefix)
45 , m_userPrefix(userPrefix)
46 , m_syncReplyFreshness(syncReplyFreshness)
47 , m_helloReplyFreshness(helloReplyFreshness)
Ashlesh Gawandeec43b362018-08-01 15:15:01 -050048 , m_segmentPublisher(m_face, m_keyChain)
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -050049{
50 addUserNode(userPrefix);
51}
52
53bool
54ProducerBase::addUserNode(const ndn::Name& prefix)
55{
56 if (m_prefixes.find(prefix) == m_prefixes.end()) {
57 m_prefixes[prefix] = 0;
58 return true;
59 }
60 else {
61 return false;
62 }
63}
64
65void
66ProducerBase::removeUserNode(const ndn::Name& prefix)
67{
68 auto it = m_prefixes.find(prefix);
69 if (it != m_prefixes.end()) {
70 uint64_t seqNo = it->second;
71 m_prefixes.erase(it);
72
73 ndn::Name prefixWithSeq = ndn::Name(prefix).appendNumber(seqNo);
74 auto hashIt = m_prefix2hash.find(prefixWithSeq);
75 if (hashIt != m_prefix2hash.end()) {
76 uint32_t hash = hashIt->second;
77 m_prefix2hash.erase(hashIt);
78 m_hash2prefix.erase(hash);
79 m_iblt.erase(hash);
80 }
81 }
82}
83
84void
85ProducerBase::updateSeqNo(const ndn::Name& prefix, uint64_t seq)
86{
87 NDN_LOG_DEBUG("UpdateSeq: " << prefix << " " << seq);
88
89 uint64_t oldSeq;
90 auto it = m_prefixes.find(prefix);
91 if (it != m_prefixes.end()) {
92 oldSeq = it->second;
93 }
94 else {
95 NDN_LOG_WARN("Prefix not found in m_prefixes");
96 return;
97 }
98
99 if (oldSeq >= seq) {
100 NDN_LOG_WARN("Update has lower/equal seq no for prefix, doing nothing!");
101 return;
102 }
103
104 // Delete the last sequence prefix from the iblt
105 // Because we don't insert zeroth prefix in IBF so no need to delete that
106 if (oldSeq != 0) {
107 ndn::Name prefixWithSeq = ndn::Name(prefix).appendNumber(oldSeq);
108 auto hashIt = m_prefix2hash.find(prefixWithSeq);
109 if (hashIt != m_prefix2hash.end()) {
110 uint32_t hash = hashIt->second;
111 m_prefix2hash.erase(hashIt);
112 m_hash2prefix.erase(hash);
113 m_iblt.erase(hash);
114 }
115 }
116
117 // Insert the new seq no
118 it->second = seq;
119 ndn::Name prefixWithSeq = ndn::Name(prefix).appendNumber(seq);
120 uint32_t newHash = murmurHash3(N_HASHCHECK, prefixWithSeq.toUri());
121 m_prefix2hash[prefixWithSeq] = newHash;
122 m_hash2prefix[newHash] = prefix;
123 m_iblt.insert(newHash);
124}
125
126void
127ProducerBase::sendApplicationNack(const ndn::Name& name)
128{
129 NDN_LOG_DEBUG("Sending application nack");
130 ndn::Name dataName(name);
131 m_iblt.appendToName(dataName);
132
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500133 dataName.appendSegment(0);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500134 ndn::Data data(dataName);
135 data.setFreshnessPeriod(m_syncReplyFreshness);
136 data.setContentType(ndn::tlv::ContentType_Nack);
Ashlesh Gawandeec43b362018-08-01 15:15:01 -0500137 data.setFinalBlock(dataName[-1]);
Ashlesh Gawande0b2897e2018-06-20 14:40:47 -0500138 m_keyChain.sign(data);
139 m_face.put(data);
140}
141
142void
143ProducerBase::onRegisterFailed(const ndn::Name& prefix, const std::string& msg) const
144{
145 NDN_LOG_ERROR("ProduerBase::onRegisterFailed " << prefix << " " << msg);
146 BOOST_THROW_EXCEPTION(Error(msg));
147}
148
149} // namespace psync