blob: 533a4514a5511f67ee40a5d8919b85bf43908bf7 [file] [log] [blame]
Yingdi Yud514c172014-08-26 21:49:39 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Davide Pesavento5f408ae2020-07-15 21:17:04 -04003 * Copyright (c) 2012-2020 University of California, Los Angeles
Yingdi Yud514c172014-08-26 21:49:39 -07004 *
5 * This file is part of ChronoSync, synchronization library for distributed realtime
6 * applications for NDN.
7 *
8 * ChronoSync 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, either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * ChronoSync 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 * ChronoSync, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
18 *
19 * @author Zhenkai Zhu <http://irl.cs.ucla.edu/~zhenkai/>
20 * @author Chaoyi Bian <bcy@pku.edu.cn>
21 * @author Alexander Afanasyev <http://lasr.cs.ucla.edu/afanasyev/index.html>
22 * @author Yingdi Yu <yingdi@cs.ucla.edu>
23 */
24
25#include "state.hpp"
26
Davide Pesavento5f408ae2020-07-15 21:17:04 -040027#include <boost/range/adaptor/reversed.hpp>
28
Yingdi Yud514c172014-08-26 21:49:39 -070029namespace chronosync {
30
Davide Pesavento5473abe2017-10-09 01:35:33 -040031State::~State() = default;
Yingdi Yud514c172014-08-26 21:49:39 -070032
33/**
34 * @brief Add or update leaf to the sync tree
35 *
36 * @param info session name of the leaf
37 * @param seq sequence number of the leaf
38 * @return 3-tuple (isInserted, isUpdated, oldSeqNo)
39 */
Ashlesh Gawande08784d42017-09-06 23:40:21 -050040std::tuple<bool, bool, SeqNo>
Yingdi Yud514c172014-08-26 21:49:39 -070041State::update(const Name& info, const SeqNo& seq)
42{
43 m_wire.reset();
44
45 LeafContainer::iterator leaf = m_leaves.find(info);
46
47 if (leaf == m_leaves.end()) {
48 m_leaves.insert(make_shared<Leaf>(info, cref(seq)));
49 return make_tuple(true, false, 0);
50 }
51 else {
52 if ((*leaf)->getSeq() == seq || seq < (*leaf)->getSeq()) {
53 return make_tuple(false, false, 0);
54 }
55
56 SeqNo old = (*leaf)->getSeq();
Davide Pesavento5f408ae2020-07-15 21:17:04 -040057 m_leaves.modify(leaf, [=] (LeafPtr& leaf) { leaf->setSeq(seq); } );
Yingdi Yud514c172014-08-26 21:49:39 -070058 return make_tuple(false, true, old);
59 }
60}
61
Ashlesh Gawande08784d42017-09-06 23:40:21 -050062ConstBufferPtr
Yingdi Yud514c172014-08-26 21:49:39 -070063State::getRootDigest() const
64{
65 m_digest.reset();
66
Davide Pesavento5f408ae2020-07-15 21:17:04 -040067 for (const auto& leaf : m_leaves.get<ordered>()) {
68 BOOST_ASSERT(leaf != nullptr);
69 m_digest.update(leaf->getDigest()->data(), leaf->getDigest()->size());
70 }
Yingdi Yud514c172014-08-26 21:49:39 -070071
72 return m_digest.computeDigest();
73}
74
Yingdi Yud514c172014-08-26 21:49:39 -070075void
76State::reset()
77{
78 m_leaves.clear();
79}
80
81State&
82State::operator+=(const State& state)
83{
Davide Pesavento5f408ae2020-07-15 21:17:04 -040084 for (const auto& leaf : state.getLeaves()) {
85 BOOST_ASSERT(leaf != nullptr);
86 update(leaf->getSessionName(), leaf->getSeq());
87 }
Yingdi Yud514c172014-08-26 21:49:39 -070088 return *this;
89}
90
Ashlesh Gawande08784d42017-09-06 23:40:21 -050091template<encoding::Tag T>
Yingdi Yud514c172014-08-26 21:49:39 -070092size_t
Ashlesh Gawande08784d42017-09-06 23:40:21 -050093State::wireEncode(encoding::EncodingImpl<T>& block) const
Yingdi Yud514c172014-08-26 21:49:39 -070094{
95 size_t totalLength = 0;
96
Davide Pesavento5f408ae2020-07-15 21:17:04 -040097 for (const auto& leaf : m_leaves.get<ordered>() | boost::adaptors::reversed) {
98 size_t entryLength = 0;
99 entryLength += prependNonNegativeIntegerBlock(block, tlv::SeqNo, leaf->getSeq());
100 entryLength += leaf->getSessionName().wireEncode(block);
101 entryLength += block.prependVarNumber(entryLength);
102 entryLength += block.prependVarNumber(tlv::StateLeaf);
103 totalLength += entryLength;
104 }
Yingdi Yud514c172014-08-26 21:49:39 -0700105
106 totalLength += block.prependVarNumber(totalLength);
107 totalLength += block.prependVarNumber(tlv::SyncReply);
108
109 return totalLength;
110}
111
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500112NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(State);
Yingdi Yud514c172014-08-26 21:49:39 -0700113
114const Block&
115State::wireEncode() const
116{
117 if (m_wire.hasWire())
118 return m_wire;
119
120 ndn::EncodingEstimator estimator;
121 size_t estimatedSize = wireEncode(estimator);
122
123 ndn::EncodingBuffer buffer(estimatedSize, 0);
124 wireEncode(buffer);
125
126 m_wire = buffer.block();
127 return m_wire;
128}
129
130void
131State::wireDecode(const Block& wire)
132{
133 if (!wire.hasWire())
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800134 BOOST_THROW_EXCEPTION(Error("The supplied block does not contain wire format"));
Yingdi Yud514c172014-08-26 21:49:39 -0700135
136 if (wire.type() != tlv::SyncReply)
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800137 BOOST_THROW_EXCEPTION(Error("Unexpected TLV type when decoding SyncReply: " +
138 boost::lexical_cast<std::string>(m_wire.type())));
Yingdi Yud514c172014-08-26 21:49:39 -0700139
140 wire.parse();
141 m_wire = wire;
142
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400143 for (auto it = wire.elements_begin(); it != wire.elements_end(); it++) {
Yingdi Yud514c172014-08-26 21:49:39 -0700144 if (it->type() == tlv::StateLeaf) {
145 it->parse();
146
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400147 auto val = it->elements_begin();
Yingdi Yud514c172014-08-26 21:49:39 -0700148 Name info(*val);
149 val++;
150
151 if (val != it->elements_end())
152 update(info, readNonNegativeInteger(*val));
153 else
Alexander Afanasyeve9eda8a2017-03-09 14:40:03 -0800154 BOOST_THROW_EXCEPTION(Error("No seqNo when decoding SyncReply"));
Yingdi Yud514c172014-08-26 21:49:39 -0700155 }
156 }
157}
158
159} // namespace chronosync