blob: 328d5f4e2c96f20e56d8d52f5d77569372e70f70 [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyev1cf5c432017-01-13 23:22:15 -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 "action-log.hpp"
Lijing Wang51837ad2016-12-25 14:43:53 -080022#include "sync-core.hpp"
23#include "core/logging.hpp"
Alexander Afanasyeva199f972013-01-02 19:37:26 -080024
Lijing Wang51837ad2016-12-25 14:43:53 -080025#include <ndn-cxx/util/string-helper.hpp>
Alexander Afanasyev0995f322013-01-22 13:16:46 -080026
Lijing Wang51837ad2016-12-25 14:43:53 -080027namespace ndn {
28namespace chronoshare {
Alexander Afanasyeva199f972013-01-02 19:37:26 -080029
Alexander Afanasyev1cf5c432017-01-13 23:22:15 -080030_LOG_INIT(ActionLog);
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080031
32const std::string INIT_DATABASE = "\
33CREATE TABLE ActionLog ( \n\
Alexander Afanasyev0995f322013-01-22 13:16:46 -080034 device_name BLOB NOT NULL, \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080035 seq_no INTEGER NOT NULL, \n\
36 \n\
37 action CHAR(1) NOT NULL, /* 0 for \"update\", 1 for \"delete\". */ \n\
38 filename TEXT NOT NULL, \n\
Alexander Afanasyev95f9f552013-02-26 23:05:20 -080039 directory TEXT, \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080040 \n\
41 version INTEGER NOT NULL, \n\
42 action_timestamp TIMESTAMP NOT NULL, \n\
43 \n\
44 file_hash BLOB, /* NULL if action is \"delete\" */ \n\
45 file_atime TIMESTAMP, \n\
46 file_mtime TIMESTAMP, \n\
47 file_ctime TIMESTAMP, \n\
48 file_chmod INTEGER, \n\
49 file_seg_num INTEGER, /* NULL if action is \"delete\" */ \n\
50 \n\
Alexander Afanasyev0995f322013-01-22 13:16:46 -080051 parent_device_name BLOB, \n\
52 parent_seq_no INTEGER, \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080053 \n\
54 action_name TEXT, \n\
55 action_content_object BLOB, \n\
56 \n\
Alexander Afanasyev785b0a02013-01-30 10:17:47 -080057 PRIMARY KEY (device_name, seq_no) \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080058); \n\
59 \n\
Alexander Afanasyev0995f322013-01-22 13:16:46 -080060CREATE INDEX ActionLog_filename_version ON ActionLog (filename,version); \n\
61CREATE INDEX ActionLog_parent ON ActionLog (parent_device_name, parent_seq_no); \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080062CREATE INDEX ActionLog_action_name ON ActionLog (action_name); \n\
Alexander Afanasyev026eaf32013-02-23 16:37:14 -080063CREATE INDEX ActionLog_filename_version_hash ON ActionLog (filename,version,file_hash); \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080064 \n\
65CREATE TRIGGER ActionLogInsert_trigger \n\
66 AFTER INSERT ON ActionLog \n\
67 FOR EACH ROW \n\
Alexander Afanasyev0995f322013-01-22 13:16:46 -080068 WHEN (SELECT device_name \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080069 FROM ActionLog \n\
70 WHERE filename=NEW.filename AND \n\
71 version > NEW.version) IS NULL AND \n\
Alexander Afanasyev0995f322013-01-22 13:16:46 -080072 (SELECT device_name \n\
73 FROM ActionLog \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080074 WHERE filename=NEW.filename AND \n\
75 version = NEW.version AND \n\
Alexander Afanasyeva35756b2013-01-22 16:59:11 -080076 device_name > NEW.device_name) IS NULL \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080077 BEGIN \n\
Alexander Afanasyev0995f322013-01-22 13:16:46 -080078 SELECT apply_action (NEW.device_name, NEW.seq_no, \
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -080079 NEW.action,NEW.filename,NEW.version,NEW.file_hash, \
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080080 strftime('%s', NEW.file_atime),strftime('%s', NEW.file_mtime),strftime('%s', NEW.file_ctime), \
Lijing Wang51837ad2016-12-25 14:43:53 -080081 NEW.file_chmod, NEW.file_seg_num); \n\
82 /* function that applies action and adds record the FileState */ \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080083 END; \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080084";
85
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080086// static void
87// xTrace(void*, const char* q)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080088// {
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080089// _LOG_TRACE("SQLITE: " << q);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080090// }
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080091
Lijing Wang51837ad2016-12-25 14:43:53 -080092ActionLog::ActionLog(Face& face, const boost::filesystem::path& path, SyncLogPtr syncLog,
Lijing Wang8e56d082016-12-25 14:45:23 -080093 const std::string& sharedFolder, const name::Component& appName,
Lijing Wang51837ad2016-12-25 14:43:53 -080094 OnFileAddedOrChangedCallback onFileAddedOrChanged,
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080095 OnFileRemovedCallback onFileRemoved)
96 : DbHelper(path / ".chronoshare", "action-log.db")
97 , m_syncLog(syncLog)
Lijing Wang51837ad2016-12-25 14:43:53 -080098 // , m_face(face)
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080099 , m_sharedFolderName(sharedFolder)
100 , m_appName(appName)
101 , m_onFileAddedOrChanged(onFileAddedOrChanged)
102 , m_onFileRemoved(onFileRemoved)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800103{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800104 sqlite3_exec(m_db, "PRAGMA foreign_keys = OFF", NULL, NULL, NULL);
105 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev785b0a02013-01-30 10:17:47 -0800106
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800107 sqlite3_exec(m_db, INIT_DATABASE.c_str(), NULL, NULL, NULL);
108 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -0800109
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800110 int res =
111 sqlite3_create_function(m_db, "apply_action", -1, SQLITE_ANY, reinterpret_cast<void*>(this),
112 ActionLog::apply_action_xFun, 0, 0);
113 if (res != SQLITE_OK) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800114 BOOST_THROW_EXCEPTION(Error("Cannot create function ``apply_action''"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800115 }
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800116
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800117 m_fileState = make_shared<FileState>(path);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800118}
119
Lijing Wang51837ad2016-12-25 14:43:53 -0800120std::tuple<sqlite3_int64 /*version*/, BufferPtr /*device name*/, sqlite3_int64 /*seq_no*/>
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800121ActionLog::GetLatestActionForFile(const std::string& filename)
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800122{
123 // check if something already exists
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800124 sqlite3_stmt* stmt;
125 int res = sqlite3_prepare_v2(m_db, "SELECT version,device_name,seq_no,action "
126 "FROM ActionLog "
127 "WHERE filename=? ORDER BY version DESC LIMIT 1",
128 -1, &stmt, 0);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800129
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800130 if (res != SQLITE_OK) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800131 BOOST_THROW_EXCEPTION(Error("Some error with GetExistingRecord"));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800132 }
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800133
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800134 sqlite3_int64 version = -1;
Lijing Wang51837ad2016-12-25 14:43:53 -0800135 BufferPtr parent_device_name;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800136 sqlite3_int64 parent_seq_no = -1;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800137
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800138 sqlite3_bind_text(stmt, 1, filename.c_str(), filename.size(), SQLITE_STATIC);
139 if (sqlite3_step(stmt) == SQLITE_ROW) {
140 version = sqlite3_column_int64(stmt, 0);
141
142 if (sqlite3_column_int(stmt, 3) == 0) // prevent "linking" if the file was previously deleted
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800143 {
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800144 parent_device_name =
Lijing Wang51837ad2016-12-25 14:43:53 -0800145 std::make_shared<Buffer>(sqlite3_column_blob(stmt, 1), sqlite3_column_bytes(stmt, 1));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800146 parent_seq_no = sqlite3_column_int64(stmt, 2);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800147 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800148 }
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800149
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800150 sqlite3_finalize(stmt);
Lijing Wang51837ad2016-12-25 14:43:53 -0800151 return std::make_tuple(version, parent_device_name, parent_seq_no);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800152}
153
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800154// local add action. remote action is extracted from content object
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800155ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800156ActionLog::AddLocalActionUpdate(const std::string& filename, const Buffer& hash, time_t wtime,
157 int mode, int seg_num)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800158{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800159 sqlite3_exec(m_db, "BEGIN TRANSACTION;", 0, 0, 0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800160
Lijing Wang51837ad2016-12-25 14:43:53 -0800161 Block device_name = m_syncLog->GetLocalName().wireEncode();
162
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800163 sqlite3_int64 seq_no = m_syncLog->GetNextLocalSeqNo();
164 sqlite3_int64 version;
Lijing Wang51837ad2016-12-25 14:43:53 -0800165 BufferPtr parent_device_name;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800166 sqlite3_int64 parent_seq_no = -1;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800167
Lijing Wang51837ad2016-12-25 14:43:53 -0800168 sqlite3_int64 action_time = std::time(0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800169
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800170 tie(version, parent_device_name, parent_seq_no) = GetLatestActionForFile(filename);
171 version++;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800172
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800173 sqlite3_stmt* stmt;
174 int res =
175 sqlite3_prepare_v2(m_db,
176 "INSERT INTO ActionLog "
177 "(device_name, seq_no, action, filename, version, action_timestamp, "
178 "file_hash, file_atime, file_mtime, file_ctime, file_chmod, file_seg_num, "
179 "parent_device_name, parent_seq_no, "
180 "action_name, action_content_object) "
Yukai Tu40f184f2017-01-26 09:00:43 -0800181 "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch', 'localtime'),"
182 " ?, datetime(?, 'unixepoch', 'localtime'), datetime(?, 'unixepoch', 'localtime'), "
183 " datetime(?, 'unixepoch', 'localtime'), ?, ?, "
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800184 " ?, ?, "
185 " ?, ?);",
186 -1, &stmt, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800187
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800188 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800189
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800190 if (res != SQLITE_OK) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800191 BOOST_THROW_EXCEPTION(Error(sqlite3_errmsg(m_db)));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800192 }
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800193
Lijing Wang51837ad2016-12-25 14:43:53 -0800194 sqlite3_bind_blob(stmt, 1, device_name.wire(), device_name.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800195 sqlite3_bind_int64(stmt, 2, seq_no);
196 sqlite3_bind_int(stmt, 3, 0);
197 sqlite3_bind_text(stmt, 4, filename.c_str(), filename.size(), SQLITE_STATIC);
198 sqlite3_bind_int64(stmt, 5, version);
199 sqlite3_bind_int64(stmt, 6, action_time);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800200
Lijing Wang51837ad2016-12-25 14:43:53 -0800201 sqlite3_bind_blob(stmt, 7, hash.buf(), hash.size(), SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800202
Lijing Wang51837ad2016-12-25 14:43:53 -0800203 // sqlite3_bind_int64(stmt, 8, atime); // NULL
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800204 sqlite3_bind_int64(stmt, 9, wtime);
Lijing Wang51837ad2016-12-25 14:43:53 -0800205 // sqlite3_bind_int64(stmt, 10, ctime); // NULL
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800206 sqlite3_bind_int(stmt, 11, mode);
207 sqlite3_bind_int(stmt, 12, seg_num);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800208
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800209 if (parent_device_name && parent_seq_no > 0) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800210 sqlite3_bind_blob(stmt, 13, parent_device_name->buf(), parent_device_name->size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800211 sqlite3_bind_int64(stmt, 14, parent_seq_no);
212 }
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800213
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800214 ActionItemPtr item = make_shared<ActionItem>();
215 item->set_action(ActionItem::UPDATE);
216 item->set_filename(filename);
217 item->set_version(version);
218 item->set_timestamp(action_time);
Lijing Wang51837ad2016-12-25 14:43:53 -0800219 item->set_file_hash(hash.buf(), hash.size());
220 // item->set_atime(atime);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800221 item->set_mtime(wtime);
Lijing Wang51837ad2016-12-25 14:43:53 -0800222 // item->set_ctime(ctime);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800223 item->set_mode(mode);
224 item->set_seg_num(seg_num);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800225
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800226 if (parent_device_name && parent_seq_no > 0) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800227 // cout << Name(*parent_device_name) << endl;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800228
Lijing Wang51837ad2016-12-25 14:43:53 -0800229 item->set_parent_device_name(parent_device_name->buf(), parent_device_name->size());
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800230 item->set_parent_seq_no(parent_seq_no);
231 }
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800232
233 // assign name to the action, serialize action, and create content object
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800234
Lijing Wang51837ad2016-12-25 14:43:53 -0800235 std::string item_msg;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800236 item->SerializeToString(&item_msg);
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800237
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800238 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
Lijing Wang51837ad2016-12-25 14:43:53 -0800239
240 Name actionName = Name("/");
241 actionName.append(m_syncLog->GetLocalName()).append(m_appName).append("action");
242 actionName.append(m_sharedFolderName).appendNumber(seq_no);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800243 _LOG_DEBUG("ActionName: " << actionName);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800244
Lijing Wang51837ad2016-12-25 14:43:53 -0800245 shared_ptr<Data> actionData = make_shared<Data>();
246 actionData->setName(actionName);
247 actionData->setFreshnessPeriod(time::seconds(60));
248 actionData->setContent(reinterpret_cast<const uint8_t*>(item_msg.c_str()), item_msg.size());
249 m_keyChain.sign(*actionData);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800250
Lijing Wang51837ad2016-12-25 14:43:53 -0800251 // _LOG_DEBUG(" >>>>>>> " << Name(namePtr->buf() << " " << namePtr->length());
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800252
Lijing Wang51837ad2016-12-25 14:43:53 -0800253 sqlite3_bind_blob(stmt, 15, actionName.wireEncode().wire(), actionName.wireEncode().size(),
254 SQLITE_STATIC);
255 sqlite3_bind_blob(stmt, 16, actionData->wireEncode().wire(), actionData->wireEncode().size(),
256 SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800257
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800258 sqlite3_step(stmt);
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800259
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800260 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800261
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800262 sqlite3_finalize(stmt);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800263
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800264 // I had a problem including directory_name assignment as part of the initial insert.
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800265 sqlite3_prepare_v2(m_db,
266 "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?",
267 -1, &stmt, 0);
268 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800269
Lijing Wang51837ad2016-12-25 14:43:53 -0800270 sqlite3_bind_blob(stmt, 1, device_name.wire(), device_name.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800271 sqlite3_bind_int64(stmt, 2, seq_no);
272 sqlite3_step(stmt);
273 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800274
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800275 sqlite3_finalize(stmt);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800276
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800277 sqlite3_exec(m_db, "END TRANSACTION;", 0, 0, 0);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800278
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800279 // set complete for local file
280 m_fileState->SetFileComplete(filename);
281
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800282 return item;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800283}
284
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800285// void
Lijing Wang51837ad2016-12-25 14:43:53 -0800286// ActionLog::AddActionMove(const std::string &oldFile, const std::string &newFile)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800287// {
288// // not supported yet
Lijing Wang51837ad2016-12-25 14:43:53 -0800289// BOOST_THROW_EXCEPTION(Error("Move operation is not yet supported"));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800290// }
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800291
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800292ActionItemPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800293ActionLog::AddLocalActionDelete(const std::string& filename)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800294{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800295 _LOG_DEBUG("Adding local action DELETE");
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800296
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800297 sqlite3_exec(m_db, "BEGIN TRANSACTION;", 0, 0, 0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800298
Lijing Wang51837ad2016-12-25 14:43:53 -0800299 const Block device_name = m_syncLog->GetLocalName().wireEncode();
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800300 sqlite3_int64 version;
Lijing Wang51837ad2016-12-25 14:43:53 -0800301 BufferPtr parent_device_name;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800302 sqlite3_int64 parent_seq_no = -1;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800303
Lijing Wang51837ad2016-12-25 14:43:53 -0800304 sqlite3_int64 action_time = std::time(0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800305
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800306 tie(version, parent_device_name, parent_seq_no) = GetLatestActionForFile(filename);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800307 if (!parent_device_name) // no records exist or file was already deleted
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800308 {
309 _LOG_DEBUG("Nothing to delete... [" << filename << "]");
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800310
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800311 // just in case, remove data from FileState
312 sqlite3_stmt* stmt;
313 sqlite3_prepare_v2(m_db, "DELETE FROM FileState WHERE filename = ? ", -1, &stmt, 0);
314 sqlite3_bind_text(stmt, 1, filename.c_str(), filename.size(), SQLITE_STATIC); // file
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800315
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800316 sqlite3_step(stmt);
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800317
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800318 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800319
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800320 sqlite3_finalize(stmt);
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800321
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800322 sqlite3_exec(m_db, "END TRANSACTION;", 0, 0, 0);
323 return ActionItemPtr();
324 }
325 version++;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800326
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800327 sqlite3_int64 seq_no = m_syncLog->GetNextLocalSeqNo();
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800328
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800329 sqlite3_stmt* stmt;
330 sqlite3_prepare_v2(m_db, "INSERT INTO ActionLog "
331 "(device_name, seq_no, action, filename, version, action_timestamp, "
332 "parent_device_name, parent_seq_no, "
333 "action_name, action_content_object) "
Yukai Tu40f184f2017-01-26 09:00:43 -0800334 "VALUES(?, ?, ?, ?, ?, datetime(?, 'unixepoch', 'localtime'),"
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800335 " ?, ?,"
336 " ?, ?)",
337 -1, &stmt, 0);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800338
Lijing Wang51837ad2016-12-25 14:43:53 -0800339 sqlite3_bind_blob(stmt, 1, device_name.wire(), device_name.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800340 sqlite3_bind_int64(stmt, 2, seq_no);
341 sqlite3_bind_int(stmt, 3, 1);
342 sqlite3_bind_text(stmt, 4, filename.c_str(), filename.size(), SQLITE_STATIC); // file
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800343
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800344 sqlite3_bind_int64(stmt, 5, version);
345 sqlite3_bind_int64(stmt, 6, action_time);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800346
Lijing Wang51837ad2016-12-25 14:43:53 -0800347 sqlite3_bind_blob(stmt, 7, parent_device_name->buf(), parent_device_name->size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800348 sqlite3_bind_int64(stmt, 8, parent_seq_no);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800349
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800350 ActionItemPtr item = make_shared<ActionItem>();
351 item->set_action(ActionItem::DELETE);
352 item->set_filename(filename);
353 item->set_version(version);
354 item->set_timestamp(action_time);
Lijing Wang51837ad2016-12-25 14:43:53 -0800355 item->set_parent_device_name(parent_device_name->buf(), parent_device_name->size());
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800356 item->set_parent_seq_no(parent_seq_no);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800357
Lijing Wang51837ad2016-12-25 14:43:53 -0800358 std::string item_msg;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800359 item->SerializeToString(&item_msg);
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800360
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800361 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
Lijing Wang51837ad2016-12-25 14:43:53 -0800362 Name actionName = Name("/");
363 actionName.append(m_syncLog->GetLocalName()).append(m_appName).append("action");
364 actionName.append(m_sharedFolderName).appendNumber(seq_no);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800365 _LOG_DEBUG("ActionName: " << actionName);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800366
Lijing Wang51837ad2016-12-25 14:43:53 -0800367 shared_ptr<Data> actionData = make_shared<Data>();
368 actionData->setName(actionName);
369 actionData->setFreshnessPeriod(time::seconds(60));
370 actionData->setContent(reinterpret_cast<const uint8_t*>(item_msg.c_str()), item_msg.size());
371 m_keyChain.sign(*actionData);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800372
Lijing Wang51837ad2016-12-25 14:43:53 -0800373 sqlite3_bind_blob(stmt, 9, actionName.wireEncode().wire(), actionName.wireEncode().size(),
374 SQLITE_STATIC);
375 sqlite3_bind_blob(stmt, 10, actionData->wireEncode().wire(), actionData->wireEncode().size(),
376 SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800377
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800378 sqlite3_step(stmt);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800379
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800380 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800381
Lijing Wang51837ad2016-12-25 14:43:53 -0800382 // cout << Name(parent_device_name) << endl;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800383
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800384 // assign name to the action, serialize action, and create content object
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800385
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800386 sqlite3_finalize(stmt);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800387
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800388 // I had a problem including directory_name assignment as part of the initial insert.
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800389 sqlite3_prepare_v2(m_db,
390 "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?",
391 -1, &stmt, 0);
392 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800393
Lijing Wang51837ad2016-12-25 14:43:53 -0800394 sqlite3_bind_blob(stmt, 1, device_name.wire(), device_name.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800395 sqlite3_bind_int64(stmt, 2, seq_no);
396 sqlite3_step(stmt);
397 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800398
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800399 sqlite3_finalize(stmt);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800400
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800401 sqlite3_exec(m_db, "END TRANSACTION;", 0, 0, 0);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800402
403 return item;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800404}
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800405
Lijing Wang51837ad2016-12-25 14:43:53 -0800406shared_ptr<Data>
407ActionLog::LookupActionData(const Name& deviceName, sqlite3_int64 seqno)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800408{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800409 sqlite3_stmt* stmt;
410 sqlite3_prepare_v2(m_db,
411 "SELECT action_content_object FROM ActionLog WHERE device_name=? AND seq_no=?",
412 -1, &stmt, 0);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800413
Lijing Wang51837ad2016-12-25 14:43:53 -0800414 sqlite3_bind_blob(stmt, 1, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
415 SQLITE_STATIC); // ndn version
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800416 sqlite3_bind_int64(stmt, 2, seqno);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800417
Lijing Wang51837ad2016-12-25 14:43:53 -0800418 shared_ptr<Data> retval;
419
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800420 if (sqlite3_step(stmt) == SQLITE_ROW) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800421 // _LOG_DEBUG(sqlite3_column_blob(stmt, 0) << ", " << sqlite3_column_bytes(stmt, 0));
422 retval = make_shared<Data>();
423 retval->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
424 sqlite3_column_bytes(stmt, 0)));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800425 }
426 else {
427 _LOG_TRACE("No action found for deviceName [" << deviceName << "] and seqno:" << seqno);
428 }
Lijing Wang51837ad2016-12-25 14:43:53 -0800429 // _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK && sqlite3_errcode(m_db) != SQLITE_ROW,
430 // sqlite3_errmsg(m_db));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800431 sqlite3_finalize(stmt);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800432
433 return retval;
434}
435
436ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800437ActionLog::LookupAction(const Name& deviceName, sqlite3_int64 seqno)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800438{
Lijing Wang51837ad2016-12-25 14:43:53 -0800439 shared_ptr<Data> data = LookupActionData(deviceName, seqno);
440 if (!data)
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800441 return ActionItemPtr();
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800442
Lijing Wang51837ad2016-12-25 14:43:53 -0800443 ActionItemPtr action =
444 deserializeMsg<ActionItem>(Buffer(data->getContent().value(), data->getContent().value_size()));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800445 return action;
446}
447
Lijing Wang51837ad2016-12-25 14:43:53 -0800448shared_ptr<Data>
449ActionLog::LookupActionData(const Name& actionName)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800450{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800451 sqlite3_stmt* stmt;
452 sqlite3_prepare_v2(m_db, "SELECT action_content_object FROM ActionLog WHERE action_name=?", -1,
453 &stmt, 0);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800454
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800455 _LOG_DEBUG(actionName);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800456
Lijing Wang51837ad2016-12-25 14:43:53 -0800457 _LOG_DEBUG(" LookActionData <<<<<<< " << actionName << " " << actionName.wireEncode().size());
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800458
Lijing Wang51837ad2016-12-25 14:43:53 -0800459 sqlite3_bind_blob(stmt, 1, actionName.wireEncode().wire(), actionName.wireEncode().size(),
460 SQLITE_STATIC);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800461
Lijing Wang51837ad2016-12-25 14:43:53 -0800462 shared_ptr<Data> retval; // = make_shared<Data>();
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800463 if (sqlite3_step(stmt) == SQLITE_ROW) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800464 // _LOG_DEBUG(sqlite3_column_blob(stmt, 0) << ", " << sqlite3_column_bytes(stmt, 0));
465 retval = make_shared<Data>();
466 retval->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
467 sqlite3_column_bytes(stmt, 0)));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800468 }
469 else {
470 _LOG_TRACE("No action found for name: " << actionName);
471 }
472 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_ROW, sqlite3_errmsg(m_db));
473 sqlite3_finalize(stmt);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800474
475 return retval;
476}
477
478ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800479ActionLog::LookupAction(const Name& actionName)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800480{
Lijing Wang51837ad2016-12-25 14:43:53 -0800481 shared_ptr<Data> data = LookupActionData(actionName);
482 if (!data)
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800483 return ActionItemPtr();
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800484
Lijing Wang51837ad2016-12-25 14:43:53 -0800485 ActionItemPtr action =
486 deserializeMsg<ActionItem>(Buffer(data->getContent().value(), data->getContent().value_size()));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800487
488 return action;
489}
490
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800491FileItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800492ActionLog::LookupAction(const std::string& filename, sqlite3_int64 version, const Buffer& filehash)
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800493{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800494 sqlite3_stmt* stmt;
495 sqlite3_prepare_v2(m_db,
496 "SELECT device_name, seq_no, strftime('%s', file_mtime), file_chmod, file_seg_num, file_hash "
497 " FROM ActionLog "
498 " WHERE action = 0 AND "
499 " filename=? AND "
500 " version=? AND "
Lijing Wang51837ad2016-12-25 14:43:53 -0800501 " is_prefix(?, file_hash)=1",
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800502 -1, &stmt, 0);
503 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800504
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800505 sqlite3_bind_text(stmt, 1, filename.c_str(), filename.size(), SQLITE_STATIC);
506 sqlite3_bind_int64(stmt, 2, version);
Lijing Wang51837ad2016-12-25 14:43:53 -0800507 sqlite3_bind_blob(stmt, 3, filehash.buf(), filehash.size(), SQLITE_STATIC);
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800508
509 FileItemPtr fileItem;
510
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800511 if (sqlite3_step(stmt) == SQLITE_ROW) {
512 fileItem = make_shared<FileItem>();
513 fileItem->set_filename(filename);
514 fileItem->set_device_name(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
515 fileItem->set_seq_no(sqlite3_column_int64(stmt, 1));
516 fileItem->set_mtime(sqlite3_column_int64(stmt, 2));
517 fileItem->set_mode(sqlite3_column_int64(stmt, 3));
518 fileItem->set_seg_num(sqlite3_column_int64(stmt, 4));
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800519
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800520 fileItem->set_file_hash(sqlite3_column_blob(stmt, 5), sqlite3_column_bytes(stmt, 5));
521 }
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800522
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800523 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE || sqlite3_errcode(m_db) != SQLITE_ROW ||
524 sqlite3_errcode(m_db) != SQLITE_OK,
525 sqlite3_errmsg(m_db));
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800526
527 return fileItem;
528}
529
530
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800531ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800532ActionLog::AddRemoteAction(const Name& deviceName, sqlite3_int64 seqno, shared_ptr<Data> actionData)
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800533{
Lijing Wang51837ad2016-12-25 14:43:53 -0800534 if (!actionData) {
535 _LOG_ERROR("actionData is not valid");
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800536 return ActionItemPtr();
537 }
Lijing Wang51837ad2016-12-25 14:43:53 -0800538 ActionItemPtr action = deserializeMsg<ActionItem>(
539 Buffer(actionData->getContent().value(), actionData->getContent().value_size()));
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800540
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800541 if (!action) {
542 _LOG_ERROR("action cannot be decoded");
543 return ActionItemPtr();
544 }
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800545
Lijing Wang51837ad2016-12-25 14:43:53 -0800546 _LOG_DEBUG("AddRemoteAction: [" << deviceName.toUri() << "] seqno: " << seqno);
Alexander Afanasyevf695aed2013-01-30 13:28:42 -0800547
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800548 sqlite3_stmt* stmt;
Lijing Wang51837ad2016-12-25 14:43:53 -0800549 sqlite3_prepare_v2(m_db,
550 "INSERT INTO ActionLog "
551 "(device_name, seq_no, action, filename, version, action_timestamp, "
552 "file_hash, file_atime, file_mtime, file_ctime, file_chmod, file_seg_num, "
553 "parent_device_name, parent_seq_no, "
554 "action_name, action_content_object) "
555 "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
556 " ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,?, "
557 " ?, ?, "
558 " ?, ?);",
559 -1, &stmt, 0);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800560 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800561
Lijing Wang51837ad2016-12-25 14:43:53 -0800562 sqlite3_bind_blob(stmt, 1, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
563 SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800564 sqlite3_bind_int64(stmt, 2, seqno);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800565
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800566 sqlite3_bind_int(stmt, 3, action->action());
567 sqlite3_bind_text(stmt, 4, action->filename().c_str(), action->filename().size(), SQLITE_STATIC);
568 sqlite3_bind_int64(stmt, 5, action->version());
569 sqlite3_bind_int64(stmt, 6, action->timestamp());
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800570
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800571 if (action->action() == ActionItem::UPDATE) {
572 sqlite3_bind_blob(stmt, 7, action->file_hash().c_str(), action->file_hash().size(),
573 SQLITE_STATIC);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800574
Lijing Wang51837ad2016-12-25 14:43:53 -0800575 // sqlite3_bind_int64(stmt, 8, atime); // NULL
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800576 sqlite3_bind_int64(stmt, 9, action->mtime());
Lijing Wang51837ad2016-12-25 14:43:53 -0800577 // sqlite3_bind_int64(stmt, 10, ctime); // NULL
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800578
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800579 sqlite3_bind_int(stmt, 11, action->mode());
580 sqlite3_bind_int(stmt, 12, action->seg_num());
581 }
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800582
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800583 if (action->has_parent_device_name()) {
584 sqlite3_bind_blob(stmt, 13, action->parent_device_name().c_str(),
585 action->parent_device_name().size(), SQLITE_STATIC);
586 sqlite3_bind_int64(stmt, 14, action->parent_seq_no());
587 }
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800588
Lijing Wang51837ad2016-12-25 14:43:53 -0800589 Name actionName = Name(deviceName);
590 actionName.append("action").append(m_sharedFolderName).appendNumber(seqno);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800591
Lijing Wang51837ad2016-12-25 14:43:53 -0800592 sqlite3_bind_blob(stmt, 15, actionName.wireEncode().wire(), actionName.wireEncode().size(),
593 SQLITE_STATIC);
594 sqlite3_bind_blob(stmt, 16, actionData->wireEncode().wire(), actionData->wireEncode().size(),
595 SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800596 sqlite3_step(stmt);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800597
598 // if action needs to be applied to file state, the trigger will take care of it
599
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800600 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800601
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800602 sqlite3_finalize(stmt);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800603
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800604 // I had a problem including directory_name assignment as part of the initial insert.
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800605 sqlite3_prepare_v2(m_db,
606 "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?",
607 -1, &stmt, 0);
608 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800609
Lijing Wang51837ad2016-12-25 14:43:53 -0800610 sqlite3_bind_blob(stmt, 1, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
611 SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800612 sqlite3_bind_int64(stmt, 2, seqno);
613 sqlite3_step(stmt);
614 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800615
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800616 sqlite3_finalize(stmt);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800617
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800618 return action;
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800619}
620
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800621ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800622ActionLog::AddRemoteAction(shared_ptr<Data> actionData)
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800623{
Lijing Wang51837ad2016-12-25 14:43:53 -0800624 Name name = actionData->getName();
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800625 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800626
Lijing Wang51837ad2016-12-25 14:43:53 -0800627 uint64_t seqno = name.get(-1).toNumber();
628 std::string sharedFolder = name.get(-2).toUri();
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800629
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800630 if (sharedFolder != m_sharedFolderName) {
631 _LOG_ERROR("Action doesn't belong to this shared folder");
632 return ActionItemPtr();
633 }
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800634
Lijing Wang8e56d082016-12-25 14:45:23 -0800635 if (name.get(-3).toUri() != "action") {
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800636 _LOG_ERROR("not an action");
637 return ActionItemPtr();
638 }
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800639
Lijing Wang8e56d082016-12-25 14:45:23 -0800640 if (name.get(-4) != m_appName) {
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800641 _LOG_ERROR("Action doesn't belong to this application");
642 return ActionItemPtr();
643 }
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800644
Lijing Wang51837ad2016-12-25 14:43:53 -0800645 Name deviceName = name.getSubName(0, name.size() - 4);
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800646
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800647 _LOG_DEBUG("From [" << name << "] extracted deviceName: " << deviceName << ", sharedFolder: "
648 << sharedFolder
649 << ", seqno: "
650 << seqno);
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800651
Lijing Wang51837ad2016-12-25 14:43:53 -0800652 return AddRemoteAction(deviceName, seqno, actionData);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800653}
654
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800655sqlite3_int64
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800656ActionLog::LogSize()
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800657{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800658 sqlite3_stmt* stmt;
659 sqlite3_prepare_v2(m_db, "SELECT count(*) FROM ActionLog", -1, &stmt, 0);
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800660
661 sqlite3_int64 retval = -1;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800662 if (sqlite3_step(stmt) == SQLITE_ROW) {
663 retval = sqlite3_column_int64(stmt, 0);
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800664 }
665
666 return retval;
667}
668
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800669bool
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800670ActionLog::LookupActionsInFolderRecursively(
Lijing Wang51837ad2016-12-25 14:43:53 -0800671 const function<void(const Name& name, sqlite3_int64 seq_no, const ActionItem&)>& visitor,
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800672 const std::string& folder, int offset /*=0*/, int limit /*=-1*/)
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800673{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800674 _LOG_DEBUG("LookupActionsInFolderRecursively: [" << folder << "]");
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800675
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800676 if (limit >= 0)
677 limit += 1; // to check if there is more data
678
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800679 sqlite3_stmt* stmt;
680 if (folder != "") {
681 /// @todo Do something to improve efficiency of this query. Right now it is basically scanning the whole database
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800682
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800683 sqlite3_prepare_v2(m_db,
684 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
685 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
686 " parent_device_name,parent_seq_no "
687 " FROM ActionLog "
688 " WHERE is_dir_prefix (?, directory)=1 "
689 " ORDER BY action_timestamp DESC "
690 " LIMIT ? OFFSET ?",
691 -1, &stmt,
692 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
693 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800694
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800695 sqlite3_bind_text(stmt, 1, folder.c_str(), folder.size(), SQLITE_STATIC);
696 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800697
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800698 sqlite3_bind_int(stmt, 2, limit);
699 sqlite3_bind_int(stmt, 3, offset);
700 }
701 else {
702 sqlite3_prepare_v2(m_db,
703 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
704 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
705 " parent_device_name,parent_seq_no "
706 " FROM ActionLog "
707 " ORDER BY action_timestamp DESC "
708 " LIMIT ? OFFSET ?",
709 -1, &stmt, 0);
710 sqlite3_bind_int(stmt, 1, limit);
711 sqlite3_bind_int(stmt, 2, offset);
712 }
713
714 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
715
716 while (sqlite3_step(stmt) == SQLITE_ROW) {
717 if (limit == 1)
718 break;
719
720 ActionItem action;
721
Lijing Wang51837ad2016-12-25 14:43:53 -0800722 Name device_name(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
723 sqlite3_column_bytes(stmt, 0)));
724
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800725 sqlite3_int64 seq_no = sqlite3_column_int64(stmt, 1);
726 action.set_action(static_cast<ActionItem_ActionType>(sqlite3_column_int(stmt, 2)));
727 action.set_filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)),
728 sqlite3_column_bytes(stmt, 3));
729 std::string directory(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 4)),
730 sqlite3_column_bytes(stmt, 4));
731 action.set_version(sqlite3_column_int64(stmt, 5));
732 action.set_timestamp(sqlite3_column_int64(stmt, 6));
733
734 if (action.action() == 0) {
735 action.set_file_hash(sqlite3_column_blob(stmt, 7), sqlite3_column_bytes(stmt, 7));
736 action.set_mtime(sqlite3_column_int(stmt, 8));
737 action.set_mode(sqlite3_column_int(stmt, 9));
738 action.set_seg_num(sqlite3_column_int64(stmt, 10));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800739 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800740 if (sqlite3_column_bytes(stmt, 11) > 0) {
741 action.set_parent_device_name(sqlite3_column_blob(stmt, 11), sqlite3_column_bytes(stmt, 11));
742 action.set_parent_seq_no(sqlite3_column_int64(stmt, 12));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800743 }
744
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800745 visitor(device_name, seq_no, action);
746 limit--;
747 }
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800748
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800749 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800750
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800751 sqlite3_finalize(stmt);
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800752
753 return (limit == 1); // more data is available
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800754}
755
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800756/**
757 * @todo Figure out the way to minimize code duplication
758 */
759bool
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800760ActionLog::LookupActionsForFile(
Lijing Wang51837ad2016-12-25 14:43:53 -0800761 const function<void(const Name& name, sqlite3_int64 seq_no, const ActionItem&)>& visitor,
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800762 const std::string& file, int offset /*=0*/, int limit /*=-1*/)
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800763{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800764 _LOG_DEBUG("LookupActionsInFolderRecursively: [" << file << "]");
765 if (file.empty())
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800766 return false;
767
768 if (limit >= 0)
769 limit += 1; // to check if there is more data
770
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800771 sqlite3_stmt* stmt;
772 sqlite3_prepare_v2(m_db,
773 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
774 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
775 " parent_device_name,parent_seq_no "
776 " FROM ActionLog "
777 " WHERE filename=? "
778 " ORDER BY action_timestamp DESC "
779 " LIMIT ? OFFSET ?",
780 -1, &stmt,
781 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
782 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800783
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800784 sqlite3_bind_text(stmt, 1, file.c_str(), file.size(), SQLITE_STATIC);
785 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800786
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800787 sqlite3_bind_int(stmt, 2, limit);
788 sqlite3_bind_int(stmt, 3, offset);
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800789
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800790 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800791
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800792 while (sqlite3_step(stmt) == SQLITE_ROW) {
793 if (limit == 1)
794 break;
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800795
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800796 ActionItem action;
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800797
Lijing Wang51837ad2016-12-25 14:43:53 -0800798 Name device_name(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
799 sqlite3_column_bytes(stmt, 0)));
800
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800801 sqlite3_int64 seq_no = sqlite3_column_int64(stmt, 1);
802 action.set_action(static_cast<ActionItem_ActionType>(sqlite3_column_int(stmt, 2)));
803 action.set_filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)),
804 sqlite3_column_bytes(stmt, 3));
805 std::string directory(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 4)),
806 sqlite3_column_bytes(stmt, 4));
807 action.set_version(sqlite3_column_int64(stmt, 5));
808 action.set_timestamp(sqlite3_column_int64(stmt, 6));
Alexander Afanasyev3c95c852013-03-01 18:58:50 -0800809
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800810 if (action.action() == 0) {
811 action.set_file_hash(sqlite3_column_blob(stmt, 7), sqlite3_column_bytes(stmt, 7));
812 action.set_mtime(sqlite3_column_int(stmt, 8));
813 action.set_mode(sqlite3_column_int(stmt, 9));
814 action.set_seg_num(sqlite3_column_int64(stmt, 10));
815 }
816 if (sqlite3_column_bytes(stmt, 11) > 0) {
817 action.set_parent_device_name(sqlite3_column_blob(stmt, 11), sqlite3_column_bytes(stmt, 11));
818 action.set_parent_seq_no(sqlite3_column_int64(stmt, 12));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800819 }
820
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800821 visitor(device_name, seq_no, action);
822 limit--;
823 }
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800824
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800825 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
826
827 sqlite3_finalize(stmt);
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800828
829 return (limit == 1); // more data is available
830}
831
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800832void
Lijing Wang51837ad2016-12-25 14:43:53 -0800833ActionLog::LookupRecentFileActions(const function<void(const std::string&, int, int)>& visitor,
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800834 int limit)
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800835{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800836 sqlite3_stmt* stmt;
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800837
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800838 sqlite3_prepare_v2(m_db,
839 "SELECT AL.filename, AL.action"
840 " FROM ActionLog AL"
841 " JOIN "
842 " (SELECT filename, MAX(action_timestamp) AS action_timestamp "
843 " FROM ActionLog "
844 " GROUP BY filename ) AS GAL"
845 " ON AL.filename = GAL.filename AND AL.action_timestamp = GAL.action_timestamp "
846 " ORDER BY AL.action_timestamp DESC "
847 " LIMIT ?;",
848 -1, &stmt, 0);
849 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800850 sqlite3_bind_int(stmt, 1, limit);
851 int index = 0;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800852 while (sqlite3_step(stmt) == SQLITE_ROW) {
853 std::string filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)),
854 sqlite3_column_bytes(stmt, 0));
855 int action = sqlite3_column_int(stmt, 1);
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800856 visitor(filename, action, index);
857 index++;
858 }
859
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800860 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800861
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800862 sqlite3_finalize(stmt);
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800863}
864
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800865
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800866///////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800867///////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800868///////////////////////////////////////////////////////////////////////////////////
869
870void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800871ActionLog::apply_action_xFun(sqlite3_context* context, int argc, sqlite3_value** argv)
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800872{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800873 ActionLog* the = reinterpret_cast<ActionLog*>(sqlite3_user_data(context));
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800874
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800875 if (argc != 11) {
876 sqlite3_result_error(context, "``apply_action'' expects 10 arguments", -1);
877 return;
878 }
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800879
Lijing Wang51837ad2016-12-25 14:43:53 -0800880 Buffer device_name(sqlite3_value_blob(argv[0]), sqlite3_value_bytes(argv[0]));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800881 sqlite3_int64 seq_no = sqlite3_value_int64(argv[1]);
882 int action = sqlite3_value_int(argv[2]);
Lijing Wang51837ad2016-12-25 14:43:53 -0800883 std::string filename = reinterpret_cast<const char*>(sqlite3_value_text(argv[3]));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800884 sqlite3_int64 version = sqlite3_value_int64(argv[4]);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800885
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800886 _LOG_TRACE("apply_function called with " << argc);
Lijing Wang51837ad2016-12-25 14:43:53 -0800887 _LOG_TRACE("device_name: " << Name(Block(reinterpret_cast<const char*>(device_name.buf()),
888 device_name.size()))
889 << ", action: "
890 << action
891 << ", file: "
892 << filename);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800893
894 if (action == 0) // update
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800895 {
Lijing Wang51837ad2016-12-25 14:43:53 -0800896 Buffer hash(sqlite3_value_blob(argv[5]), sqlite3_value_bytes(argv[5]));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800897 time_t atime = static_cast<time_t>(sqlite3_value_int64(argv[6]));
898 time_t mtime = static_cast<time_t>(sqlite3_value_int64(argv[7]));
899 time_t ctime = static_cast<time_t>(sqlite3_value_int64(argv[8]));
900 int mode = sqlite3_value_int(argv[9]);
901 int seg_num = sqlite3_value_int(argv[10]);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800902
Lijing Wang51837ad2016-12-25 14:43:53 -0800903 _LOG_DEBUG("Update " << filename << " " << atime << " " << mtime << " " << ctime << " "
904 << toHex(hash));
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800905
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800906 the->m_fileState->UpdateFile(filename, version, hash, device_name, seq_no, atime, mtime, ctime,
907 mode, seg_num);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800908
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800909 // no callback here
910 }
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800911 else if (action == 1) // delete
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800912 {
913 the->m_fileState->DeleteFile(filename);
Alexander Afanasyev0c545ed2013-01-26 00:12:32 -0800914
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800915 the->m_onFileRemoved(filename);
916 }
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800917
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800918 sqlite3_result_null(context);
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800919}
Lijing Wang51837ad2016-12-25 14:43:53 -0800920
921} // namespace chronoshare
922} // namespace ndn