blob: 6dde05c2055dbebabc5f6133965fa1326952700a [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyeva9369b42017-01-11 11:58:00 -08003 * Copyright (c) 2013-2017, Regents of the University of California.
Alexander Afanasyeva199f972013-01-02 19:37:26 -08004 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08005 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
Alexander Afanasyeva199f972013-01-02 19:37:26 -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.
Alexander Afanasyeva199f972013-01-02 19:37:26 -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.
Alexander Afanasyeva199f972013-01-02 19:37:26 -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.
Alexander Afanasyeva199f972013-01-02 19:37:26 -080019 */
20
Alexander Afanasyevf4cde4e2016-12-25 13:42:57 -080021#include "sync-log.hpp"
Lijing Wange84adea2015-05-31 16:25:16 -070022#include "core/logging.hpp"
Alexander Afanasyeva199f972013-01-02 19:37:26 -080023
Lijing Wange84adea2015-05-31 16:25:16 -070024#include <ndn-cxx/util/sqlite3-statement.hpp>
25#include <ndn-cxx/util/string-helper.hpp>
26
27namespace ndn {
28namespace chronoshare {
29
30using util::Sqlite3Statement;
Alexander Afanasyeva199f972013-01-02 19:37:26 -080031
Alexander Afanasyev1cf5c432017-01-13 23:22:15 -080032_LOG_INIT(Sync.Log);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -080033
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080034// static void
35// xTrace(void*, const char* q)
Alexander Afanasyevd7245812013-02-13 21:06:57 -080036// {
37// cout << q << endl;
38// }
Alexander Afanasyevbeee0b42013-01-16 18:25:08 -080039
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080040const std::string INIT_DATABASE = "\
41CREATE TABLE \n\
42 SyncNodes( \n\
43 device_id INTEGER PRIMARY KEY AUTOINCREMENT, \n\
44 device_name BLOB NOT NULL, \n\
45 description TEXT, \n\
46 seq_no INTEGER NOT NULL, \n\
47 last_known_locator BLOB, \n\
48 last_update TIMESTAMP \n\
49 ); \n\
50 \n\
51CREATE TRIGGER SyncNodesUpdater_trigger \n\
52 BEFORE INSERT ON SyncNodes \n\
53 FOR EACH ROW \n\
54 WHEN (SELECT device_id \n\
55 FROM SyncNodes \n\
56 WHERE device_name=NEW.device_name) \n\
57 IS NOT NULL \n\
58 BEGIN \n\
59 UPDATE SyncNodes \n\
60 SET seq_no=max(seq_no,NEW.seq_no) \n\
61 WHERE device_name=NEW.device_name; \n\
62 SELECT RAISE(IGNORE); \n\
63 END; \n\
64 \n\
65CREATE INDEX SyncNodes_device_name ON SyncNodes (device_name); \n\
66 \n\
67CREATE TABLE SyncLog( \n\
68 state_id INTEGER PRIMARY KEY AUTOINCREMENT, \n\
69 state_hash BLOB NOT NULL UNIQUE, \n\
70 last_update TIMESTAMP NOT NULL \n\
71 ); \n\
72 \n\
73CREATE TABLE \n\
74 SyncStateNodes( \n\
75 id INTEGER PRIMARY KEY AUTOINCREMENT, \n\
76 state_id INTEGER NOT NULL \n\
77 REFERENCES SyncLog (state_id) ON UPDATE CASCADE ON DELETE CASCADE, \n\
78 device_id INTEGER NOT NULL \n\
79 REFERENCES SyncNodes (device_id) ON UPDATE CASCADE ON DELETE CASCADE, \n\
80 seq_no INTEGER NOT NULL \n\
81 ); \n\
82 \n\
83CREATE INDEX SyncStateNodes_device_id ON SyncStateNodes (device_id); \n\
84CREATE INDEX SyncStateNodes_state_id ON SyncStateNodes (state_id); \n\
85CREATE INDEX SyncStateNodes_seq_no ON SyncStateNodes (seq_no); \n\
86 \n\
87CREATE TRIGGER SyncLogGuard_trigger \n\
88 BEFORE INSERT ON SyncLog \n\
89 FOR EACH ROW \n\
90 WHEN (SELECT state_hash \n\
91 FROM SyncLog \n\
92 WHERE state_hash=NEW.state_hash) \n\
93 IS NOT NULL \n\
94 BEGIN \n\
95 DELETE FROM SyncLog WHERE state_hash=NEW.state_hash; \n\
96 END; \n\
97";
98
Lijing Wange84adea2015-05-31 16:25:16 -070099SyncLog::SyncLog(const boost::filesystem::path& path, const Name& localName)
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800100 : DbHelper(path / ".chronoshare", "sync-log.db")
101 , m_localName(localName)
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800102{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800103 sqlite3_exec(m_db, INIT_DATABASE.c_str(), NULL, NULL, NULL);
Alexander Afanasyev1cf5c432017-01-13 23:22:15 -0800104 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, "DB Constructor: " << sqlite3_errmsg(m_db));
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -0800105
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800106 UpdateDeviceSeqNo(localName, 0);
Alexander Afanasyev66f4c492013-01-20 23:32:50 -0800107
Lijing Wange84adea2015-05-31 16:25:16 -0700108 Sqlite3Statement stmt(m_db, "SELECT device_id, seq_no FROM SyncNodes WHERE device_name=?");
109 stmt.bind(1, m_localName.wireEncode(), SQLITE_STATIC);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800110
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800111 if (sqlite3_step(stmt) == SQLITE_ROW) {
Lijing Wange84adea2015-05-31 16:25:16 -0700112 m_localDeviceId = stmt.getInt(0);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800113 }
114 else {
Lijing Wange84adea2015-05-31 16:25:16 -0700115 BOOST_THROW_EXCEPTION(Error("Impossible thing in SyncLog::SyncLog"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800116 }
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800117}
118
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800119sqlite3_int64
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800120SyncLog::GetNextLocalSeqNo()
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800121{
Lijing Wange84adea2015-05-31 16:25:16 -0700122 Sqlite3Statement stmt_seq(m_db, "SELECT seq_no FROM SyncNodes WHERE device_id = ?");
123 stmt_seq.bind(1, m_localDeviceId);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800124
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800125 if (sqlite3_step(stmt_seq) != SQLITE_ROW) {
Lijing Wange84adea2015-05-31 16:25:16 -0700126 BOOST_THROW_EXCEPTION(Error("Impossible thing in SyncLog::GetNextLocalSeqNo"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800127 }
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800128
Lijing Wange84adea2015-05-31 16:25:16 -0700129 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE,
130 "DB GetNextLocalSeqNo: " << sqlite3_errmsg(m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800131
Lijing Wange84adea2015-05-31 16:25:16 -0700132 sqlite3_int64 seq_no = stmt_seq.getInt(0) + 1;
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800133
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800134 UpdateDeviceSeqNo(m_localDeviceId, seq_no);
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800135
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800136 return seq_no;
137}
138
Lijing Wange84adea2015-05-31 16:25:16 -0700139ConstBufferPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800140SyncLog::RememberStateInStateLog()
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800141{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800142 WriteLock lock(m_stateUpdateMutex);
Alexander Afanasyevbeee0b42013-01-16 18:25:08 -0800143
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800144 int res = sqlite3_exec(m_db, "BEGIN TRANSACTION;", 0, 0, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800145
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800146 res += sqlite3_exec(m_db, "\
Alexander Afanasyev49ab6f82013-01-15 16:58:13 -0800147INSERT INTO SyncLog \
148 (state_hash, last_update) \
149 SELECT \
150 hash(device_name, seq_no), datetime('now') \
151 FROM (SELECT * FROM SyncNodes \
152 ORDER BY device_name); \
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800153",
154 0, 0, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800155
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800156 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, "DbError: " << sqlite3_errmsg(m_db));
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800157
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800158 if (res != SQLITE_OK) {
159 sqlite3_exec(m_db, "ROLLBACK TRANSACTION;", 0, 0, 0);
Lijing Wange84adea2015-05-31 16:25:16 -0700160 BOOST_THROW_EXCEPTION(Error(sqlite3_errmsg(m_db)));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800161 }
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800162
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800163 sqlite3_int64 rowId = sqlite3_last_insert_rowid(m_db);
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800164
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800165 sqlite3_stmt* insertStmt;
166 res += sqlite3_prepare(m_db, "\
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800167INSERT INTO SyncStateNodes \
168 (state_id, device_id, seq_no) \
169 SELECT ?, device_id, seq_no \
170 FROM SyncNodes; \
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800171",
172 -1, &insertStmt, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800173
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800174 res += sqlite3_bind_int64(insertStmt, 1, rowId);
175 sqlite3_step(insertStmt);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800176
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800177 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, "DbError: " << sqlite3_errmsg(m_db));
178 if (res != SQLITE_OK) {
179 sqlite3_exec(m_db, "ROLLBACK TRANSACTION;", 0, 0, 0);
Lijing Wange84adea2015-05-31 16:25:16 -0700180 BOOST_THROW_EXCEPTION(Error(sqlite3_errmsg(m_db)));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800181 }
182 sqlite3_finalize(insertStmt);
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800183
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800184 sqlite3_stmt* getHashStmt;
185 res += sqlite3_prepare(m_db, "\
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800186SELECT state_hash FROM SyncLog WHERE state_id = ?\
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800187",
188 -1, &getHashStmt, 0);
189 res += sqlite3_bind_int64(getHashStmt, 1, rowId);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800190
Lijing Wange84adea2015-05-31 16:25:16 -0700191 BufferPtr retval;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800192 int stepRes = sqlite3_step(getHashStmt);
193 if (stepRes == SQLITE_ROW) {
Lijing Wange84adea2015-05-31 16:25:16 -0700194 retval = make_shared<Buffer>(static_cast<const uint8_t*>(sqlite3_column_blob(getHashStmt, 0)),
195 sqlite3_column_bytes(getHashStmt, 0));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800196 }
197 else {
198 sqlite3_exec(m_db, "ROLLBACK TRANSACTION;", 0, 0, 0);
Alexander Afanasyevbeee0b42013-01-16 18:25:08 -0800199
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800200 _LOG_ERROR("DbError: " << sqlite3_errmsg(m_db));
Lijing Wange84adea2015-05-31 16:25:16 -0700201 BOOST_THROW_EXCEPTION(Error("Not a valid hash in rememberStateInStateLog"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800202 }
203 sqlite3_finalize(getHashStmt);
204 res += sqlite3_exec(m_db, "COMMIT;", 0, 0, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800205
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800206 if (res != SQLITE_OK) {
207 sqlite3_exec(m_db, "ROLLBACK TRANSACTION;", 0, 0, 0);
Lijing Wange84adea2015-05-31 16:25:16 -0700208 BOOST_THROW_EXCEPTION(Error("Some error with rememberStateInStateLog"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800209 }
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800210
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800211 return retval;
212}
213
214sqlite3_int64
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800215SyncLog::LookupSyncLog(const std::string& stateHash)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800216{
Lijing Wange84adea2015-05-31 16:25:16 -0700217 return LookupSyncLog(*fromHex(stateHash));
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800218}
219
220sqlite3_int64
Lijing Wange84adea2015-05-31 16:25:16 -0700221SyncLog::LookupSyncLog(const Buffer& stateHash)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800222{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800223 sqlite3_stmt* stmt;
224 int res = sqlite3_prepare(m_db, "SELECT state_id FROM SyncLog WHERE state_hash = ?", -1, &stmt, 0);
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800225
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800226 if (res != SQLITE_OK) {
Lijing Wange84adea2015-05-31 16:25:16 -0700227 BOOST_THROW_EXCEPTION(Error("Cannot prepare statement"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800228 }
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800229
Lijing Wange84adea2015-05-31 16:25:16 -0700230 res = sqlite3_bind_blob(stmt, 1, stateHash.buf(), stateHash.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800231 if (res != SQLITE_OK) {
Lijing Wange84adea2015-05-31 16:25:16 -0700232 BOOST_THROW_EXCEPTION(Error("Cannot bind"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800233 }
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800234
235 sqlite3_int64 row = 0; // something bad
236
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800237 if (sqlite3_step(stmt) == SQLITE_ROW) {
238 row = sqlite3_column_int64(stmt, 0);
239 }
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800240
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800241 sqlite3_finalize(stmt);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800242
243 return row;
244}
245
246void
Lijing Wange84adea2015-05-31 16:25:16 -0700247SyncLog::UpdateDeviceSeqNo(const Name& name, sqlite3_int64 seqNo)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800248{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800249 sqlite3_stmt* stmt;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800250 // update is performed using trigger
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800251 int res =
252 sqlite3_prepare(m_db, "INSERT INTO SyncNodes (device_name, seq_no) VALUES (?,?);", -1, &stmt, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800253
Lijing Wange84adea2015-05-31 16:25:16 -0700254 res +=
255 sqlite3_bind_blob(stmt, 1, name.wireEncode().wire(), name.wireEncode().size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800256 res += sqlite3_bind_int64(stmt, 2, seqNo);
257 sqlite3_step(stmt);
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800258
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800259 if (res != SQLITE_OK) {
Lijing Wange84adea2015-05-31 16:25:16 -0700260 BOOST_THROW_EXCEPTION(Error("Some error with UpdateDeviceSeqNo(name)"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800261 }
262 sqlite3_finalize(stmt);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800263}
264
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800265void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800266SyncLog::UpdateLocalSeqNo(sqlite3_int64 seqNo)
Alexander Afanasyev7326a252013-01-20 23:43:25 -0800267{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800268 return UpdateDeviceSeqNo(m_localDeviceId, seqNo);
Alexander Afanasyev7326a252013-01-20 23:43:25 -0800269}
270
271void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800272SyncLog::UpdateDeviceSeqNo(sqlite3_int64 deviceId, sqlite3_int64 seqNo)
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800273{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800274 sqlite3_stmt* stmt;
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800275 // update is performed using trigger
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800276 int res = sqlite3_prepare(m_db, "UPDATE SyncNodes SET seq_no=MAX(seq_no,?) WHERE device_id=?;",
277 -1, &stmt, 0);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800278
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800279 res += sqlite3_bind_int64(stmt, 1, seqNo);
280 res += sqlite3_bind_int64(stmt, 2, deviceId);
281 sqlite3_step(stmt);
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800282
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800283 if (res != SQLITE_OK) {
Lijing Wange84adea2015-05-31 16:25:16 -0700284 BOOST_THROW_EXCEPTION(Error("Some error with UpdateDeviceSeqNo(id)"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800285 }
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800286
Lijing Wange84adea2015-05-31 16:25:16 -0700287 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK,
288 "DB UpdateDeviceSeqNo: " << sqlite3_errmsg(m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800289
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800290 sqlite3_finalize(stmt);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800291}
292
Zhenkai Zhue851b952013-01-13 22:29:57 -0800293Name
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800294SyncLog::LookupLocator(const Name& deviceName)
Zhenkai Zhue851b952013-01-13 22:29:57 -0800295{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800296 sqlite3_stmt* stmt;
297 sqlite3_prepare_v2(m_db, "SELECT last_known_locator FROM SyncNodes WHERE device_name=?;", -1,
298 &stmt, 0);
Lijing Wange84adea2015-05-31 16:25:16 -0700299 sqlite3_bind_blob(stmt, 1, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
300 SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800301 int res = sqlite3_step(stmt);
Zhenkai Zhue851b952013-01-13 22:29:57 -0800302 Name locator;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800303 switch (res) {
304 case SQLITE_ROW: {
Lijing Wange84adea2015-05-31 16:25:16 -0700305 locator = Name(Block(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0)));
Zhenkai Zhue851b952013-01-13 22:29:57 -0800306 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800307 case SQLITE_DONE:
308 break;
309 default:
Lijing Wange84adea2015-05-31 16:25:16 -0700310 BOOST_THROW_EXCEPTION(Error("Error in LookupLocator()"));
Zhenkai Zhue851b952013-01-13 22:29:57 -0800311 }
312
313 sqlite3_finalize(stmt);
314
315 return locator;
316}
317
Lijing Wange84adea2015-05-31 16:25:16 -0700318Name
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800319SyncLog::LookupLocalLocator()
Alexander Afanasyev758f51b2013-01-24 13:48:18 -0800320{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800321 return LookupLocator(m_localName);
Alexander Afanasyev758f51b2013-01-24 13:48:18 -0800322}
323
Zhenkai Zhue851b952013-01-13 22:29:57 -0800324void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800325SyncLog::UpdateLocator(const Name& deviceName, const Name& locator)
Zhenkai Zhue851b952013-01-13 22:29:57 -0800326{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800327 sqlite3_stmt* stmt;
Lijing Wange84adea2015-05-31 16:25:16 -0700328 sqlite3_prepare_v2(m_db, "UPDATE SyncNodes SET last_known_locator=?,last_update=datetime('now', "
329 "'localtime') WHERE device_name=?;",
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800330 -1, &stmt, 0);
Lijing Wange84adea2015-05-31 16:25:16 -0700331
332 sqlite3_bind_blob(stmt, 1, locator.wireEncode().wire(), locator.wireEncode().size(), SQLITE_STATIC);
333 sqlite3_bind_blob(stmt, 2, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
334 SQLITE_STATIC);
335
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800336 int res = sqlite3_step(stmt);
Zhenkai Zhue851b952013-01-13 22:29:57 -0800337
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800338 if (res != SQLITE_OK && res != SQLITE_DONE) {
Lijing Wange84adea2015-05-31 16:25:16 -0700339 BOOST_THROW_EXCEPTION(Error("Error in UpdateLoactor()"));
Zhenkai Zhue851b952013-01-13 22:29:57 -0800340 }
341
342 sqlite3_finalize(stmt);
343}
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800344
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800345void
Lijing Wange84adea2015-05-31 16:25:16 -0700346SyncLog::UpdateLocalLocator(const Name& forwardingHint)
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800347{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800348 return UpdateLocator(m_localName, forwardingHint);
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800349}
350
Alexander Afanasyev6f70a0f2013-01-02 20:44:09 -0800351SyncStateMsgPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800352SyncLog::FindStateDifferences(const std::string& oldHash, const std::string& newHash,
353 bool includeOldSeq)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800354{
Lijing Wange84adea2015-05-31 16:25:16 -0700355 return FindStateDifferences(*fromHex(oldHash), *fromHex(newHash), includeOldSeq);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800356}
357
Alexander Afanasyev6f70a0f2013-01-02 20:44:09 -0800358SyncStateMsgPtr
Lijing Wange84adea2015-05-31 16:25:16 -0700359SyncLog::FindStateDifferences(const Buffer& oldHash, const Buffer& newHash, bool includeOldSeq)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800360{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800361 sqlite3_stmt* stmt;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800362
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800363 int res = sqlite3_prepare_v2(m_db, "\
Zhenkai Zhue851b952013-01-13 22:29:57 -0800364SELECT sn.device_name, sn.last_known_locator, s_old.seq_no, s_new.seq_no\
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800365 FROM (SELECT * \
366 FROM SyncStateNodes \
367 WHERE state_id=(SELECT state_id \
368 FROM SyncLog \
369 WHERE state_hash=:old_hash)) s_old \
370 LEFT JOIN (SELECT * \
371 FROM SyncStateNodes \
372 WHERE state_id=(SELECT state_id \
373 FROM SyncLog \
374 WHERE state_hash=:new_hash)) s_new \
375 \
376 ON s_old.device_id = s_new.device_id \
377 JOIN SyncNodes sn ON sn.device_id = s_old.device_id \
378 \
379 WHERE s_new.seq_no IS NULL OR \
380 s_old.seq_no != s_new.seq_no \
381 \
382UNION ALL \
383 \
Zhenkai Zhue851b952013-01-13 22:29:57 -0800384SELECT sn.device_name, sn.last_known_locator, s_old.seq_no, s_new.seq_no\
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800385 FROM (SELECT * \
386 FROM SyncStateNodes \
387 WHERE state_id=(SELECT state_id \
388 FROM SyncLog \
389 WHERE state_hash=:new_hash )) s_new \
390 LEFT JOIN (SELECT * \
391 FROM SyncStateNodes \
392 WHERE state_id=(SELECT state_id \
393 FROM SyncLog \
394 WHERE state_hash=:old_hash)) s_old \
395 \
396 ON s_old.device_id = s_new.device_id \
397 JOIN SyncNodes sn ON sn.device_id = s_new.device_id \
398 \
399 WHERE s_old.seq_no IS NULL \
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800400",
401 -1, &stmt, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800402
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800403 if (res != SQLITE_OK) {
Lijing Wange84adea2015-05-31 16:25:16 -0700404 BOOST_THROW_EXCEPTION(Error("Some error with FindStateDifferences"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800405 }
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800406
Lijing Wange84adea2015-05-31 16:25:16 -0700407 res += sqlite3_bind_blob(stmt, 1, oldHash.buf(), oldHash.size(), SQLITE_STATIC);
408 res += sqlite3_bind_blob(stmt, 2, newHash.buf(), newHash.size(), SQLITE_STATIC);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800409
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800410 SyncStateMsgPtr msg = make_shared<SyncStateMsg>();
Alexander Afanasyeva44a7a22013-01-14 17:37:06 -0800411
412 // sqlite3_trace(m_db, xTrace, NULL);
Alexander Afanasyevdac84922013-01-20 23:32:17 -0800413
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800414 while (sqlite3_step(stmt) == SQLITE_ROW) {
415 SyncState* state = msg->add_state();
Alexander Afanasyev6f70a0f2013-01-02 20:44:09 -0800416
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800417 // set name
418 state->set_name(reinterpret_cast<const char*>(sqlite3_column_blob(stmt, 0)),
419 sqlite3_column_bytes(stmt, 0));
Alexander Afanasyev6f70a0f2013-01-02 20:44:09 -0800420
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800421 // locator is optional, so must check if it is null
422 if (sqlite3_column_type(stmt, 1) == SQLITE_BLOB) {
423 state->set_locator(reinterpret_cast<const char*>(sqlite3_column_blob(stmt, 1)),
424 sqlite3_column_bytes(stmt, 1));
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800425 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800426
427 // set old seq
428 if (includeOldSeq) {
429 if (sqlite3_column_type(stmt, 2) == SQLITE_NULL) {
430 // old seq is zero; we always have an initial action of zero seq
431 // other's do not need to fetch this action
432 state->set_old_seq(0);
433 }
434 else {
435 sqlite3_int64 oldSeqNo = sqlite3_column_int64(stmt, 2);
436 state->set_old_seq(oldSeqNo);
437 }
438 }
439
440 // set new seq
441 if (sqlite3_column_type(stmt, 3) == SQLITE_NULL) {
442 state->set_type(SyncState::DELETE);
443 }
444 else {
445 sqlite3_int64 newSeqNo = sqlite3_column_int64(stmt, 3);
446 state->set_type(SyncState::UPDATE);
447 state->set_seq(newSeqNo);
448 }
449
450 // std::cout << sqlite3_column_text (stmt, 0) <<
451 // ": from " << sqlite3_column_int64 (stmt, 1) <<
452 // " to " << sqlite3_column_int64 (stmt, 2) <<
453 // std::endl;
454 }
455 sqlite3_finalize(stmt);
Alexander Afanasyev6f70a0f2013-01-02 20:44:09 -0800456
Alexander Afanasyeva44a7a22013-01-14 17:37:06 -0800457 // sqlite3_trace(m_db, NULL, NULL);
458
Alexander Afanasyev6f70a0f2013-01-02 20:44:09 -0800459 return msg;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800460}
Zhenkai Zhu9501b8b2013-01-17 12:37:00 -0800461
462sqlite3_int64
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800463SyncLog::SeqNo(const Name& name)
Zhenkai Zhu9501b8b2013-01-17 12:37:00 -0800464{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800465 sqlite3_stmt* stmt;
Zhenkai Zhu9501b8b2013-01-17 12:37:00 -0800466 sqlite3_int64 seq = -1;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800467 sqlite3_prepare_v2(m_db, "SELECT seq_no FROM SyncNodes WHERE device_name=?;", -1, &stmt, 0);
Lijing Wange84adea2015-05-31 16:25:16 -0700468
469 sqlite3_bind_blob(stmt, 1, name.wireEncode().wire(), name.wireEncode().size(), SQLITE_STATIC);
470
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800471 if (sqlite3_step(stmt) == SQLITE_ROW) {
472 seq = sqlite3_column_int64(stmt, 0);
Zhenkai Zhu9501b8b2013-01-17 12:37:00 -0800473 }
474
475 return seq;
476}
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800477
478sqlite3_int64
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800479SyncLog::LogSize()
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800480{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800481 sqlite3_stmt* stmt;
482 sqlite3_prepare_v2(m_db, "SELECT count(*) FROM SyncLog", -1, &stmt, 0);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800483
484 sqlite3_int64 retval = -1;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800485 if (sqlite3_step(stmt) == SQLITE_ROW) {
486 retval = sqlite3_column_int64(stmt, 0);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800487 }
488
489 return retval;
490}
Lijing Wange84adea2015-05-31 16:25:16 -0700491
492} // namespace chronoshare
493} // namespace ndn