blob: 7dbc663f868106a226c16d3370a490200c49e9cc [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,
93 const std::string& sharedFolder, const std::string& appName,
94 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) "
181 "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
182 " ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,?, "
183 " ?, ?, "
184 " ?, ?);",
185 -1, &stmt, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800186
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800187 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800188
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800189 if (res != SQLITE_OK) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800190 BOOST_THROW_EXCEPTION(Error(sqlite3_errmsg(m_db)));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800191 }
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800192
Lijing Wang51837ad2016-12-25 14:43:53 -0800193 sqlite3_bind_blob(stmt, 1, device_name.wire(), device_name.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800194 sqlite3_bind_int64(stmt, 2, seq_no);
195 sqlite3_bind_int(stmt, 3, 0);
196 sqlite3_bind_text(stmt, 4, filename.c_str(), filename.size(), SQLITE_STATIC);
197 sqlite3_bind_int64(stmt, 5, version);
198 sqlite3_bind_int64(stmt, 6, action_time);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800199
Lijing Wang51837ad2016-12-25 14:43:53 -0800200 sqlite3_bind_blob(stmt, 7, hash.buf(), hash.size(), SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800201
Lijing Wang51837ad2016-12-25 14:43:53 -0800202 // sqlite3_bind_int64(stmt, 8, atime); // NULL
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800203 sqlite3_bind_int64(stmt, 9, wtime);
Lijing Wang51837ad2016-12-25 14:43:53 -0800204 // sqlite3_bind_int64(stmt, 10, ctime); // NULL
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800205 sqlite3_bind_int(stmt, 11, mode);
206 sqlite3_bind_int(stmt, 12, seg_num);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800207
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800208 if (parent_device_name && parent_seq_no > 0) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800209 sqlite3_bind_blob(stmt, 13, parent_device_name->buf(), parent_device_name->size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800210 sqlite3_bind_int64(stmt, 14, parent_seq_no);
211 }
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800212
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800213 ActionItemPtr item = make_shared<ActionItem>();
214 item->set_action(ActionItem::UPDATE);
215 item->set_filename(filename);
216 item->set_version(version);
217 item->set_timestamp(action_time);
Lijing Wang51837ad2016-12-25 14:43:53 -0800218 item->set_file_hash(hash.buf(), hash.size());
219 // item->set_atime(atime);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800220 item->set_mtime(wtime);
Lijing Wang51837ad2016-12-25 14:43:53 -0800221 // item->set_ctime(ctime);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800222 item->set_mode(mode);
223 item->set_seg_num(seg_num);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800224
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800225 if (parent_device_name && parent_seq_no > 0) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800226 // cout << Name(*parent_device_name) << endl;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800227
Lijing Wang51837ad2016-12-25 14:43:53 -0800228 item->set_parent_device_name(parent_device_name->buf(), parent_device_name->size());
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800229 item->set_parent_seq_no(parent_seq_no);
230 }
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800231
232 // assign name to the action, serialize action, and create content object
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800233
Lijing Wang51837ad2016-12-25 14:43:53 -0800234 std::string item_msg;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800235 item->SerializeToString(&item_msg);
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800236
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800237 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
Lijing Wang51837ad2016-12-25 14:43:53 -0800238
239 Name actionName = Name("/");
240 actionName.append(m_syncLog->GetLocalName()).append(m_appName).append("action");
241 actionName.append(m_sharedFolderName).appendNumber(seq_no);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800242 _LOG_DEBUG("ActionName: " << actionName);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800243
Lijing Wang51837ad2016-12-25 14:43:53 -0800244 shared_ptr<Data> actionData = make_shared<Data>();
245 actionData->setName(actionName);
246 actionData->setFreshnessPeriod(time::seconds(60));
247 actionData->setContent(reinterpret_cast<const uint8_t*>(item_msg.c_str()), item_msg.size());
248 m_keyChain.sign(*actionData);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800249
Lijing Wang51837ad2016-12-25 14:43:53 -0800250 // _LOG_DEBUG(" >>>>>>> " << Name(namePtr->buf() << " " << namePtr->length());
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800251
Lijing Wang51837ad2016-12-25 14:43:53 -0800252 sqlite3_bind_blob(stmt, 15, actionName.wireEncode().wire(), actionName.wireEncode().size(),
253 SQLITE_STATIC);
254 sqlite3_bind_blob(stmt, 16, actionData->wireEncode().wire(), actionData->wireEncode().size(),
255 SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800256
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800257 sqlite3_step(stmt);
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800258
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800259 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800260
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800261 sqlite3_finalize(stmt);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800262
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800263 // I had a problem including directory_name assignment as part of the initial insert.
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800264 sqlite3_prepare_v2(m_db,
265 "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?",
266 -1, &stmt, 0);
267 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800268
Lijing Wang51837ad2016-12-25 14:43:53 -0800269 sqlite3_bind_blob(stmt, 1, device_name.wire(), device_name.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800270 sqlite3_bind_int64(stmt, 2, seq_no);
271 sqlite3_step(stmt);
272 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800273
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800274 sqlite3_finalize(stmt);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800275
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800276 sqlite3_exec(m_db, "END TRANSACTION;", 0, 0, 0);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800277
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800278 // set complete for local file
279 m_fileState->SetFileComplete(filename);
280
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800281 return item;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800282}
283
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800284// void
Lijing Wang51837ad2016-12-25 14:43:53 -0800285// ActionLog::AddActionMove(const std::string &oldFile, const std::string &newFile)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800286// {
287// // not supported yet
Lijing Wang51837ad2016-12-25 14:43:53 -0800288// BOOST_THROW_EXCEPTION(Error("Move operation is not yet supported"));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800289// }
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800290
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800291ActionItemPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800292ActionLog::AddLocalActionDelete(const std::string& filename)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800293{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800294 _LOG_DEBUG("Adding local action DELETE");
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800295
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800296 sqlite3_exec(m_db, "BEGIN TRANSACTION;", 0, 0, 0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800297
Lijing Wang51837ad2016-12-25 14:43:53 -0800298 const Block device_name = m_syncLog->GetLocalName().wireEncode();
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800299 sqlite3_int64 version;
Lijing Wang51837ad2016-12-25 14:43:53 -0800300 BufferPtr parent_device_name;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800301 sqlite3_int64 parent_seq_no = -1;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800302
Lijing Wang51837ad2016-12-25 14:43:53 -0800303 sqlite3_int64 action_time = std::time(0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800304
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800305 tie(version, parent_device_name, parent_seq_no) = GetLatestActionForFile(filename);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800306 if (!parent_device_name) // no records exist or file was already deleted
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800307 {
308 _LOG_DEBUG("Nothing to delete... [" << filename << "]");
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800309
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800310 // just in case, remove data from FileState
311 sqlite3_stmt* stmt;
312 sqlite3_prepare_v2(m_db, "DELETE FROM FileState WHERE filename = ? ", -1, &stmt, 0);
313 sqlite3_bind_text(stmt, 1, filename.c_str(), filename.size(), SQLITE_STATIC); // file
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800314
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800315 sqlite3_step(stmt);
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800316
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800317 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800318
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800319 sqlite3_finalize(stmt);
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800320
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800321 sqlite3_exec(m_db, "END TRANSACTION;", 0, 0, 0);
322 return ActionItemPtr();
323 }
324 version++;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800325
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800326 sqlite3_int64 seq_no = m_syncLog->GetNextLocalSeqNo();
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800327
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800328 sqlite3_stmt* stmt;
329 sqlite3_prepare_v2(m_db, "INSERT INTO ActionLog "
330 "(device_name, seq_no, action, filename, version, action_timestamp, "
331 "parent_device_name, parent_seq_no, "
332 "action_name, action_content_object) "
Lijing Wang51837ad2016-12-25 14:43:53 -0800333 "VALUES(?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800334 " ?, ?,"
335 " ?, ?)",
336 -1, &stmt, 0);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800337
Lijing Wang51837ad2016-12-25 14:43:53 -0800338 sqlite3_bind_blob(stmt, 1, device_name.wire(), device_name.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800339 sqlite3_bind_int64(stmt, 2, seq_no);
340 sqlite3_bind_int(stmt, 3, 1);
341 sqlite3_bind_text(stmt, 4, filename.c_str(), filename.size(), SQLITE_STATIC); // file
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800342
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800343 sqlite3_bind_int64(stmt, 5, version);
344 sqlite3_bind_int64(stmt, 6, action_time);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800345
Lijing Wang51837ad2016-12-25 14:43:53 -0800346 sqlite3_bind_blob(stmt, 7, parent_device_name->buf(), parent_device_name->size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800347 sqlite3_bind_int64(stmt, 8, parent_seq_no);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800348
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800349 ActionItemPtr item = make_shared<ActionItem>();
350 item->set_action(ActionItem::DELETE);
351 item->set_filename(filename);
352 item->set_version(version);
353 item->set_timestamp(action_time);
Lijing Wang51837ad2016-12-25 14:43:53 -0800354 item->set_parent_device_name(parent_device_name->buf(), parent_device_name->size());
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800355 item->set_parent_seq_no(parent_seq_no);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800356
Lijing Wang51837ad2016-12-25 14:43:53 -0800357 std::string item_msg;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800358 item->SerializeToString(&item_msg);
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800359
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800360 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
Lijing Wang51837ad2016-12-25 14:43:53 -0800361 Name actionName = Name("/");
362 actionName.append(m_syncLog->GetLocalName()).append(m_appName).append("action");
363 actionName.append(m_sharedFolderName).appendNumber(seq_no);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800364 _LOG_DEBUG("ActionName: " << actionName);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800365
Lijing Wang51837ad2016-12-25 14:43:53 -0800366 shared_ptr<Data> actionData = make_shared<Data>();
367 actionData->setName(actionName);
368 actionData->setFreshnessPeriod(time::seconds(60));
369 actionData->setContent(reinterpret_cast<const uint8_t*>(item_msg.c_str()), item_msg.size());
370 m_keyChain.sign(*actionData);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800371
Lijing Wang51837ad2016-12-25 14:43:53 -0800372 sqlite3_bind_blob(stmt, 9, actionName.wireEncode().wire(), actionName.wireEncode().size(),
373 SQLITE_STATIC);
374 sqlite3_bind_blob(stmt, 10, actionData->wireEncode().wire(), actionData->wireEncode().size(),
375 SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800376
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800377 sqlite3_step(stmt);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800378
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800379 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800380
Lijing Wang51837ad2016-12-25 14:43:53 -0800381 // cout << Name(parent_device_name) << endl;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800382
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800383 // assign name to the action, serialize action, and create content object
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800384
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800385 sqlite3_finalize(stmt);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800386
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800387 // I had a problem including directory_name assignment as part of the initial insert.
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800388 sqlite3_prepare_v2(m_db,
389 "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?",
390 -1, &stmt, 0);
391 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800392
Lijing Wang51837ad2016-12-25 14:43:53 -0800393 sqlite3_bind_blob(stmt, 1, device_name.wire(), device_name.size(), SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800394 sqlite3_bind_int64(stmt, 2, seq_no);
395 sqlite3_step(stmt);
396 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800397
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800398 sqlite3_finalize(stmt);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800399
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800400 sqlite3_exec(m_db, "END TRANSACTION;", 0, 0, 0);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800401
402 return item;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800403}
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800404
Lijing Wang51837ad2016-12-25 14:43:53 -0800405shared_ptr<Data>
406ActionLog::LookupActionData(const Name& deviceName, sqlite3_int64 seqno)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800407{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800408 sqlite3_stmt* stmt;
409 sqlite3_prepare_v2(m_db,
410 "SELECT action_content_object FROM ActionLog WHERE device_name=? AND seq_no=?",
411 -1, &stmt, 0);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800412
Lijing Wang51837ad2016-12-25 14:43:53 -0800413 sqlite3_bind_blob(stmt, 1, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
414 SQLITE_STATIC); // ndn version
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800415 sqlite3_bind_int64(stmt, 2, seqno);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800416
Lijing Wang51837ad2016-12-25 14:43:53 -0800417 shared_ptr<Data> retval;
418
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800419 if (sqlite3_step(stmt) == SQLITE_ROW) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800420 // _LOG_DEBUG(sqlite3_column_blob(stmt, 0) << ", " << sqlite3_column_bytes(stmt, 0));
421 retval = make_shared<Data>();
422 retval->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
423 sqlite3_column_bytes(stmt, 0)));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800424 }
425 else {
426 _LOG_TRACE("No action found for deviceName [" << deviceName << "] and seqno:" << seqno);
427 }
Lijing Wang51837ad2016-12-25 14:43:53 -0800428 // _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK && sqlite3_errcode(m_db) != SQLITE_ROW,
429 // sqlite3_errmsg(m_db));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800430 sqlite3_finalize(stmt);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800431
432 return retval;
433}
434
435ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800436ActionLog::LookupAction(const Name& deviceName, sqlite3_int64 seqno)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800437{
Lijing Wang51837ad2016-12-25 14:43:53 -0800438 shared_ptr<Data> data = LookupActionData(deviceName, seqno);
439 if (!data)
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800440 return ActionItemPtr();
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800441
Lijing Wang51837ad2016-12-25 14:43:53 -0800442 ActionItemPtr action =
443 deserializeMsg<ActionItem>(Buffer(data->getContent().value(), data->getContent().value_size()));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800444 return action;
445}
446
Lijing Wang51837ad2016-12-25 14:43:53 -0800447shared_ptr<Data>
448ActionLog::LookupActionData(const Name& actionName)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800449{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800450 sqlite3_stmt* stmt;
451 sqlite3_prepare_v2(m_db, "SELECT action_content_object FROM ActionLog WHERE action_name=?", -1,
452 &stmt, 0);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800453
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800454 _LOG_DEBUG(actionName);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800455
Lijing Wang51837ad2016-12-25 14:43:53 -0800456 _LOG_DEBUG(" LookActionData <<<<<<< " << actionName << " " << actionName.wireEncode().size());
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800457
Lijing Wang51837ad2016-12-25 14:43:53 -0800458 sqlite3_bind_blob(stmt, 1, actionName.wireEncode().wire(), actionName.wireEncode().size(),
459 SQLITE_STATIC);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800460
Lijing Wang51837ad2016-12-25 14:43:53 -0800461 shared_ptr<Data> retval; // = make_shared<Data>();
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800462 if (sqlite3_step(stmt) == SQLITE_ROW) {
Lijing Wang51837ad2016-12-25 14:43:53 -0800463 // _LOG_DEBUG(sqlite3_column_blob(stmt, 0) << ", " << sqlite3_column_bytes(stmt, 0));
464 retval = make_shared<Data>();
465 retval->wireDecode(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
466 sqlite3_column_bytes(stmt, 0)));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800467 }
468 else {
469 _LOG_TRACE("No action found for name: " << actionName);
470 }
471 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_ROW, sqlite3_errmsg(m_db));
472 sqlite3_finalize(stmt);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800473
474 return retval;
475}
476
477ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800478ActionLog::LookupAction(const Name& actionName)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800479{
Lijing Wang51837ad2016-12-25 14:43:53 -0800480 shared_ptr<Data> data = LookupActionData(actionName);
481 if (!data)
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800482 return ActionItemPtr();
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800483
Lijing Wang51837ad2016-12-25 14:43:53 -0800484 ActionItemPtr action =
485 deserializeMsg<ActionItem>(Buffer(data->getContent().value(), data->getContent().value_size()));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800486
487 return action;
488}
489
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800490FileItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800491ActionLog::LookupAction(const std::string& filename, sqlite3_int64 version, const Buffer& filehash)
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800492{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800493 sqlite3_stmt* stmt;
494 sqlite3_prepare_v2(m_db,
495 "SELECT device_name, seq_no, strftime('%s', file_mtime), file_chmod, file_seg_num, file_hash "
496 " FROM ActionLog "
497 " WHERE action = 0 AND "
498 " filename=? AND "
499 " version=? AND "
Lijing Wang51837ad2016-12-25 14:43:53 -0800500 " is_prefix(?, file_hash)=1",
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800501 -1, &stmt, 0);
502 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800503
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800504 sqlite3_bind_text(stmt, 1, filename.c_str(), filename.size(), SQLITE_STATIC);
505 sqlite3_bind_int64(stmt, 2, version);
Lijing Wang51837ad2016-12-25 14:43:53 -0800506 sqlite3_bind_blob(stmt, 3, filehash.buf(), filehash.size(), SQLITE_STATIC);
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800507
508 FileItemPtr fileItem;
509
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800510 if (sqlite3_step(stmt) == SQLITE_ROW) {
511 fileItem = make_shared<FileItem>();
512 fileItem->set_filename(filename);
513 fileItem->set_device_name(sqlite3_column_blob(stmt, 0), sqlite3_column_bytes(stmt, 0));
514 fileItem->set_seq_no(sqlite3_column_int64(stmt, 1));
515 fileItem->set_mtime(sqlite3_column_int64(stmt, 2));
516 fileItem->set_mode(sqlite3_column_int64(stmt, 3));
517 fileItem->set_seg_num(sqlite3_column_int64(stmt, 4));
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800518
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800519 fileItem->set_file_hash(sqlite3_column_blob(stmt, 5), sqlite3_column_bytes(stmt, 5));
520 }
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800521
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800522 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE || sqlite3_errcode(m_db) != SQLITE_ROW ||
523 sqlite3_errcode(m_db) != SQLITE_OK,
524 sqlite3_errmsg(m_db));
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800525
526 return fileItem;
527}
528
529
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800530ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800531ActionLog::AddRemoteAction(const Name& deviceName, sqlite3_int64 seqno, shared_ptr<Data> actionData)
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800532{
Lijing Wang51837ad2016-12-25 14:43:53 -0800533 if (!actionData) {
534 _LOG_ERROR("actionData is not valid");
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800535 return ActionItemPtr();
536 }
Lijing Wang51837ad2016-12-25 14:43:53 -0800537 ActionItemPtr action = deserializeMsg<ActionItem>(
538 Buffer(actionData->getContent().value(), actionData->getContent().value_size()));
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800539
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800540 if (!action) {
541 _LOG_ERROR("action cannot be decoded");
542 return ActionItemPtr();
543 }
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800544
Lijing Wang51837ad2016-12-25 14:43:53 -0800545 _LOG_DEBUG("AddRemoteAction: [" << deviceName.toUri() << "] seqno: " << seqno);
Alexander Afanasyevf695aed2013-01-30 13:28:42 -0800546
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800547 sqlite3_stmt* stmt;
Lijing Wang51837ad2016-12-25 14:43:53 -0800548 sqlite3_prepare_v2(m_db,
549 "INSERT INTO ActionLog "
550 "(device_name, seq_no, action, filename, version, action_timestamp, "
551 "file_hash, file_atime, file_mtime, file_ctime, file_chmod, file_seg_num, "
552 "parent_device_name, parent_seq_no, "
553 "action_name, action_content_object) "
554 "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
555 " ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,?, "
556 " ?, ?, "
557 " ?, ?);",
558 -1, &stmt, 0);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800559 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800560
Lijing Wang51837ad2016-12-25 14:43:53 -0800561 sqlite3_bind_blob(stmt, 1, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
562 SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800563 sqlite3_bind_int64(stmt, 2, seqno);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800564
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800565 sqlite3_bind_int(stmt, 3, action->action());
566 sqlite3_bind_text(stmt, 4, action->filename().c_str(), action->filename().size(), SQLITE_STATIC);
567 sqlite3_bind_int64(stmt, 5, action->version());
568 sqlite3_bind_int64(stmt, 6, action->timestamp());
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800569
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800570 if (action->action() == ActionItem::UPDATE) {
571 sqlite3_bind_blob(stmt, 7, action->file_hash().c_str(), action->file_hash().size(),
572 SQLITE_STATIC);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800573
Lijing Wang51837ad2016-12-25 14:43:53 -0800574 // sqlite3_bind_int64(stmt, 8, atime); // NULL
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800575 sqlite3_bind_int64(stmt, 9, action->mtime());
Lijing Wang51837ad2016-12-25 14:43:53 -0800576 // sqlite3_bind_int64(stmt, 10, ctime); // NULL
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800577
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800578 sqlite3_bind_int(stmt, 11, action->mode());
579 sqlite3_bind_int(stmt, 12, action->seg_num());
580 }
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800581
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800582 if (action->has_parent_device_name()) {
583 sqlite3_bind_blob(stmt, 13, action->parent_device_name().c_str(),
584 action->parent_device_name().size(), SQLITE_STATIC);
585 sqlite3_bind_int64(stmt, 14, action->parent_seq_no());
586 }
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800587
Lijing Wang51837ad2016-12-25 14:43:53 -0800588 Name actionName = Name(deviceName);
589 actionName.append("action").append(m_sharedFolderName).appendNumber(seqno);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800590
Lijing Wang51837ad2016-12-25 14:43:53 -0800591 sqlite3_bind_blob(stmt, 15, actionName.wireEncode().wire(), actionName.wireEncode().size(),
592 SQLITE_STATIC);
593 sqlite3_bind_blob(stmt, 16, actionData->wireEncode().wire(), actionData->wireEncode().size(),
594 SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800595 sqlite3_step(stmt);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800596
597 // if action needs to be applied to file state, the trigger will take care of it
598
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800599 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800600
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800601 sqlite3_finalize(stmt);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800602
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800603 // I had a problem including directory_name assignment as part of the initial insert.
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800604 sqlite3_prepare_v2(m_db,
605 "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?",
606 -1, &stmt, 0);
607 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800608
Lijing Wang51837ad2016-12-25 14:43:53 -0800609 sqlite3_bind_blob(stmt, 1, deviceName.wireEncode().wire(), deviceName.wireEncode().size(),
610 SQLITE_STATIC);
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800611 sqlite3_bind_int64(stmt, 2, seqno);
612 sqlite3_step(stmt);
613 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800614
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800615 sqlite3_finalize(stmt);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800616
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800617 return action;
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800618}
619
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800620ActionItemPtr
Lijing Wang51837ad2016-12-25 14:43:53 -0800621ActionLog::AddRemoteAction(shared_ptr<Data> actionData)
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800622{
Lijing Wang51837ad2016-12-25 14:43:53 -0800623 Name name = actionData->getName();
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800624 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800625
Lijing Wang51837ad2016-12-25 14:43:53 -0800626 uint64_t seqno = name.get(-1).toNumber();
627 std::string sharedFolder = name.get(-2).toUri();
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800628
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800629 if (sharedFolder != m_sharedFolderName) {
630 _LOG_ERROR("Action doesn't belong to this shared folder");
631 return ActionItemPtr();
632 }
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800633
Lijing Wang51837ad2016-12-25 14:43:53 -0800634 std::string action = name.get(-3).toUri();
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800635
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800636 if (action != "action") {
637 _LOG_ERROR("not an action");
638 return ActionItemPtr();
639 }
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800640
Lijing Wang51837ad2016-12-25 14:43:53 -0800641 std::string appName = name.get(-4).toUri();
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800642 if (appName != m_appName) {
643 _LOG_ERROR("Action doesn't belong to this application");
644 return ActionItemPtr();
645 }
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800646
Lijing Wang51837ad2016-12-25 14:43:53 -0800647 Name deviceName = name.getSubName(0, name.size() - 4);
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800648
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800649 _LOG_DEBUG("From [" << name << "] extracted deviceName: " << deviceName << ", sharedFolder: "
650 << sharedFolder
651 << ", seqno: "
652 << seqno);
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800653
Lijing Wang51837ad2016-12-25 14:43:53 -0800654 return AddRemoteAction(deviceName, seqno, actionData);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800655}
656
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800657sqlite3_int64
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800658ActionLog::LogSize()
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800659{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800660 sqlite3_stmt* stmt;
661 sqlite3_prepare_v2(m_db, "SELECT count(*) FROM ActionLog", -1, &stmt, 0);
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800662
663 sqlite3_int64 retval = -1;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800664 if (sqlite3_step(stmt) == SQLITE_ROW) {
665 retval = sqlite3_column_int64(stmt, 0);
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800666 }
667
668 return retval;
669}
670
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800671bool
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800672ActionLog::LookupActionsInFolderRecursively(
Lijing Wang51837ad2016-12-25 14:43:53 -0800673 const function<void(const Name& name, sqlite3_int64 seq_no, const ActionItem&)>& visitor,
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800674 const std::string& folder, int offset /*=0*/, int limit /*=-1*/)
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800675{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800676 _LOG_DEBUG("LookupActionsInFolderRecursively: [" << folder << "]");
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800677
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800678 if (limit >= 0)
679 limit += 1; // to check if there is more data
680
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800681 sqlite3_stmt* stmt;
682 if (folder != "") {
683 /// @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 -0800684
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800685 sqlite3_prepare_v2(m_db,
686 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
687 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
688 " parent_device_name,parent_seq_no "
689 " FROM ActionLog "
690 " WHERE is_dir_prefix (?, directory)=1 "
691 " ORDER BY action_timestamp DESC "
692 " LIMIT ? OFFSET ?",
693 -1, &stmt,
694 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
695 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800696
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800697 sqlite3_bind_text(stmt, 1, folder.c_str(), folder.size(), SQLITE_STATIC);
698 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800699
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800700 sqlite3_bind_int(stmt, 2, limit);
701 sqlite3_bind_int(stmt, 3, offset);
702 }
703 else {
704 sqlite3_prepare_v2(m_db,
705 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
706 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
707 " parent_device_name,parent_seq_no "
708 " FROM ActionLog "
709 " ORDER BY action_timestamp DESC "
710 " LIMIT ? OFFSET ?",
711 -1, &stmt, 0);
712 sqlite3_bind_int(stmt, 1, limit);
713 sqlite3_bind_int(stmt, 2, offset);
714 }
715
716 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
717
718 while (sqlite3_step(stmt) == SQLITE_ROW) {
719 if (limit == 1)
720 break;
721
722 ActionItem action;
723
Lijing Wang51837ad2016-12-25 14:43:53 -0800724 Name device_name(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
725 sqlite3_column_bytes(stmt, 0)));
726
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800727 sqlite3_int64 seq_no = sqlite3_column_int64(stmt, 1);
728 action.set_action(static_cast<ActionItem_ActionType>(sqlite3_column_int(stmt, 2)));
729 action.set_filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)),
730 sqlite3_column_bytes(stmt, 3));
731 std::string directory(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 4)),
732 sqlite3_column_bytes(stmt, 4));
733 action.set_version(sqlite3_column_int64(stmt, 5));
734 action.set_timestamp(sqlite3_column_int64(stmt, 6));
735
736 if (action.action() == 0) {
737 action.set_file_hash(sqlite3_column_blob(stmt, 7), sqlite3_column_bytes(stmt, 7));
738 action.set_mtime(sqlite3_column_int(stmt, 8));
739 action.set_mode(sqlite3_column_int(stmt, 9));
740 action.set_seg_num(sqlite3_column_int64(stmt, 10));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800741 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800742 if (sqlite3_column_bytes(stmt, 11) > 0) {
743 action.set_parent_device_name(sqlite3_column_blob(stmt, 11), sqlite3_column_bytes(stmt, 11));
744 action.set_parent_seq_no(sqlite3_column_int64(stmt, 12));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800745 }
746
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800747 visitor(device_name, seq_no, action);
748 limit--;
749 }
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800750
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800751 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800752
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800753 sqlite3_finalize(stmt);
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800754
755 return (limit == 1); // more data is available
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800756}
757
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800758/**
759 * @todo Figure out the way to minimize code duplication
760 */
761bool
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800762ActionLog::LookupActionsForFile(
Lijing Wang51837ad2016-12-25 14:43:53 -0800763 const function<void(const Name& name, sqlite3_int64 seq_no, const ActionItem&)>& visitor,
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800764 const std::string& file, int offset /*=0*/, int limit /*=-1*/)
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800765{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800766 _LOG_DEBUG("LookupActionsInFolderRecursively: [" << file << "]");
767 if (file.empty())
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800768 return false;
769
770 if (limit >= 0)
771 limit += 1; // to check if there is more data
772
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800773 sqlite3_stmt* stmt;
774 sqlite3_prepare_v2(m_db,
775 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
776 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
777 " parent_device_name,parent_seq_no "
778 " FROM ActionLog "
779 " WHERE filename=? "
780 " ORDER BY action_timestamp DESC "
781 " LIMIT ? OFFSET ?",
782 -1, &stmt,
783 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
784 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800785
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800786 sqlite3_bind_text(stmt, 1, file.c_str(), file.size(), SQLITE_STATIC);
787 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800788
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800789 sqlite3_bind_int(stmt, 2, limit);
790 sqlite3_bind_int(stmt, 3, offset);
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800791
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800792 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800793
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800794 while (sqlite3_step(stmt) == SQLITE_ROW) {
795 if (limit == 1)
796 break;
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800797
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800798 ActionItem action;
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800799
Lijing Wang51837ad2016-12-25 14:43:53 -0800800 Name device_name(Block(reinterpret_cast<const uint8_t*>(sqlite3_column_blob(stmt, 0)),
801 sqlite3_column_bytes(stmt, 0)));
802
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800803 sqlite3_int64 seq_no = sqlite3_column_int64(stmt, 1);
804 action.set_action(static_cast<ActionItem_ActionType>(sqlite3_column_int(stmt, 2)));
805 action.set_filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 3)),
806 sqlite3_column_bytes(stmt, 3));
807 std::string directory(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 4)),
808 sqlite3_column_bytes(stmt, 4));
809 action.set_version(sqlite3_column_int64(stmt, 5));
810 action.set_timestamp(sqlite3_column_int64(stmt, 6));
Alexander Afanasyev3c95c852013-03-01 18:58:50 -0800811
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800812 if (action.action() == 0) {
813 action.set_file_hash(sqlite3_column_blob(stmt, 7), sqlite3_column_bytes(stmt, 7));
814 action.set_mtime(sqlite3_column_int(stmt, 8));
815 action.set_mode(sqlite3_column_int(stmt, 9));
816 action.set_seg_num(sqlite3_column_int64(stmt, 10));
817 }
818 if (sqlite3_column_bytes(stmt, 11) > 0) {
819 action.set_parent_device_name(sqlite3_column_blob(stmt, 11), sqlite3_column_bytes(stmt, 11));
820 action.set_parent_seq_no(sqlite3_column_int64(stmt, 12));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800821 }
822
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800823 visitor(device_name, seq_no, action);
824 limit--;
825 }
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800826
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800827 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
828
829 sqlite3_finalize(stmt);
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800830
831 return (limit == 1); // more data is available
832}
833
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800834void
Lijing Wang51837ad2016-12-25 14:43:53 -0800835ActionLog::LookupRecentFileActions(const function<void(const std::string&, int, int)>& visitor,
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800836 int limit)
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800837{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800838 sqlite3_stmt* stmt;
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800839
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800840 sqlite3_prepare_v2(m_db,
841 "SELECT AL.filename, AL.action"
842 " FROM ActionLog AL"
843 " JOIN "
844 " (SELECT filename, MAX(action_timestamp) AS action_timestamp "
845 " FROM ActionLog "
846 " GROUP BY filename ) AS GAL"
847 " ON AL.filename = GAL.filename AND AL.action_timestamp = GAL.action_timestamp "
848 " ORDER BY AL.action_timestamp DESC "
849 " LIMIT ?;",
850 -1, &stmt, 0);
851 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800852 sqlite3_bind_int(stmt, 1, limit);
853 int index = 0;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800854 while (sqlite3_step(stmt) == SQLITE_ROW) {
855 std::string filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)),
856 sqlite3_column_bytes(stmt, 0));
857 int action = sqlite3_column_int(stmt, 1);
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800858 visitor(filename, action, index);
859 index++;
860 }
861
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800862 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800863
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800864 sqlite3_finalize(stmt);
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800865}
866
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800867
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800868///////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800869///////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800870///////////////////////////////////////////////////////////////////////////////////
871
872void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800873ActionLog::apply_action_xFun(sqlite3_context* context, int argc, sqlite3_value** argv)
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800874{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800875 ActionLog* the = reinterpret_cast<ActionLog*>(sqlite3_user_data(context));
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800876
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800877 if (argc != 11) {
878 sqlite3_result_error(context, "``apply_action'' expects 10 arguments", -1);
879 return;
880 }
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800881
Lijing Wang51837ad2016-12-25 14:43:53 -0800882 Buffer device_name(sqlite3_value_blob(argv[0]), sqlite3_value_bytes(argv[0]));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800883 sqlite3_int64 seq_no = sqlite3_value_int64(argv[1]);
884 int action = sqlite3_value_int(argv[2]);
Lijing Wang51837ad2016-12-25 14:43:53 -0800885 std::string filename = reinterpret_cast<const char*>(sqlite3_value_text(argv[3]));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800886 sqlite3_int64 version = sqlite3_value_int64(argv[4]);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800887
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800888 _LOG_TRACE("apply_function called with " << argc);
Lijing Wang51837ad2016-12-25 14:43:53 -0800889 _LOG_TRACE("device_name: " << Name(Block(reinterpret_cast<const char*>(device_name.buf()),
890 device_name.size()))
891 << ", action: "
892 << action
893 << ", file: "
894 << filename);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800895
896 if (action == 0) // update
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800897 {
Lijing Wang51837ad2016-12-25 14:43:53 -0800898 Buffer hash(sqlite3_value_blob(argv[5]), sqlite3_value_bytes(argv[5]));
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800899 time_t atime = static_cast<time_t>(sqlite3_value_int64(argv[6]));
900 time_t mtime = static_cast<time_t>(sqlite3_value_int64(argv[7]));
901 time_t ctime = static_cast<time_t>(sqlite3_value_int64(argv[8]));
902 int mode = sqlite3_value_int(argv[9]);
903 int seg_num = sqlite3_value_int(argv[10]);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800904
Lijing Wang51837ad2016-12-25 14:43:53 -0800905 _LOG_DEBUG("Update " << filename << " " << atime << " " << mtime << " " << ctime << " "
906 << toHex(hash));
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800907
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800908 the->m_fileState->UpdateFile(filename, version, hash, device_name, seq_no, atime, mtime, ctime,
909 mode, seg_num);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800910
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800911 // no callback here
912 }
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800913 else if (action == 1) // delete
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800914 {
915 the->m_fileState->DeleteFile(filename);
Alexander Afanasyev0c545ed2013-01-26 00:12:32 -0800916
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800917 the->m_onFileRemoved(filename);
918 }
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800919
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800920 sqlite3_result_null(context);
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800921}
Lijing Wang51837ad2016-12-25 14:43:53 -0800922
923} // namespace chronoshare
924} // namespace ndn