Index: webkit/fileapi/file_system_directory_database.cc |
diff --git a/webkit/fileapi/file_system_directory_database.cc b/webkit/fileapi/file_system_directory_database.cc |
index 217b98ffbff74be110ffd358b3425f8b5ed586b2..1cad6b3a23a1533009b9de138faf8cb4967abd25 100644 |
--- a/webkit/fileapi/file_system_directory_database.cc |
+++ b/webkit/fileapi/file_system_directory_database.cc |
@@ -12,6 +12,7 @@ |
#include "base/string_util.h" |
#include "base/sys_string_conversions.h" |
#include "third_party/leveldatabase/src/include/leveldb/iterator.h" |
+#include "third_party/leveldatabase/src/include/leveldb/status.h" |
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
#include "webkit/fileapi/file_system_util.h" |
@@ -130,7 +131,7 @@ FileSystemDirectoryDatabase::~FileSystemDirectoryDatabase() { |
bool FileSystemDirectoryDatabase::GetChildWithName( |
FileId parent_id, const FilePath::StringType& name, FileId* child_id) { |
- if (!Init()) |
+ if (!Init(true)) |
jsbell
2012/03/09 23:10:11
The Boolean argument isn't very readable. Use an e
tzik
2012/03/10 00:16:55
Done.
|
return false; |
DCHECK(child_id); |
std::string child_key = GetChildLookupKey(parent_id, name); |
@@ -171,7 +172,7 @@ bool FileSystemDirectoryDatabase::GetFileWithPath( |
bool FileSystemDirectoryDatabase::ListChildren( |
FileId parent_id, std::vector<FileId>* children) { |
// Check to add later: fail if parent is a file, at least in debug builds. |
- if (!Init()) |
+ if (!Init(true)) |
return false; |
DCHECK(children); |
std::string child_key_prefix = GetChildListingKeyPrefix(parent_id); |
@@ -194,7 +195,7 @@ bool FileSystemDirectoryDatabase::ListChildren( |
} |
bool FileSystemDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { |
- if (!Init()) |
+ if (!Init(true)) |
return false; |
DCHECK(info); |
std::string file_key = GetFileLookupKey(file_id); |
@@ -221,7 +222,7 @@ bool FileSystemDirectoryDatabase::GetFileInfo(FileId file_id, FileInfo* info) { |
bool FileSystemDirectoryDatabase::AddFileInfo( |
const FileInfo& info, FileId* file_id) { |
- if (!Init()) |
+ if (!Init(true)) |
return false; |
DCHECK(file_id); |
std::string child_key = GetChildLookupKey(info.parent_id, info.name); |
@@ -263,7 +264,7 @@ bool FileSystemDirectoryDatabase::AddFileInfo( |
} |
bool FileSystemDirectoryDatabase::RemoveFileInfo(FileId file_id) { |
- if (!Init()) |
+ if (!Init(true)) |
return false; |
leveldb::WriteBatch batch; |
if (!RemoveFileInfoHelper(file_id, &batch)) |
@@ -280,7 +281,7 @@ bool FileSystemDirectoryDatabase::UpdateFileInfo( |
FileId file_id, const FileInfo& new_info) { |
// TODO: We should also check to see that this doesn't create a loop, but |
// perhaps only in a debug build. |
- if (!Init()) |
+ if (!Init(true)) |
return false; |
DCHECK(file_id); // You can't remove the root, ever. Just delete the DB. |
FileInfo old_info; |
@@ -364,7 +365,7 @@ bool FileSystemDirectoryDatabase::OverwritingMoveFile( |
} |
bool FileSystemDirectoryDatabase::GetNextInteger(int64* next) { |
- if (!Init()) |
+ if (!Init(true)) |
return false; |
DCHECK(next); |
std::string int_string; |
@@ -413,20 +414,40 @@ bool FileSystemDirectoryDatabase::DestroyDatabase(const FilePath& path) { |
return false; |
} |
-bool FileSystemDirectoryDatabase::Init() { |
- if (db_.get()) |
- return true; |
- |
- leveldb::Options options; |
- options.create_if_missing = true; |
- leveldb::DB* db; |
- leveldb::Status status = leveldb::DB::Open(options, path_, &db); |
- if (status.ok()) { |
- db_.reset(db); |
- return true; |
- } |
- HandleError(FROM_HERE, status); |
- return false; |
+bool FileSystemDirectoryDatabase::Init(bool cleanup_if_corrupted) { |
+ if (db_.get()) |
+ return true; |
+ |
+ leveldb::Options options; |
+ options.create_if_missing = true; |
+ leveldb::DB* db; |
+ leveldb::Status status = leveldb::DB::Open(options, path_, &db); |
+ // TODO(tzik): Collect status metrics here. |
+ if (status.ok()) { |
+ db_.reset(db); |
+ return true; |
+ } |
+ HandleError(FROM_HERE, status); |
+ |
+ if (cleanup_if_corrupted && CheckIfDatabaseCorrupted(status)) { |
+ LOG(WARNING) << "FileSystem API directory database is corrupted." |
+ << " Attempting cleanup."; |
+ if (leveldb::DestroyDB(path_, leveldb::Options()).ok()) { |
+ LOG(WARNING) << "FileSystem API directory database cleanup completed." |
+ << " Reopening."; |
+ return Init(false); |
+ } |
+ LOG(WARNING) << "Failed to cleanup FileSystem API directory database."; |
+ } |
+ |
+ return false; |
+} |
+ |
+bool FileSystemDirectoryDatabase::CheckIfDatabaseCorrupted( |
jsbell
2012/03/09 23:10:11
What is the benefit in factoring this method out?
tzik
2012/03/10 00:16:55
I'd initially thought, we have many thing to do he
|
+ const leveldb::Status& status) const { |
+ // TODO(tzik): Return status.code() == leveldb::Status::kCorruption, after |
+ // leveldb roll. |
+ return !status.ok(); |
} |
bool FileSystemDirectoryDatabase::StoreDefaultValues() { |
@@ -456,7 +477,7 @@ bool FileSystemDirectoryDatabase::StoreDefaultValues() { |
} |
bool FileSystemDirectoryDatabase::GetLastFileId(FileId* file_id) { |
- if (!Init()) |
+ if (!Init(true)) |
return false; |
DCHECK(file_id); |
std::string id_string; |