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

Side by Side Diff: sql/recovery.cc

Issue 2710823005: [sql] RecoverDatabase() deletes SQLITE_NOTADB databases. (Closed)
Patch Set: Histograms Created 3 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
« no previous file with comments | « sql/recovery.h ('k') | sql/recovery_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "sql/recovery.h" 5 #include "sql/recovery.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/format_macros.h" 10 #include "base/format_macros.h"
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
101 101
102 // Failed to recover an individual table. 102 // Failed to recover an individual table.
103 RECOVERY_FAILED_AUTORECOVERDB_TABLE, 103 RECOVERY_FAILED_AUTORECOVERDB_TABLE,
104 104
105 // Failed to recover [sqlite_sequence] table. 105 // Failed to recover [sqlite_sequence] table.
106 RECOVERY_FAILED_AUTORECOVERDB_SEQUENCE, 106 RECOVERY_FAILED_AUTORECOVERDB_SEQUENCE,
107 107
108 // Failed to recover triggers or views or virtual tables. 108 // Failed to recover triggers or views or virtual tables.
109 RECOVERY_FAILED_AUTORECOVERDB_AUX, 109 RECOVERY_FAILED_AUTORECOVERDB_AUX,
110 110
111 // After SQLITE_NOTADB failure setting up for recovery, Delete() failed.
112 RECOVERY_FAILED_AUTORECOVERDB_NOTADB_DELETE,
113
114 // After SQLITE_NOTADB failure setting up for recovery, Delete() succeeded
115 // then Open() failed.
116 RECOVERY_FAILED_AUTORECOVERDB_NOTADB_REOPEN,
117
118 // After SQLITE_NOTADB failure setting up for recovery, Delete() and Open()
119 // succeeded, then querying the database failed.
pwnall 2017/02/27 22:28:33 Based on some of the comments below, do you need a
Scott Hess - ex-Googler 2017/02/27 23:39:39 I don't know. Substantially all of the FAILED eve
120 RECOVERY_FAILED_AUTORECOVERDB_NOTADB_QUERY,
121
122 // After SQLITE_NOTADB failure setting up for recovery, the database was
123 // successfully deleted.
124 RECOVERY_SUCCESS_AUTORECOVERDB_NOTADB_DELETE,
125
111 // Always keep this at the end. 126 // Always keep this at the end.
112 RECOVERY_EVENT_MAX, 127 RECOVERY_EVENT_MAX,
113 }; 128 };
114 129
115 void RecordRecoveryEvent(RecoveryEventType recovery_event) { 130 void RecordRecoveryEvent(RecoveryEventType recovery_event) {
116 UMA_HISTOGRAM_ENUMERATION("Sqlite.RecoveryEvents", 131 UMA_HISTOGRAM_ENUMERATION("Sqlite.RecoveryEvents",
117 recovery_event, RECOVERY_EVENT_MAX); 132 recovery_event, RECOVERY_EVENT_MAX);
118 } 133 }
119 134
120 } // namespace 135 } // namespace
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
581 // TODO(shess): This conservatively uses Rollback() rather than Unrecoverable(). 596 // TODO(shess): This conservatively uses Rollback() rather than Unrecoverable().
582 // With Rollback(), it is expected that the database will continue to generate 597 // With Rollback(), it is expected that the database will continue to generate
583 // errors. Change the failure cases to Unrecoverable() if/when histogram 598 // errors. Change the failure cases to Unrecoverable() if/when histogram
584 // results indicate that everything is working reasonably. 599 // results indicate that everything is working reasonably.
585 // 600 //
586 // static 601 // static
587 void Recovery::RecoverDatabase(Connection* db, 602 void Recovery::RecoverDatabase(Connection* db,
588 const base::FilePath& db_path) { 603 const base::FilePath& db_path) {
589 std::unique_ptr<sql::Recovery> recovery = sql::Recovery::Begin(db, db_path); 604 std::unique_ptr<sql::Recovery> recovery = sql::Recovery::Begin(db, db_path);
590 if (!recovery) { 605 if (!recovery) {
591 // TODO(shess): If recovery can't even get started, Raze() or Delete(). 606 // |db| was poisoned by Begin(). Probe for SQLITE_NOTADB when attaching to
pwnall 2017/02/27 22:28:33 Is it possible to DCHECK that db was poisoned?
Scott Hess - ex-Googler 2017/02/27 23:39:39 The comment was only there because it's a non-obvi
pwnall 2017/02/27 23:54:51 I'd have been fine with a DCHECK... it's like a co
592 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVERDB_BEGIN); 607 // db_path.
593 db->Poison(); 608 {
609 Connection probe_db;
610 if (!probe_db.OpenInMemory() ||
611 probe_db.AttachDatabase(db_path, "corrupt") ||
612 probe_db.GetErrorCode() != SQLITE_NOTADB) {
613 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVERDB_BEGIN);
614 return;
615 }
616 }
617
618 // The database has invalid data in the SQLite header, so it is almost
619 // certainly not recoverable without manual intervention (and likely not
620 // recoverable _with_ manual intervention). Clear away the broken database.
621 if (!sql::Connection::Delete(db_path)) {
622 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVERDB_NOTADB_DELETE);
623 return;
624 }
625
626 // Probe to see if that worked. These reports should not be possible in a
pwnall 2017/02/27 22:28:33 "that worked" -> "the database got deleted"? (min
Scott Hess - ex-Googler 2017/02/27 23:39:39 Are you familiar with the problem where deleting a
pwnall 2017/02/27 23:54:51 Sorry for being unclear! I understood the problem
Scott Hess - ex-Googler 2017/02/28 01:14:51 Done.
627 // properly-working system.
628 {
629 Connection probe_db;
630 if (!probe_db.Open(db_path)) {
631 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVERDB_NOTADB_REOPEN);
632 return;
633 }
634 if (!probe_db.Execute("PRAGMA auto_vacuum")) {
635 RecordRecoveryEvent(RECOVERY_FAILED_AUTORECOVERDB_NOTADB_QUERY);
636 return;
637 }
638 }
639
640 // Recovery could be run on the re-opened database, but there is no point to
641 // that, as there is no schema or data to recover.
642 RecordRecoveryEvent(RECOVERY_SUCCESS_AUTORECOVERDB_NOTADB_DELETE);
594 return; 643 return;
595 } 644 }
596 645
597 #if DCHECK_IS_ON() 646 #if DCHECK_IS_ON()
598 // This code silently fails to recover fts3 virtual tables. At this time no 647 // This code silently fails to recover fts3 virtual tables. At this time no
599 // browser database contain fts3 tables. Just to be safe, complain loudly if 648 // browser database contain fts3 tables. Just to be safe, complain loudly if
600 // the database contains virtual tables. 649 // the database contains virtual tables.
601 // 650 //
602 // fts3 has an [x_segdir] table containing a column [end_block INTEGER]. But 651 // fts3 has an [x_segdir] table containing a column [end_block INTEGER]. But
603 // it actually stores either an integer or a text containing a pair of 652 // it actually stores either an integer or a text containing a pair of
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 // - SQLITE_READONLY - permissions could be fixed. 755 // - SQLITE_READONLY - permissions could be fixed.
707 // - SQLITE_IOERR - rewrite using new blocks. 756 // - SQLITE_IOERR - rewrite using new blocks.
708 // - SQLITE_FULL - recover in memory and rewrite subset of data. 757 // - SQLITE_FULL - recover in memory and rewrite subset of data.
709 758
710 default: 759 default:
711 return false; 760 return false;
712 } 761 }
713 } 762 }
714 763
715 } // namespace sql 764 } // namespace sql
OLDNEW
« no previous file with comments | « sql/recovery.h ('k') | sql/recovery_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698