blob: f41bc0cde25c313afdfd87ef361acd73bfe100cb [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Lijing Wange84adea2015-05-31 16:25:16 -07003 * Copyright (c) 2013-2017, Regents of the University of California.
Zhenkai Zhu8224bb62013-01-06 15:58:02 -08004 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08005 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
Zhenkai Zhu8224bb62013-01-06 15:58:02 -08006 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08007 * ChronoShare is free software: you can redistribute it and/or modify it under the terms
8 * of the GNU General Public License as published by the Free Software Foundation, either
9 * version 3 of the License, or (at your option) any later version.
Zhenkai Zhu8224bb62013-01-06 15:58:02 -080010 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -080011 * ChronoShare is distributed in the hope that it will be useful, but WITHOUT ANY
12 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
13 * PARTICULAR PURPOSE. See the GNU General Public License for more details.
Zhenkai Zhu8224bb62013-01-06 15:58:02 -080014 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -080015 * You should have received copies of the GNU General Public License along with
16 * ChronoShare, e.g., in COPYING.md file. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * See AUTHORS.md for complete list of ChronoShare authors and contributors.
Zhenkai Zhu8224bb62013-01-06 15:58:02 -080019 */
20
21#ifndef SYNC_CORE_H
22#define SYNC_CORE_H
23
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080024#include "sync-log.hpp"
Lijing Wange84adea2015-05-31 16:25:16 -070025#include "core/chronoshare-common.hpp"
26#include "core/random-interval-generator.hpp"
Alexander Afanasyevabe952a2013-01-17 17:06:32 -080027
Lijing Wange84adea2015-05-31 16:25:16 -070028#include <ndn-cxx/face.hpp>
29#include <ndn-cxx/security/key-chain.hpp>
30#include <ndn-cxx/util/scheduler-scoped-event-id.hpp>
31#include <ndn-cxx/util/scheduler.hpp>
32
33#include <boost/iostreams/device/back_inserter.hpp>
34#include <boost/iostreams/filter/gzip.hpp>
35#include <boost/iostreams/filtering_stream.hpp>
36
37namespace ndn {
38namespace chronoshare {
39
40// No use this now
41template <class Msg>
42BufferPtr
43serializeMsg(const Msg& msg)
44{
45 int size = msg.ByteSize();
46 BufferPtr bytes = std::make_shared<Buffer>(size);
47 msg.SerializeToArray(bytes->buf(), size);
48 return bytes;
49}
50
51template <class Msg>
52shared_ptr<Msg>
53deserializeMsg(const Buffer& bytes)
54{
55 shared_ptr<Msg> retval(new Msg());
56 if (!retval->ParseFromArray(bytes.buf(), bytes.size())) {
57 // to indicate an error
58 return shared_ptr<Msg>();
59 }
60 return retval;
61}
62
63template <class Msg>
64BufferPtr
65serializeGZipMsg(const Msg& msg)
66{
67 std::vector<char> bytes; // Bytes couldn't work
68 {
69 boost::iostreams::filtering_ostream out;
70 out.push(boost::iostreams::gzip_compressor()); // gzip filter
71 out.push(boost::iostreams::back_inserter(bytes)); // back_inserter sink
72
73 msg.SerializeToOstream(&out);
74 }
75 BufferPtr uBytes = std::make_shared<Buffer>(bytes.size());
76 memcpy(&(*uBytes)[0], &bytes[0], bytes.size());
77 return uBytes;
78}
79
80template <class Msg>
81shared_ptr<Msg>
82deserializeGZipMsg(const Buffer& bytes)
83{
84 std::vector<char> sBytes(bytes.size());
85 memcpy(&sBytes[0], &bytes[0], bytes.size());
86 boost::iostreams::filtering_istream in;
87 in.push(boost::iostreams::gzip_decompressor()); // gzip filter
88 in.push(boost::make_iterator_range(sBytes)); // source
89
90 shared_ptr<Msg> retval = make_shared<Msg>();
91 if (!retval->ParseFromIstream(&in)) {
92 // to indicate an error
93 return shared_ptr<Msg>();
94 }
95
96 return retval;
97}
Zhenkai Zhu8224bb62013-01-06 15:58:02 -080098
99class SyncCore
100{
101public:
Lijing Wange84adea2015-05-31 16:25:16 -0700102 typedef function<void(SyncStateMsgPtr stateMsg)> StateMsgCallback;
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800103
Lijing Wange84adea2015-05-31 16:25:16 -0700104 static const int FRESHNESS; // seconds
105 static const std::string RECOVER;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800106 static const double WAIT; // seconds;
Zhenkai Zhue851b952013-01-13 22:29:57 -0800107 static const double RANDOM_PERCENT; // seconds;
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800108
Lijing Wange84adea2015-05-31 16:25:16 -0700109 class Error : public boost::exception, public std::runtime_error
110 {
111 public:
112 explicit Error(const std::string& what)
113 : std::runtime_error(what)
114 {
115 }
116 };
117
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800118public:
Lijing Wange84adea2015-05-31 16:25:16 -0700119 SyncCore(Face& face, SyncLogPtr syncLog, const Name& userName,
120 const Name& localPrefix // routable name used by the local user
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800121 ,
Lijing Wange84adea2015-05-31 16:25:16 -0700122 const Name& syncPrefix // the prefix for the sync collection
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800123 ,
124 const StateMsgCallback& callback // callback when state change is detected
125 ,
Lijing Wang8e56d082016-12-25 14:45:23 -0800126 time::seconds syncInterestInterval = time::seconds(0));
Zhenkai Zhu8224bb62013-01-06 15:58:02 -0800127 ~SyncCore();
128
Lijing Wange84adea2015-05-31 16:25:16 -0700129 void updateLocalState(sqlite3_int64);
130
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800131 void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800132 localStateChanged();
Zhenkai Zhu8224bb62013-01-06 15:58:02 -0800133
Alexander Afanasyeva2fabcf2013-02-05 11:26:37 -0800134 /**
135 * @brief Schedule an event to update local state with a small delay
136 *
137 * This call is preferred to localStateChanged if many local state updates
138 * are anticipated within a short period of time
139 */
140 void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800141 localStateChangedDelayed();
Alexander Afanasyeva2fabcf2013-02-05 11:26:37 -0800142
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800143 // ------------------ only used in test -------------------------
Lijing Wange84adea2015-05-31 16:25:16 -0700144
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800145public:
Lijing Wange84adea2015-05-31 16:25:16 -0700146 ConstBufferPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800147 root() const
148 {
Lijing Wange84adea2015-05-31 16:25:16 -0700149 return m_rootDigest;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800150 }
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800151
152 sqlite3_int64
Lijing Wange84adea2015-05-31 16:25:16 -0700153 seq(const Name& name);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800154
155private:
156 void
Lijing Wange84adea2015-05-31 16:25:16 -0700157 onRegisterFailed(const Name& prefix, const std::string& reason)
158 {
159 std::cerr << "ERROR: Failed to register prefix \"" << prefix << "\" in local hub's daemon ("
160 << reason << ")" << std::endl;
161 throw Error("ERROR: Failed to register prefix (" + reason + ")");
162 }
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800163
164 void
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800165 sendSyncInterest();
166
Zhenkai Zhue851b952013-01-13 22:29:57 -0800167 void
Lijing Wange84adea2015-05-31 16:25:16 -0700168 sendPeriodicSyncInterest(const time::seconds& interval);
Zhenkai Zhue851b952013-01-13 22:29:57 -0800169
170 void
Lijing Wange84adea2015-05-31 16:25:16 -0700171 recover(ConstBufferPtr digest);
Zhenkai Zhue851b952013-01-13 22:29:57 -0800172
173 void
Lijing Wange84adea2015-05-31 16:25:16 -0700174 handleInterest(const InterestFilter& filter, const Interest& interest);
175
176 void
177 handleSyncInterest(const Name& name);
178
179 void
180 handleRecoverInterest(const Name& name);
181
182 void
183 handleSyncInterestTimeout(const Interest& interest);
184
185 void
186 handleRecoverInterestTimeout(const Interest& interest);
187
188 void
189 handleSyncData(const Interest& interest, Data& data);
190
191 void
192 handleRecoverData(const Interest& interest, Data& data);
193
194 void
195 handleStateData(const Buffer& content);
196
197 void
198 deregister(const Name& name);
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800199
Alexander Afanasyevc507ac22013-01-21 16:01:58 -0800200private:
Lijing Wange84adea2015-05-31 16:25:16 -0700201 Face& m_face;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800202
Zhenkai Zhub330aed2013-01-17 13:29:37 -0800203 SyncLogPtr m_log;
Lijing Wange84adea2015-05-31 16:25:16 -0700204
205 Scheduler m_scheduler;
206 util::scheduler::ScopedEventId m_syncInterestEvent;
207 util::scheduler::ScopedEventId m_periodicInterestEvent;
208 util::scheduler::ScopedEventId m_localStateDelayedEvent;
209
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800210 StateMsgCallback m_stateMsgCallback;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800211
Lijing Wange84adea2015-05-31 16:25:16 -0700212 Name m_syncPrefix;
213 ConstBufferPtr m_rootDigest;
Zhenkai Zhu74dd53c2013-01-10 23:39:57 -0800214
Zhenkai Zhue573ae82013-01-15 13:15:52 -0800215 IntervalGeneratorPtr m_recoverWaitGenerator;
Zhenkai Zhu3b406592013-01-25 21:07:49 -0800216
Lijing Wang8e56d082016-12-25 14:45:23 -0800217 time::seconds m_syncInterestInterval;
Lijing Wange84adea2015-05-31 16:25:16 -0700218 KeyChain m_keyChain;
219 const RegisteredPrefixId* m_registeredPrefixId;
Zhenkai Zhu8224bb62013-01-06 15:58:02 -0800220};
221
Lijing Wange84adea2015-05-31 16:25:16 -0700222} // namespace chronoshare
223} // namespace ndn
224
Zhenkai Zhu8224bb62013-01-06 15:58:02 -0800225#endif // SYNC_CORE_H