blob: 2f31b8983eb911752cc3dea352f7f7858f9af960 [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>
Davide Pesaventoe7dc7762020-12-22 20:47:52 -050028#include <ndn-cxx/util/exception.hpp>
Davide Pesavento5f408ae2020-07-15 21:17:04 -040029
Yingdi Yud514c172014-08-26 21:49:39 -070030namespace chronosync {
31
Davide Pesavento5473abe2017-10-09 01:35:33 -040032State::~State() = default;
Yingdi Yud514c172014-08-26 21:49:39 -070033
Ashlesh Gawande08784d42017-09-06 23:40:21 -050034std::tuple<bool, bool, SeqNo>
Yingdi Yud514c172014-08-26 21:49:39 -070035State::update(const Name& info, const SeqNo& seq)
36{
37 m_wire.reset();
38
39 LeafContainer::iterator leaf = m_leaves.find(info);
40
41 if (leaf == m_leaves.end()) {
42 m_leaves.insert(make_shared<Leaf>(info, cref(seq)));
43 return make_tuple(true, false, 0);
44 }
45 else {
46 if ((*leaf)->getSeq() == seq || seq < (*leaf)->getSeq()) {
47 return make_tuple(false, false, 0);
48 }
49
50 SeqNo old = (*leaf)->getSeq();
Davide Pesavento5f408ae2020-07-15 21:17:04 -040051 m_leaves.modify(leaf, [=] (LeafPtr& leaf) { leaf->setSeq(seq); } );
Yingdi Yud514c172014-08-26 21:49:39 -070052 return make_tuple(false, true, old);
53 }
54}
55
Ashlesh Gawande08784d42017-09-06 23:40:21 -050056ConstBufferPtr
Yingdi Yud514c172014-08-26 21:49:39 -070057State::getRootDigest() const
58{
59 m_digest.reset();
60
Davide Pesavento5f408ae2020-07-15 21:17:04 -040061 for (const auto& leaf : m_leaves.get<ordered>()) {
62 BOOST_ASSERT(leaf != nullptr);
63 m_digest.update(leaf->getDigest()->data(), leaf->getDigest()->size());
64 }
Yingdi Yud514c172014-08-26 21:49:39 -070065
66 return m_digest.computeDigest();
67}
68
Yingdi Yud514c172014-08-26 21:49:39 -070069void
70State::reset()
71{
72 m_leaves.clear();
73}
74
75State&
76State::operator+=(const State& state)
77{
Davide Pesavento5f408ae2020-07-15 21:17:04 -040078 for (const auto& leaf : state.getLeaves()) {
79 BOOST_ASSERT(leaf != nullptr);
80 update(leaf->getSessionName(), leaf->getSeq());
81 }
Yingdi Yud514c172014-08-26 21:49:39 -070082 return *this;
83}
84
Ashlesh Gawande08784d42017-09-06 23:40:21 -050085template<encoding::Tag T>
Yingdi Yud514c172014-08-26 21:49:39 -070086size_t
Ashlesh Gawande08784d42017-09-06 23:40:21 -050087State::wireEncode(encoding::EncodingImpl<T>& block) const
Yingdi Yud514c172014-08-26 21:49:39 -070088{
89 size_t totalLength = 0;
90
Davide Pesavento5f408ae2020-07-15 21:17:04 -040091 for (const auto& leaf : m_leaves.get<ordered>() | boost::adaptors::reversed) {
92 size_t entryLength = 0;
93 entryLength += prependNonNegativeIntegerBlock(block, tlv::SeqNo, leaf->getSeq());
94 entryLength += leaf->getSessionName().wireEncode(block);
95 entryLength += block.prependVarNumber(entryLength);
96 entryLength += block.prependVarNumber(tlv::StateLeaf);
97 totalLength += entryLength;
98 }
Yingdi Yud514c172014-08-26 21:49:39 -070099
100 totalLength += block.prependVarNumber(totalLength);
101 totalLength += block.prependVarNumber(tlv::SyncReply);
102
103 return totalLength;
104}
105
Ashlesh Gawande08784d42017-09-06 23:40:21 -0500106NDN_CXX_DEFINE_WIRE_ENCODE_INSTANTIATIONS(State);
Yingdi Yud514c172014-08-26 21:49:39 -0700107
108const Block&
109State::wireEncode() const
110{
111 if (m_wire.hasWire())
112 return m_wire;
113
114 ndn::EncodingEstimator estimator;
115 size_t estimatedSize = wireEncode(estimator);
116
117 ndn::EncodingBuffer buffer(estimatedSize, 0);
118 wireEncode(buffer);
119
120 m_wire = buffer.block();
121 return m_wire;
122}
123
124void
125State::wireDecode(const Block& wire)
126{
127 if (!wire.hasWire())
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500128 NDN_THROW(Error("The supplied block does not contain wire format"));
Yingdi Yud514c172014-08-26 21:49:39 -0700129
130 if (wire.type() != tlv::SyncReply)
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500131 NDN_THROW(Error("Unexpected TLV type when decoding SyncReply: " + ndn::to_string(wire.type())));
Yingdi Yud514c172014-08-26 21:49:39 -0700132
133 wire.parse();
134 m_wire = wire;
135
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400136 for (auto it = wire.elements_begin(); it != wire.elements_end(); it++) {
Yingdi Yud514c172014-08-26 21:49:39 -0700137 if (it->type() == tlv::StateLeaf) {
138 it->parse();
139
Davide Pesavento5f408ae2020-07-15 21:17:04 -0400140 auto val = it->elements_begin();
Yingdi Yud514c172014-08-26 21:49:39 -0700141 Name info(*val);
142 val++;
143
144 if (val != it->elements_end())
145 update(info, readNonNegativeInteger(*val));
146 else
Davide Pesaventoe7dc7762020-12-22 20:47:52 -0500147 NDN_THROW(Error("No SeqNo when decoding SyncReply"));
Yingdi Yud514c172014-08-26 21:49:39 -0700148 }
149 }
150}
151
152} // namespace chronosync