blob: 42e40de49cd8ddbdbffb3b559ed93fc08f2b3da7 [file] [log] [blame]
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08001/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
2/**
Alexander Afanasyeva9369b42017-01-11 11:58:00 -08003 * Copyright (c) 2013-2017, Regents of the University of California.
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -08004 *
Alexander Afanasyevfa2f6622016-12-25 12:28:00 -08005 * This file is part of ChronoShare, a decentralized file sharing application over NDN.
Alexander Afanasyev0a30a0c2013-01-29 17:25:42 -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 Afanasyev0a30a0c2013-01-29 17:25:42 -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 Afanasyev0a30a0c2013-01-29 17:25:42 -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 Afanasyev0a30a0c2013-01-29 17:25:42 -080019 */
20
21#include "file-state.h"
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080022#include "logging.h"
Alexander Afanasyev95f9f552013-02-26 23:05:20 -080023#include <boost/bind.hpp>
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080024
Alexander Afanasyeva9369b42017-01-11 11:58:00 -080025INIT_LOGGER("FileState")
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080026
27using namespace boost;
28using namespace std;
29
30const std::string INIT_DATABASE = "\
31 \n\
32CREATE TABLE FileState ( \n\
33 type INTEGER NOT NULL, /* 0 - newest, 1 - oldest */ \n\
34 filename TEXT NOT NULL, \n\
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -080035 version INTEGER, \n\
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080036 directory TEXT, \n\
37 device_name BLOB NOT NULL, \n\
38 seq_no INTEGER NOT NULL, \n\
39 file_hash BLOB NOT NULL, \n\
40 file_atime TIMESTAMP, \n\
41 file_mtime TIMESTAMP, \n\
42 file_ctime TIMESTAMP, \n\
43 file_chmod INTEGER, \n\
44 file_seg_num INTEGER, \n\
45 is_complete INTEGER, \n\
46 \n\
47 PRIMARY KEY (type, filename) \n\
48); \n\
49 \n\
50CREATE INDEX FileState_device_name_seq_no ON FileState (device_name, seq_no); \n\
51CREATE INDEX FileState_type_file_hash ON FileState (type, file_hash); \n\
52";
53
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080054FileState::FileState(const boost::filesystem::path& path)
55 : DbHelper(path / ".chronoshare", "file-state.db")
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080056{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080057 sqlite3_exec(m_db, INIT_DATABASE.c_str(), NULL, NULL, NULL);
58 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080059}
60
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080061FileState::~FileState()
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080062{
63}
64
65void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080066FileState::UpdateFile(const std::string& filename, sqlite3_int64 version, const Hash& hash,
67 const Ccnx::CcnxCharbuf& device_name, sqlite3_int64 seq_no, time_t atime,
68 time_t mtime, time_t ctime, int mode, int seg_num)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080069{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080070 sqlite3_stmt* stmt;
71 sqlite3_prepare_v2(m_db, "UPDATE FileState "
72 "SET "
73 "device_name=?, seq_no=?, "
74 "version=?,"
75 "file_hash=?,"
76 "file_atime=datetime(?, 'unixepoch'),"
77 "file_mtime=datetime(?, 'unixepoch'),"
78 "file_ctime=datetime(?, 'unixepoch'),"
79 "file_chmod=?, "
80 "file_seg_num=? "
81 "WHERE type=0 AND filename=?",
82 -1, &stmt, 0);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080083
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080084 sqlite3_bind_blob(stmt, 1, device_name.buf(), device_name.length(), SQLITE_STATIC);
85 sqlite3_bind_int64(stmt, 2, seq_no);
86 sqlite3_bind_int64(stmt, 3, version);
87 sqlite3_bind_blob(stmt, 4, hash.GetHash(), hash.GetHashBytes(), SQLITE_STATIC);
88 sqlite3_bind_int64(stmt, 5, atime);
89 sqlite3_bind_int64(stmt, 6, mtime);
90 sqlite3_bind_int64(stmt, 7, ctime);
91 sqlite3_bind_int(stmt, 8, mode);
92 sqlite3_bind_int(stmt, 9, seg_num);
93 sqlite3_bind_text(stmt, 10, filename.c_str(), -1, SQLITE_STATIC);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080094
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080095 sqlite3_step(stmt);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080096
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -080097 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_ROW && sqlite3_errcode(m_db) != SQLITE_DONE,
98 sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080099
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800100 sqlite3_finalize(stmt);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800101
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800102 int affected_rows = sqlite3_changes(m_db);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800103 if (affected_rows == 0) // file didn't exist
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800104 {
105 sqlite3_stmt* stmt;
106 sqlite3_prepare_v2(m_db,
107 "INSERT INTO FileState "
108 "(type,filename,version,device_name,seq_no,file_hash,file_atime,file_mtime,file_ctime,file_chmod,file_seg_num) "
109 "VALUES (0, ?, ?, ?, ?, ?, "
110 "datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?, ?)",
111 -1, &stmt, 0);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800112
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800113 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800114
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800115 sqlite3_bind_text(stmt, 1, filename.c_str(), -1, SQLITE_STATIC);
116 sqlite3_bind_int64(stmt, 2, version);
117 sqlite3_bind_blob(stmt, 3, device_name.buf(), device_name.length(), SQLITE_STATIC);
118 sqlite3_bind_int64(stmt, 4, seq_no);
119 sqlite3_bind_blob(stmt, 5, hash.GetHash(), hash.GetHashBytes(), SQLITE_STATIC);
120 sqlite3_bind_int64(stmt, 6, atime);
121 sqlite3_bind_int64(stmt, 7, mtime);
122 sqlite3_bind_int64(stmt, 8, ctime);
123 sqlite3_bind_int(stmt, 9, mode);
124 sqlite3_bind_int(stmt, 10, seg_num);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800125
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800126 sqlite3_step(stmt);
127 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
128 sqlite3_finalize(stmt);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800129
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800130 sqlite3_prepare_v2(m_db,
131 "UPDATE FileState SET directory=directory_name(filename) WHERE filename=?",
132 -1, &stmt, 0);
133 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800134
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800135 sqlite3_bind_text(stmt, 1, filename.c_str(), -1, SQLITE_STATIC);
136 sqlite3_step(stmt);
137 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
138 sqlite3_finalize(stmt);
139 }
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800140}
141
142
143void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800144FileState::DeleteFile(const std::string& filename)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800145{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800146 sqlite3_stmt* stmt;
147 sqlite3_prepare_v2(m_db, "DELETE FROM FileState WHERE type=0 AND filename=?", -1, &stmt, 0);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800148 sqlite3_bind_text(stmt, 1, filename.c_str(), -1, SQLITE_STATIC);
149
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800150 _LOG_DEBUG("Delete " << filename);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800151
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800152 sqlite3_step(stmt);
153 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
154 sqlite3_finalize(stmt);
155}
156
157
158void
159FileState::SetFileComplete(const std::string& filename)
160{
161 sqlite3_stmt* stmt;
162 sqlite3_prepare_v2(m_db, "UPDATE FileState SET is_complete=1 WHERE type = 0 AND filename = ?", -1,
163 &stmt, 0);
164 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
165 sqlite3_bind_text(stmt, 1, filename.c_str(), -1, SQLITE_STATIC);
166
167 sqlite3_step(stmt);
168 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
169
170 sqlite3_finalize(stmt);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800171}
172
173
174/**
175 * @todo Implement checking modification time and permissions
176 */
177FileItemPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800178FileState::LookupFile(const std::string& filename)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800179{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800180 sqlite3_stmt* stmt;
181 sqlite3_prepare_v2(m_db,
182 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
183 " FROM FileState "
184 " WHERE type = 0 AND filename = ?",
185 -1, &stmt, 0);
186 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800187 sqlite3_bind_text(stmt, 1, filename.c_str(), -1, SQLITE_STATIC);
188
189 FileItemPtr retval;
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800190 if (sqlite3_step(stmt) == SQLITE_ROW) {
191 retval = make_shared<FileItem>();
192 retval->set_filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)),
193 sqlite3_column_bytes(stmt, 0));
194 retval->set_version(sqlite3_column_int64(stmt, 1));
195 retval->set_device_name(sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2));
196 retval->set_seq_no(sqlite3_column_int64(stmt, 3));
197 retval->set_file_hash(sqlite3_column_blob(stmt, 4), sqlite3_column_bytes(stmt, 4));
198 retval->set_mtime(sqlite3_column_int(stmt, 5));
199 retval->set_mode(sqlite3_column_int(stmt, 6));
200 retval->set_seg_num(sqlite3_column_int64(stmt, 7));
201 retval->set_is_complete(sqlite3_column_int(stmt, 8));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800202 }
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800203 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
204 sqlite3_finalize(stmt);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800205
206 return retval;
207}
208
209FileItemsPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800210FileState::LookupFilesForHash(const Hash& hash)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800211{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800212 sqlite3_stmt* stmt;
213 sqlite3_prepare_v2(m_db,
214 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
215 " FROM FileState "
216 " WHERE type = 0 AND file_hash = ?",
217 -1, &stmt, 0);
218 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
219 sqlite3_bind_blob(stmt, 1, hash.GetHash(), hash.GetHashBytes(), SQLITE_STATIC);
220 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800221
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800222 FileItemsPtr retval = make_shared<FileItems>();
223 while (sqlite3_step(stmt) == SQLITE_ROW) {
224 FileItem file;
225 file.set_filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)),
226 sqlite3_column_bytes(stmt, 0));
227 file.set_version(sqlite3_column_int64(stmt, 1));
228 file.set_device_name(sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2));
229 file.set_seq_no(sqlite3_column_int64(stmt, 3));
230 file.set_file_hash(sqlite3_column_blob(stmt, 4), sqlite3_column_bytes(stmt, 4));
231 file.set_mtime(sqlite3_column_int(stmt, 5));
232 file.set_mode(sqlite3_column_int(stmt, 6));
233 file.set_seg_num(sqlite3_column_int64(stmt, 7));
234 file.set_is_complete(sqlite3_column_int(stmt, 8));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800235
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800236 retval->push_back(file);
237 }
238 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800239
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800240 sqlite3_finalize(stmt);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800241
242 return retval;
243}
244
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800245void
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800246FileState::LookupFilesInFolder(const boost::function<void(const FileItem&)>& visitor,
247 const std::string& folder, int offset /*=0*/, int limit /*=-1*/)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800248{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800249 sqlite3_stmt* stmt;
250 sqlite3_prepare_v2(m_db,
251 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
252 " FROM FileState "
253 " WHERE type = 0 AND directory = ?"
254 " LIMIT ? OFFSET ?",
255 -1, &stmt, 0);
256 if (folder.size() == 0)
257 sqlite3_bind_null(stmt, 1);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800258 else
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800259 sqlite3_bind_text(stmt, 1, folder.c_str(), folder.size(), SQLITE_STATIC);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800260
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800261 sqlite3_bind_int(stmt, 2, limit);
262 sqlite3_bind_int(stmt, 3, offset);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800263
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800264 while (sqlite3_step(stmt) == SQLITE_ROW) {
265 FileItem file;
266 file.set_filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)),
267 sqlite3_column_bytes(stmt, 0));
268 file.set_version(sqlite3_column_int64(stmt, 1));
269 file.set_device_name(sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2));
270 file.set_seq_no(sqlite3_column_int64(stmt, 3));
271 file.set_file_hash(sqlite3_column_blob(stmt, 4), sqlite3_column_bytes(stmt, 4));
272 file.set_mtime(sqlite3_column_int(stmt, 5));
273 file.set_mode(sqlite3_column_int(stmt, 6));
274 file.set_seg_num(sqlite3_column_int64(stmt, 7));
275 file.set_is_complete(sqlite3_column_int(stmt, 8));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800276
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800277 visitor(file);
278 }
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800279
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800280 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800281
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800282 sqlite3_finalize(stmt);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800283}
284
285FileItemsPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800286FileState::LookupFilesInFolder(const std::string& folder, int offset /*=0*/, int limit /*=-1*/)
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800287{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800288 FileItemsPtr retval = make_shared<FileItems>();
289 LookupFilesInFolder(boost::bind(&FileItems::push_back, retval.get(), _1), folder, offset, limit);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800290
291 return retval;
292}
293
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800294bool
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800295FileState::LookupFilesInFolderRecursively(const boost::function<void(const FileItem&)>& visitor,
296 const std::string& folder, int offset /*=0*/,
297 int limit /*=-1*/)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800298{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800299 _LOG_DEBUG("LookupFilesInFolderRecursively: [" << folder << "]");
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800300
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800301 if (limit >= 0)
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800302 limit++;
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800303
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800304 sqlite3_stmt* stmt;
305 if (folder != "") {
306 /// @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 -0800307
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800308 sqlite3_prepare_v2(m_db,
309 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
310 " FROM FileState "
311 " WHERE type = 0 AND is_dir_prefix (?, directory)=1 "
312 " ORDER BY filename "
313 " LIMIT ? OFFSET ?",
314 -1, &stmt,
315 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
316 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800317
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800318 sqlite3_bind_text(stmt, 1, folder.c_str(), folder.size(), SQLITE_STATIC);
319 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800320
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800321 sqlite3_bind_int(stmt, 2, limit);
322 sqlite3_bind_int(stmt, 3, offset);
323 }
324 else {
325 sqlite3_prepare_v2(m_db,
326 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
327 " FROM FileState "
328 " WHERE type = 0"
329 " ORDER BY filename "
330 " LIMIT ? OFFSET ?",
331 -1, &stmt, 0);
332 sqlite3_bind_int(stmt, 1, limit);
333 sqlite3_bind_int(stmt, 2, offset);
334 }
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800335
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800336 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_OK, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800337
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800338 while (sqlite3_step(stmt) == SQLITE_ROW) {
339 if (limit == 1)
340 break;
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800341
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800342 FileItem file;
343 file.set_filename(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)),
344 sqlite3_column_bytes(stmt, 0));
345 file.set_version(sqlite3_column_int64(stmt, 1));
346 file.set_device_name(sqlite3_column_blob(stmt, 2), sqlite3_column_bytes(stmt, 2));
347 file.set_seq_no(sqlite3_column_int64(stmt, 3));
348 file.set_file_hash(sqlite3_column_blob(stmt, 4), sqlite3_column_bytes(stmt, 4));
349 file.set_mtime(sqlite3_column_int(stmt, 5));
350 file.set_mode(sqlite3_column_int(stmt, 6));
351 file.set_seg_num(sqlite3_column_int64(stmt, 7));
352 file.set_is_complete(sqlite3_column_int(stmt, 8));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800353
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800354 visitor(file);
355 limit--;
356 }
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800357
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800358 _LOG_DEBUG_COND(sqlite3_errcode(m_db) != SQLITE_DONE, sqlite3_errmsg(m_db));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800359
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800360 sqlite3_finalize(stmt);
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800361
362 return (limit == 1);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800363}
364
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800365FileItemsPtr
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800366FileState::LookupFilesInFolderRecursively(const std::string& folder, int offset /*=0*/,
367 int limit /*=-1*/)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800368{
Alexander Afanasyeveda3b7a2016-12-25 11:26:40 -0800369 FileItemsPtr retval = make_shared<FileItems>();
370 LookupFilesInFolder(boost::bind(&FileItems::push_back, retval.get(), _1), folder, offset, limit);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800371
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800372 return retval;
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800373}