blob: 7904586a1d2b1c772a91a6bed745b2b945ad3fe8 [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 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
25INIT_LOGGER ("FileState");
26
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
Yingdi Yuadb54eb2013-08-15 10:28:28 -070054FileState::FileState (const boost::filesystem::path &path, bool cow)
55 : DbHelper (path / ".chronoshare", (cow ? "file-state-tmp.db" : "file-state.db"))
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080056{
57 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
61FileState::~FileState ()
62{
63}
64
65void
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -080066FileState::UpdateFile (const std::string &filename, sqlite3_int64 version,
Alexander Afanasyev1dd37ed2013-08-14 18:08:09 -070067 const Hash &hash, const Ndnx::NdnxCharbuf &device_name, sqlite3_int64 seq_no,
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080068 time_t atime, time_t mtime, time_t ctime, int mode, int seg_num)
69{
70 sqlite3_stmt *stmt;
71 sqlite3_prepare_v2 (m_db, "UPDATE FileState "
72 "SET "
73 "device_name=?, seq_no=?, "
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -080074 "version=?,"
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080075 "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=?", -1, &stmt, 0);
82
Alexander Afanasyev026eaf32013-02-23 16:37:14 -080083 sqlite3_bind_blob (stmt, 1, device_name.buf (), device_name.length (), SQLITE_STATIC);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080084 sqlite3_bind_int64 (stmt, 2, seq_no);
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -080085 sqlite3_bind_int64 (stmt, 3, version);
86 sqlite3_bind_blob (stmt, 4, hash.GetHash (), hash.GetHashBytes (), SQLITE_STATIC);
87 sqlite3_bind_int64 (stmt, 5, atime);
88 sqlite3_bind_int64 (stmt, 6, mtime);
89 sqlite3_bind_int64 (stmt, 7, ctime);
90 sqlite3_bind_int (stmt, 8, mode);
91 sqlite3_bind_int (stmt, 9, seg_num);
92 sqlite3_bind_text (stmt, 10, filename.c_str (), -1, SQLITE_STATIC);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -080093
94 sqlite3_step (stmt);
95
96 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_ROW && sqlite3_errcode (m_db) != SQLITE_DONE,
97 sqlite3_errmsg (m_db));
98
99 sqlite3_finalize (stmt);
100
101 int affected_rows = sqlite3_changes (m_db);
102 if (affected_rows == 0) // file didn't exist
103 {
104 sqlite3_stmt *stmt;
105 sqlite3_prepare_v2 (m_db, "INSERT INTO FileState "
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800106 "(type,filename,version,device_name,seq_no,file_hash,file_atime,file_mtime,file_ctime,file_chmod,file_seg_num) "
107 "VALUES (0, ?, ?, ?, ?, ?, "
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800108 "datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), datetime(?, 'unixepoch'), ?, ?)", -1, &stmt, 0);
109
110 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
111
112 sqlite3_bind_text (stmt, 1, filename.c_str (), -1, SQLITE_STATIC);
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800113 sqlite3_bind_int64 (stmt, 2, version);
114 sqlite3_bind_blob (stmt, 3, device_name.buf (), device_name.length (), SQLITE_STATIC);
115 sqlite3_bind_int64 (stmt, 4, seq_no);
116 sqlite3_bind_blob (stmt, 5, hash.GetHash (), hash.GetHashBytes (), SQLITE_STATIC);
117 sqlite3_bind_int64 (stmt, 6, atime);
118 sqlite3_bind_int64 (stmt, 7, mtime);
119 sqlite3_bind_int64 (stmt, 8, ctime);
120 sqlite3_bind_int (stmt, 9, mode);
121 sqlite3_bind_int (stmt, 10, seg_num);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800122
123 sqlite3_step (stmt);
124 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE,
125 sqlite3_errmsg (m_db));
126 sqlite3_finalize (stmt);
127
128 sqlite3_prepare_v2 (m_db, "UPDATE FileState SET directory=directory_name(filename) WHERE filename=?", -1, &stmt, 0);
129 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
130
131 sqlite3_bind_text (stmt, 1, filename.c_str (), -1, SQLITE_STATIC);
132 sqlite3_step (stmt);
133 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE,
134 sqlite3_errmsg (m_db));
135 sqlite3_finalize (stmt);
136 }
137}
138
139
140void
141FileState::DeleteFile (const std::string &filename)
142{
143
144 sqlite3_stmt *stmt;
145 sqlite3_prepare_v2 (m_db, "DELETE FROM FileState WHERE type=0 AND filename=?", -1, &stmt, 0);
146 sqlite3_bind_text (stmt, 1, filename.c_str (), -1, SQLITE_STATIC);
147
148 _LOG_DEBUG ("Delete " << filename);
149
150 sqlite3_step (stmt);
151 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE,
152 sqlite3_errmsg (m_db));
153 sqlite3_finalize (stmt);
154}
155
156
157void
158FileState::SetFileComplete (const std::string &filename)
159{
160 sqlite3_stmt *stmt;
161 sqlite3_prepare_v2 (m_db,
162 "UPDATE FileState SET is_complete=1 WHERE type = 0 AND filename = ?", -1, &stmt, 0);
163 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
164 sqlite3_bind_text(stmt, 1, filename.c_str(), -1, SQLITE_STATIC);
165
166 sqlite3_step (stmt);
167 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
168
169 sqlite3_finalize (stmt);
170}
171
172
173/**
174 * @todo Implement checking modification time and permissions
175 */
176FileItemPtr
177FileState::LookupFile (const std::string &filename)
178{
179 sqlite3_stmt *stmt;
180 sqlite3_prepare_v2 (m_db,
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800181 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800182 " FROM FileState "
183 " WHERE type = 0 AND filename = ?", -1, &stmt, 0);
184 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
185 sqlite3_bind_text(stmt, 1, filename.c_str(), -1, SQLITE_STATIC);
186
187 FileItemPtr retval;
188 if (sqlite3_step (stmt) == SQLITE_ROW)
189 {
190 retval = make_shared<FileItem> ();
191 retval->set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 0)), sqlite3_column_bytes (stmt, 0));
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800192 retval->set_version (sqlite3_column_int64 (stmt, 1));
193 retval->set_device_name (sqlite3_column_blob (stmt, 2), sqlite3_column_bytes (stmt, 2));
194 retval->set_seq_no (sqlite3_column_int64 (stmt, 3));
195 retval->set_file_hash (sqlite3_column_blob (stmt, 4), sqlite3_column_bytes (stmt, 4));
196 retval->set_mtime (sqlite3_column_int (stmt, 5));
197 retval->set_mode (sqlite3_column_int (stmt, 6));
198 retval->set_seg_num (sqlite3_column_int64 (stmt, 7));
199 retval->set_is_complete (sqlite3_column_int (stmt, 8));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800200 }
201 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
202 sqlite3_finalize (stmt);
203
204 return retval;
205}
206
207FileItemsPtr
208FileState::LookupFilesForHash (const Hash &hash)
209{
210 sqlite3_stmt *stmt;
211 sqlite3_prepare_v2 (m_db,
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800212 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800213 " FROM FileState "
214 " WHERE type = 0 AND file_hash = ?", -1, &stmt, 0);
215 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
216 sqlite3_bind_blob(stmt, 1, hash.GetHash (), hash.GetHashBytes (), SQLITE_STATIC);
217 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
218
219 FileItemsPtr retval = make_shared<FileItems> ();
220 while (sqlite3_step (stmt) == SQLITE_ROW)
221 {
222 FileItem file;
223 file.set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 0)), sqlite3_column_bytes (stmt, 0));
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800224 file.set_version (sqlite3_column_int64 (stmt, 1));
225 file.set_device_name (sqlite3_column_blob (stmt, 2), sqlite3_column_bytes (stmt, 2));
226 file.set_seq_no (sqlite3_column_int64 (stmt, 3));
227 file.set_file_hash (sqlite3_column_blob (stmt, 4), sqlite3_column_bytes (stmt, 4));
228 file.set_mtime (sqlite3_column_int (stmt, 5));
229 file.set_mode (sqlite3_column_int (stmt, 6));
230 file.set_seg_num (sqlite3_column_int64 (stmt, 7));
231 file.set_is_complete (sqlite3_column_int (stmt, 8));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800232
233 retval->push_back (file);
234 }
235 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
236
237 sqlite3_finalize (stmt);
238
239 return retval;
240}
241
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800242void
243FileState::LookupFilesInFolder (const boost::function<void (const FileItem&)> &visitor, const std::string &folder, int offset/*=0*/, int limit/*=-1*/)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800244{
245 sqlite3_stmt *stmt;
246 sqlite3_prepare_v2 (m_db,
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800247 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800248 " FROM FileState "
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800249 " WHERE type = 0 AND directory = ?"
250 " LIMIT ? OFFSET ?", -1, &stmt, 0);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800251 if (folder.size () == 0)
252 sqlite3_bind_null (stmt, 1);
253 else
254 sqlite3_bind_text (stmt, 1, folder.c_str (), folder.size (), SQLITE_STATIC);
255
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800256 sqlite3_bind_int (stmt, 2, limit);
257 sqlite3_bind_int (stmt, 3, offset);
258
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800259 while (sqlite3_step (stmt) == SQLITE_ROW)
260 {
261 FileItem file;
262 file.set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 0)), sqlite3_column_bytes (stmt, 0));
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800263 file.set_version (sqlite3_column_int64 (stmt, 1));
264 file.set_device_name (sqlite3_column_blob (stmt, 2), sqlite3_column_bytes (stmt, 2));
265 file.set_seq_no (sqlite3_column_int64 (stmt, 3));
266 file.set_file_hash (sqlite3_column_blob (stmt, 4), sqlite3_column_bytes (stmt, 4));
267 file.set_mtime (sqlite3_column_int (stmt, 5));
268 file.set_mode (sqlite3_column_int (stmt, 6));
269 file.set_seg_num (sqlite3_column_int64 (stmt, 7));
270 file.set_is_complete (sqlite3_column_int (stmt, 8));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800271
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800272 visitor (file);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800273 }
274
275 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
276
277 sqlite3_finalize (stmt);
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800278}
279
280FileItemsPtr
281FileState::LookupFilesInFolder (const std::string &folder, int offset/*=0*/, int limit/*=-1*/)
282{
283 FileItemsPtr retval = make_shared<FileItems> ();
284 LookupFilesInFolder (boost::bind (&FileItems::push_back, retval.get (), _1), folder, offset, limit);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800285
286 return retval;
287}
288
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800289bool
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800290FileState::LookupFilesInFolderRecursively (const boost::function<void (const FileItem&)> &visitor, const std::string &folder, int offset/*=0*/, int limit/*=-1*/)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800291{
292 _LOG_DEBUG ("LookupFilesInFolderRecursively: [" << folder << "]");
293
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800294 if (limit >= 0)
295 limit ++;
296
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800297 sqlite3_stmt *stmt;
298 if (folder != "")
299 {
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800300 /// @todo Do something to improve efficiency of this query. Right now it is basically scanning the whole database
301
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800302 sqlite3_prepare_v2 (m_db,
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800303 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800304 " FROM FileState "
Alexander Afanasyev20fd84a2013-02-27 12:17:00 -0800305 " WHERE type = 0 AND is_dir_prefix (?, directory)=1 "
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800306 " ORDER BY filename "
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800307 " LIMIT ? OFFSET ?", -1, &stmt, 0); // there is a small ambiguity with is_prefix matching, but should be ok for now
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800308 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
309
310 sqlite3_bind_text (stmt, 1, folder.c_str (), folder.size (), SQLITE_STATIC);
311 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
312
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800313 sqlite3_bind_int (stmt, 2, limit);
314 sqlite3_bind_int (stmt, 3, offset);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800315 }
316 else
317 {
318 sqlite3_prepare_v2 (m_db,
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800319 "SELECT filename,version,device_name,seq_no,file_hash,strftime('%s', file_mtime),file_chmod,file_seg_num,is_complete "
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800320 " FROM FileState "
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800321 " WHERE type = 0"
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800322 " ORDER BY filename "
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800323 " LIMIT ? OFFSET ?", -1, &stmt, 0);
324 sqlite3_bind_int (stmt, 1, limit);
325 sqlite3_bind_int (stmt, 2, offset);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800326 }
327
328 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_OK, sqlite3_errmsg (m_db));
329
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800330 while (sqlite3_step (stmt) == SQLITE_ROW)
331 {
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800332 if (limit == 1)
333 break;
334
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800335 FileItem file;
336 file.set_filename (reinterpret_cast<const char *> (sqlite3_column_text (stmt, 0)), sqlite3_column_bytes (stmt, 0));
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800337 file.set_version (sqlite3_column_int64 (stmt, 1));
338 file.set_device_name (sqlite3_column_blob (stmt, 2), sqlite3_column_bytes (stmt, 2));
339 file.set_seq_no (sqlite3_column_int64 (stmt, 3));
340 file.set_file_hash (sqlite3_column_blob (stmt, 4), sqlite3_column_bytes (stmt, 4));
341 file.set_mtime (sqlite3_column_int (stmt, 5));
342 file.set_mode (sqlite3_column_int (stmt, 6));
343 file.set_seg_num (sqlite3_column_int64 (stmt, 7));
344 file.set_is_complete (sqlite3_column_int (stmt, 8));
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800345
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800346 visitor (file);
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800347 limit --;
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800348 }
349
350 _LOG_DEBUG_COND (sqlite3_errcode (m_db) != SQLITE_DONE, sqlite3_errmsg (m_db));
351
352 sqlite3_finalize (stmt);
Alexander Afanasyev6fb5dc62013-02-27 11:34:52 -0800353
354 return (limit == 1);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800355}
356
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800357FileItemsPtr
358FileState::LookupFilesInFolderRecursively (const std::string &folder, int offset/*=0*/, int limit/*=-1*/)
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800359{
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800360 FileItemsPtr retval = make_shared<FileItems> ();
361 LookupFilesInFolder (boost::bind (&FileItems::push_back, retval.get (), _1), folder, offset, limit);
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800362
Alexander Afanasyev95f9f552013-02-26 23:05:20 -0800363 return retval;
Alexander Afanasyevd6364ef2013-02-06 13:13:07 -0800364}