blob: 18a8fa89c7ccb995e87f240ae56137dbfccc8b1e [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
3 * Copyright (c) 2013-2016, 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"
22#include "logging.hpp"
Alexander Afanasyeva199f972013-01-02 19:37:26 -080023
Alexander Afanasyev0995f322013-01-22 13:16:46 -080024#include <boost/make_shared.hpp>
25
Alexander Afanasyeva199f972013-01-02 19:37:26 -080026using namespace boost;
27using namespace std;
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -070028using namespace Ndnx;
Alexander Afanasyeva199f972013-01-02 19:37:26 -080029
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080030INIT_LOGGER ("ActionLog");
31
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), \
81 NEW.file_chmod, NEW.file_seg_num); /* function that applies action and adds record the FileState */ \n \
82 END; \n\
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080083";
84
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080085// static void xTrace (void*, const char* q)
86// {
87// _LOG_TRACE ("SQLITE: " << q);
88// }
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080089
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -070090ActionLog::ActionLog (Ndnx::NdnxWrapperPtr ndnx, const boost::filesystem::path &path,
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080091 SyncLogPtr syncLog,
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -080092 const std::string &sharedFolder, const std::string &appName,
Alexander Afanasyevf9978f82013-01-23 16:30:31 -080093 OnFileAddedOrChangedCallback onFileAddedOrChanged, OnFileRemovedCallback onFileRemoved)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -080094 : DbHelper (path / ".chronoshare", "action-log.db")
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -080095 , m_syncLog (syncLog)
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -070096 , m_ndnx (ndnx)
Alexander Afanasyevc9eb68f2013-01-07 13:40:00 -080097 , m_sharedFolderName (sharedFolder)
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -080098 , m_appName (appName)
Alexander Afanasyevf9978f82013-01-23 16:30:31 -080099 , m_onFileAddedOrChanged (onFileAddedOrChanged)
100 , m_onFileRemoved (onFileRemoved)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800101{
Alexander Afanasyev785b0a02013-01-30 10:17:47 -0800102 sqlite3_exec (m_db, "PRAGMA foreign_keys = OFF", NULL, NULL, NULL);
103 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
104
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -0800105 sqlite3_exec (m_db, INIT_DATABASE.c_str (), NULL, NULL, NULL);
106 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
107
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800108 int res = sqlite3_create_function (m_db, "apply_action", -1, SQLITE_ANY, reinterpret_cast<void*> (this),
109 ActionLog::apply_action_xFun,
110 0, 0);
111 if (res != SQLITE_OK)
112 {
113 BOOST_THROW_EXCEPTION (Error::Db ()
114 << errmsg_info_str ("Cannot create function ``apply_action''"));
115 }
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800116
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800117 m_fileState = make_shared<FileState> (path);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800118}
119
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700120tuple<sqlite3_int64 /*version*/, Ndnx::NdnxCharbufPtr /*device name*/, sqlite3_int64 /*seq_no*/>
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800121ActionLog::GetLatestActionForFile (const std::string &filename)
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800122{
123 // check if something already exists
124 sqlite3_stmt *stmt;
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800125 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", -1, &stmt, 0);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800128
129 if (res != SQLITE_OK)
130 {
131 BOOST_THROW_EXCEPTION (Error::Db ()
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800132 << errmsg_info_str ("Some error with GetExistingRecord"));
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800133 }
134
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800135 sqlite3_int64 version = -1;
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700136 NdnxCharbufPtr parent_device_name;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800137 sqlite3_int64 parent_seq_no = -1;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800138
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800139 sqlite3_bind_text (stmt, 1, filename.c_str (), filename.size (), SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800140 if (sqlite3_step (stmt) == SQLITE_ROW)
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800141 {
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800142 version = sqlite3_column_int64 (stmt, 0);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800143
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800144 if (sqlite3_column_int (stmt, 3) == 0) // prevent "linking" if the file was previously deleted
145 {
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700146 parent_device_name = make_shared<NdnxCharbuf> (sqlite3_column_blob (stmt, 1), sqlite3_column_bytes (stmt, 1));
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800147 parent_seq_no = sqlite3_column_int64 (stmt, 2);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800148 }
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800149 }
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800150
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800151 sqlite3_finalize (stmt);
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800152 return make_tuple (version, parent_device_name, parent_seq_no);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800153}
154
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800155// local add action. remote action is extracted from content object
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800156ActionItemPtr
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800157ActionLog::AddLocalActionUpdate (const std::string &filename,
158 const Hash &hash,
159 time_t wtime,
160 int mode,
161 int seg_num)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800162{
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800163 sqlite3_exec (m_db, "BEGIN TRANSACTION;", 0,0,0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800164
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700165 NdnxCharbufPtr device_name = m_syncLog->GetLocalName ().toNdnxCharbuf ();
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800166 sqlite3_int64 seq_no = m_syncLog->GetNextLocalSeqNo ();
167 sqlite3_int64 version;
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700168 NdnxCharbufPtr parent_device_name;
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800169 sqlite3_int64 parent_seq_no = -1;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800170
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800171 sqlite3_int64 action_time = time (0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800172
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800173 tie (version, parent_device_name, parent_seq_no) = GetLatestActionForFile (filename);
174 version ++;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800175
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800176 sqlite3_stmt *stmt;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800177 int res = sqlite3_prepare_v2 (m_db, "INSERT INTO ActionLog "
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800178 "(device_name, seq_no, action, filename, version, action_timestamp, "
Alexander Afanasyev334aac82013-01-18 14:06:39 -0800179 "file_hash, file_atime, file_mtime, file_ctime, file_chmod, file_seg_num, "
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800180 "parent_device_name, parent_seq_no, "
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800181 "action_name, action_content_object) "
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800182 "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800183 " ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,?, "
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800184 " ?, ?, "
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800185 " ?, ?);", -1, &stmt, 0);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800186
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800187 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
188
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800189 if (res != SQLITE_OK)
190 {
191 BOOST_THROW_EXCEPTION (Error::Db ()
192 << errmsg_info_str (sqlite3_errmsg (m_db))
193 );
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800194 }
195
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800196 sqlite3_bind_blob (stmt, 1, device_name->buf (), device_name->length (), SQLITE_STATIC);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800197 sqlite3_bind_int64 (stmt, 2, seq_no);
198 sqlite3_bind_int (stmt, 3, 0);
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800199 sqlite3_bind_text (stmt, 4, filename.c_str (), filename.size (), SQLITE_STATIC);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800200 sqlite3_bind_int64 (stmt, 5, version);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800201 sqlite3_bind_int64 (stmt, 6, action_time);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800202
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800203 sqlite3_bind_blob (stmt, 7, hash.GetHash (), hash.GetHashBytes (), SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800204
Alexander Afanasyev68f2a952013-01-08 14:34:16 -0800205 // sqlite3_bind_int64 (stmt, 8, atime); // NULL
206 sqlite3_bind_int64 (stmt, 9, wtime);
207 // sqlite3_bind_int64 (stmt, 10, ctime); // NULL
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800208 sqlite3_bind_int (stmt, 11, mode);
Alexander Afanasyev334aac82013-01-18 14:06:39 -0800209 sqlite3_bind_int (stmt, 12, seg_num);
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800210
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800211 if (parent_device_name && parent_seq_no > 0)
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800212 {
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800213 sqlite3_bind_blob (stmt, 13, parent_device_name->buf (), parent_device_name->length (), SQLITE_STATIC);
Alexander Afanasyev334aac82013-01-18 14:06:39 -0800214 sqlite3_bind_int64 (stmt, 14, parent_seq_no);
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800215 }
Alexander Afanasyev433ecda2013-01-02 22:13:45 -0800216
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800217 ActionItemPtr item = make_shared<ActionItem> ();
218 item->set_action (ActionItem::UPDATE);
219 item->set_filename (filename);
220 item->set_version (version);
221 item->set_timestamp (action_time);
222 item->set_file_hash (hash.GetHash (), hash.GetHashBytes ());
223 // item->set_atime (atime);
224 item->set_mtime (wtime);
225 // item->set_ctime (ctime);
226 item->set_mode (mode);
227 item->set_seg_num (seg_num);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800228
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800229 if (parent_device_name && parent_seq_no > 0)
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800230 {
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800231 // cout << Name (*parent_device_name) << endl;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800232
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800233 item->set_parent_device_name (parent_device_name->buf (), parent_device_name->length ());
234 item->set_parent_seq_no (parent_seq_no);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800235 }
236
237 // assign name to the action, serialize action, and create content object
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800238
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800239
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800240 string item_msg;
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800241 item->SerializeToString (&item_msg);
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800242
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800243 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
244 Name actionName = Name ("/")(m_syncLog->GetLocalName ())(m_appName)("action")(m_sharedFolderName)(seq_no);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800245 _LOG_DEBUG ("ActionName: " << actionName);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800246
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700247 Bytes actionData = m_ndnx->createContentObject (actionName, item_msg.c_str (), item_msg.size ());
248 NdnxCharbufPtr namePtr = actionName.toNdnxCharbuf ();
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800249
Alexander Afanasyevfc720362013-01-24 21:49:48 -0800250 // _LOG_DEBUG (" >>>>>>> " << Name (namePtr->buf () << " " << namePtr->length ());
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800251
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800252 sqlite3_bind_blob (stmt, 15, namePtr->buf (), namePtr->length (), SQLITE_STATIC);
253 sqlite3_bind_blob (stmt, 16, head (actionData), actionData.size (), SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800254
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800255 sqlite3_step (stmt);
256
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800257 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800258
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800259 sqlite3_finalize (stmt);
260
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800261 // I had a problem including directory_name assignment as part of the initial insert.
262 sqlite3_prepare_v2 (m_db, "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?", -1, &stmt, 0);
263 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
264
265 sqlite3_bind_blob (stmt, 1, device_name->buf (), device_name->length (), SQLITE_STATIC);
266 sqlite3_bind_int64 (stmt, 2, seq_no);
267 sqlite3_step (stmt);
268 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
269
270 sqlite3_finalize (stmt);
271
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800272 sqlite3_exec (m_db, "END TRANSACTION;", 0,0,0);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800273
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800274 // set complete for local file
275 m_fileState->SetFileComplete(filename);
276
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800277 return item;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800278}
279
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800280// void
281// ActionLog::AddActionMove (const std::string &oldFile, const std::string &newFile)
282// {
283// // not supported yet
284// BOOST_THROW_EXCEPTION (Error::Db ()
285// << errmsg_info_str ("Move operation is not yet supported"));
286// }
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800287
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800288ActionItemPtr
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800289ActionLog::AddLocalActionDelete (const std::string &filename)
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800290{
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800291 _LOG_DEBUG ("Adding local action DELETE");
292
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800293 sqlite3_exec (m_db, "BEGIN TRANSACTION;", 0,0,0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800294
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700295 NdnxCharbufPtr device_name = m_syncLog->GetLocalName ().toNdnxCharbuf ();
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800296 sqlite3_int64 version;
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700297 NdnxCharbufPtr parent_device_name;
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800298 sqlite3_int64 parent_seq_no = -1;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800299
300 sqlite3_int64 action_time = time (0);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800301
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800302 tie (version, parent_device_name, parent_seq_no) = GetLatestActionForFile (filename);
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800303 if (!parent_device_name) // no records exist or file was already deleted
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800304 {
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800305 _LOG_DEBUG ("Nothing to delete... [" << filename << "]");
306
307 // just in case, remove data from FileState
308 sqlite3_stmt *stmt;
309 sqlite3_prepare_v2 (m_db, "DELETE FROM FileState WHERE filename = ? ", -1, &stmt, 0);
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800310 sqlite3_bind_text (stmt, 1, filename.c_str (), filename.size (), SQLITE_STATIC); // file
Alexander Afanasyev4a8781c2013-01-29 17:59:44 -0800311
312 sqlite3_step (stmt);
313
314 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
315
316 sqlite3_finalize (stmt);
317
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800318 sqlite3_exec (m_db, "END TRANSACTION;", 0,0,0);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800319 return ActionItemPtr ();
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800320 }
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800321 version ++;
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800322
Alexander Afanasyev8e2104a2013-01-22 10:56:18 -0800323 sqlite3_int64 seq_no = m_syncLog->GetNextLocalSeqNo ();
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800324
325 sqlite3_stmt *stmt;
326 sqlite3_prepare_v2 (m_db, "INSERT INTO ActionLog "
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800327 "(device_name, seq_no, action, filename, version, action_timestamp, "
328 "parent_device_name, parent_seq_no, "
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800329 "action_name, action_content_object) "
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800330 "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
Alexander Afanasyevebf75182013-01-07 17:00:24 -0800331 " ?, ?,"
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800332 " ?, ?)", -1, &stmt, 0);
333
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800334 sqlite3_bind_blob (stmt, 1, device_name->buf (), device_name->length (), SQLITE_STATIC);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800335 sqlite3_bind_int64 (stmt, 2, seq_no);
336 sqlite3_bind_int (stmt, 3, 1);
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800337 sqlite3_bind_text (stmt, 4, filename.c_str (), filename.size (), SQLITE_STATIC); // file
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800338
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800339 sqlite3_bind_int64 (stmt, 5, version);
340 sqlite3_bind_int64 (stmt, 6, action_time);
341
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800342 sqlite3_bind_blob (stmt, 7, parent_device_name->buf (), parent_device_name->length (), SQLITE_STATIC);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800343 sqlite3_bind_int64 (stmt, 8, parent_seq_no);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800344
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800345 ActionItemPtr item = make_shared<ActionItem> ();
Alexander Afanasyev6d4befc2013-01-26 00:01:28 -0800346 item->set_action (ActionItem::DELETE);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800347 item->set_filename (filename);
348 item->set_version (version);
349 item->set_timestamp (action_time);
350 item->set_parent_device_name (parent_device_name->buf (), parent_device_name->length ());
351 item->set_parent_seq_no (parent_seq_no);
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800352
Alexander Afanasyevc9eb68f2013-01-07 13:40:00 -0800353 string item_msg;
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800354 item->SerializeToString (&item_msg);
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800355
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800356 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
357 Name actionName = Name ("/")(m_syncLog->GetLocalName ())(m_appName)("action")(m_sharedFolderName)(seq_no);
Alexander Afanasyev1d1cc832013-02-05 20:03:36 -0800358 _LOG_DEBUG ("ActionName: " << actionName);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800359
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700360 Bytes actionData = m_ndnx->createContentObject (actionName, item_msg.c_str (), item_msg.size ());
361 NdnxCharbufPtr namePtr = actionName.toNdnxCharbuf ();
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800362
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800363 sqlite3_bind_blob (stmt, 9, namePtr->buf (), namePtr->length (), SQLITE_STATIC);
364 sqlite3_bind_blob (stmt, 10, &actionData[0], actionData.size (), SQLITE_STATIC);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800365
Alexander Afanasyevc9eb68f2013-01-07 13:40:00 -0800366 sqlite3_step (stmt);
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800367
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800368 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800369
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700370 // cout << Ndnx::Name (parent_device_name) << endl;
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800371
Alexander Afanasyevb6bc01a2013-01-02 23:34:20 -0800372 // assign name to the action, serialize action, and create content object
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800373
374 sqlite3_finalize (stmt);
375
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800376 // I had a problem including directory_name assignment as part of the initial insert.
377 sqlite3_prepare_v2 (m_db, "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?", -1, &stmt, 0);
378 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
379
380 sqlite3_bind_blob (stmt, 1, device_name->buf (), device_name->length (), SQLITE_STATIC);
381 sqlite3_bind_int64 (stmt, 2, seq_no);
382 sqlite3_step (stmt);
383 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
384
385 sqlite3_finalize (stmt);
386
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800387 sqlite3_exec (m_db, "END TRANSACTION;", 0,0,0);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800388
389 return item;
Alexander Afanasyeva199f972013-01-02 19:37:26 -0800390}
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800391
392
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800393PcoPtr
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700394ActionLog::LookupActionPco (const Ndnx::Name &deviceName, sqlite3_int64 seqno)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800395{
396 sqlite3_stmt *stmt;
397 sqlite3_prepare_v2 (m_db, "SELECT action_content_object FROM ActionLog WHERE device_name=? AND seq_no=?", -1, &stmt, 0);
398
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700399 NdnxCharbufPtr name = deviceName.toNdnxCharbuf ();
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800400
401 sqlite3_bind_blob (stmt, 1, name->buf (), name->length (), SQLITE_STATIC);
402 sqlite3_bind_int64 (stmt, 2, seqno);
403
404 PcoPtr retval;
405 if (sqlite3_step (stmt) == SQLITE_ROW)
406 {
407 // _LOG_DEBUG (sqlite3_column_blob (stmt, 0) << ", " << sqlite3_column_bytes (stmt, 0));
408 retval = make_shared<ParsedContentObject> (reinterpret_cast<const unsigned char *> (sqlite3_column_blob (stmt, 0)), sqlite3_column_bytes (stmt, 0));
409 }
410 else
411 {
412 _LOG_TRACE ("No action found for deviceName [" << deviceName << "] and seqno:" << seqno);
413 }
414 // _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK && sqlite3_errcode (m_db) != SQLITE_ROW, sqlite3_errmsg (m_db));
415 sqlite3_finalize (stmt);
416
417 return retval;
418}
419
420ActionItemPtr
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700421ActionLog::LookupAction (const Ndnx::Name &deviceName, sqlite3_int64 seqno)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800422{
423 PcoPtr pco = LookupActionPco (deviceName, seqno);
424 if (!pco) return ActionItemPtr ();
425
426 ActionItemPtr action = deserializeMsg<ActionItem> (pco->content ());
427
428 return action;
429}
430
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700431Ndnx::PcoPtr
432ActionLog::LookupActionPco (const Ndnx::Name &actionName)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800433{
434 sqlite3_stmt *stmt;
435 sqlite3_prepare_v2 (m_db, "SELECT action_content_object FROM ActionLog WHERE action_name=?", -1, &stmt, 0);
436
437 _LOG_DEBUG (actionName);
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700438 NdnxCharbufPtr name = actionName.toNdnxCharbuf ();
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800439
440 _LOG_DEBUG (" <<<<<<< " << name->buf () << " " << name->length ());
441
442 sqlite3_bind_blob (stmt, 1, name->buf (), name->length (), SQLITE_STATIC);
443
444 PcoPtr retval;
445 if (sqlite3_step (stmt) == SQLITE_ROW)
446 {
447 // _LOG_DEBUG (sqlite3_column_blob (stmt, 0) << ", " << sqlite3_column_bytes (stmt, 0));
448 retval = make_shared<ParsedContentObject> (reinterpret_cast<const unsigned char *> (sqlite3_column_blob (stmt, 0)), sqlite3_column_bytes (stmt, 0));
449 }
450 else
451 {
452 _LOG_TRACE ("No action found for name: " << actionName);
453 }
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800454 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_ROW, sqlite3_errmsg (m_db));
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800455 sqlite3_finalize (stmt);
456
457 return retval;
458}
459
460ActionItemPtr
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700461ActionLog::LookupAction (const Ndnx::Name &actionName)
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800462{
463 PcoPtr pco = LookupActionPco (actionName);
464 if (!pco) return ActionItemPtr ();
465
466 ActionItemPtr action = deserializeMsg<ActionItem> (pco->content ());
467
468 return action;
469}
470
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800471FileItemPtr
472ActionLog::LookupAction (const std::string &filename, sqlite3_int64 version, const Hash &filehash)
473{
474 sqlite3_stmt *stmt;
475 sqlite3_prepare_v2 (m_db,
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800476 "SELECT device_name, seq_no, strftime('%s', file_mtime), file_chmod, file_seg_num, file_hash "
Alexander Afanasyev026eaf32013-02-23 16:37:14 -0800477 " FROM ActionLog "
478 " WHERE action = 0 AND "
479 " filename=? AND "
480 " version=? AND "
481 " is_prefix (?, file_hash)=1", -1, &stmt, 0);
482 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
483
484 sqlite3_bind_text (stmt, 1, filename.c_str (), filename.size (), SQLITE_STATIC);
485 sqlite3_bind_int64 (stmt, 2, version);
486 sqlite3_bind_blob (stmt, 3, filehash.GetHash (), filehash.GetHashBytes (), SQLITE_STATIC);
487
488 FileItemPtr fileItem;
489
490 if (sqlite3_step (stmt) == SQLITE_ROW)
491 {
492 fileItem = make_shared<FileItem> ();
493 fileItem->set_filename (filename);
494 fileItem->set_device_name (sqlite3_column_blob (stmt, 0), sqlite3_column_bytes (stmt, 0));
495 fileItem->set_seq_no (sqlite3_column_int64 (stmt, 1));
496 fileItem->set_mtime (sqlite3_column_int64 (stmt, 2));
497 fileItem->set_mode (sqlite3_column_int64 (stmt, 3));
498 fileItem->set_seg_num (sqlite3_column_int64 (stmt, 4));
499
500 fileItem->set_file_hash (sqlite3_column_blob (stmt, 5), sqlite3_column_bytes (stmt, 5));
501 }
502
503 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE || sqlite3_errcode (m_db) != SQLITE_ROW || sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
504
505 return fileItem;
506}
507
508
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800509ActionItemPtr
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700510ActionLog::AddRemoteAction (const Ndnx::Name &deviceName, sqlite3_int64 seqno, Ndnx::PcoPtr actionPco)
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800511{
512 if (!actionPco)
513 {
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800514 _LOG_ERROR ("actionPco is not valid");
515 return ActionItemPtr ();
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800516 }
517 ActionItemPtr action = deserializeMsg<ActionItem> (actionPco->content ());
518
519 if (!action)
520 {
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800521 _LOG_ERROR ("action cannot be decoded");
522 return ActionItemPtr ();
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800523 }
524
Alexander Afanasyevf695aed2013-01-30 13:28:42 -0800525 _LOG_DEBUG ("AddRemoteAction: [" << deviceName << "] seqno: " << seqno);
526
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800527 sqlite3_stmt *stmt;
528 int res = sqlite3_prepare_v2 (m_db, "INSERT INTO ActionLog "
529 "(device_name, seq_no, action, filename, version, action_timestamp, "
530 "file_hash, file_atime, file_mtime, file_ctime, file_chmod, file_seg_num, "
531 "parent_device_name, parent_seq_no, "
532 "action_name, action_content_object) "
533 "VALUES (?, ?, ?, ?, ?, datetime(?, 'unixepoch'),"
534 " ?, datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?,?, "
535 " ?, ?, "
536 " ?, ?);", -1, &stmt, 0);
Alexander Afanasyevf695aed2013-01-30 13:28:42 -0800537 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800538
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700539 NdnxCharbufPtr device_name = deviceName.toNdnxCharbuf ();
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800540 sqlite3_bind_blob (stmt, 1, device_name->buf (), device_name->length (), SQLITE_STATIC);
541 sqlite3_bind_int64 (stmt, 2, seqno);
542
543 sqlite3_bind_int (stmt, 3, action->action ());
544 sqlite3_bind_text (stmt, 4, action->filename ().c_str (), action->filename ().size (), SQLITE_STATIC);
545 sqlite3_bind_int64 (stmt, 5, action->version ());
546 sqlite3_bind_int64 (stmt, 6, action->timestamp ());
547
548 if (action->action () == ActionItem::UPDATE)
549 {
550 sqlite3_bind_blob (stmt, 7, action->file_hash ().c_str (), action->file_hash ().size (), SQLITE_STATIC);
551
552 // sqlite3_bind_int64 (stmt, 8, atime); // NULL
553 sqlite3_bind_int64 (stmt, 9, action->mtime ());
554 // sqlite3_bind_int64 (stmt, 10, ctime); // NULL
555
556 sqlite3_bind_int (stmt, 11, action->mode ());
557 sqlite3_bind_int (stmt, 12, action->seg_num ());
558 }
559
560 if (action->has_parent_device_name ())
561 {
Alexander Afanasyev2b760d02013-02-07 13:47:29 -0800562 sqlite3_bind_blob (stmt, 13, action->parent_device_name ().c_str (), action->parent_device_name ().size (), SQLITE_STATIC);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800563 sqlite3_bind_int64 (stmt, 14, action->parent_seq_no ());
564 }
565
566 Name actionName = Name (deviceName)("action")(m_sharedFolderName)(seqno);
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700567 NdnxCharbufPtr namePtr = actionName.toNdnxCharbuf ();
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800568
569 sqlite3_bind_blob (stmt, 15, namePtr->buf (), namePtr->length (), SQLITE_STATIC);
570 sqlite3_bind_blob (stmt, 16, head (actionPco->buf ()), actionPco->buf ().size (), SQLITE_STATIC);
571 sqlite3_step (stmt);
572
573 // if action needs to be applied to file state, the trigger will take care of it
574
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -0800575 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800576
577 sqlite3_finalize (stmt);
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800578
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800579 // I had a problem including directory_name assignment as part of the initial insert.
580 sqlite3_prepare_v2 (m_db, "UPDATE ActionLog SET directory=directory_name(filename) WHERE device_name=? AND seq_no=?", -1, &stmt, 0);
581 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
582
583 sqlite3_bind_blob (stmt, 1, device_name->buf (), device_name->length (), SQLITE_STATIC);
584 sqlite3_bind_int64 (stmt, 2, seqno);
585 sqlite3_step (stmt);
586 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
587
588 sqlite3_finalize (stmt);
589
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800590 return action;
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800591}
592
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800593ActionItemPtr
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700594ActionLog::AddRemoteAction (Ndnx::PcoPtr actionPco)
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800595{
596 Name name = actionPco->name ();
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800597 // action name: /<device_name>/<appname>/action/<shared-folder>/<action-seq>
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800598
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800599 uint64_t seqno = name.getCompFromBackAsInt (0);
600 string sharedFolder = name.getCompFromBackAsString (1);
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800601
602 if (sharedFolder != m_sharedFolderName)
603 {
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800604 _LOG_ERROR ("Action doesn't belong to this shared folder");
605 return ActionItemPtr ();
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800606 }
607
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800608 string action = name.getCompFromBackAsString (2);
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800609
610 if (action != "action")
611 {
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800612 _LOG_ERROR ("not an action");
613 return ActionItemPtr ();
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800614 }
Alexander Afanasyev4d086752013-02-07 13:06:04 -0800615
616 string appName = name.getCompFromBackAsString (3);
617 if (appName != m_appName)
618 {
619 _LOG_ERROR ("Action doesn't belong to this application");
620 return ActionItemPtr ();
621 }
622
623 Name deviceName = name.getPartialName (0, name.size ()-4);
Alexander Afanasyev08aa70a2013-01-22 22:16:25 -0800624
625 _LOG_DEBUG ("From [" << name << "] extracted deviceName: " << deviceName << ", sharedFolder: " << sharedFolder << ", seqno: " << seqno);
626
Alexander Afanasyevf9978f82013-01-23 16:30:31 -0800627 return AddRemoteAction (deviceName, seqno, actionPco);
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800628}
629
Alexander Afanasyevf2c16e02013-01-23 18:08:04 -0800630sqlite3_int64
631ActionLog::LogSize ()
632{
633 sqlite3_stmt *stmt;
634 sqlite3_prepare_v2 (m_db, "SELECT count(*) FROM ActionLog", -1, &stmt, 0);
635
636 sqlite3_int64 retval = -1;
637 if (sqlite3_step (stmt) == SQLITE_ROW)
638 {
639 retval = sqlite3_column_int64 (stmt, 0);
640 }
641
642 return retval;
643}
644
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800645
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800646bool
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700647ActionLog::LookupActionsInFolderRecursively (const boost::function<void (const Ndnx::Name &name, sqlite3_int64 seq_no, const ActionItem &)> &visitor,
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800648 const std::string &folder, int offset/*=0*/, int limit/*=-1*/)
649{
650 _LOG_DEBUG ("LookupActionsInFolderRecursively: [" << folder << "]");
651
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800652 if (limit >= 0)
653 limit += 1; // to check if there is more data
654
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800655 sqlite3_stmt *stmt;
656 if (folder != "")
657 {
658 /// @todo Do something to improve efficiency of this query. Right now it is basically scanning the whole database
659
660 sqlite3_prepare_v2 (m_db,
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800661 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
662 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800663 " parent_device_name,parent_seq_no "
664 " FROM ActionLog "
Alexander Afanasyev20fd84a2013-02-27 12:17:00 -0800665 " WHERE is_dir_prefix (?, directory)=1 "
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800666 " ORDER BY action_timestamp DESC "
667 " LIMIT ? OFFSET ?", -1, &stmt, 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
668 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
669
670 sqlite3_bind_text (stmt, 1, folder.c_str (), folder.size (), SQLITE_STATIC);
671 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
672
673 sqlite3_bind_int (stmt, 2, limit);
674 sqlite3_bind_int (stmt, 3, offset);
675 }
676 else
677 {
678 sqlite3_prepare_v2 (m_db,
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800679 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
680 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800681 " parent_device_name,parent_seq_no "
682 " FROM ActionLog "
683 " ORDER BY action_timestamp DESC "
684 " LIMIT ? OFFSET ?", -1, &stmt, 0);
685 sqlite3_bind_int (stmt, 1, limit);
686 sqlite3_bind_int (stmt, 2, offset);
687 }
688
689 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
690
691 while (sqlite3_step (stmt) == SQLITE_ROW)
692 {
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800693 if (limit == 1)
694 break;
695
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800696 ActionItem action;
697
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700698 Ndnx::Name device_name (sqlite3_column_blob (stmt, 0), sqlite3_column_bytes (stmt, 0));
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800699 sqlite3_int64 seq_no = sqlite3_column_int64 (stmt, 1);
700 action.set_action (static_cast<ActionItem_ActionType> (sqlite3_column_int (stmt, 2)));
701 action.set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 3)), sqlite3_column_bytes (stmt, 3));
702 std::string directory (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 4)), sqlite3_column_bytes (stmt, 4));
Alexander Afanasyev3c95c852013-03-01 18:58:50 -0800703 action.set_version (sqlite3_column_int64 (stmt, 5));
Alexander Afanasyev4c17b482013-03-02 01:32:35 -0800704 action.set_timestamp (sqlite3_column_int64 (stmt, 6));
Alexander Afanasyev3c95c852013-03-01 18:58:50 -0800705
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800706 if (action.action () == 0)
707 {
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800708 action.set_file_hash (sqlite3_column_blob (stmt, 7), sqlite3_column_bytes (stmt, 7));
709 action.set_mtime (sqlite3_column_int (stmt, 8));
710 action.set_mode (sqlite3_column_int (stmt, 9));
711 action.set_seg_num (sqlite3_column_int64 (stmt, 10));
712 }
713 if (sqlite3_column_bytes (stmt, 11) > 0)
714 {
715 action.set_parent_device_name (sqlite3_column_blob (stmt, 11), sqlite3_column_bytes (stmt, 11));
716 action.set_parent_seq_no (sqlite3_column_int64 (stmt, 12));
717 }
718
719 visitor (device_name, seq_no, action);
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800720 limit --;
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800721 }
722
723 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
724
725 sqlite3_finalize (stmt);
Alexander Afanasyeve1c95042013-02-27 01:02:36 -0800726
727 return (limit == 1); // more data is available
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800728}
729
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800730/**
731 * @todo Figure out the way to minimize code duplication
732 */
733bool
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700734ActionLog::LookupActionsForFile (const boost::function<void (const Ndnx::Name &name, sqlite3_int64 seq_no, const ActionItem &)> &visitor,
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800735 const std::string &file, int offset/*=0*/, int limit/*=-1*/)
736{
737 _LOG_DEBUG ("LookupActionsInFolderRecursively: [" << file << "]");
738 if (file.empty ())
739 return false;
740
741 if (limit >= 0)
742 limit += 1; // to check if there is more data
743
744 sqlite3_stmt *stmt;
745 sqlite3_prepare_v2 (m_db,
746 "SELECT device_name,seq_no,action,filename,directory,version,strftime('%s', action_timestamp), "
747 " file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num, "
748 " parent_device_name,parent_seq_no "
749 " FROM ActionLog "
750 " WHERE filename=? "
751 " ORDER BY action_timestamp DESC "
752 " LIMIT ? OFFSET ?", -1, &stmt, 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
753 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
754
755 sqlite3_bind_text (stmt, 1, file.c_str (), file.size (), SQLITE_STATIC);
756 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
757
758 sqlite3_bind_int (stmt, 2, limit);
759 sqlite3_bind_int (stmt, 3, offset);
760
761 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
762
763 while (sqlite3_step (stmt) == SQLITE_ROW)
764 {
765 if (limit == 1)
766 break;
767
768 ActionItem action;
769
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700770 Ndnx::Name device_name (sqlite3_column_blob (stmt, 0), sqlite3_column_bytes (stmt, 0));
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800771 sqlite3_int64 seq_no = sqlite3_column_int64 (stmt, 1);
772 action.set_action (static_cast<ActionItem_ActionType> (sqlite3_column_int (stmt, 2)));
773 action.set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 3)), sqlite3_column_bytes (stmt, 3));
774 std::string directory (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 4)), sqlite3_column_bytes (stmt, 4));
Alexander Afanasyev3c95c852013-03-01 18:58:50 -0800775 action.set_version (sqlite3_column_int64 (stmt, 5));
Alexander Afanasyev4c17b482013-03-02 01:32:35 -0800776 action.set_timestamp (sqlite3_column_int64 (stmt, 6));
Alexander Afanasyev3c95c852013-03-01 18:58:50 -0800777
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800778 if (action.action () == 0)
779 {
Alexander Afanasyev39dbc4b2013-03-01 10:39:23 -0800780 action.set_file_hash (sqlite3_column_blob (stmt, 7), sqlite3_column_bytes (stmt, 7));
781 action.set_mtime (sqlite3_column_int (stmt, 8));
782 action.set_mode (sqlite3_column_int (stmt, 9));
783 action.set_seg_num (sqlite3_column_int64 (stmt, 10));
784 }
785 if (sqlite3_column_bytes (stmt, 11) > 0)
786 {
787 action.set_parent_device_name (sqlite3_column_blob (stmt, 11), sqlite3_column_bytes (stmt, 11));
788 action.set_parent_seq_no (sqlite3_column_int64 (stmt, 12));
789 }
790
791 visitor (device_name, seq_no, action);
792 limit --;
793 }
794
795 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
796
797 sqlite3_finalize (stmt);
798
799 return (limit == 1); // more data is available
800}
801
802
Zhenkai Zhu25e13582013-02-27 15:33:01 -0800803void
804ActionLog::LookupRecentFileActions(const boost::function<void (const string &, int, int)> &visitor, int limit)
805{
806 sqlite3_stmt *stmt;
807
808 sqlite3_prepare_v2 (m_db,
809 "SELECT AL.filename, AL.action"
810 " FROM ActionLog AL"
811 " JOIN "
812 " (SELECT filename, MAX(action_timestamp) AS action_timestamp "
813 " FROM ActionLog "
814 " GROUP BY filename ) AS GAL"
815 " ON AL.filename = GAL.filename AND AL.action_timestamp = GAL.action_timestamp "
816 " ORDER BY AL.action_timestamp DESC "
817 " LIMIT ?;",
818 -1, &stmt, 0);
819 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
820 sqlite3_bind_int(stmt, 1, limit);
821 int index = 0;
822 while (sqlite3_step(stmt) == SQLITE_ROW)
823 {
824 std::string filename(reinterpret_cast<const char *> (sqlite3_column_text (stmt, 0)), sqlite3_column_bytes (stmt, 0));
825 int action = sqlite3_column_int (stmt, 1);
826 visitor(filename, action, index);
827 index++;
828 }
829
830 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
831
832 sqlite3_finalize (stmt);
833}
834
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800835
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800836///////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800837///////////////////////////////////////////////////////////////////////////////////
Alexander Afanasyev053e5ac2013-01-22 20:59:13 -0800838///////////////////////////////////////////////////////////////////////////////////
839
840void
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800841ActionLog::apply_action_xFun (sqlite3_context *context, int argc, sqlite3_value **argv)
842{
843 ActionLog *the = reinterpret_cast<ActionLog*> (sqlite3_user_data (context));
844
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800845 if (argc != 11)
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800846 {
Alexander Afanasyeva35756b2013-01-22 16:59:11 -0800847 sqlite3_result_error (context, "``apply_action'' expects 10 arguments", -1);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800848 return;
849 }
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800850
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -0700851 NdnxCharbuf device_name (sqlite3_value_blob (argv[0]), sqlite3_value_bytes (argv[0]));
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800852 sqlite3_int64 seq_no = sqlite3_value_int64 (argv[1]);
853 int action = sqlite3_value_int (argv[2]);
854 string filename = reinterpret_cast<const char*> (sqlite3_value_text (argv[3]));
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800855 sqlite3_int64 version = sqlite3_value_int64 (argv[4]);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800856
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800857 _LOG_TRACE ("apply_function called with " << argc);
858 _LOG_TRACE ("device_name: " << Name (device_name)
859 << ", action: " << action
860 << ", file: " << filename);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800861
862 if (action == 0) // update
863 {
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800864 Hash hash (sqlite3_value_blob (argv[5]), sqlite3_value_bytes (argv[5]));
865 time_t atime = static_cast<time_t> (sqlite3_value_int64 (argv[6]));
866 time_t mtime = static_cast<time_t> (sqlite3_value_int64 (argv[7]));
867 time_t ctime = static_cast<time_t> (sqlite3_value_int64 (argv[8]));
868 int mode = sqlite3_value_int (argv[9]);
869 int seg_num = sqlite3_value_int (argv[10]);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800870
Alexander Afanasyev0995f322013-01-22 13:16:46 -0800871 _LOG_DEBUG ("Update " << filename << " " << atime << " " << mtime << " " << ctime << " " << hash);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800872
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800873 the->m_fileState->UpdateFile (filename, version, hash, device_name, seq_no, atime, mtime, ctime, mode, seg_num);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800874
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800875 // no callback here
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800876 }
877 else if (action == 1) // delete
878 {
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800879 the->m_fileState->DeleteFile (filename);
Alexander Afanasyev0c545ed2013-01-26 00:12:32 -0800880
881 the->m_onFileRemoved (filename);
Alexander Afanasyeva2f77e92013-01-03 22:46:52 -0800882 }
Alexander Afanasyev49a30d02013-01-21 21:38:48 -0800883
Alexander Afanasyevee7e6132013-01-03 20:03:14 -0800884 sqlite3_result_null (context);
885}
Zhenkai Zhuc3fd51e2013-01-22 10:45:54 -0800886
Alexander Afanasyev7a647002013-01-30 11:54:52 -0800887