blob: 260d49356a6c5e3844f27dfd6742f95dcf2b2c39 [file] [log] [blame]
Yingdi Yud514c172014-08-26 21:49:39 -07001/* -*- Mode: C++; c-file-style: "gnu"; indent-tabs-mode:nil -*- */
2/*
Davide Pesavento5f5101a2022-03-11 20:05:03 -05003 * Copyright (c) 2012-2022 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"
Davide Pesavento780e6462021-02-08 20:58:12 -050026#include "detail/tlv.hpp"
Yingdi Yud514c172014-08-26 21:49:39 -070027
Davide Pesavento5f408ae2020-07-15 21:17:04 -040028#include <boost/range/adaptor/reversed.hpp>
Davide Pesaventoe7dc7762020-12-22 20:47:52 -050029#include <ndn-cxx/util/exception.hpp>
Davide Pesavento5f408ae2020-07-15 21:17:04 -040030
Yingdi Yud514c172014-08-26 21:49:39 -070031namespace chronosync {
32
Davide Pesavento5473abe2017-10-09 01:35:33 -040033State::~State() = default;
Yingdi Yud514c172014-08-26 21:49:39 -070034
Ashlesh Gawande08784d42017-09-06 23:40:21 -050035std::tuple<bool, bool, SeqNo>
Yingdi Yud514c172014-08-26 21:49:39 -070036State::update(const Name& info, const SeqNo& seq)
37{
38 m_wire.reset();
39
Davide Pesavento780e6462021-02-08 20:58:12 -050040 auto leaf = m_leaves.find(info);
Yingdi Yud514c172014-08-26 21:49:39 -070041 if (leaf == m_leaves.end()) {
Davide Pesavento780e6462021-02-08 20:58:12 -050042 m_leaves.insert(make_shared<Leaf>(info, seq));
Davide Pesavento8663ed12022-07-23 03:04:27 -040043 return {true, false, 0};
Yingdi Yud514c172014-08-26 21:49:39 -070044 }
45 else {
46 if ((*leaf)->getSeq() == seq || seq < (*leaf)->getSeq()) {
Davide Pesavento8663ed12022-07-23 03:04:27 -040047 return {false, false, 0};
Yingdi Yud514c172014-08-26 21:49:39 -070048 }
49
50 SeqNo old = (*leaf)->getSeq();
Davide Pesavento5f5101a2022-03-11 20:05:03 -050051 m_leaves.modify(leaf, [seq] (LeafPtr& leaf) { leaf->setSeq(seq); } );
Davide Pesavento8663ed12022-07-23 03:04:27 -040052 return {false, true, old};
Yingdi Yud514c172014-08-26 21:49:39 -070053 }
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);
Davide Pesavento5f5101a2022-03-11 20:05:03 -050063 m_digest.update(*leaf->getDigest());
Davide Pesavento5f408ae2020-07-15 21:17:04 -040064 }
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
Davide Pesavento780e6462021-02-08 20:58:12 -050085template<ndn::encoding::Tag T>
Yingdi Yud514c172014-08-26 21:49:39 -070086size_t
Davide Pesavento780e6462021-02-08 20:58:12 -050087State::wireEncode(ndn::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 Pesavento8663ed12022-07-23 03:04:27 -0400131 NDN_THROW(Error("Unexpected TLV type when decoding SyncReply: " + std::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