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

Side by Side Diff: webkit/fileapi/file_system_directory_database.cc

Issue 9663021: Add database recovery for FileSystemOriginDatabase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: '' Created 8 years, 9 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/fileapi/file_system_directory_database.h" 5 #include "webkit/fileapi/file_system_directory_database.h"
6 6
7 #include <math.h> 7 #include <math.h>
8 8
9 #include "base/file_util.h"
9 #include "base/location.h" 10 #include "base/location.h"
10 #include "base/pickle.h" 11 #include "base/pickle.h"
11 #include "base/string_number_conversions.h" 12 #include "base/string_number_conversions.h"
12 #include "base/string_util.h" 13 #include "base/string_util.h"
13 #include "base/sys_string_conversions.h" 14 #include "base/utf_string_conversions.h"
14 #include "third_party/leveldatabase/src/include/leveldb/iterator.h" 15 #include "third_party/leveldatabase/src/include/leveldb/iterator.h"
16 #include "third_party/leveldatabase/src/include/leveldb/status.h"
15 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 17 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
16 #include "webkit/fileapi/file_system_util.h" 18 #include "webkit/fileapi/file_system_util.h"
17 19
18 namespace { 20 namespace {
19 21
22 std::string FilePathStringToString(const FilePath::StringType& path) {
kinuko 2012/03/26 05:25:09 Hmm. Could we move this into file_system_util.h o
tzik 2012/03/26 08:04:56 Done.
23 // TODO(tzik): Unify this to FilePathToString in
24 // third_party/leveldatabase/env_chromium.cc.
25 #if defined(OS_WIN)
26 return UTF16ToUTF8(path);
27 #elif defined(OS_POSIX)
28 return path;
29 #endif
30 }
31
32 std::string FilePathToString(const FilePath& path) {
33 return FilePathStringToString(path.value());
34 }
35
36 FilePath::StringType StringToFilePathString(const std::string& path_string) {
37 // TODO(tzik): Unify this to CreateFilePath in
38 // third_party/leveldatabase/env_chromium.cc.
39 #if defined(OS_WIN)
40 return UTF8ToUTF16(path_string);
41 #elif defined(OS_POSIX)
42 return path_string;
43 #endif
44 }
45
46 FilePath StringToFilePath(const std::string& path_string) {
47 return FilePath(StringToFilePathString(path_string));
48 }
49
20 bool PickleFromFileInfo( 50 bool PickleFromFileInfo(
21 const fileapi::FileSystemDirectoryDatabase::FileInfo& info, 51 const fileapi::FileSystemDirectoryDatabase::FileInfo& info,
22 Pickle* pickle) { 52 Pickle* pickle) {
23 DCHECK(pickle); 53 DCHECK(pickle);
24 std::string data_path; 54 std::string data_path;
25 // Round off here to match the behavior of the filesystem on real files. 55 // Round off here to match the behavior of the filesystem on real files.
26 base::Time time = 56 base::Time time =
27 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT())); 57 base::Time::FromDoubleT(floor(info.modification_time.ToDoubleT()));
28 std::string name; 58 std::string name;
29 59
30 #if defined(OS_POSIX) 60 data_path = FilePathToString(info.data_path);
31 data_path = info.data_path.value(); 61 name = FilePathStringToString(info.name);
32 name = info.name; 62
33 #elif defined(OS_WIN)
34 data_path = base::SysWideToUTF8(info.data_path.value());
35 name = base::SysWideToUTF8(info.name);
36 #endif
37 if (pickle->WriteInt64(info.parent_id) && 63 if (pickle->WriteInt64(info.parent_id) &&
38 pickle->WriteString(data_path) && 64 pickle->WriteString(data_path) &&
39 pickle->WriteString(name) && 65 pickle->WriteString(name) &&
40 pickle->WriteInt64(time.ToInternalValue())) 66 pickle->WriteInt64(time.ToInternalValue()))
41 return true; 67 return true;
42 68
43 NOTREACHED(); 69 NOTREACHED();
44 return false; 70 return false;
45 } 71 }
46 72
47 bool FileInfoFromPickle( 73 bool FileInfoFromPickle(
48 const Pickle& pickle, 74 const Pickle& pickle,
49 fileapi::FileSystemDirectoryDatabase::FileInfo* info) { 75 fileapi::FileSystemDirectoryDatabase::FileInfo* info) {
50 PickleIterator iter(pickle); 76 PickleIterator iter(pickle);
51 std::string data_path; 77 std::string data_path;
52 std::string name; 78 std::string name;
53 int64 internal_time; 79 int64 internal_time;
54 80
55 if (pickle.ReadInt64(&iter, &info->parent_id) && 81 if (pickle.ReadInt64(&iter, &info->parent_id) &&
56 pickle.ReadString(&iter, &data_path) && 82 pickle.ReadString(&iter, &data_path) &&
57 pickle.ReadString(&iter, &name) && 83 pickle.ReadString(&iter, &name) &&
58 pickle.ReadInt64(&iter, &internal_time)) { 84 pickle.ReadInt64(&iter, &internal_time)) {
59 #if defined(OS_POSIX) 85
60 info->data_path = FilePath(data_path); 86 info->data_path = FilePath(StringToFilePath(data_path));
61 info->name = name; 87 info->name = StringToFilePathString(name);
62 #elif defined(OS_WIN)
63 info->data_path = FilePath(base::SysUTF8ToWide(data_path));
64 info->name = base::SysUTF8ToWide(name);
65 #endif
66 info->modification_time = base::Time::FromInternalValue(internal_time); 88 info->modification_time = base::Time::FromInternalValue(internal_time);
67 return true; 89 return true;
68 } 90 }
69 LOG(ERROR) << "Pickle could not be digested!"; 91 LOG(ERROR) << "Pickle could not be digested!";
70 return false; 92 return false;
71 } 93 }
72 94
95 const FilePath::CharType kDirectoryDatabaseName[] = FILE_PATH_LITERAL("Paths");
73 const char kChildLookupPrefix[] = "CHILD_OF:"; 96 const char kChildLookupPrefix[] = "CHILD_OF:";
74 const char kChildLookupSeparator[] = ":"; 97 const char kChildLookupSeparator[] = ":";
75 const char kLastFileIdKey[] = "LAST_FILE_ID"; 98 const char kLastFileIdKey[] = "LAST_FILE_ID";
76 const char kLastIntegerKey[] = "LAST_INTEGER"; 99 const char kLastIntegerKey[] = "LAST_INTEGER";
77 100
78 std::string GetChildLookupKey( 101 std::string GetChildLookupKey(
79 fileapi::FileSystemDirectoryDatabase::FileId parent_id, 102 fileapi::FileSystemDirectoryDatabase::FileId parent_id,
80 const FilePath::StringType& child_name) { 103 const FilePath::StringType& child_name) {
81 std::string name; 104 std::string name;
82 #if defined(OS_POSIX) 105 name = FilePathStringToString(child_name);
83 name = child_name;
84 #elif defined(OS_WIN)
85 name = base::SysWideToUTF8(child_name);
86 #endif
87 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + 106 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) +
88 std::string(kChildLookupSeparator) + name; 107 std::string(kChildLookupSeparator) + name;
89 } 108 }
90 109
91 std::string GetChildListingKeyPrefix( 110 std::string GetChildListingKeyPrefix(
92 fileapi::FileSystemDirectoryDatabase::FileId parent_id) { 111 fileapi::FileSystemDirectoryDatabase::FileId parent_id) {
93 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) + 112 return std::string(kChildLookupPrefix) + base::Int64ToString(parent_id) +
94 std::string(kChildLookupSeparator); 113 std::string(kChildLookupSeparator);
95 } 114 }
96 115
(...skipping 13 matching lines...) Expand all
110 } // namespace 129 } // namespace
111 130
112 namespace fileapi { 131 namespace fileapi {
113 132
114 FileSystemDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) { 133 FileSystemDirectoryDatabase::FileInfo::FileInfo() : parent_id(0) {
115 } 134 }
116 135
117 FileSystemDirectoryDatabase::FileInfo::~FileInfo() { 136 FileSystemDirectoryDatabase::FileInfo::~FileInfo() {
118 } 137 }
119 138
120 FileSystemDirectoryDatabase::FileSystemDirectoryDatabase(const FilePath& path) { 139 FileSystemDirectoryDatabase::FileSystemDirectoryDatabase(
121 #if defined(OS_POSIX) 140 const FilePath& sandbox_directory)
122 path_ = path.value(); 141 : sandbox_directory_(sandbox_directory) {
123 #elif defined(OS_WIN)
124 path_ = base::SysWideToUTF8(path.value());
125 #endif
126 } 142 }
127 143
128 FileSystemDirectoryDatabase::~FileSystemDirectoryDatabase() { 144 FileSystemDirectoryDatabase::~FileSystemDirectoryDatabase() {
129 } 145 }
130 146
131 bool FileSystemDirectoryDatabase::GetChildWithName( 147 bool FileSystemDirectoryDatabase::GetChildWithName(
132 FileId parent_id, const FilePath::StringType& name, FileId* child_id) { 148 FileId parent_id, const FilePath::StringType& name, FileId* child_id) {
133 if (!Init()) 149 if (!Init(FAIL_ON_CORRUPTION))
134 return false; 150 return false;
135 DCHECK(child_id); 151 DCHECK(child_id);
136 std::string child_key = GetChildLookupKey(parent_id, name); 152 std::string child_key = GetChildLookupKey(parent_id, name);
137 std::string child_id_string; 153 std::string child_id_string;
138 leveldb::Status status = 154 leveldb::Status status =
139 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); 155 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string);
140 if (status.IsNotFound()) 156 if (status.IsNotFound())
141 return false; 157 return false;
142 if (status.ok()) { 158 if (status.ok()) {
143 if (!base::StringToInt64(child_id_string, child_id)) { 159 if (!base::StringToInt64(child_id_string, child_id)) {
(...skipping 20 matching lines...) Expand all
164 if (!GetChildWithName(local_id, name, &local_id)) 180 if (!GetChildWithName(local_id, name, &local_id))
165 return false; 181 return false;
166 } 182 }
167 *file_id = local_id; 183 *file_id = local_id;
168 return true; 184 return true;
169 } 185 }
170 186
171 bool FileSystemDirectoryDatabase::ListChildren( 187 bool FileSystemDirectoryDatabase::ListChildren(
172 FileId parent_id, std::vector<FileId>* children) { 188 FileId parent_id, std::vector<FileId>* children) {
173 // Check to add later: fail if parent is a file, at least in debug builds. 189 // Check to add later: fail if parent is a file, at least in debug builds.
174 if (!Init()) 190 if (!Init(FAIL_ON_CORRUPTION))
175 return false; 191 return false;
176 DCHECK(children); 192 DCHECK(children);
177 std::string child_key_prefix = GetChildListingKeyPrefix(parent_id); 193 std::string child_key_prefix = GetChildListingKeyPrefix(parent_id);
178 194
179 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); 195 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions()));
180 iter->Seek(child_key_prefix); 196 iter->Seek(child_key_prefix);
181 children->clear(); 197 children->clear();
182 while (iter->Valid() && 198 while (iter->Valid() &&
183 StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) { 199 StartsWithASCII(iter->key().ToString(), child_key_prefix, true)) {
184 std::string child_id_string = iter->value().ToString(); 200 std::string child_id_string = iter->value().ToString();
185 FileId child_id; 201 FileId child_id;
186 if (!base::StringToInt64(child_id_string, &child_id)) { 202 if (!base::StringToInt64(child_id_string, &child_id)) {
187 LOG(ERROR) << "Hit database corruption!"; 203 LOG(ERROR) << "Hit database corruption!";
188 return false; 204 return false;
189 } 205 }
190 children->push_back(child_id); 206 children->push_back(child_id);
191 iter->Next(); 207 iter->Next();
192 } 208 }
193 return true; 209 return true;
194 } 210 }
195 211
196 bool FileSystemDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { 212 bool FileSystemDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) {
197 if (!Init()) 213 if (!Init(FAIL_ON_CORRUPTION))
198 return false; 214 return false;
199 DCHECK(info); 215 DCHECK(info);
200 std::string file_key = GetFileLookupKey(file_id); 216 std::string file_key = GetFileLookupKey(file_id);
201 std::string file_data_string; 217 std::string file_data_string;
202 leveldb::Status status = 218 leveldb::Status status =
203 db_->Get(leveldb::ReadOptions(), file_key, &file_data_string); 219 db_->Get(leveldb::ReadOptions(), file_key, &file_data_string);
204 if (status.ok()) { 220 if (status.ok()) {
205 return FileInfoFromPickle( 221 return FileInfoFromPickle(
206 Pickle(file_data_string.data(), file_data_string.length()), info); 222 Pickle(file_data_string.data(), file_data_string.length()), info);
207 } 223 }
208 // Special-case the root, for databases that haven't been initialized yet. 224 // Special-case the root, for databases that haven't been initialized yet.
209 // Without this, a query for the root's file info, made before creating the 225 // Without this, a query for the root's file info, made before creating the
210 // first file in the database, will fail and confuse callers. 226 // first file in the database, will fail and confuse callers.
211 if (status.IsNotFound() && !file_id) { 227 if (status.IsNotFound() && !file_id) {
212 info->name = FilePath::StringType(); 228 info->name = FilePath::StringType();
213 info->data_path = FilePath(); 229 info->data_path = FilePath();
214 info->modification_time = base::Time::Now(); 230 info->modification_time = base::Time::Now();
215 info->parent_id = 0; 231 info->parent_id = 0;
216 return true; 232 return true;
217 } 233 }
218 HandleError(FROM_HERE, status); 234 HandleError(FROM_HERE, status);
219 return false; 235 return false;
220 } 236 }
221 237
222 bool FileSystemDirectoryDatabase::AddFileInfo( 238 bool FileSystemDirectoryDatabase::AddFileInfo(
223 const FileInfo& info, FileId* file_id) { 239 const FileInfo& info, FileId* file_id) {
224 if (!Init()) 240 if (!Init(FAIL_ON_CORRUPTION))
225 return false; 241 return false;
226 DCHECK(file_id); 242 DCHECK(file_id);
227 std::string child_key = GetChildLookupKey(info.parent_id, info.name); 243 std::string child_key = GetChildLookupKey(info.parent_id, info.name);
228 std::string child_id_string; 244 std::string child_id_string;
229 leveldb::Status status = 245 leveldb::Status status =
230 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string); 246 db_->Get(leveldb::ReadOptions(), child_key, &child_id_string);
231 if (status.ok()) { 247 if (status.ok()) {
232 LOG(ERROR) << "File exists already!"; 248 LOG(ERROR) << "File exists already!";
233 return false; 249 return false;
234 } 250 }
(...skipping 21 matching lines...) Expand all
256 status = db_->Write(leveldb::WriteOptions(), &batch); 272 status = db_->Write(leveldb::WriteOptions(), &batch);
257 if (!status.ok()) { 273 if (!status.ok()) {
258 HandleError(FROM_HERE, status); 274 HandleError(FROM_HERE, status);
259 return false; 275 return false;
260 } 276 }
261 *file_id = temp_id; 277 *file_id = temp_id;
262 return true; 278 return true;
263 } 279 }
264 280
265 bool FileSystemDirectoryDatabase::RemoveFileInfo(FileId file_id) { 281 bool FileSystemDirectoryDatabase::RemoveFileInfo(FileId file_id) {
266 if (!Init()) 282 if (!Init(FAIL_ON_CORRUPTION))
267 return false; 283 return false;
268 leveldb::WriteBatch batch; 284 leveldb::WriteBatch batch;
269 if (!RemoveFileInfoHelper(file_id, &batch)) 285 if (!RemoveFileInfoHelper(file_id, &batch))
270 return false; 286 return false;
271 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 287 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
272 if (!status.ok()) { 288 if (!status.ok()) {
273 HandleError(FROM_HERE, status); 289 HandleError(FROM_HERE, status);
274 return false; 290 return false;
275 } 291 }
276 return true; 292 return true;
277 } 293 }
278 294
279 bool FileSystemDirectoryDatabase::UpdateFileInfo( 295 bool FileSystemDirectoryDatabase::UpdateFileInfo(
280 FileId file_id, const FileInfo& new_info) { 296 FileId file_id, const FileInfo& new_info) {
281 // TODO: We should also check to see that this doesn't create a loop, but 297 // TODO: We should also check to see that this doesn't create a loop, but
282 // perhaps only in a debug build. 298 // perhaps only in a debug build.
283 if (!Init()) 299 if (!Init(FAIL_ON_CORRUPTION))
284 return false; 300 return false;
285 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. 301 DCHECK(file_id); // You can't remove the root, ever. Just delete the DB.
286 FileInfo old_info; 302 FileInfo old_info;
287 if (!GetFileInfo(file_id, &old_info)) 303 if (!GetFileInfo(file_id, &old_info))
288 return false; 304 return false;
289 if (old_info.parent_id != new_info.parent_id && 305 if (old_info.parent_id != new_info.parent_id &&
290 !VerifyIsDirectory(new_info.parent_id)) 306 !VerifyIsDirectory(new_info.parent_id))
291 return false; 307 return false;
292 if (old_info.parent_id != new_info.parent_id || 308 if (old_info.parent_id != new_info.parent_id ||
293 old_info.name != new_info.name) { 309 old_info.name != new_info.name) {
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
357 pickle.size())); 373 pickle.size()));
358 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 374 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
359 if (!status.ok()) { 375 if (!status.ok()) {
360 HandleError(FROM_HERE, status); 376 HandleError(FROM_HERE, status);
361 return false; 377 return false;
362 } 378 }
363 return true; 379 return true;
364 } 380 }
365 381
366 bool FileSystemDirectoryDatabase::GetNextInteger(int64* next) { 382 bool FileSystemDirectoryDatabase::GetNextInteger(int64* next) {
367 if (!Init()) 383 if (!Init(FAIL_ON_CORRUPTION))
368 return false; 384 return false;
369 DCHECK(next); 385 DCHECK(next);
370 std::string int_string; 386 std::string int_string;
371 leveldb::Status status = 387 leveldb::Status status =
372 db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string); 388 db_->Get(leveldb::ReadOptions(), LastIntegerKey(), &int_string);
373 if (status.ok()) { 389 if (status.ok()) {
374 int64 temp; 390 int64 temp;
375 if (!base::StringToInt64(int_string, &temp)) { 391 if (!base::StringToInt64(int_string, &temp)) {
376 LOG(ERROR) << "Hit database corruption!"; 392 LOG(ERROR) << "Hit database corruption!";
377 return false; 393 return false;
(...skipping 14 matching lines...) Expand all
392 } 408 }
393 // The database must not yet exist; initialize it. 409 // The database must not yet exist; initialize it.
394 if (!StoreDefaultValues()) 410 if (!StoreDefaultValues())
395 return false; 411 return false;
396 412
397 return GetNextInteger(next); 413 return GetNextInteger(next);
398 } 414 }
399 415
400 // static 416 // static
401 bool FileSystemDirectoryDatabase::DestroyDatabase(const FilePath& path) { 417 bool FileSystemDirectoryDatabase::DestroyDatabase(const FilePath& path) {
402 std::string name; 418 std::string name = FilePathToString(path.Append(kDirectoryDatabaseName));
403 #if defined(OS_POSIX)
404 name = path.value();
405 #elif defined(OS_WIN)
406 name = base::SysWideToUTF8(path.value());
407 #endif
408 leveldb::Status status = leveldb::DestroyDB(name, leveldb::Options()); 419 leveldb::Status status = leveldb::DestroyDB(name, leveldb::Options());
409 if (status.ok()) 420 if (status.ok())
410 return true; 421 return true;
411 LOG(WARNING) << "Failed to destroy a database with status " << 422 LOG(WARNING) << "Failed to destroy a database with status " <<
412 status.ToString(); 423 status.ToString();
413 return false; 424 return false;
414 } 425 }
415 426
416 bool FileSystemDirectoryDatabase::Init() { 427 bool FileSystemDirectoryDatabase::Init(RecoveryOption recovery_option) {
417 if (db_.get()) 428 if (db_.get())
418 return true; 429 return true;
419 430
420 leveldb::Options options; 431 std::string path =
421 options.create_if_missing = true; 432 FilePathToString(sandbox_directory_.Append(kDirectoryDatabaseName));
422 leveldb::DB* db; 433 leveldb::Options options;
423 leveldb::Status status = leveldb::DB::Open(options, path_, &db); 434 options.create_if_missing = true;
424 if (status.ok()) { 435 leveldb::DB* db;
425 db_.reset(db); 436 leveldb::Status status = leveldb::DB::Open(options, path, &db);
426 return true; 437 // TODO(tzik): Collect status metrics here.
427 } 438 if (status.ok()) {
428 HandleError(FROM_HERE, status); 439 db_.reset(db);
429 return false; 440 return true;
441 }
442 HandleError(FROM_HERE, status);
443
444 if (recovery_option == FAIL_ON_CORRUPTION)
445 return false;
446
447 DCHECK_EQ(DELETE_ON_CORRUPTION, recovery_option);
448 if (!file_util::Delete(sandbox_directory_, true))
449 return false;
450 if (!file_util::CreateDirectory(sandbox_directory_))
451 return false;
452 return Init(FAIL_ON_CORRUPTION);
430 } 453 }
431 454
432 bool FileSystemDirectoryDatabase::StoreDefaultValues() { 455 bool FileSystemDirectoryDatabase::StoreDefaultValues() {
433 // Verify that this is a totally new database, and initialize it. 456 // Verify that this is a totally new database, and initialize it.
434 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions())); 457 scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions()));
435 iter->SeekToFirst(); 458 iter->SeekToFirst();
436 if (iter->Valid()) { // DB was not empty--we shouldn't have been called. 459 if (iter->Valid()) { // DB was not empty--we shouldn't have been called.
437 LOG(ERROR) << "File system origin database is corrupt!"; 460 LOG(ERROR) << "File system origin database is corrupt!";
438 return false; 461 return false;
439 } 462 }
440 // This is always the first write into the database. If we ever add a 463 // This is always the first write into the database. If we ever add a
441 // version number, it should go in this transaction too. 464 // version number, it should go in this transaction too.
442 FileInfo root; 465 FileInfo root;
443 root.parent_id = 0; 466 root.parent_id = 0;
444 root.modification_time = base::Time::Now(); 467 root.modification_time = base::Time::Now();
445 leveldb::WriteBatch batch; 468 leveldb::WriteBatch batch;
446 if (!AddFileInfoHelper(root, 0, &batch)) 469 if (!AddFileInfoHelper(root, 0, &batch))
447 return false; 470 return false;
448 batch.Put(LastFileIdKey(), base::Int64ToString(0)); 471 batch.Put(LastFileIdKey(), base::Int64ToString(0));
449 batch.Put(LastIntegerKey(), base::Int64ToString(-1)); 472 batch.Put(LastIntegerKey(), base::Int64ToString(-1));
450 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); 473 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
451 if (!status.ok()) { 474 if (!status.ok()) {
452 HandleError(FROM_HERE, status); 475 HandleError(FROM_HERE, status);
453 return false; 476 return false;
454 } 477 }
455 return true; 478 return true;
456 } 479 }
457 480
458 bool FileSystemDirectoryDatabase::GetLastFileId(FileId* file_id) { 481 bool FileSystemDirectoryDatabase::GetLastFileId(FileId* file_id) {
459 if (!Init()) 482 if (!Init(FAIL_ON_CORRUPTION))
460 return false; 483 return false;
461 DCHECK(file_id); 484 DCHECK(file_id);
462 std::string id_string; 485 std::string id_string;
463 leveldb::Status status = 486 leveldb::Status status =
464 db_->Get(leveldb::ReadOptions(), LastFileIdKey(), &id_string); 487 db_->Get(leveldb::ReadOptions(), LastFileIdKey(), &id_string);
465 if (status.ok()) { 488 if (status.ok()) {
466 if (!base::StringToInt64(id_string, file_id)) { 489 if (!base::StringToInt64(id_string, file_id)) {
467 LOG(ERROR) << "Hit database corruption!"; 490 LOG(ERROR) << "Hit database corruption!";
468 return false; 491 return false;
469 } 492 }
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
539 562
540 void FileSystemDirectoryDatabase::HandleError( 563 void FileSystemDirectoryDatabase::HandleError(
541 const tracked_objects::Location& from_here, 564 const tracked_objects::Location& from_here,
542 leveldb::Status status) { 565 leveldb::Status status) {
543 LOG(ERROR) << "FileSystemDirectoryDatabase failed at: " 566 LOG(ERROR) << "FileSystemDirectoryDatabase failed at: "
544 << from_here.ToString() << " with error: " << status.ToString(); 567 << from_here.ToString() << " with error: " << status.ToString();
545 db_.reset(); 568 db_.reset();
546 } 569 }
547 570
548 } // namespace fileapi 571 } // namespace fileapi
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698