Commit 63188114 authored by shess's avatar shess Committed by Commit bot

[sql] Track SQLite error codes from sql::Recovery ATTACH.

The major reason for sql::Recover::Begin() to fail is in the statement
attaching the original database to the recovery database.  I believe
this is because of SQLITE_NOTADB.  This is to verify that hypothesis.
If the hypothesis is true, then the best course of action is to Raze()
the database, as SQLITE_NOTADB means that some or all of the SQLite
header data appears to be garbage.

BUG=597785
R=michaeln@chromium.org

Review-Url: https://codereview.chromium.org/2274883003
Cr-Commit-Position: refs/heads/master@{#414885}
parent c3308d79
......@@ -240,6 +240,8 @@ bool Recovery::Init(const base::FilePath& db_path) {
if (!recover_db_.AttachDatabase(db_path, "corrupt")) {
RecordRecoveryEvent(RECOVERY_FAILED_ATTACH);
UMA_HISTOGRAM_SPARSE_SLOWLY("Sqlite.RecoveryAttachError",
recover_db_.GetErrorCode());
return false;
}
......
......@@ -16,6 +16,7 @@
#include "base/files/scoped_temp_dir.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/histogram_tester.h"
#include "sql/connection.h"
#include "sql/meta_table.h"
#include "sql/statement.h"
......@@ -832,4 +833,38 @@ TEST_F(SQLRecoveryTest, RecoverDatabase) {
EXPECT_EQ("trailer", ExecuteWithResults(&db(), kVSql, "|", "\n"));
}
// Test histograms recorded when the invalid database cannot be attached.
TEST_F(SQLRecoveryTest, AttachFailure) {
// Create a valid database, then write junk over the header. This should lead
// to SQLITE_NOTADB, which will cause ATTACH to fail.
ASSERT_TRUE(db().Execute("CREATE TABLE x (t TEXT)"));
ASSERT_TRUE(db().Execute("INSERT INTO x VALUES ('This is a test')"));
db().Close();
WriteJunkToDatabase(SQLTestBase::TYPE_OVERWRITE);
const char kEventHistogramName[] = "Sqlite.RecoveryEvents";
const int kEventEnum = 5; // RECOVERY_FAILED_ATTACH
const char kErrorHistogramName[] = "Sqlite.RecoveryAttachError";
base::HistogramTester tester;
{
sql::test::ScopedErrorExpecter expecter;
expecter.ExpectError(SQLITE_NOTADB);
// Reopen() here because it will see SQLITE_NOTADB.
ASSERT_TRUE(Reopen());
// Begin() should fail.
std::unique_ptr<sql::Recovery>
recovery = sql::Recovery::Begin(&db(), db_path());
ASSERT_FALSE(recovery.get());
ASSERT_TRUE(expecter.SawExpectedErrors());
}
// Verify that the failure was in the right place with the expected code.
tester.ExpectBucketCount(kEventHistogramName, kEventEnum, 1);
tester.ExpectBucketCount(kErrorHistogramName, SQLITE_NOTADB, 1);
}
} // namespace
......@@ -57060,6 +57060,13 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries.
<summary>Errors truncating database for Raze().</summary>
</histogram>
<histogram name="Sqlite.RecoveryAttachError" enum="SqliteErrorCode">
<owner>shess@chromium.org</owner>
<summary>
SQLite error code from failed ATTACH in sql::Recovery::Init().
</summary>
</histogram>
<histogram name="Sqlite.RecoveryEvents" enum="SqliteRecoveryEventEnum">
<owner>shess@chromium.org</owner>
<summary>
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment