Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(487)

Side by Side Diff: storage/browser/fileapi/sandbox_directory_database.cc

Issue 442383002: Move storage-related files from webkit/ to new top-level directory storage/ (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "webkit/browser/fileapi/sandbox_directory_database.h" 5 #include "storage/browser/fileapi/sandbox_directory_database.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <set> 9 #include <set>
10 #include <stack> 10 #include <stack>
11 11
12 #include "base/file_util.h" 12 #include "base/file_util.h"
13 #include "base/files/file_enumerator.h" 13 #include "base/files/file_enumerator.h"
14 #include "base/location.h" 14 #include "base/location.h"
15 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
16 #include "base/pickle.h" 16 #include "base/pickle.h"
17 #include "base/strings/string_number_conversions.h" 17 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 18 #include "base/strings/string_util.h"
19 #include "third_party/leveldatabase/src/include/leveldb/db.h" 19 #include "third_party/leveldatabase/src/include/leveldb/db.h"
20 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 20 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
21 #include "webkit/browser/fileapi/file_system_usage_cache.h" 21 #include "storage/browser/fileapi/file_system_usage_cache.h"
22 #include "webkit/common/fileapi/file_system_util.h" 22 #include "storage/common/fileapi/file_system_util.h"
23 23
24 namespace { 24 namespace {
25 25
26 bool PickleFromFileInfo( 26 bool PickleFromFileInfo(const storage::SandboxDirectoryDatabase::FileInfo& info,
27 const fileapi::SandboxDirectoryDatabase::FileInfo& info, 27 Pickle* pickle) {
28 Pickle* pickle) {
29 DCHECK(pickle); 28 DCHECK(pickle);
30 std::string data_path; 29 std::string data_path;
31 // Round off here to match the behavior of the filesystem on real files. 30 // Round off here to match the behavior of the filesystem on real files.
32 base::Time time = 31 base::Time time =
33 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); 32 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT()));
34 std::string name; 33 std::string name;
35 34
36 data_path = fileapi::FilePathToString(info.data_path); 35 data_path = storage::FilePathToString(info.data_path);
37 name = fileapi::FilePathToString(base::FilePath(info.name)); 36 name = storage::FilePathToString(base::FilePath(info.name));
38 37
39 if (pickle->WriteInt64(info.parent_id) && 38 if (pickle->WriteInt64(info.parent_id) && pickle->WriteString(data_path) &&
40 pickle->WriteString(data_path) && 39 pickle->WriteString(name) && pickle->WriteInt64(time.ToInternalValue()))
41 pickle->WriteString(name) &&
42 pickle->WriteInt64(time.ToInternalValue()))
43 return true; 40 return true;
44 41
45 NOTREACHED(); 42 NOTREACHED();
46 return false; 43 return false;
47 } 44 }
48 45
49 bool FileInfoFromPickle( 46 bool FileInfoFromPickle(const Pickle& pickle,
50 const Pickle& pickle, 47 storage::SandboxDirectoryDatabase::FileInfo* info) {
51 fileapi::SandboxDirectoryDatabase::FileInfo* info) {
52 PickleIterator iter(pickle); 48 PickleIterator iter(pickle);
53 std::string data_path; 49 std::string data_path;
54 std::string name; 50 std::string name;
55 int64 internal_time; 51 int64 internal_time;
56 52
57 if (pickle.ReadInt64(&iter, &info->parent_id) && 53 if (pickle.ReadInt64(&iter, &info->parent_id) &&
58 pickle.ReadString(&iter, &data_path) && 54 pickle.ReadString(&iter, &data_path) && pickle.ReadString(&iter, &name) &&
59 pickle.ReadString(&iter, &name) &&
60 pickle.ReadInt64(&iter, &internal_time)) { 55 pickle.ReadInt64(&iter, &internal_time)) {
61 info->data_path = fileapi::StringToFilePath(data_path); 56 info->data_path = storage::StringToFilePath(data_path);
62 info->name = fileapi::StringToFilePath(name).value(); 57 info->name = storage::StringToFilePath(name).value();
63 info->modification_time = base::Time::FromInternalValue(internal_time); 58 info->modification_time = base::Time::FromInternalValue(internal_time);
64 return true; 59 return true;
65 } 60 }
66 LOG(ERROR) << "Pickle could not be digested!"; 61 LOG(ERROR) << "Pickle could not be digested!";
67 return false; 62 return false;
68 } 63 }
69 64
70 const base::FilePath::CharType kDirectoryDatabaseName[] = 65 const base::FilePath::CharType kDirectoryDatabaseName[] =
71 FILE_PATH_LITERAL("Paths"); 66 FILE_PATH_LITERAL("Paths");
72 const char kChildLookupPrefix[] = "CHILD_OF:"; 67 const char kChildLookupPrefix[] = "CHILD_OF:";
73 const char kChildLookupSeparator[] = ":"; 68 const char kChildLookupSeparator[] = ":";
74 const char kLastFileIdKey[] = "LAST_FILE_ID"; 69 const char kLastFileIdKey[] = "LAST_FILE_ID";
75 const char kLastIntegerKey[] = "LAST_INTEGER"; 70 const char kLastIntegerKey[] = "LAST_INTEGER";
76 const int64 kMinimumReportIntervalHours = 1; 71 const int64 kMinimumReportIntervalHours = 1;
77 const char kInitStatusHistogramLabel[] = "FileSystem.DirectoryDatabaseInit"; 72 const char kInitStatusHistogramLabel[] = "FileSystem.DirectoryDatabaseInit";
78 const char kDatabaseRepairHistogramLabel[] = 73 const char kDatabaseRepairHistogramLabel[] =
79 "FileSystem.DirectoryDatabaseRepair"; 74 "FileSystem.DirectoryDatabaseRepair";
80 75
81 enum InitStatus { 76 enum InitStatus {
82 INIT_STATUS_OK = 0, 77 INIT_STATUS_OK = 0,
83 INIT_STATUS_CORRUPTION, 78 INIT_STATUS_CORRUPTION,
84 INIT_STATUS_IO_ERROR, 79 INIT_STATUS_IO_ERROR,
85 INIT_STATUS_UNKNOWN_ERROR, 80 INIT_STATUS_UNKNOWN_ERROR,
86 INIT_STATUS_MAX 81 INIT_STATUS_MAX
87 }; 82 };
88 83
89 enum RepairResult { 84 enum RepairResult { DB_REPAIR_SUCCEEDED = 0, DB_REPAIR_FAILED, DB_REPAIR_MAX };
90 DB_REPAIR_SUCCEEDED = 0,
91 DB_REPAIR_FAILED,
92 DB_REPAIR_MAX
93 };
94 85
95 std::string GetChildLookupKey( 86 std::string GetChildLookupKey(
96 fileapi::SandboxDirectoryDatabase::FileId parent_id, 87 storage::SandboxDirectoryDatabase::FileId parent_id,
97 const base::FilePath::StringType& child_name) { 88 const base::FilePath::StringType& child_name) {
98 std::string name; 89 std::string name;
99 name = fileapi::FilePathToString(base::FilePath(child_name)); 90 name = storage::FilePathToString(base::FilePath(child_name));
100 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + 91 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) +
101 std::string(kChildLookupSeparator) + name; 92 std::string(kChildLookupSeparator) + name;
102 } 93 }
103 94
104 std::string GetChildListingKeyPrefix( 95 std::string GetChildListingKeyPrefix(
105 fileapi::SandboxDirectoryDatabase::FileId parent_id) { 96 storage::SandboxDirectoryDatabase::FileId parent_id) {
106 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + 97 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) +
107 std::string(kChildLookupSeparator); 98 std::string(kChildLookupSeparator);
108 } 99 }
109 100
110 const char* LastFileIdKey() { 101 const char* LastFileIdKey() {
111 return kLastFileIdKey; 102 return kLastFileIdKey;
112 } 103 }
113 104
114 const char* LastIntegerKey() { 105 const char* LastIntegerKey() {
115 return kLastIntegerKey; 106 return kLastIntegerKey;
116 } 107 }
117 108
118 std::string GetFileLookupKey( 109 std::string GetFileLookupKey(
119 fileapi::SandboxDirectoryDatabase::FileId file_id) { 110 storage::SandboxDirectoryDatabase::FileId file_id) {
120 return base::Int64ToString(file_id); 111 return base::Int64ToString(file_id);
121 } 112 }
122 113
123 // Assumptions: 114 // Assumptions:
124 // - Any database entry is one of: 115 // - Any database entry is one of:
125 // - ("CHILD_OF:|parent_id|:<name>", "|file_id|"), 116 // - ("CHILD_OF:|parent_id|:<name>", "|file_id|"),
126 // - ("LAST_FILE_ID", "|last_file_id|"), 117 // - ("LAST_FILE_ID", "|last_file_id|"),
127 // - ("LAST_INTEGER", "|last_integer|"), 118 // - ("LAST_INTEGER", "|last_integer|"),
128 // - ("|file_id|", "pickled FileInfo") 119 // - ("|file_id|", "pickled FileInfo")
129 // where FileInfo has |parent_id|, |data_path|, |name| and 120 // where FileInfo has |parent_id|, |data_path|, |name| and
130 // |modification_time|, 121 // |modification_time|,
131 // Constraints: 122 // Constraints:
132 // - Each file in the database has unique backing file. 123 // - Each file in the database has unique backing file.
133 // - Each file in |filesystem_data_directory_| has a database entry. 124 // - Each file in |filesystem_data_directory_| has a database entry.
134 // - Directory structure is tree, i.e. connected and acyclic. 125 // - Directory structure is tree, i.e. connected and acyclic.
135 class DatabaseCheckHelper { 126 class DatabaseCheckHelper {
136 public: 127 public:
137 typedef fileapi::SandboxDirectoryDatabase::FileId FileId; 128 typedef storage::SandboxDirectoryDatabase::FileId FileId;
138 typedef fileapi::SandboxDirectoryDatabase::FileInfo FileInfo; 129 typedef storage::SandboxDirectoryDatabase::FileInfo FileInfo;
139 130
140 DatabaseCheckHelper(fileapi::SandboxDirectoryDatabase* dir_db, 131 DatabaseCheckHelper(storage::SandboxDirectoryDatabase* dir_db,
141 leveldb::DB* db, 132 leveldb::DB* db,
142 const base::FilePath& path); 133 const base::FilePath& path);
143 134
144 bool IsFileSystemConsistent() { 135 bool IsFileSystemConsistent() {
145 return IsDatabaseEmpty() || 136 return IsDatabaseEmpty() ||
146 (ScanDatabase() && ScanDirectory() && ScanHierarchy()); 137 (ScanDatabase() && ScanDirectory() && ScanHierarchy());
147 } 138 }
148 139
149 private: 140 private:
150 bool IsDatabaseEmpty(); 141 bool IsDatabaseEmpty();
151 // These 3 methods need to be called in the order. Each method requires its 142 // These 3 methods need to be called in the order. Each method requires its
152 // previous method finished successfully. They also require the database is 143 // previous method finished successfully. They also require the database is
153 // not empty. 144 // not empty.
154 bool ScanDatabase(); 145 bool ScanDatabase();
155 bool ScanDirectory(); 146 bool ScanDirectory();
156 bool ScanHierarchy(); 147 bool ScanHierarchy();
157 148
158 fileapi::SandboxDirectoryDatabase* dir_db_; 149 storage::SandboxDirectoryDatabase* dir_db_;
159 leveldb::DB* db_; 150 leveldb::DB* db_;
160 base::FilePath path_; 151 base::FilePath path_;
161 152
162 std::set<base::FilePath> files_in_db_; 153 std::set<base::FilePath> files_in_db_;
163 154
164 size_t num_directories_in_db_; 155 size_t num_directories_in_db_;
165 size_t num_files_in_db_; 156 size_t num_files_in_db_;
166 size_t num_hierarchy_links_in_db_; 157 size_t num_hierarchy_links_in_db_;
167 158
168 FileId last_file_id_; 159 FileId last_file_id_;
169 FileId last_integer_; 160 FileId last_integer_;
170 }; 161 };
171 162
172 DatabaseCheckHelper::DatabaseCheckHelper( 163 DatabaseCheckHelper::DatabaseCheckHelper(
173 fileapi::SandboxDirectoryDatabase* dir_db, 164 storage::SandboxDirectoryDatabase* dir_db,
174 leveldb::DB* db, 165 leveldb::DB* db,
175 const base::FilePath& path) 166 const base::FilePath& path)
176 : dir_db_(dir_db), db_(db), path_(path), 167 : dir_db_(dir_db),
168 db_(db),
169 path_(path),
177 num_directories_in_db_(0), 170 num_directories_in_db_(0),
178 num_files_in_db_(0), 171 num_files_in_db_(0),
179 num_hierarchy_links_in_db_(0), 172 num_hierarchy_links_in_db_(0),
180 last_file_id_(-1), last_integer_(-1) { 173 last_file_id_(-1),
174 last_integer_(-1) {
181 DCHECK(dir_db_); 175 DCHECK(dir_db_);
182 DCHECK(db_); 176 DCHECK(db_);
183 DCHECK(!path_.empty() && base::DirectoryExists(path_)); 177 DCHECK(!path_.empty() && base::DirectoryExists(path_));
184 } 178 }
185 179
186 bool DatabaseCheckHelper::IsDatabaseEmpty() { 180 bool DatabaseCheckHelper::IsDatabaseEmpty() {
187 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions())); 181 scoped_ptr<leveldb::Iterator> itr(db_->NewIterator(leveldb::ReadOptions()));
188 itr->SeekToFirst(); 182 itr->SeekToFirst();
189 return !itr->Valid(); 183 return !itr->Valid();
190 } 184 }
(...skipping 23 matching lines...) Expand all
214 } else if (key == kLastIntegerKey) { 208 } else if (key == kLastIntegerKey) {
215 // key: "LAST_INTEGER" 209 // key: "LAST_INTEGER"
216 // value: "<last_integer>" 210 // value: "<last_integer>"
217 if (last_integer_ >= 0 || 211 if (last_integer_ >= 0 ||
218 !base::StringToInt64(itr->value().ToString(), &last_integer_)) 212 !base::StringToInt64(itr->value().ToString(), &last_integer_))
219 return false; 213 return false;
220 } else { 214 } else {
221 // key: "<entry_id>" 215 // key: "<entry_id>"
222 // value: "<pickled FileInfo>" 216 // value: "<pickled FileInfo>"
223 FileInfo file_info; 217 FileInfo file_info;
224 if (!FileInfoFromPickle( 218 if (!FileInfoFromPickle(Pickle(itr->value().data(), itr->value().size()),
225 Pickle(itr->value().data(), itr->value().size()), &file_info)) 219 &file_info))
226 return false; 220 return false;
227 221
228 FileId file_id = -1; 222 FileId file_id = -1;
229 if (!base::StringToInt64(key, &file_id) || file_id < 0) 223 if (!base::StringToInt64(key, &file_id) || file_id < 0)
230 return false; 224 return false;
231 225
232 if (max_file_id < file_id) 226 if (max_file_id < file_id)
233 max_file_id = file_id; 227 max_file_id = file_id;
234 if (!file_ids.insert(file_id).second) 228 if (!file_ids.insert(file_id).second)
235 return false; 229 return false;
236 230
237 if (file_info.is_directory()) { 231 if (file_info.is_directory()) {
238 ++num_directories_in_db_; 232 ++num_directories_in_db_;
239 DCHECK(file_info.data_path.empty()); 233 DCHECK(file_info.data_path.empty());
240 } else { 234 } else {
241 // Ensure any pair of file entry don't share their data_path. 235 // Ensure any pair of file entry don't share their data_path.
242 if (!files_in_db_.insert(file_info.data_path).second) 236 if (!files_in_db_.insert(file_info.data_path).second)
243 return false; 237 return false;
244 238
245 // Ensure the backing file exists as a normal file. 239 // Ensure the backing file exists as a normal file.
246 base::File::Info platform_file_info; 240 base::File::Info platform_file_info;
247 if (!base::GetFileInfo( 241 if (!base::GetFileInfo(path_.Append(file_info.data_path),
248 path_.Append(file_info.data_path), &platform_file_info) || 242 &platform_file_info) ||
249 platform_file_info.is_directory || 243 platform_file_info.is_directory ||
250 platform_file_info.is_symbolic_link) { 244 platform_file_info.is_symbolic_link) {
251 // leveldb::Iterator iterates a snapshot of the database. 245 // leveldb::Iterator iterates a snapshot of the database.
252 // So even after RemoveFileInfo() call, we'll visit hierarchy link 246 // So even after RemoveFileInfo() call, we'll visit hierarchy link
253 // from |parent_id| to |file_id|. 247 // from |parent_id| to |file_id|.
254 if (!dir_db_->RemoveFileInfo(file_id)) 248 if (!dir_db_->RemoveFileInfo(file_id))
255 return false; 249 return false;
256 --num_hierarchy_links_in_db_; 250 --num_hierarchy_links_in_db_;
257 files_in_db_.erase(file_info.data_path); 251 files_in_db_.erase(file_info.data_path);
258 } else { 252 } else {
259 ++num_files_in_db_; 253 ++num_files_in_db_;
260 } 254 }
261 } 255 }
262 } 256 }
263 } 257 }
264 258
265 // TODO(tzik): Add constraint for |last_integer_| to avoid possible 259 // TODO(tzik): Add constraint for |last_integer_| to avoid possible
266 // data path confliction on ObfuscatedFileUtil. 260 // data path confliction on ObfuscatedFileUtil.
267 return max_file_id <= last_file_id_; 261 return max_file_id <= last_file_id_;
268 } 262 }
269 263
270 bool DatabaseCheckHelper::ScanDirectory() { 264 bool DatabaseCheckHelper::ScanDirectory() {
271 // TODO(kinuko): Scans all local file system entries to verify each of them 265 // TODO(kinuko): Scans all local file system entries to verify each of them
272 // has a database entry. 266 // has a database entry.
273 const base::FilePath kExcludes[] = { 267 const base::FilePath kExcludes[] = {
274 base::FilePath(kDirectoryDatabaseName), 268 base::FilePath(kDirectoryDatabaseName),
275 base::FilePath(fileapi::FileSystemUsageCache::kUsageFileName), 269 base::FilePath(storage::FileSystemUsageCache::kUsageFileName),
276 }; 270 };
277 271
278 // Any path in |pending_directories| is relative to |path_|. 272 // Any path in |pending_directories| is relative to |path_|.
279 std::stack<base::FilePath> pending_directories; 273 std::stack<base::FilePath> pending_directories;
280 pending_directories.push(base::FilePath()); 274 pending_directories.push(base::FilePath());
281 275
282 while (!pending_directories.empty()) { 276 while (!pending_directories.empty()) {
283 base::FilePath dir_path = pending_directories.top(); 277 base::FilePath dir_path = pending_directories.top();
284 pending_directories.pop(); 278 pending_directories.pop();
285 279
286 base::FileEnumerator file_enum( 280 base::FileEnumerator file_enum(
287 dir_path.empty() ? path_ : path_.Append(dir_path), 281 dir_path.empty() ? path_ : path_.Append(dir_path),
288 false /* not recursive */, 282 false /* not recursive */,
289 base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES); 283 base::FileEnumerator::DIRECTORIES | base::FileEnumerator::FILES);
290 284
291 base::FilePath absolute_file_path; 285 base::FilePath absolute_file_path;
292 while (!(absolute_file_path = file_enum.Next()).empty()) { 286 while (!(absolute_file_path = file_enum.Next()).empty()) {
293 base::FileEnumerator::FileInfo find_info = file_enum.GetInfo(); 287 base::FileEnumerator::FileInfo find_info = file_enum.GetInfo();
294 288
295 base::FilePath relative_file_path; 289 base::FilePath relative_file_path;
296 if (!path_.AppendRelativePath(absolute_file_path, &relative_file_path)) 290 if (!path_.AppendRelativePath(absolute_file_path, &relative_file_path))
297 return false; 291 return false;
298 292
299 if (std::find(kExcludes, kExcludes + arraysize(kExcludes), 293 if (std::find(kExcludes,
294 kExcludes + arraysize(kExcludes),
300 relative_file_path) != kExcludes + arraysize(kExcludes)) 295 relative_file_path) != kExcludes + arraysize(kExcludes))
301 continue; 296 continue;
302 297
303 if (find_info.IsDirectory()) { 298 if (find_info.IsDirectory()) {
304 pending_directories.push(relative_file_path); 299 pending_directories.push(relative_file_path);
305 continue; 300 continue;
306 } 301 }
307 302
308 // Check if the file has a database entry. 303 // Check if the file has a database entry.
309 std::set<base::FilePath>::iterator itr = 304 std::set<base::FilePath>::iterator itr =
(...skipping 15 matching lines...) Expand all
325 size_t visited_files = 0; 320 size_t visited_files = 0;
326 size_t visited_links = 0; 321 size_t visited_links = 0;
327 322
328 std::stack<FileId> directories; 323 std::stack<FileId> directories;
329 directories.push(0); 324 directories.push(0);
330 325
331 // Check if the root directory exists as a directory. 326 // Check if the root directory exists as a directory.
332 FileInfo file_info; 327 FileInfo file_info;
333 if (!dir_db_->GetFileInfo(0, &file_info)) 328 if (!dir_db_->GetFileInfo(0, &file_info))
334 return false; 329 return false;
335 if (file_info.parent_id != 0 || 330 if (file_info.parent_id != 0 || !file_info.is_directory())
336 !file_info.is_directory())
337 return false; 331 return false;
338 332
339 while (!directories.empty()) { 333 while (!directories.empty()) {
340 ++visited_directories; 334 ++visited_directories;
341 FileId dir_id = directories.top(); 335 FileId dir_id = directories.top();
342 directories.pop(); 336 directories.pop();
343 337
344 std::vector<FileId> children; 338 std::vector<FileId> children;
345 if (!dir_db_->ListChildren(dir_id, &children)) 339 if (!dir_db_->ListChildren(dir_id, &children))
346 return false; 340 return false;
(...skipping 20 matching lines...) Expand all
367 if (file_info.is_directory()) 361 if (file_info.is_directory())
368 directories.push(*itr); 362 directories.push(*itr);
369 else 363 else
370 ++visited_files; 364 ++visited_files;
371 ++visited_links; 365 ++visited_links;
372 } 366 }
373 } 367 }
374 368
375 // Check if we've visited all database entries. 369 // Check if we've visited all database entries.
376 return num_directories_in_db_ == visited_directories && 370 return num_directories_in_db_ == visited_directories &&
377 num_files_in_db_ == visited_files && 371 num_files_in_db_ == visited_files &&
378 num_hierarchy_links_in_db_ == visited_links; 372 num_hierarchy_links_in_db_ == visited_links;
379 } 373 }
380 374
381 // Returns true if the given |data_path| contains no parent references ("..") 375 // Returns true if the given |data_path| contains no parent references ("..")
382 // and does not refer to special system files. 376 // and does not refer to special system files.
383 // This is called in GetFileInfo, AddFileInfo and UpdateFileInfo to 377 // This is called in GetFileInfo, AddFileInfo and UpdateFileInfo to
384 // ensure we're only dealing with valid data paths. 378 // ensure we're only dealing with valid data paths.
385 bool VerifyDataPath(const base::FilePath& data_path) { 379 bool VerifyDataPath(const base::FilePath& data_path) {
386 // |data_path| should not contain any ".." and should be a relative path 380 // |data_path| should not contain any ".." and should be a relative path
387 // (to the filesystem_data_directory_). 381 // (to the filesystem_data_directory_).
388 if (data_path.ReferencesParent() || data_path.IsAbsolute()) 382 if (data_path.ReferencesParent() || data_path.IsAbsolute())
389 return false; 383 return false;
390 // See if it's not pointing to the special system paths. 384 // See if it's not pointing to the special system paths.
391 const base::FilePath kExcludes[] = { 385 const base::FilePath kExcludes[] = {
392 base::FilePath(kDirectoryDatabaseName), 386 base::FilePath(kDirectoryDatabaseName),
393 base::FilePath(fileapi::FileSystemUsageCache::kUsageFileName), 387 base::FilePath(storage::FileSystemUsageCache::kUsageFileName),
394 }; 388 };
395 for (size_t i = 0; i < arraysize(kExcludes); ++i) { 389 for (size_t i = 0; i < arraysize(kExcludes); ++i) {
396 if (data_path == kExcludes[i] || kExcludes[i].IsParent(data_path)) 390 if (data_path == kExcludes[i] || kExcludes[i].IsParent(data_path))
397 return false; 391 return false;
398 } 392 }
399 return true; 393 return true;
400 } 394 }
401 395
402 } // namespace 396 } // namespace
403 397
404 namespace fileapi { 398 namespace storage {
405 399
406 SandboxDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) { 400 SandboxDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) {
407 } 401 }
408 402
409 SandboxDirectoryDatabase::FileInfo::~FileInfo() { 403 SandboxDirectoryDatabase::FileInfo::~FileInfo() {
410 } 404 }
411 405
412 SandboxDirectoryDatabase::SandboxDirectoryDatabase( 406 SandboxDirectoryDatabase::SandboxDirectoryDatabase(
413 const base::FilePath& filesystem_data_directory, 407 const base::FilePath& filesystem_data_directory,
414 leveldb::Env* env_override) 408 leveldb::Env* env_override)
(...skipping 21 matching lines...) Expand all
436 if (!base::StringToInt64(child_id_string, child_id)) { 430 if (!base::StringToInt64(child_id_string, child_id)) {
437 LOG(ERROR) << "Hit database corruption!"; 431 LOG(ERROR) << "Hit database corruption!";
438 return false; 432 return false;
439 } 433 }
440 return true; 434 return true;
441 } 435 }
442 HandleError(FROM_HERE, status); 436 HandleError(FROM_HERE, status);
443 return false; 437 return false;
444 } 438 }
445 439
446 bool SandboxDirectoryDatabase::GetFileWithPath( 440 bool SandboxDirectoryDatabase::GetFileWithPath(const base::FilePath& path,
447 const base::FilePath& path, FileId* file_id) { 441 FileId* file_id) {
448 std::vector<base::FilePath::StringType> components; 442 std::vector<base::FilePath::StringType> components;
449 VirtualPath::GetComponents(path, &components); 443 VirtualPath::GetComponents(path, &components);
450 FileId local_id = 0; 444 FileId local_id = 0;
451 std::vector<base::FilePath::StringType>::iterator iter; 445 std::vector<base::FilePath::StringType>::iterator iter;
452 for (iter = components.begin(); iter != components.end(); ++iter) { 446 for (iter = components.begin(); iter != components.end(); ++iter) {
453 base::FilePath::StringType name; 447 base::FilePath::StringType name;
454 name = *iter; 448 name = *iter;
455 if (name == FILE_PATH_LITERAL("/")) 449 if (name == FILE_PATH_LITERAL("/"))
456 continue; 450 continue;
457 if (!GetChildWithName(local_id, name, &local_id)) 451 if (!GetChildWithName(local_id, name, &local_id))
458 return false; 452 return false;
459 } 453 }
460 *file_id = local_id; 454 *file_id = local_id;
461 return true; 455 return true;
462 } 456 }
463 457
464 bool SandboxDirectoryDatabase::ListChildren( 458 bool SandboxDirectoryDatabase::ListChildren(FileId parent_id,
465 FileId parent_id, std::vector<FileId>* children) { 459 std::vector<FileId>* children) {
466 // Check to add later: fail if parent is a file, at least in debug builds. 460 // Check to add later: fail if parent is a file, at least in debug builds.
467 if (!Init(REPAIR_ON_CORRUPTION)) 461 if (!Init(REPAIR_ON_CORRUPTION))
468 return false; 462 return false;
469 DCHECK(children); 463 DCHECK(children);
470 std::string child_key_prefix = GetChildListingKeyPrefix(parent_id); 464 std::string child_key_prefix = GetChildListingKeyPrefix(parent_id);
471 465
472 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); 466 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions()));
473 iter->Seek(child_key_prefix); 467 iter->Seek(child_key_prefix);
474 children->clear(); 468 children->clear();
475 while (iter->Valid() && 469 while (iter->Valid() &&
476 StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) { 470 StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) {
477 std::string child_id_string = iter->value().ToString(); 471 std::string child_id_string = iter->value().ToString();
478 FileId child_id; 472 FileId child_id;
479 if (!base::StringToInt64(child_id_string, &child_id)) { 473 if (!base::StringToInt64(child_id_string, &child_id)) {
480 LOG(ERROR) << "Hit database corruption!"; 474 LOG(ERROR) << "Hit database corruption!";
481 return false; 475 return false;
482 } 476 }
483 children->push_back(child_id); 477 children->push_back(child_id);
484 iter->Next(); 478 iter->Next();
485 } 479 }
486 return true; 480 return true;
(...skipping 26 matching lines...) Expand all
513 info->name = base::FilePath::StringType(); 507 info->name = base::FilePath::StringType();
514 info->data_path = base::FilePath(); 508 info->data_path = base::FilePath();
515 info->modification_time = base::Time::Now(); 509 info->modification_time = base::Time::Now();
516 info->parent_id = 0; 510 info->parent_id = 0;
517 return true; 511 return true;
518 } 512 }
519 HandleError(FROM_HERE, status); 513 HandleError(FROM_HERE, status);
520 return false; 514 return false;
521 } 515 }
522 516
523 base::File::Error SandboxDirectoryDatabase::AddFileInfo( 517 base::File::Error SandboxDirectoryDatabase::AddFileInfo(const FileInfo& info,
524 const FileInfo& info, FileId* file_id) { 518 FileId* file_id) {
525 if (!Init(REPAIR_ON_CORRUPTION)) 519 if (!Init(REPAIR_ON_CORRUPTION))
526 return base::File::FILE_ERROR_FAILED; 520 return base::File::FILE_ERROR_FAILED;
527 DCHECK(file_id); 521 DCHECK(file_id);
528 std::string child_key = GetChildLookupKey(info.parent_id, info.name); 522 std::string child_key = GetChildLookupKey(info.parent_id, info.name);
529 std::string child_id_string; 523 std::string child_id_string;
530 leveldb::Status status = 524 leveldb::Status status =
531 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); 525 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string);
532 if (status.ok()) { 526 if (status.ok()) {
533 LOG(ERROR) << "File exists already!"; 527 LOG(ERROR) << "File exists already!";
534 return base::File::FILE_ERROR_EXISTS; 528 return base::File::FILE_ERROR_EXISTS;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
572 if (!RemoveFileInfoHelper(file_id, &batch)) 566 if (!RemoveFileInfoHelper(file_id, &batch))
573 return false; 567 return false;
574 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 568 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
575 if (!status.ok()) { 569 if (!status.ok()) {
576 HandleError(FROM_HERE, status); 570 HandleError(FROM_HERE, status);
577 return false; 571 return false;
578 } 572 }
579 return true; 573 return true;
580 } 574 }
581 575
582 bool SandboxDirectoryDatabase::UpdateFileInfo( 576 bool SandboxDirectoryDatabase::UpdateFileInfo(FileId file_id,
583 FileId file_id, const FileInfo& new_info) { 577 const FileInfo& new_info) {
584 // TODO(ericu): We should also check to see that this doesn't create a loop, 578 // TODO(ericu): We should also check to see that this doesn't create a loop,
585 // but perhaps only in a debug build. 579 // but perhaps only in a debug build.
586 if (!Init(REPAIR_ON_CORRUPTION)) 580 if (!Init(REPAIR_ON_CORRUPTION))
587 return false; 581 return false;
588 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. 582 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB.
589 FileInfo old_info; 583 FileInfo old_info;
590 if (!GetFileInfo(file_id, &old_info)) 584 if (!GetFileInfo(file_id, &old_info))
591 return false; 585 return false;
592 if (old_info.parent_id != new_info.parent_id && 586 if (old_info.parent_id != new_info.parent_id &&
593 !IsDirectory(new_info.parent_id)) 587 !IsDirectory(new_info.parent_id))
(...skipping 13 matching lines...) Expand all
607 return false; 601 return false;
608 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 602 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
609 if (!status.ok()) { 603 if (!status.ok()) {
610 HandleError(FROM_HERE, status); 604 HandleError(FROM_HERE, status);
611 return false; 605 return false;
612 } 606 }
613 return true; 607 return true;
614 } 608 }
615 609
616 bool SandboxDirectoryDatabase::UpdateModificationTime( 610 bool SandboxDirectoryDatabase::UpdateModificationTime(
617 FileId file_id, const base::Time& modification_time) { 611 FileId file_id,
612 const base::Time& modification_time) {
618 FileInfo info; 613 FileInfo info;
619 if (!GetFileInfo(file_id, &info)) 614 if (!GetFileInfo(file_id, &info))
620 return false; 615 return false;
621 info.modification_time = modification_time; 616 info.modification_time = modification_time;
622 Pickle pickle; 617 Pickle pickle;
623 if (!PickleFromFileInfo(info, &pickle)) 618 if (!PickleFromFileInfo(info, &pickle))
624 return false; 619 return false;
625 leveldb::Status status = db_->Put( 620 leveldb::Status status =
626 leveldb::WriteOptions(), 621 db_->Put(leveldb::WriteOptions(),
627 GetFileLookupKey(file_id), 622 GetFileLookupKey(file_id),
628 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), 623 leveldb::Slice(reinterpret_cast<const char*>(pickle.data()),
629 pickle.size())); 624 pickle.size()));
630 if (!status.ok()) { 625 if (!status.ok()) {
631 HandleError(FROM_HERE, status); 626 HandleError(FROM_HERE, status);
632 return false; 627 return false;
633 } 628 }
634 return true; 629 return true;
635 } 630 }
636 631
637 bool SandboxDirectoryDatabase::OverwritingMoveFile( 632 bool SandboxDirectoryDatabase::OverwritingMoveFile(FileId src_file_id,
638 FileId src_file_id, FileId dest_file_id) { 633 FileId dest_file_id) {
639 FileInfo src_file_info; 634 FileInfo src_file_info;
640 FileInfo dest_file_info; 635 FileInfo dest_file_info;
641 636
642 if (!GetFileInfo(src_file_id, &src_file_info)) 637 if (!GetFileInfo(src_file_id, &src_file_info))
643 return false; 638 return false;
644 if (!GetFileInfo(dest_file_id, &dest_file_info)) 639 if (!GetFileInfo(dest_file_id, &dest_file_info))
645 return false; 640 return false;
646 if (src_file_info.is_directory() || dest_file_info.is_directory()) 641 if (src_file_info.is_directory() || dest_file_info.is_directory())
647 return false; 642 return false;
648 leveldb::WriteBatch batch; 643 leveldb::WriteBatch batch;
649 // This is the only field that really gets moved over; if you add fields to 644 // This is the only field that really gets moved over; if you add fields to
650 // FileInfo, e.g. ctime, they might need to be copied here. 645 // FileInfo, e.g. ctime, they might need to be copied here.
651 dest_file_info.data_path = src_file_info.data_path; 646 dest_file_info.data_path = src_file_info.data_path;
652 if (!RemoveFileInfoHelper(src_file_id, &batch)) 647 if (!RemoveFileInfoHelper(src_file_id, &batch))
653 return false; 648 return false;
654 Pickle pickle; 649 Pickle pickle;
655 if (!PickleFromFileInfo(dest_file_info, &pickle)) 650 if (!PickleFromFileInfo(dest_file_info, &pickle))
656 return false; 651 return false;
657 batch.Put( 652 batch.Put(GetFileLookupKey(dest_file_id),
658 GetFileLookupKey(dest_file_id), 653 leveldb::Slice(reinterpret_cast<const char*>(pickle.data()),
659 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), 654 pickle.size()));
660 pickle.size()));
661 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 655 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
662 if (!status.ok()) { 656 if (!status.ok()) {
663 HandleError(FROM_HERE, status); 657 HandleError(FROM_HERE, status);
664 return false; 658 return false;
665 } 659 }
666 return true; 660 return true;
667 } 661 }
668 662
669 bool SandboxDirectoryDatabase::GetNextInteger(int64* next) { 663 bool SandboxDirectoryDatabase::GetNextInteger(int64* next) {
670 if (!Init(REPAIR_ON_CORRUPTION)) 664 if (!Init(REPAIR_ON_CORRUPTION))
671 return false; 665 return false;
672 DCHECK(next); 666 DCHECK(next);
673 std::string int_string; 667 std::string int_string;
674 leveldb::Status status = 668 leveldb::Status status =
675 db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string); 669 db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string);
676 if (status.ok()) { 670 if (status.ok()) {
677 int64 temp; 671 int64 temp;
678 if (!base::StringToInt64(int_string, &temp)) { 672 if (!base::StringToInt64(int_string, &temp)) {
679 LOG(ERROR) << "Hit database corruption!"; 673 LOG(ERROR) << "Hit database corruption!";
680 return false; 674 return false;
681 } 675 }
682 ++temp; 676 ++temp;
683 status = db_->Put(leveldb::WriteOptions(), LastIntegerKey(), 677 status = db_->Put(
684 base::Int64ToString(temp)); 678 leveldb::WriteOptions(), LastIntegerKey(), base::Int64ToString(temp));
685 if (!status.ok()) { 679 if (!status.ok()) {
686 HandleError(FROM_HERE, status); 680 HandleError(FROM_HERE, status);
687 return false; 681 return false;
688 } 682 }
689 *next = temp; 683 *next = temp;
690 return true; 684 return true;
691 } 685 }
692 if (!status.IsNotFound()) { 686 if (!status.IsNotFound()) {
693 HandleError(FROM_HERE, status); 687 HandleError(FROM_HERE, status);
694 return false; 688 return false;
695 } 689 }
696 // The database must not yet exist; initialize it. 690 // The database must not yet exist; initialize it.
697 if (!StoreDefaultValues()) 691 if (!StoreDefaultValues())
698 return false; 692 return false;
699 693
700 return GetNextInteger(next); 694 return GetNextInteger(next);
701 } 695 }
702 696
703 // static 697 // static
704 bool SandboxDirectoryDatabase::DestroyDatabase(const base::FilePath& path, 698 bool SandboxDirectoryDatabase::DestroyDatabase(const base::FilePath& path,
705 leveldb::Env* env_override) { 699 leveldb::Env* env_override) {
706 std::string name = FilePathToString(path.Append(kDirectoryDatabaseName)); 700 std::string name = FilePathToString(path.Append(kDirectoryDatabaseName));
707 leveldb::Options options; 701 leveldb::Options options;
708 if (env_override) 702 if (env_override)
709 options.env = env_override; 703 options.env = env_override;
710 leveldb::Status status = leveldb::DestroyDB(name, options); 704 leveldb::Status status = leveldb::DestroyDB(name, options);
711 if (status.ok()) 705 if (status.ok())
712 return true; 706 return true;
713 LOG(WARNING) << "Failed to destroy a database with status " << 707 LOG(WARNING) << "Failed to destroy a database with status "
714 status.ToString(); 708 << status.ToString();
715 return false; 709 return false;
716 } 710 }
717 711
718 bool SandboxDirectoryDatabase::Init(RecoveryOption recovery_option) { 712 bool SandboxDirectoryDatabase::Init(RecoveryOption recovery_option) {
719 if (db_) 713 if (db_)
720 return true; 714 return true;
721 715
722 std::string path = 716 std::string path = FilePathToString(
723 FilePathToString(filesystem_data_directory_.Append( 717 filesystem_data_directory_.Append(kDirectoryDatabaseName));
724 kDirectoryDatabaseName));
725 leveldb::Options options; 718 leveldb::Options options;
726 options.max_open_files = 0; // Use minimum. 719 options.max_open_files = 0; // Use minimum.
727 options.create_if_missing = true; 720 options.create_if_missing = true;
728 if (env_override_) 721 if (env_override_)
729 options.env = env_override_; 722 options.env = env_override_;
730 leveldb::DB* db; 723 leveldb::DB* db;
731 leveldb::Status status = leveldb::DB::Open(options, path, &db); 724 leveldb::Status status = leveldb::DB::Open(options, path, &db);
732 ReportInitStatus(status); 725 ReportInitStatus(status);
733 if (status.ok()) { 726 if (status.ok()) {
734 db_.reset(db); 727 db_.reset(db);
735 return true; 728 return true;
736 } 729 }
737 HandleError(FROM_HERE, status); 730 HandleError(FROM_HERE, status);
738 731
739 // Corruption due to missing necessary MANIFEST-* file causes IOError instead 732 // Corruption due to missing necessary MANIFEST-* file causes IOError instead
740 // of Corruption error. 733 // of Corruption error.
741 // Try to repair database even when IOError case. 734 // Try to repair database even when IOError case.
742 if (!status.IsCorruption() && !status.IsIOError()) 735 if (!status.IsCorruption() && !status.IsIOError())
743 return false; 736 return false;
744 737
745 switch (recovery_option) { 738 switch (recovery_option) {
746 case FAIL_ON_CORRUPTION: 739 case FAIL_ON_CORRUPTION:
747 return false; 740 return false;
748 case REPAIR_ON_CORRUPTION: 741 case REPAIR_ON_CORRUPTION:
749 LOG(WARNING) << "Corrupted SandboxDirectoryDatabase detected." 742 LOG(WARNING) << "Corrupted SandboxDirectoryDatabase detected."
750 << " Attempting to repair."; 743 << " Attempting to repair.";
751 if (RepairDatabase(path)) { 744 if (RepairDatabase(path)) {
752 UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, 745 UMA_HISTOGRAM_ENUMERATION(
753 DB_REPAIR_SUCCEEDED, DB_REPAIR_MAX); 746 kDatabaseRepairHistogramLabel, DB_REPAIR_SUCCEEDED, DB_REPAIR_MAX);
754 return true; 747 return true;
755 } 748 }
756 UMA_HISTOGRAM_ENUMERATION(kDatabaseRepairHistogramLabel, 749 UMA_HISTOGRAM_ENUMERATION(
757 DB_REPAIR_FAILED, DB_REPAIR_MAX); 750 kDatabaseRepairHistogramLabel, DB_REPAIR_FAILED, DB_REPAIR_MAX);
758 LOG(WARNING) << "Failed to repair SandboxDirectoryDatabase."; 751 LOG(WARNING) << "Failed to repair SandboxDirectoryDatabase.";
759 // fall through 752 // fall through
760 case DELETE_ON_CORRUPTION: 753 case DELETE_ON_CORRUPTION:
761 LOG(WARNING) << "Clearing SandboxDirectoryDatabase."; 754 LOG(WARNING) << "Clearing SandboxDirectoryDatabase.";
762 if (!base::DeleteFile(filesystem_data_directory_, true)) 755 if (!base::DeleteFile(filesystem_data_directory_, true))
763 return false; 756 return false;
764 if (!base::CreateDirectory(filesystem_data_directory_)) 757 if (!base::CreateDirectory(filesystem_data_directory_))
765 return false; 758 return false;
766 return Init(FAIL_ON_CORRUPTION); 759 return Init(FAIL_ON_CORRUPTION);
767 } 760 }
768 761
769 NOTREACHED(); 762 NOTREACHED();
(...skipping 27 matching lines...) Expand all
797 return true; 790 return true;
798 } 791 }
799 792
800 bool SandboxDirectoryDatabase::IsFileSystemConsistent() { 793 bool SandboxDirectoryDatabase::IsFileSystemConsistent() {
801 if (!Init(FAIL_ON_CORRUPTION)) 794 if (!Init(FAIL_ON_CORRUPTION))
802 return false; 795 return false;
803 DatabaseCheckHelper helper(this, db_.get(), filesystem_data_directory_); 796 DatabaseCheckHelper helper(this, db_.get(), filesystem_data_directory_);
804 return helper.IsFileSystemConsistent(); 797 return helper.IsFileSystemConsistent();
805 } 798 }
806 799
807 void SandboxDirectoryDatabase::ReportInitStatus( 800 void SandboxDirectoryDatabase::ReportInitStatus(const leveldb::Status& status) {
808 const leveldb::Status& status) {
809 base::Time now = base::Time::Now(); 801 base::Time now = base::Time::Now();
810 const base::TimeDelta minimum_interval = 802 const base::TimeDelta minimum_interval =
811 base::TimeDelta::FromHours(kMinimumReportIntervalHours); 803 base::TimeDelta::FromHours(kMinimumReportIntervalHours);
812 if (last_reported_time_ + minimum_interval >= now) 804 if (last_reported_time_ + minimum_interval >= now)
813 return; 805 return;
814 last_reported_time_ = now; 806 last_reported_time_ = now;
815 807
816 if (status.ok()) { 808 if (status.ok()) {
817 UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, 809 UMA_HISTOGRAM_ENUMERATION(
818 INIT_STATUS_OK, INIT_STATUS_MAX); 810 kInitStatusHistogramLabel, INIT_STATUS_OK, INIT_STATUS_MAX);
819 } else if (status.IsCorruption()) { 811 } else if (status.IsCorruption()) {
820 UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, 812 UMA_HISTOGRAM_ENUMERATION(
821 INIT_STATUS_CORRUPTION, INIT_STATUS_MAX); 813 kInitStatusHistogramLabel, INIT_STATUS_CORRUPTION, INIT_STATUS_MAX);
822 } else if (status.IsIOError()) { 814 } else if (status.IsIOError()) {
823 UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, 815 UMA_HISTOGRAM_ENUMERATION(
824 INIT_STATUS_IO_ERROR, INIT_STATUS_MAX); 816 kInitStatusHistogramLabel, INIT_STATUS_IO_ERROR, INIT_STATUS_MAX);
825 } else { 817 } else {
826 UMA_HISTOGRAM_ENUMERATION(kInitStatusHistogramLabel, 818 UMA_HISTOGRAM_ENUMERATION(
827 INIT_STATUS_UNKNOWN_ERROR, INIT_STATUS_MAX); 819 kInitStatusHistogramLabel, INIT_STATUS_UNKNOWN_ERROR, INIT_STATUS_MAX);
828 } 820 }
829 } 821 }
830 822
831 bool SandboxDirectoryDatabase::StoreDefaultValues() { 823 bool SandboxDirectoryDatabase::StoreDefaultValues() {
832 // Verify that this is a totally new database, and initialize it. 824 // Verify that this is a totally new database, and initialize it.
833 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); 825 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions()));
834 iter->SeekToFirst(); 826 iter->SeekToFirst();
835 if (iter->Valid()) { // DB was not empty--we shouldn't have been called. 827 if (iter->Valid()) { // DB was not empty--we shouldn't have been called.
836 LOG(ERROR) << "File system origin database is corrupt!"; 828 LOG(ERROR) << "File system origin database is corrupt!";
837 return false; 829 return false;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
873 return false; 865 return false;
874 } 866 }
875 // The database must not yet exist; initialize it. 867 // The database must not yet exist; initialize it.
876 if (!StoreDefaultValues()) 868 if (!StoreDefaultValues())
877 return false; 869 return false;
878 *file_id = 0; 870 *file_id = 0;
879 return true; 871 return true;
880 } 872 }
881 873
882 // This does very few safety checks! 874 // This does very few safety checks!
883 bool SandboxDirectoryDatabase::AddFileInfoHelper( 875 bool SandboxDirectoryDatabase::AddFileInfoHelper(const FileInfo& info,
884 const FileInfo& info, FileId file_id, leveldb::WriteBatch* batch) { 876 FileId file_id,
877 leveldb::WriteBatch* batch) {
885 if (!VerifyDataPath(info.data_path)) { 878 if (!VerifyDataPath(info.data_path)) {
886 LOG(ERROR) << "Invalid data path is given: " << info.data_path.value(); 879 LOG(ERROR) << "Invalid data path is given: " << info.data_path.value();
887 return false; 880 return false;
888 } 881 }
889 std::string id_string = GetFileLookupKey(file_id); 882 std::string id_string = GetFileLookupKey(file_id);
890 if (!file_id) { 883 if (!file_id) {
891 // The root directory doesn't need to be looked up by path from its parent. 884 // The root directory doesn't need to be looked up by path from its parent.
892 DCHECK(!info.parent_id); 885 DCHECK(!info.parent_id);
893 DCHECK(info.data_path.empty()); 886 DCHECK(info.data_path.empty());
894 } else { 887 } else {
895 std::string child_key = GetChildLookupKey(info.parent_id, info.name); 888 std::string child_key = GetChildLookupKey(info.parent_id, info.name);
896 batch->Put(child_key, id_string); 889 batch->Put(child_key, id_string);
897 } 890 }
898 Pickle pickle; 891 Pickle pickle;
899 if (!PickleFromFileInfo(info, &pickle)) 892 if (!PickleFromFileInfo(info, &pickle))
900 return false; 893 return false;
901 batch->Put( 894 batch->Put(id_string,
902 id_string, 895 leveldb::Slice(reinterpret_cast<const char*>(pickle.data()),
903 leveldb::Slice(reinterpret_cast<const char *>(pickle.data()), 896 pickle.size()));
904 pickle.size()));
905 return true; 897 return true;
906 } 898 }
907 899
908 // This does very few safety checks! 900 // This does very few safety checks!
909 bool SandboxDirectoryDatabase::RemoveFileInfoHelper( 901 bool SandboxDirectoryDatabase::RemoveFileInfoHelper(
910 FileId file_id, leveldb::WriteBatch* batch) { 902 FileId file_id,
903 leveldb::WriteBatch* batch) {
911 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. 904 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB.
912 FileInfo info; 905 FileInfo info;
913 if (!GetFileInfo(file_id, &info)) 906 if (!GetFileInfo(file_id, &info))
914 return false; 907 return false;
915 if (info.data_path.empty()) { // It's a directory 908 if (info.data_path.empty()) { // It's a directory
916 std::vector<FileId> children; 909 std::vector<FileId> children;
917 // TODO(ericu): Make a faster is-the-directory-empty check. 910 // TODO(ericu): Make a faster is-the-directory-empty check.
918 if (!ListChildren(file_id, &children)) 911 if (!ListChildren(file_id, &children))
919 return false; 912 return false;
920 if (children.size()) { 913 if (children.size()) {
921 LOG(ERROR) << "Can't remove a directory with children."; 914 LOG(ERROR) << "Can't remove a directory with children.";
922 return false; 915 return false;
923 } 916 }
924 } 917 }
925 batch->Delete(GetChildLookupKey(info.parent_id, info.name)); 918 batch->Delete(GetChildLookupKey(info.parent_id, info.name));
926 batch->Delete(GetFileLookupKey(file_id)); 919 batch->Delete(GetFileLookupKey(file_id));
927 return true; 920 return true;
928 } 921 }
929 922
930 void SandboxDirectoryDatabase::HandleError( 923 void SandboxDirectoryDatabase::HandleError(
931 const tracked_objects::Location& from_here, 924 const tracked_objects::Location& from_here,
932 const leveldb::Status& status) { 925 const leveldb::Status& status) {
933 LOG(ERROR) << "SandboxDirectoryDatabase failed at: " 926 LOG(ERROR) << "SandboxDirectoryDatabase failed at: " << from_here.ToString()
934 << from_here.ToString() << " with error: " << status.ToString(); 927 << " with error: " << status.ToString();
935 db_.reset(); 928 db_.reset();
936 } 929 }
937 930
938 } // namespace fileapi 931 } // namespace storage
OLDNEW
« no previous file with comments | « storage/browser/fileapi/sandbox_directory_database.h ('k') | storage/browser/fileapi/sandbox_file_stream_writer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698