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

Unified Diff: webkit/fileapi/file_system_origin_database.cc

Issue 9663021: Add database recovery for FileSystemOriginDatabase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: address comments 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 side-by-side diff with in-line comments
Download patch
Index: webkit/fileapi/file_system_origin_database.cc
diff --git a/webkit/fileapi/file_system_origin_database.cc b/webkit/fileapi/file_system_origin_database.cc
index 125576ae38d1eda4f7dfeae35a63059f1b326c06..b26c7fd5397f0bcab8cef3acee5ff13aa069bec8 100644
--- a/webkit/fileapi/file_system_origin_database.cc
+++ b/webkit/fileapi/file_system_origin_database.cc
@@ -4,18 +4,21 @@
#include "webkit/fileapi/file_system_origin_database.h"
+#include "base/file_util.h"
#include "base/format_macros.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/string_number_conversions.h"
#include "base/stringprintf.h"
#include "base/string_util.h"
-#include "base/sys_string_conversions.h"
+#include "base/utf_string_conversions.h"
#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
#include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
+#include "webkit/fileapi/file_system_util.h"
namespace {
+const FilePath::CharType kOriginDatabaseName[] = FILE_PATH_LITERAL("Origins");
const char kOriginKeyPrefix[] = "ORIGIN:";
const char kLastPathKey[] = "LAST_PATH";
@@ -43,31 +46,108 @@ FileSystemOriginDatabase::OriginRecord::OriginRecord(
FileSystemOriginDatabase::OriginRecord::~OriginRecord() {
}
-FileSystemOriginDatabase::FileSystemOriginDatabase(const FilePath& path) {
-#if defined(OS_POSIX)
- path_ = path.value();
-#elif defined(OS_WIN)
- path_ = base::SysWideToUTF8(path.value());
-#endif
+FileSystemOriginDatabase::FileSystemOriginDatabase(
+ const FilePath& file_system_directory)
+ : file_system_directory_(file_system_directory) {
}
FileSystemOriginDatabase::~FileSystemOriginDatabase() {
}
-bool FileSystemOriginDatabase::Init() {
+bool FileSystemOriginDatabase::Init(RecoveryOption recovery_option) {
if (db_.get())
return true;
+ std::string path =
+ FilePathToString(file_system_directory_.Append(kOriginDatabaseName));
leveldb::Options options;
options.create_if_missing = true;
leveldb::DB* db;
- leveldb::Status status = leveldb::DB::Open(options, path_, &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);
- return false;
+
+ switch (recovery_option) {
+ case FAIL_ON_CORRUPTION:
+ return false;
+ case REPAIR_ON_CORRUPTION:
+ LOG(WARNING) << "Attempting to repair FileSystemOriginDatabase.";
+ if (RepairDatabase(path)) {
+ LOG(WARNING) << "Repairing FileSystemOriginDatabase completed.";
+ return true;
+ }
+ // fall through
+ case DELETE_ON_CORRUPTION:
+ if (!file_util::Delete(file_system_directory_, true))
+ return false;
+ if (!file_util::CreateDirectory(file_system_directory_))
+ return false;
+ return Init(FAIL_ON_CORRUPTION);
+ default:
kinuko 2012/03/26 08:43:45 Let's not to have default here so that we get a wa
tzik 2012/03/26 11:27:37 Done.
+ NOTREACHED();
+ return false;
+ }
+}
+
+bool FileSystemOriginDatabase::RepairDatabase(const std::string& db_path) {
+ DCHECK(!db_.get());
+ if (!leveldb::RepairDB(db_path, leveldb::Options()).ok() ||
+ !Init(FAIL_ON_CORRUPTION)) {
+ LOG(WARNING) << "Failed to repair FileSystemOriginDatabase.";
+ return false;
+ }
+
+ // See if the repaired entries match with what we have on disk.
+ std::set<FilePath> directories;
+ file_util::FileEnumerator file_enum(file_system_directory_,
+ false /* recursive */,
+ file_util::FileEnumerator::DIRECTORIES);
+ FilePath path_each;
+ while (!(path_each = file_enum.Next()).empty())
+ directories.insert(path_each.BaseName());
+ std::set<FilePath>::iterator db_dir_itr =
+ directories.find(FilePath(kOriginDatabaseName));
+ // Make sure we have the database file in its directory and therefore we are
+ // working on the correct path.
+ DCHECK(db_dir_itr != directories.end());
+ directories.erase(db_dir_itr);
+
+ std::vector<OriginRecord> origins;
+ if (!ListAllOrigins(&origins)) {
+ DropDatabase();
+ return false;
+ }
+ for (std::vector<OriginRecord>::iterator db_origin_itr = origins.begin();
+ db_origin_itr != origins.end();
+ ++db_origin_itr) {
+ std::set<FilePath>::iterator dir_itr =
+ directories.find(db_origin_itr->path);
+ if (dir_itr == directories.end()) {
+ if (!RemovePathForOrigin(db_origin_itr->origin)) {
+ DropDatabase();
+ return false;
+ }
+ } else {
+ directories.erase(dir_itr);
+ }
+ }
+
+ // Delete any directories not listed in the origins database.
+ for (std::set<FilePath>::iterator dir_itr = directories.begin();
+ dir_itr != directories.end();
+ ++dir_itr) {
+ if (!file_util::Delete(file_system_directory_.Append(*dir_itr),
+ true /* recursive */)) {
+ DropDatabase();
+ return false;
+ }
+ }
+
+ return true;
}
void FileSystemOriginDatabase::HandleError(
@@ -78,7 +158,7 @@ void FileSystemOriginDatabase::HandleError(
}
bool FileSystemOriginDatabase::HasOriginPath(const std::string& origin) {
- if (!Init())
+ if (!Init(REPAIR_ON_CORRUPTION))
return false;
if (origin.empty())
return false;
@@ -95,7 +175,7 @@ bool FileSystemOriginDatabase::HasOriginPath(const std::string& origin) {
bool FileSystemOriginDatabase::GetPathForOrigin(
const std::string& origin, FilePath* directory) {
- if (!Init())
+ if (!Init(REPAIR_ON_CORRUPTION))
return false;
DCHECK(directory);
if (origin.empty())
@@ -120,11 +200,7 @@ bool FileSystemOriginDatabase::GetPathForOrigin(
}
}
if (status.ok()) {
-#if defined(OS_POSIX)
- *directory = FilePath(path_string);
-#elif defined(OS_WIN)
- *directory = FilePath(base::SysUTF8ToWide(path_string));
-#endif
+ *directory = StringToFilePath(path_string);
return true;
}
HandleError(FROM_HERE, status);
@@ -132,7 +208,7 @@ bool FileSystemOriginDatabase::GetPathForOrigin(
}
bool FileSystemOriginDatabase::RemovePathForOrigin(const std::string& origin) {
- if (!Init())
+ if (!Init(REPAIR_ON_CORRUPTION))
return false;
leveldb::Status status =
db_->Delete(leveldb::WriteOptions(), OriginToOriginKey(origin));
@@ -144,7 +220,7 @@ bool FileSystemOriginDatabase::RemovePathForOrigin(const std::string& origin) {
bool FileSystemOriginDatabase::ListAllOrigins(
std::vector<OriginRecord>* origins) {
- if (!Init())
+ if (!Init(REPAIR_ON_CORRUPTION))
return false;
DCHECK(origins);
scoped_ptr<leveldb::Iterator> iter(db_->NewIterator(leveldb::ReadOptions()));
@@ -155,11 +231,7 @@ bool FileSystemOriginDatabase::ListAllOrigins(
StartsWithASCII(iter->key().ToString(), origin_key_prefix, true)) {
std::string origin =
iter->key().ToString().substr(origin_key_prefix.length());
-#if defined(OS_POSIX)
- FilePath path = FilePath(iter->value().ToString());
-#elif defined(OS_WIN)
- FilePath path = FilePath(base::SysUTF8ToWide(iter->value().ToString()));
-#endif
+ FilePath path = StringToFilePath(iter->value().ToString());
origins->push_back(OriginRecord(origin, path));
iter->Next();
}
@@ -171,7 +243,7 @@ void FileSystemOriginDatabase::DropDatabase() {
}
bool FileSystemOriginDatabase::GetLastPathNumber(int* number) {
- if (!Init())
+ if (!Init(REPAIR_ON_CORRUPTION))
return false;
DCHECK(number);
std::string number_string;
« no previous file with comments | « webkit/fileapi/file_system_origin_database.h ('k') | webkit/fileapi/file_system_origin_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698