SQL: recovery cleanup - rename BuiltInRecovery and delete dead code.
Bug: 40061775 Change-Id: I62aea84fccbeb735029a54bff4a652816c4e41b9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5328615 Reviewed-by: Austin Sullivan <asully@chromium.org> Commit-Queue: Evan Stade <estade@chromium.org> Reviewed-by: Ayu Ishii <ayui@chromium.org> Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org> Reviewed-by: Cait Phillips <caitkp@chromium.org> Cr-Commit-Position: refs/heads/main@{#1271620}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
39d5d2a9c9
commit
4c7d6b3b77
components
blocklist
opt_out_blocklist
favicon
history
core
browser
media_device_salt
omnibox
browser
content/browser
attribution_reporting
browsing_topics
first_party_sets
database
sql
database.ccdatabase.hdatabase_unittest.cc
fuzzers
internal_api_token.hrecovery.ccrecovery.hrecovery_fuzzer.ccrecovery_unittest.ccstorage/browser/quota
tools/metrics/histograms/metadata/storage
@ -94,8 +94,8 @@ void DatabaseErrorCallback(sql::Database* db,
|
||||
int extended_error,
|
||||
sql::Statement* stmt) {
|
||||
// Attempt to recover a corrupt database, if it is eligible to be recovered.
|
||||
if (sql::BuiltInRecovery::RecoverIfPossible(
|
||||
db, extended_error, sql::BuiltInRecovery::Strategy::kRecoverOrRaze)) {
|
||||
if (sql::Recovery::RecoverIfPossible(
|
||||
db, extended_error, sql::Recovery::Strategy::kRecoverOrRaze)) {
|
||||
// Recovery was attempted. The database handle has been poisoned and the
|
||||
// error callback has been reset.
|
||||
|
||||
|
@ -195,9 +195,9 @@ void DatabaseErrorCallback(sql::Database* db,
|
||||
// see how to reach that.
|
||||
|
||||
// Attempt to recover a corrupt database, if it is eligible to be recovered.
|
||||
if (sql::BuiltInRecovery::RecoverIfPossible(
|
||||
if (sql::Recovery::RecoverIfPossible(
|
||||
db, extended_error,
|
||||
sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
// Recovery was attempted. The database handle has been poisoned and the
|
||||
// error callback has been reset.
|
||||
|
||||
|
@ -113,9 +113,9 @@ void TopSitesDatabase::DatabaseErrorCallback(const base::FilePath& db_path,
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
DCHECK(db_);
|
||||
|
||||
if (sql::BuiltInRecovery::RecoverIfPossible(
|
||||
if (sql::Recovery::RecoverIfPossible(
|
||||
db_.get(), extended_error,
|
||||
sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
// Recovery was attempted. The database handle has been poisoned and the
|
||||
// error callback has been reset.
|
||||
|
||||
|
@ -221,9 +221,8 @@ void MediaDeviceSaltDatabase::OnDatabaseError(int error,
|
||||
sql::Statement* statement) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
sql::UmaHistogramSqliteResult("Media.MediaDevices.SaltDatabaseErrors", error);
|
||||
std::ignore = sql::BuiltInRecovery::RecoverIfPossible(
|
||||
&db_, error,
|
||||
sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze);
|
||||
std::ignore = sql::Recovery::RecoverIfPossible(
|
||||
&db_, error, sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze);
|
||||
}
|
||||
|
||||
} // namespace media_device_salt
|
||||
|
@ -64,8 +64,8 @@ void DatabaseErrorCallback(sql::Database* db,
|
||||
int extended_error,
|
||||
sql::Statement* stmt) {
|
||||
// Attempt to recover a corrupt database, if it is eligible to be recovered.
|
||||
if (sql::BuiltInRecovery::RecoverIfPossible(
|
||||
db, extended_error, sql::BuiltInRecovery::Strategy::kRecoverOrRaze)) {
|
||||
if (sql::Recovery::RecoverIfPossible(
|
||||
db, extended_error, sql::Recovery::Strategy::kRecoverOrRaze)) {
|
||||
// Recovery was attempted. The database handle has been poisoned and the
|
||||
// error callback has been reset.
|
||||
|
||||
|
@ -2619,9 +2619,9 @@ void AttributionStorageSql::DatabaseErrorCallback(int extended_error,
|
||||
sql::Statement* stmt) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
// Attempt to recover a corrupt database, if it is eligible to be recovered.
|
||||
if (sql::BuiltInRecovery::RecoverIfPossible(
|
||||
if (sql::Recovery::RecoverIfPossible(
|
||||
&db_, extended_error,
|
||||
sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
// Recovery was attempted. The database handle has been poisoned and the
|
||||
// error callback has been reset.
|
||||
|
||||
|
@ -343,9 +343,9 @@ void BrowsingTopicsSiteDataStorage::DatabaseErrorCallback(
|
||||
sql::Statement* stmt) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
// Attempt to recover a corrupt database, if it is eligible to be recovered.
|
||||
if (sql::BuiltInRecovery::RecoverIfPossible(
|
||||
if (sql::Recovery::RecoverIfPossible(
|
||||
db_.get(), extended_error,
|
||||
sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
// Recovery was attempted. The database handle has been poisoned and the
|
||||
// error callback has been reset.
|
||||
|
||||
|
@ -734,9 +734,9 @@ void FirstPartySetsDatabase::DatabaseErrorCallback(int extended_error,
|
||||
sql::Statement* stmt) {
|
||||
CHECK(db_);
|
||||
// Attempt to recover a corrupt database, if it is eligible to be recovered.
|
||||
if (sql::BuiltInRecovery::RecoverIfPossible(
|
||||
if (sql::Recovery::RecoverIfPossible(
|
||||
db_.get(), extended_error,
|
||||
sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
// Recovery was attempted. The database handle has been poisoned and the
|
||||
// error callback has been reset.
|
||||
|
||||
|
@ -331,7 +331,7 @@ bool Database::Open(const base::FilePath& path) {
|
||||
DCHECK_NE(path_string, kSqliteOpenInMemoryPath)
|
||||
<< "Path conflicts with SQLite magic identifier";
|
||||
|
||||
if (OpenInternal(path_string, OpenMode::kNone)) {
|
||||
if (OpenInternal(path_string)) {
|
||||
return true;
|
||||
}
|
||||
// OpenInternal() may have run the error callback before returning false. If
|
||||
@ -339,7 +339,7 @@ bool Database::Open(const base::FilePath& path) {
|
||||
// razed, so a second attempt may succeed.
|
||||
if (poisoned_) {
|
||||
Close();
|
||||
return OpenInternal(path_string, OpenMode::kNone);
|
||||
return OpenInternal(path_string);
|
||||
}
|
||||
// Otherwise, do not attempt to reopen.
|
||||
return false;
|
||||
@ -351,7 +351,7 @@ bool Database::OpenInMemory() {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
|
||||
in_memory_ = true;
|
||||
return OpenInternal(kSqliteOpenInMemoryPath, OpenMode::kInMemory);
|
||||
return OpenInternal(kSqliteOpenInMemoryPath);
|
||||
}
|
||||
|
||||
void Database::DetachFromSequence() {
|
||||
@ -359,13 +359,6 @@ void Database::DetachFromSequence() {
|
||||
DETACH_FROM_SEQUENCE(sequence_checker_);
|
||||
}
|
||||
|
||||
bool Database::OpenTemporary(base::PassKey<Recovery>) {
|
||||
TRACE_EVENT0("sql", "Database::OpenTemporary");
|
||||
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
return OpenInternal(std::string(), OpenMode::kTemporary);
|
||||
}
|
||||
|
||||
void Database::CloseInternal(bool forced) {
|
||||
TRACE_EVENT0("sql", "Database::CloseInternal");
|
||||
|
||||
@ -1796,22 +1789,10 @@ const char* Database::GetErrorMessage() const {
|
||||
return sqlite3_errmsg(db_);
|
||||
}
|
||||
|
||||
bool Database::OpenInternal(const std::string& db_file_path,
|
||||
Database::OpenMode mode) {
|
||||
bool Database::OpenInternal(const std::string& db_file_path) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
TRACE_EVENT1("sql", "Database::OpenInternal", "path", db_file_path);
|
||||
|
||||
DCHECK(mode != OpenMode::kTemporary || db_file_path.empty())
|
||||
<< "Temporary databases should be open with an empty file path";
|
||||
|
||||
if (mode == OpenMode::kInMemory) {
|
||||
DCHECK_EQ(db_file_path, kSqliteOpenInMemoryPath)
|
||||
<< "In-memory databases should be open with the magic :memory: path";
|
||||
} else {
|
||||
DCHECK_NE(db_file_path, kSqliteOpenInMemoryPath)
|
||||
<< "Database file path conflicts with SQLite magic identifier";
|
||||
}
|
||||
|
||||
if (is_open()) {
|
||||
DLOG(FATAL) << "sql::Database is already open.";
|
||||
return false;
|
||||
@ -1843,7 +1824,8 @@ bool Database::OpenInternal(const std::string& db_file_path,
|
||||
std::string uri_file_path = db_file_path;
|
||||
if (options_.exclusive_database_file_lock) {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
if (mode == OpenMode::kNone) {
|
||||
const bool in_memory = db_file_path == kSqliteOpenInMemoryPath;
|
||||
if (!in_memory) {
|
||||
// Do not allow query injection.
|
||||
if (base::Contains(db_file_path, '?')) {
|
||||
return false;
|
||||
|
@ -53,7 +53,6 @@ class ChromeSqlDiagnostics;
|
||||
namespace sql {
|
||||
|
||||
class DatabaseMemoryDumpProvider;
|
||||
class Recovery;
|
||||
class Statement;
|
||||
|
||||
namespace test {
|
||||
@ -110,8 +109,7 @@ struct COMPONENT_EXPORT(SQL) DatabaseOptions {
|
||||
// If true, enables SQLite's Write-Ahead Logging (WAL).
|
||||
//
|
||||
// WAL integration is under development, and should not be used in shipping
|
||||
// Chrome features yet. In particular, our custom database recovery code does
|
||||
// not support the WAL log file.
|
||||
// Chrome features yet.
|
||||
//
|
||||
// WAL mode is currently not fully supported on FuchsiaOS. It will only be
|
||||
// turned on if the database is also using exclusive locking mode.
|
||||
@ -393,14 +391,6 @@ class COMPONENT_EXPORT(SQL) Database {
|
||||
// is closed.
|
||||
[[nodiscard]] bool OpenInMemory();
|
||||
|
||||
// Alternative to Open() that creates a temporary on-disk database.
|
||||
//
|
||||
// Returns true in case of success, false in case of failure.
|
||||
//
|
||||
// The files associated with the temporary database will be deleted when the
|
||||
// database is closed.
|
||||
[[nodiscard]] bool OpenTemporary(base::PassKey<Recovery>);
|
||||
|
||||
// Returns true if the database has been successfully opened.
|
||||
bool is_open() const;
|
||||
|
||||
@ -739,24 +729,12 @@ class COMPONENT_EXPORT(SQL) Database {
|
||||
FRIEND_TEST_ALL_PREFIXES(SQLiteFeaturesTest, WALNoClose);
|
||||
FRIEND_TEST_ALL_PREFIXES(SQLEmptyPathDatabaseTest, EmptyPathTest);
|
||||
|
||||
// Enables a special behavior for OpenInternal().
|
||||
enum class OpenMode {
|
||||
// No special behavior.
|
||||
kNone,
|
||||
|
||||
// Open an in-memory database. Used by OpenInMemory().
|
||||
kInMemory,
|
||||
|
||||
// Open a temporary database. Used by OpenTemporary().
|
||||
kTemporary,
|
||||
};
|
||||
|
||||
// Implements Open(), OpenInMemory(), and OpenTemporary().
|
||||
// Implements Open(), OpenInMemory().
|
||||
//
|
||||
// `db_file_path` is a UTF-8 path to the file storing the database pages. The
|
||||
// path must be empty if `mode` is kTemporary. The path must be the SQLite
|
||||
// magic memory path string if `mode` is kMemory.
|
||||
bool OpenInternal(const std::string& file_name, OpenMode mode);
|
||||
// `db_file_path` is a UTF-8 path to the file storing the database pages. If
|
||||
// `file_name` is the SQLite magic memory path :memory:, the database will be
|
||||
// opened in-memory.
|
||||
bool OpenInternal(const std::string& file_name);
|
||||
|
||||
// Configures the underlying sqlite3* object via sqlite3_db_config().
|
||||
//
|
||||
@ -955,9 +933,7 @@ class COMPONENT_EXPORT(SQL) Database {
|
||||
// Returns a SQLite VFS interface pointer to the file storing database pages.
|
||||
//
|
||||
// Returns null if the database is not backed by a VFS file. This is always
|
||||
// the case for in-memory databases. Temporary databases (only used by sq
|
||||
// ::Recovery) start without a backing VFS file, and only get a file when they
|
||||
// outgrow their page cache.
|
||||
// the case for in-memory databases.
|
||||
//
|
||||
// This method must only be called while the database is successfully opened.
|
||||
sqlite3_file* GetSqliteVfsFile();
|
||||
|
@ -2273,8 +2273,8 @@ TEST_P(SQLDatabaseTest, OpenWithRecoveryHandlesCorruption) {
|
||||
size_t error_count = 0;
|
||||
auto callback = base::BindLambdaForTesting([&](int error, Statement* stmt) {
|
||||
error_count++;
|
||||
ASSERT_TRUE(BuiltInRecovery::RecoverIfPossible(
|
||||
db_.get(), error, sql::BuiltInRecovery::Strategy::kRecoverOrRaze));
|
||||
ASSERT_TRUE(Recovery::RecoverIfPossible(
|
||||
db_.get(), error, sql::Recovery::Strategy::kRecoverOrRaze));
|
||||
if (corrupt_after_recovery) {
|
||||
// Corrupt the file again after temporarily recovering it.
|
||||
ASSERT_TRUE(sql::test::CorruptSizeInHeader(db_path_));
|
||||
|
@ -129,7 +129,7 @@ class TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
sql::BuiltInRecovery::Strategy strategy() const { return strategy_; }
|
||||
sql::Recovery::Strategy strategy() const { return strategy_; }
|
||||
bool wal_mode() const { return wal_mode_; }
|
||||
base::span<const Mutation> mutations() const { return mutations_; }
|
||||
std::string_view sql_statement() const { return sql_statement_; }
|
||||
@ -157,18 +157,17 @@ class TestCase {
|
||||
|
||||
private:
|
||||
// Converts an arbitrary int to a valid enum value.
|
||||
static sql::BuiltInRecovery::Strategy RecoveryStrategyFromInt(int input);
|
||||
static sql::Recovery::Strategy RecoveryStrategyFromInt(int input);
|
||||
// Converts arbitrary bytes in `s` to a human-readable ASCII string.
|
||||
// Non-printable characters are hex-escaped.
|
||||
static std::string DebugFormat(std::string_view s);
|
||||
// Converts the value of `strategy`, which must be a valid enum value, to a
|
||||
// human-readable string.
|
||||
static constexpr const char* DebugFormat(
|
||||
sql::BuiltInRecovery::Strategy strategy);
|
||||
static constexpr const char* DebugFormat(sql::Recovery::Strategy strategy);
|
||||
|
||||
// Fields parsed from the fuzzer input:
|
||||
const sql::BuiltInRecovery::Strategy strategy_ =
|
||||
sql::BuiltInRecovery::Strategy::kRecoverOrRaze;
|
||||
const sql::Recovery::Strategy strategy_ =
|
||||
sql::Recovery::Strategy::kRecoverOrRaze;
|
||||
const bool wal_mode_ = false;
|
||||
std::vector<Mutation> mutations_;
|
||||
const std::string sql_statement_;
|
||||
@ -266,7 +265,7 @@ DEFINE_PROTO_FUZZER(const sql_fuzzers::RecoveryFuzzerTestCase& fuzzer_input) {
|
||||
auto error_callback =
|
||||
base::BindLambdaForTesting([&](int extended_error, sql::Statement*) {
|
||||
if (!attempted_recovery) {
|
||||
attempted_recovery = sql::BuiltInRecovery::RecoverIfPossible(
|
||||
attempted_recovery = sql::Recovery::RecoverIfPossible(
|
||||
&database, extended_error, test_case.strategy());
|
||||
}
|
||||
});
|
||||
@ -291,22 +290,22 @@ DEFINE_PROTO_FUZZER(const sql_fuzzers::RecoveryFuzzerTestCase& fuzzer_input) {
|
||||
|
||||
namespace {
|
||||
|
||||
sql::BuiltInRecovery::Strategy TestCase::RecoveryStrategyFromInt(int input) {
|
||||
sql::Recovery::Strategy TestCase::RecoveryStrategyFromInt(int input) {
|
||||
static_assert(
|
||||
std::is_same_v<std::underlying_type<sql::BuiltInRecovery::Strategy>::type,
|
||||
std::is_same_v<std::underlying_type<sql::Recovery::Strategy>::type,
|
||||
decltype(input)>,
|
||||
"sql::BuiltInRecovery::Strategy's underlying type must match the input");
|
||||
"sql::Recovery::Strategy's underlying type must match the input");
|
||||
|
||||
const auto strategy = static_cast<sql::BuiltInRecovery::Strategy>(input);
|
||||
const auto strategy = static_cast<sql::Recovery::Strategy>(input);
|
||||
|
||||
// Ensure that we remember to update the fuzzer if more strategies are added.
|
||||
switch (strategy) {
|
||||
case sql::BuiltInRecovery::Strategy::kRecoverOrRaze:
|
||||
case sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze:
|
||||
case sql::Recovery::Strategy::kRecoverOrRaze:
|
||||
case sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze:
|
||||
return strategy;
|
||||
}
|
||||
// When `input` is out of range, return a default value.
|
||||
return sql::BuiltInRecovery::Strategy::kRecoverOrRaze;
|
||||
return sql::Recovery::Strategy::kRecoverOrRaze;
|
||||
}
|
||||
|
||||
std::string TestCase::DebugFormat(std::string_view s) {
|
||||
@ -326,12 +325,11 @@ std::string TestCase::DebugFormat(std::string_view s) {
|
||||
return out;
|
||||
}
|
||||
|
||||
constexpr const char* TestCase::DebugFormat(
|
||||
sql::BuiltInRecovery::Strategy strategy) {
|
||||
constexpr const char* TestCase::DebugFormat(sql::Recovery::Strategy strategy) {
|
||||
switch (strategy) {
|
||||
case sql::BuiltInRecovery::Strategy::kRecoverOrRaze:
|
||||
case sql::Recovery::Strategy::kRecoverOrRaze:
|
||||
return "kRecoverOrRaze";
|
||||
case sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze:
|
||||
case sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze:
|
||||
return "kRecoverWithMetaVersionOrRaze";
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ class InternalApiToken {
|
||||
InternalApiToken() {}
|
||||
InternalApiToken(const InternalApiToken&) = default;
|
||||
|
||||
friend class BuiltInRecovery;
|
||||
friend class Recovery;
|
||||
friend class DatabaseTestPeer;
|
||||
friend class Recovery;
|
||||
friend class Transaction;
|
||||
|
@ -38,8 +38,7 @@ constexpr char kMainDatabaseName[] = "main";
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
bool BuiltInRecovery::ShouldAttemptRecovery(Database* database,
|
||||
int extended_error) {
|
||||
bool Recovery::ShouldAttemptRecovery(Database* database, int extended_error) {
|
||||
return database && database->is_open() &&
|
||||
!database->DbPath(InternalApiToken()).empty() &&
|
||||
#if BUILDFLAG(IS_FUCHSIA)
|
||||
@ -50,16 +49,16 @@ bool BuiltInRecovery::ShouldAttemptRecovery(Database* database,
|
||||
}
|
||||
|
||||
// static
|
||||
SqliteResultCode BuiltInRecovery::RecoverDatabase(Database* database,
|
||||
Strategy strategy) {
|
||||
auto recovery = BuiltInRecovery(database, strategy);
|
||||
SqliteResultCode Recovery::RecoverDatabase(Database* database,
|
||||
Strategy strategy) {
|
||||
auto recovery = Recovery(database, strategy);
|
||||
return recovery.RecoverAndReplaceDatabase();
|
||||
}
|
||||
|
||||
// static
|
||||
bool BuiltInRecovery::RecoverIfPossible(Database* database,
|
||||
int extended_error,
|
||||
Strategy strategy) {
|
||||
bool Recovery::RecoverIfPossible(Database* database,
|
||||
int extended_error,
|
||||
Strategy strategy) {
|
||||
if (!ShouldAttemptRecovery(database, extended_error)) {
|
||||
return false;
|
||||
}
|
||||
@ -69,7 +68,7 @@ bool BuiltInRecovery::RecoverIfPossible(Database* database,
|
||||
// re-entry.
|
||||
database->reset_error_callback();
|
||||
|
||||
auto result = BuiltInRecovery::RecoverDatabase(database, strategy);
|
||||
auto result = Recovery::RecoverDatabase(database, strategy);
|
||||
if (!IsSqliteSuccessCode(result)) {
|
||||
DLOG(ERROR) << "Database recovery failed with result code: " << result;
|
||||
}
|
||||
@ -77,7 +76,7 @@ bool BuiltInRecovery::RecoverIfPossible(Database* database,
|
||||
return true;
|
||||
}
|
||||
|
||||
BuiltInRecovery::BuiltInRecovery(Database* database, Strategy strategy)
|
||||
Recovery::Recovery(Database* database, Strategy strategy)
|
||||
: strategy_(strategy),
|
||||
db_(database),
|
||||
recover_db_(sql::DatabaseOptions{
|
||||
@ -107,7 +106,7 @@ BuiltInRecovery::BuiltInRecovery(Database* database, Strategy strategy)
|
||||
db_->RollbackAllTransactions();
|
||||
}
|
||||
|
||||
BuiltInRecovery::~BuiltInRecovery() {
|
||||
Recovery::~Recovery() {
|
||||
// Recovery result must be set before we reach this point.
|
||||
CHECK_NE(result_, Result::kUnknown);
|
||||
|
||||
@ -143,15 +142,15 @@ BuiltInRecovery::~BuiltInRecovery() {
|
||||
sql::Database::Delete(recovery_database_path_);
|
||||
}
|
||||
|
||||
void BuiltInRecovery::SetRecoverySucceeded() {
|
||||
void Recovery::SetRecoverySucceeded() {
|
||||
// Recovery result must only be set once.
|
||||
CHECK_EQ(result_, Result::kUnknown);
|
||||
|
||||
result_ = Result::kSuccess;
|
||||
}
|
||||
|
||||
void BuiltInRecovery::SetRecoveryFailed(Result failure_result,
|
||||
SqliteResultCode result_code) {
|
||||
void Recovery::SetRecoveryFailed(Result failure_result,
|
||||
SqliteResultCode result_code) {
|
||||
// Recovery result must only be set once.
|
||||
CHECK_EQ(result_, Result::kUnknown);
|
||||
|
||||
@ -175,7 +174,7 @@ void BuiltInRecovery::SetRecoveryFailed(Result failure_result,
|
||||
sqlite_result_code_ = result_code;
|
||||
}
|
||||
|
||||
SqliteResultCode BuiltInRecovery::RecoverAndReplaceDatabase() {
|
||||
SqliteResultCode Recovery::RecoverAndReplaceDatabase() {
|
||||
auto sqlite_result_code = AttemptToRecoverDatabaseToBackup();
|
||||
if (sqlite_result_code != SqliteResultCode::kOk) {
|
||||
return sqlite_result_code;
|
||||
@ -202,7 +201,7 @@ SqliteResultCode BuiltInRecovery::RecoverAndReplaceDatabase() {
|
||||
return ReplaceOriginalWithRecoveredDb();
|
||||
}
|
||||
|
||||
SqliteResultCode BuiltInRecovery::AttemptToRecoverDatabaseToBackup() {
|
||||
SqliteResultCode Recovery::AttemptToRecoverDatabaseToBackup() {
|
||||
CHECK(db_->is_open());
|
||||
CHECK(!recover_db_.is_open());
|
||||
|
||||
@ -274,7 +273,7 @@ SqliteResultCode BuiltInRecovery::AttemptToRecoverDatabaseToBackup() {
|
||||
return sqlite_result_code;
|
||||
}
|
||||
|
||||
SqliteResultCode BuiltInRecovery::ReplaceOriginalWithRecoveredDb() {
|
||||
SqliteResultCode Recovery::ReplaceOriginalWithRecoveredDb() {
|
||||
CHECK(db_->is_open());
|
||||
CHECK(recover_db_.is_open());
|
||||
|
||||
@ -342,7 +341,7 @@ SqliteResultCode BuiltInRecovery::ReplaceOriginalWithRecoveredDb() {
|
||||
return SqliteResultCode::kOk;
|
||||
}
|
||||
|
||||
bool BuiltInRecovery::RecoveredDbHasValidMetaTable() {
|
||||
bool Recovery::RecoveredDbHasValidMetaTable() {
|
||||
CHECK(recover_db_.is_open());
|
||||
|
||||
if (!MetaTable::DoesTableExist(&recover_db_)) {
|
||||
|
@ -32,7 +32,7 @@ namespace sql {
|
||||
// recovery should not be attempted on WAL databases for now.
|
||||
//
|
||||
// Uses SQLite's recovery extension: https://www.sqlite.org/recovery.html
|
||||
class COMPONENT_EXPORT(SQL) BuiltInRecovery {
|
||||
class COMPONENT_EXPORT(SQL) Recovery {
|
||||
public:
|
||||
enum class Strategy {
|
||||
// Razes the database if it could not be recovered.
|
||||
@ -137,9 +137,9 @@ class COMPONENT_EXPORT(SQL) BuiltInRecovery {
|
||||
// Recommended usage from within a database error callback:
|
||||
//
|
||||
// // Attempt to recover the database, if recovery is possible.
|
||||
// if (sql::BuiltInRecovery::RecoverIfPossible(
|
||||
// if (sql::Recovery::RecoverIfPossible(
|
||||
// &db, extended_error,
|
||||
// sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
// sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze)) {
|
||||
// // Recovery was attempted. The database handle has been poisoned and the
|
||||
// // error callback has been reset.
|
||||
//
|
||||
@ -150,12 +150,12 @@ class COMPONENT_EXPORT(SQL) BuiltInRecovery {
|
||||
int extended_error,
|
||||
Strategy strategy);
|
||||
|
||||
BuiltInRecovery(const BuiltInRecovery&) = delete;
|
||||
BuiltInRecovery& operator=(const BuiltInRecovery&) = delete;
|
||||
Recovery(const Recovery&) = delete;
|
||||
Recovery& operator=(const Recovery&) = delete;
|
||||
|
||||
private:
|
||||
BuiltInRecovery(Database* database, Strategy strategy);
|
||||
~BuiltInRecovery();
|
||||
Recovery(Database* database, Strategy strategy);
|
||||
~Recovery();
|
||||
|
||||
// Entry point.
|
||||
SqliteResultCode RecoverAndReplaceDatabase();
|
||||
|
@ -47,28 +47,27 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
bool should_attempt_recovery = false;
|
||||
database.set_error_callback(
|
||||
base::BindLambdaForTesting([&](int extended_error, sql::Statement*) {
|
||||
should_attempt_recovery = sql::BuiltInRecovery::ShouldAttemptRecovery(
|
||||
&database, extended_error);
|
||||
should_attempt_recovery =
|
||||
sql::Recovery::ShouldAttemptRecovery(&database, extended_error);
|
||||
}));
|
||||
std::ignore = database.Open(env.data_file_path());
|
||||
|
||||
// Select a recovery strategy pseudorandomly.
|
||||
auto strategy =
|
||||
size % 2 == 0
|
||||
? sql::BuiltInRecovery::Strategy::kRecoverOrRaze
|
||||
: sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze;
|
||||
auto strategy = size % 2 == 0
|
||||
? sql::Recovery::Strategy::kRecoverOrRaze
|
||||
: sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze;
|
||||
|
||||
// Ensure that we remember to update the fuzzer if more strategies are added.
|
||||
switch (strategy) {
|
||||
case sql::BuiltInRecovery::Strategy::kRecoverOrRaze:
|
||||
case sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze:
|
||||
case sql::Recovery::Strategy::kRecoverOrRaze:
|
||||
case sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze:
|
||||
break;
|
||||
}
|
||||
|
||||
// Attempt recovery.
|
||||
if (should_attempt_recovery) {
|
||||
database.reset_error_callback();
|
||||
std::ignore = sql::BuiltInRecovery::RecoverDatabase(&database, strategy);
|
||||
std::ignore = sql::Recovery::RecoverDatabase(&database, strategy);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -116,28 +116,26 @@ INSTANTIATE_TEST_SUITE_P(All, SqlRecoveryTest, testing::Bool());
|
||||
|
||||
TEST_P(SqlRecoveryTest, ShouldAttemptRecovery) {
|
||||
// Attempt to recover from corruption.
|
||||
ASSERT_TRUE(BuiltInRecovery::ShouldAttemptRecovery(&db_, SQLITE_CORRUPT));
|
||||
ASSERT_TRUE(Recovery::ShouldAttemptRecovery(&db_, SQLITE_CORRUPT));
|
||||
|
||||
// Do not attempt to recover from transient errors.
|
||||
EXPECT_FALSE(BuiltInRecovery::ShouldAttemptRecovery(&db_, SQLITE_BUSY));
|
||||
EXPECT_FALSE(Recovery::ShouldAttemptRecovery(&db_, SQLITE_BUSY));
|
||||
|
||||
// Do not attempt to recover null databases.
|
||||
EXPECT_FALSE(BuiltInRecovery::ShouldAttemptRecovery(nullptr, SQLITE_CORRUPT));
|
||||
EXPECT_FALSE(Recovery::ShouldAttemptRecovery(nullptr, SQLITE_CORRUPT));
|
||||
|
||||
// Do not attempt to recover closed databases.
|
||||
Database invalid_db;
|
||||
EXPECT_FALSE(
|
||||
BuiltInRecovery::ShouldAttemptRecovery(&invalid_db, SQLITE_CORRUPT));
|
||||
EXPECT_FALSE(Recovery::ShouldAttemptRecovery(&invalid_db, SQLITE_CORRUPT));
|
||||
|
||||
// Do not attempt to recover in-memory databases.
|
||||
ASSERT_TRUE(invalid_db.OpenInMemory());
|
||||
EXPECT_FALSE(
|
||||
BuiltInRecovery::ShouldAttemptRecovery(&invalid_db, SQLITE_CORRUPT));
|
||||
EXPECT_FALSE(Recovery::ShouldAttemptRecovery(&invalid_db, SQLITE_CORRUPT));
|
||||
|
||||
// Return true for databases which have an error callback set, even though
|
||||
// the error callback should be reset before recovery is attempted.
|
||||
db_.set_error_callback(base::DoNothing());
|
||||
EXPECT_TRUE(BuiltInRecovery::ShouldAttemptRecovery(&db_, SQLITE_CORRUPT));
|
||||
EXPECT_TRUE(Recovery::ShouldAttemptRecovery(&db_, SQLITE_CORRUPT));
|
||||
}
|
||||
|
||||
TEST_P(SqlRecoveryTest, RecoverCorruptIndex) {
|
||||
@ -168,11 +166,11 @@ TEST_P(SqlRecoveryTest, RecoverCorruptIndex) {
|
||||
// Recovery::Begin() does not support a pre-existing error callback.
|
||||
db_.reset_error_callback();
|
||||
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
EXPECT_EQ(
|
||||
Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultHistogramName,
|
||||
BuiltInRecovery::Result::kSuccess,
|
||||
Recovery::Result::kSuccess,
|
||||
/*expected_bucket_count=*/1);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultCodeHistogramName,
|
||||
SqliteLoggedResultCode::kNoError,
|
||||
@ -271,9 +269,9 @@ TEST_P(SqlRecoveryTest, RecoverCorruptTable) {
|
||||
// Recovery::Begin() does not support a pre-existing error callback.
|
||||
db_.reset_error_callback();
|
||||
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
EXPECT_EQ(
|
||||
Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
}));
|
||||
|
||||
// SUM(unindexed) heavily nudges SQLite to use the table instead of the index.
|
||||
@ -305,11 +303,11 @@ TEST_P(SqlRecoveryTest, Meta) {
|
||||
}
|
||||
|
||||
// Test expected case where everything works.
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(
|
||||
&db_, Recovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultHistogramName,
|
||||
BuiltInRecovery::Result::kSuccess,
|
||||
Recovery::Result::kSuccess,
|
||||
/*expected_bucket_count=*/1);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultCodeHistogramName,
|
||||
SqliteLoggedResultCode::kNoError,
|
||||
@ -322,12 +320,12 @@ TEST_P(SqlRecoveryTest, Meta) {
|
||||
// Test version row missing.
|
||||
EXPECT_TRUE(db_.Execute("DELETE FROM meta WHERE key = 'version'"));
|
||||
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(
|
||||
&db_, Recovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
SqliteResultCode::kError);
|
||||
histogram_tester_.ExpectBucketCount(
|
||||
kRecoveryResultHistogramName,
|
||||
BuiltInRecovery::Result::kFailedMetaTableVersionWasInvalid,
|
||||
Recovery::Result::kFailedMetaTableVersionWasInvalid,
|
||||
/*expected_count=*/1);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultCodeHistogramName,
|
||||
SqliteLoggedResultCode::kNoError,
|
||||
@ -337,12 +335,12 @@ TEST_P(SqlRecoveryTest, Meta) {
|
||||
// Test meta table missing.
|
||||
ASSERT_FALSE(db_.DoesTableExist("meta"));
|
||||
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(
|
||||
&db_, Recovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
SqliteResultCode::kError);
|
||||
histogram_tester_.ExpectBucketCount(
|
||||
kRecoveryResultHistogramName,
|
||||
BuiltInRecovery::Result::kFailedMetaTableDoesNotExist,
|
||||
Recovery::Result::kFailedMetaTableDoesNotExist,
|
||||
/*expected_count=*/1);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultCodeHistogramName,
|
||||
SqliteLoggedResultCode::kNoError,
|
||||
@ -363,8 +361,7 @@ TEST_P(SqlRecoveryTest, AutoRecoverTable) {
|
||||
static const char kXSql[] = "SELECT * FROM x ORDER BY 1";
|
||||
const std::string orig_data(ExecuteWithResults(&db_, kXSql, "|", "\n"));
|
||||
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
|
||||
// Since the database was not corrupt, the entire schema and all
|
||||
@ -374,8 +371,7 @@ TEST_P(SqlRecoveryTest, AutoRecoverTable) {
|
||||
ASSERT_EQ(orig_data, ExecuteWithResults(&db_, kXSql, "|", "\n"));
|
||||
|
||||
// Recovery succeeds silently, since there's nothing to do.
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
}
|
||||
|
||||
@ -405,8 +401,7 @@ TEST_P(SqlRecoveryTest, AutoRecoverTableWithDefault) {
|
||||
|
||||
std::string final_schema(orig_schema);
|
||||
std::string final_data(orig_data);
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
|
||||
// Since the database was not corrupt, the entire schema and all
|
||||
@ -431,8 +426,7 @@ TEST_P(SqlRecoveryTest, AutoRecoverTableWithRowid) {
|
||||
static const char kXSql[] = "SELECT * FROM x ORDER BY 1";
|
||||
const std::string orig_data(ExecuteWithResults(&db_, kXSql, "|", "\n"));
|
||||
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
|
||||
// Since the database was not corrupt, the entire schema and all
|
||||
@ -516,9 +510,9 @@ void TestRecoverDatabase(Database& db,
|
||||
|
||||
TEST_P(SqlRecoveryTest, RecoverDatabase) {
|
||||
auto run_recovery = base::BindLambdaForTesting([&]() {
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
EXPECT_EQ(
|
||||
Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
});
|
||||
|
||||
TestRecoverDatabase(db_, db_path_, /*with_meta=*/false,
|
||||
@ -527,10 +521,9 @@ TEST_P(SqlRecoveryTest, RecoverDatabase) {
|
||||
|
||||
TEST_P(SqlRecoveryTest, RecoverDatabaseMeta) {
|
||||
auto run_recovery = base::BindLambdaForTesting([&]() {
|
||||
EXPECT_EQ(
|
||||
BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(
|
||||
&db_, Recovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
});
|
||||
|
||||
TestRecoverDatabase(db_, db_path_, /*with_meta=*/true,
|
||||
@ -539,8 +532,8 @@ TEST_P(SqlRecoveryTest, RecoverDatabaseMeta) {
|
||||
|
||||
TEST_P(SqlRecoveryTest, RecoverIfPossible) {
|
||||
auto run_recovery = base::BindLambdaForTesting([&]() {
|
||||
EXPECT_TRUE(BuiltInRecovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT, BuiltInRecovery::Strategy::kRecoverOrRaze));
|
||||
EXPECT_TRUE(Recovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT, Recovery::Strategy::kRecoverOrRaze));
|
||||
});
|
||||
|
||||
TestRecoverDatabase(db_, db_path_, /*with_meta=*/false,
|
||||
@ -549,9 +542,9 @@ TEST_P(SqlRecoveryTest, RecoverIfPossible) {
|
||||
|
||||
TEST_P(SqlRecoveryTest, RecoverIfPossibleMeta) {
|
||||
auto run_recovery = base::BindLambdaForTesting([&]() {
|
||||
EXPECT_TRUE(BuiltInRecovery::RecoverIfPossible(
|
||||
EXPECT_TRUE(Recovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT,
|
||||
BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze));
|
||||
Recovery::Strategy::kRecoverWithMetaVersionOrRaze));
|
||||
});
|
||||
|
||||
TestRecoverDatabase(db_, db_path_, /*with_meta=*/true,
|
||||
@ -562,9 +555,9 @@ TEST_P(SqlRecoveryTest, RecoverIfPossibleWithoutErrorCallback) {
|
||||
auto run_recovery = base::BindLambdaForTesting([&]() {
|
||||
// `RecoverIfPossible()` should not set an error callback.
|
||||
EXPECT_FALSE(db_.has_error_callback());
|
||||
bool recovery_was_attempted = BuiltInRecovery::RecoverIfPossible(
|
||||
bool recovery_was_attempted = Recovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT,
|
||||
BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze);
|
||||
Recovery::Strategy::kRecoverWithMetaVersionOrRaze);
|
||||
EXPECT_TRUE(recovery_was_attempted);
|
||||
EXPECT_FALSE(db_.has_error_callback());
|
||||
});
|
||||
@ -578,9 +571,9 @@ TEST_P(SqlRecoveryTest, RecoverIfPossibleWithErrorCallback) {
|
||||
db_.set_error_callback(base::DoNothing());
|
||||
// The error callback should be reset during `RecoverIfPossible()` if
|
||||
// recovery was attempted.
|
||||
bool recovery_was_attempted = BuiltInRecovery::RecoverIfPossible(
|
||||
bool recovery_was_attempted = Recovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT,
|
||||
BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze);
|
||||
Recovery::Strategy::kRecoverWithMetaVersionOrRaze);
|
||||
EXPECT_TRUE(recovery_was_attempted);
|
||||
EXPECT_NE(db_.has_error_callback(), recovery_was_attempted);
|
||||
});
|
||||
@ -594,8 +587,8 @@ TEST_P(SqlRecoveryTest, RecoverIfPossibleWithClosedDatabase) {
|
||||
// Recovery should not be attempted on a closed database.
|
||||
db_.Close();
|
||||
|
||||
EXPECT_FALSE(BuiltInRecovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT, BuiltInRecovery::Strategy::kRecoverOrRaze));
|
||||
EXPECT_FALSE(Recovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT, Recovery::Strategy::kRecoverOrRaze));
|
||||
});
|
||||
|
||||
TestRecoverDatabase(db_, db_path_, /*with_meta=*/false,
|
||||
@ -604,8 +597,8 @@ TEST_P(SqlRecoveryTest, RecoverIfPossibleWithClosedDatabase) {
|
||||
|
||||
TEST_P(SqlRecoveryTest, RecoverIfPossibleWithPerDatabaseUma) {
|
||||
auto run_recovery = base::BindLambdaForTesting([&]() {
|
||||
EXPECT_TRUE(BuiltInRecovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT, BuiltInRecovery::Strategy::kRecoverOrRaze));
|
||||
EXPECT_TRUE(Recovery::RecoverIfPossible(
|
||||
&db_, SQLITE_CORRUPT, Recovery::Strategy::kRecoverOrRaze));
|
||||
});
|
||||
|
||||
TestRecoverDatabase(db_, db_path_, /*with_meta=*/false,
|
||||
@ -613,7 +606,7 @@ TEST_P(SqlRecoveryTest, RecoverIfPossibleWithPerDatabaseUma) {
|
||||
|
||||
// Log to the overall histograms.
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultHistogramName,
|
||||
BuiltInRecovery::Result::kSuccess,
|
||||
Recovery::Result::kSuccess,
|
||||
/*expected_bucket_count=*/1);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultCodeHistogramName,
|
||||
SqliteLoggedResultCode::kNoError,
|
||||
@ -621,7 +614,7 @@ TEST_P(SqlRecoveryTest, RecoverIfPossibleWithPerDatabaseUma) {
|
||||
// And the histograms for this specific feature.
|
||||
histogram_tester_.ExpectUniqueSample(
|
||||
base::StrCat({kRecoveryResultHistogramName, ".MyFeatureDatabase"}),
|
||||
BuiltInRecovery::Result::kSuccess,
|
||||
Recovery::Result::kSuccess,
|
||||
/*expected_bucket_count=*/1);
|
||||
histogram_tester_.ExpectUniqueSample(
|
||||
base::StrCat({kRecoveryResultCodeHistogramName, ".MyFeatureDatabase"}),
|
||||
@ -665,8 +658,7 @@ TEST_P(SqlRecoveryTest, RecoverDatabaseWithView) {
|
||||
// Database handle is valid before recovery, poisoned after.
|
||||
static constexpr char kTrivialSql[] = "SELECT COUNT(*) FROM sqlite_schema";
|
||||
EXPECT_TRUE(db.IsSQLValid(kTrivialSql));
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(&db, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
EXPECT_FALSE(db.IsSQLValid(kTrivialSql));
|
||||
|
||||
@ -694,13 +686,12 @@ TEST_P(SqlRecoveryTest, RecoverDatabaseDelete) {
|
||||
ASSERT_FALSE(Reopen());
|
||||
|
||||
// This should "recover" the database by making it valid, but empty.
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kNotADatabase);
|
||||
histogram_tester_.ExpectUniqueSample(
|
||||
kRecoveryResultHistogramName,
|
||||
BuiltInRecovery::Result::kFailedRecoveryRun,
|
||||
/*expected_bucket_count=*/1);
|
||||
EXPECT_EQ(
|
||||
Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kNotADatabase);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultHistogramName,
|
||||
Recovery::Result::kFailedRecoveryRun,
|
||||
/*expected_bucket_count=*/1);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultCodeHistogramName,
|
||||
SqliteLoggedResultCode::kNotADatabase,
|
||||
/*expected_bucket_count=*/1);
|
||||
@ -745,8 +736,7 @@ TEST_P(SqlRecoveryTest, BeginRecoverDatabase) {
|
||||
}
|
||||
|
||||
// Run recovery code, then commit. The index is recovered.
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
db_.Close();
|
||||
ASSERT_TRUE(Reopen());
|
||||
@ -771,13 +761,12 @@ TEST_P(SqlRecoveryTest, AttachFailure) {
|
||||
ASSERT_FALSE(Reopen());
|
||||
|
||||
// Begin() should fail.
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kNotADatabase);
|
||||
histogram_tester_.ExpectUniqueSample(
|
||||
kRecoveryResultHistogramName,
|
||||
BuiltInRecovery::Result::kFailedRecoveryRun,
|
||||
/*expected_bucket_count=*/1);
|
||||
EXPECT_EQ(
|
||||
Recovery::RecoverDatabase(&db_, Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kNotADatabase);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultHistogramName,
|
||||
Recovery::Result::kFailedRecoveryRun,
|
||||
/*expected_bucket_count=*/1);
|
||||
histogram_tester_.ExpectUniqueSample(kRecoveryResultCodeHistogramName,
|
||||
SqliteLoggedResultCode::kNotADatabase,
|
||||
/*expected_bucket_count=*/1);
|
||||
@ -816,8 +805,8 @@ void TestPageSize(const base::FilePath& db_prefix,
|
||||
ASSERT_TRUE(recover_db.Open(db_path));
|
||||
// Recovery will use the page size set in the database object, which may not
|
||||
// match the file's page size.
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&recover_db, BuiltInRecovery::Strategy::kRecoverOrRaze),
|
||||
EXPECT_EQ(Recovery::RecoverDatabase(&recover_db,
|
||||
Recovery::Strategy::kRecoverOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
|
||||
// Recovery poisoned the handle, must re-open.
|
||||
@ -864,15 +853,15 @@ TEST_P(SqlRecoveryTest, PageSize) {
|
||||
TEST_P(SqlRecoveryTest, CannotRecoverClosedDb) {
|
||||
db_.Close();
|
||||
|
||||
EXPECT_CHECK_DEATH(std::ignore = BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze));
|
||||
EXPECT_CHECK_DEATH(std::ignore = Recovery::RecoverDatabase(
|
||||
&db_, Recovery::Strategy::kRecoverOrRaze));
|
||||
}
|
||||
|
||||
TEST_P(SqlRecoveryTest, CannotRecoverDbWithErrorCallback) {
|
||||
db_.set_error_callback(base::DoNothing());
|
||||
|
||||
EXPECT_CHECK_DEATH(std::ignore = BuiltInRecovery::RecoverDatabase(
|
||||
&db_, BuiltInRecovery::Strategy::kRecoverOrRaze));
|
||||
EXPECT_CHECK_DEATH(std::ignore = Recovery::RecoverDatabase(
|
||||
&db_, Recovery::Strategy::kRecoverOrRaze));
|
||||
}
|
||||
|
||||
// TODO(https://crbug.com/1255316): Ideally this would be a
|
||||
@ -880,8 +869,8 @@ TEST_P(SqlRecoveryTest, CannotRecoverDbWithErrorCallback) {
|
||||
// that it is passed a non-null database pointer and will instead likely result
|
||||
// in unexpected behavior or crashes.
|
||||
TEST_P(SqlRecoveryTest, CannotRecoverNullDb) {
|
||||
EXPECT_CHECK_DEATH(std::ignore = BuiltInRecovery::RecoverDatabase(
|
||||
nullptr, BuiltInRecovery::Strategy::kRecoverOrRaze));
|
||||
EXPECT_CHECK_DEATH(std::ignore = Recovery::RecoverDatabase(
|
||||
nullptr, Recovery::Strategy::kRecoverOrRaze));
|
||||
}
|
||||
|
||||
// TODO(https://crbug.com/1255316): Ideally this would be a
|
||||
@ -892,9 +881,8 @@ TEST_P(SqlRecoveryTest, CannotRecoverInMemoryDb) {
|
||||
Database in_memory_db;
|
||||
ASSERT_TRUE(in_memory_db.OpenInMemory());
|
||||
|
||||
EXPECT_CHECK_DEATH(
|
||||
std::ignore = BuiltInRecovery::RecoverDatabase(
|
||||
&in_memory_db, BuiltInRecovery::Strategy::kRecoverOrRaze));
|
||||
EXPECT_CHECK_DEATH(std::ignore = Recovery::RecoverDatabase(
|
||||
&in_memory_db, Recovery::Strategy::kRecoverOrRaze));
|
||||
}
|
||||
|
||||
// This test mimics the case where a database that was using WAL mode crashed,
|
||||
@ -925,10 +913,10 @@ TEST_P(SqlRecoveryTest, RecoverFormerlyWalDbAfterCrash) {
|
||||
ASSERT_TRUE(non_wal_db.Open(wal_db_path));
|
||||
|
||||
auto run_recovery = base::BindLambdaForTesting([&]() {
|
||||
EXPECT_EQ(BuiltInRecovery::RecoverDatabase(
|
||||
&non_wal_db,
|
||||
BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
EXPECT_EQ(
|
||||
Recovery::RecoverDatabase(
|
||||
&non_wal_db, Recovery::Strategy::kRecoverWithMetaVersionOrRaze),
|
||||
SqliteResultCode::kOk);
|
||||
});
|
||||
|
||||
TestRecoverDatabase(non_wal_db, wal_db_path, /*with_meta=*/true,
|
||||
|
@ -807,9 +807,9 @@ QuotaError QuotaDatabase::SetIsBootstrapped(bool bootstrap_flag) {
|
||||
bool QuotaDatabase::RecoverOrRaze(int error_code) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
|
||||
std::ignore = sql::BuiltInRecovery::RecoverIfPossible(
|
||||
std::ignore = sql::Recovery::RecoverIfPossible(
|
||||
db_.get(), error_code,
|
||||
sql::BuiltInRecovery::Strategy::kRecoverWithMetaVersionOrRaze);
|
||||
sql::Recovery::Strategy::kRecoverWithMetaVersionOrRaze);
|
||||
|
||||
db_.reset();
|
||||
EnsureOpened();
|
||||
|
@ -230,8 +230,8 @@ chromium-metrics-reviews@google.com.
|
||||
|
||||
<enum name="SqlRecoveryResult">
|
||||
<summary>
|
||||
Outcome of attempting to recover a database with sql::BuiltInRecovery. See
|
||||
sql::BuiltInRecovery::Result for descriptions.
|
||||
Outcome of attempting to recover a database with sql::Recovery. See
|
||||
sql::Recovery::Result for descriptions.
|
||||
</summary>
|
||||
<int value="0" label="kUnknown"/>
|
||||
<int value="1" label="kSuccess"/>
|
||||
|
@ -272,7 +272,7 @@ chromium-metrics-reviews@google.com.
|
||||
<owner>asully@chromium.org</owner>
|
||||
<owner>chrome-owp-storage@google.com</owner>
|
||||
<summary>
|
||||
Outcome of attempting to recover a database with sql::BuiltInRecovery.
|
||||
Outcome of attempting to recover a database with sql::Recovery.
|
||||
</summary>
|
||||
</histogram>
|
||||
|
||||
@ -282,7 +282,7 @@ chromium-metrics-reviews@google.com.
|
||||
<owner>chrome-owp-storage@google.com</owner>
|
||||
<summary>
|
||||
Outcome of attempting to recover the {DatabaseTag} database with
|
||||
sql::BuiltInRecovery.
|
||||
sql::Recovery.
|
||||
</summary>
|
||||
<token key="DatabaseTag" variants="DatabaseTag"/>
|
||||
</histogram>
|
||||
@ -292,11 +292,11 @@ chromium-metrics-reviews@google.com.
|
||||
<owner>asully@chromium.org</owner>
|
||||
<owner>chrome-owp-storage@google.com</owner>
|
||||
<summary>
|
||||
SQLite result code from attempting to recover a database with
|
||||
sql::BuiltInRecovery. Note that kNoError does not necessarily indicate that
|
||||
recovery succeeded (see Sql.Recovery.Result for that information), since not
|
||||
all recoveries fail due to SQLite errors (e.g. if a version number could not
|
||||
be read from the meta table).
|
||||
SQLite result code from attempting to recover a database with sql::Recovery.
|
||||
Note that kNoError does not necessarily indicate that recovery succeeded
|
||||
(see Sql.Recovery.Result for that information), since not all recoveries
|
||||
fail due to SQLite errors (e.g. if a version number could not be read from
|
||||
the meta table).
|
||||
</summary>
|
||||
</histogram>
|
||||
|
||||
@ -306,10 +306,10 @@ chromium-metrics-reviews@google.com.
|
||||
<owner>chrome-owp-storage@google.com</owner>
|
||||
<summary>
|
||||
SQLite result code from attempting to recover the {DatabaseTag} database
|
||||
with sql::BuiltInRecovery. Note that kNoError does not necessarily indicate
|
||||
that recovery succeeded (see Sql.Recovery.Result for that information),
|
||||
since not all recoveries fail due to SQLite errors (e.g. if a version number
|
||||
could not be read from the meta table).
|
||||
with sql::Recovery. Note that kNoError does not necessarily indicate that
|
||||
recovery succeeded (see Sql.Recovery.Result for that information), since not
|
||||
all recoveries fail due to SQLite errors (e.g. if a version number could not
|
||||
be read from the meta table).
|
||||
</summary>
|
||||
<token key="DatabaseTag" variants="DatabaseTag"/>
|
||||
</histogram>
|
||||
|
Reference in New Issue
Block a user