blob: e24fb5b00e23c9a654b08a8ae753a7bb39c16ee2 [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)
48{
49 addUserNode(userPrefix);
50}
51
52bool
53ProducerBase::addUserNode(const ndn::Name& prefix)
54{
55 if (m_prefixes.find(prefix) == m_prefixes.end()) {
56 m_prefixes[prefix] = 0;
57 return true;
58 }
59 else {
60 return false;
61 }
62}
63
64void
65ProducerBase::removeUserNode(const ndn::Name& prefix)
66{
67 auto it = m_prefixes.find(prefix);
68 if (it != m_prefixes.end()) {
69 uint64_t seqNo = it->second;
70 m_prefixes.erase(it);
71
72 ndn::Name prefixWithSeq = ndn::Name(prefix).appendNumber(seqNo);
73 auto hashIt = m_prefix2hash.find(prefixWithSeq);
74 if (hashIt != m_prefix2hash.end()) {
75 uint32_t hash = hashIt->second;
76 m_prefix2hash.erase(hashIt);
77 m_hash2prefix.erase(hash);
78 m_iblt.erase(hash);
79 }
80 }
81}
82
83void
84ProducerBase::updateSeqNo(const ndn::Name& prefix, uint64_t seq)
85{
86 NDN_LOG_DEBUG("UpdateSeq: " << prefix << " " << seq);
87
88 uint64_t oldSeq;
89 auto it = m_prefixes.find(prefix);
90 if (it != m_prefixes.end()) {
91 oldSeq = it->second;
92 }
93 else {
94 NDN_LOG_WARN("Prefix not found in m_prefixes");
95 return;
96 }
97
98 if (oldSeq >= seq) {
99 NDN_LOG_WARN("Update has lower/equal seq no for prefix, doing nothing!");
100 return;
101 }
102
103 // Delete the last sequence prefix from the iblt
104 // Because we don't insert zeroth prefix in IBF so no need to delete that
105 if (oldSeq != 0) {
106 ndn::Name prefixWithSeq = ndn::Name(prefix).appendNumber(oldSeq);
107 auto hashIt = m_prefix2hash.find(prefixWithSeq);
108 if (hashIt != m_prefix2hash.end()) {
109 uint32_t hash = hashIt->second;
110 m_prefix2hash.erase(hashIt);
111 m_hash2prefix.erase(hash);
112 m_iblt.erase(hash);
113 }
114 }
115
116 // Insert the new seq no
117 it->second = seq;
118 ndn::Name prefixWithSeq = ndn::Name(prefix).appendNumber(seq);
119 uint32_t newHash = murmurHash3(N_HASHCHECK, prefixWithSeq.toUri());
120 m_prefix2hash[prefixWithSeq] = newHash;
121 m_hash2prefix[newHash] = prefix;
122 m_iblt.insert(newHash);
123}
124
125void
126ProducerBase::sendApplicationNack(const ndn::Name& name)
127{
128 NDN_LOG_DEBUG("Sending application nack");
129 ndn::Name dataName(name);
130 m_iblt.appendToName(dataName);
131
132 ndn::Data data(dataName);
133 data.setFreshnessPeriod(m_syncReplyFreshness);
134 data.setContentType(ndn::tlv::ContentType_Nack);
135 m_keyChain.sign(data);
136 m_face.put(data);
137}
138
139void
140ProducerBase::onRegisterFailed(const ndn::Name& prefix, const std::string& msg) const
141{
142 NDN_LOG_ERROR("ProduerBase::onRegisterFailed " << prefix << " " << msg);
143 BOOST_THROW_EXCEPTION(Error(msg));
144}
145
146} // namespace psync