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

Side by Side Diff: extensions/browser/value_store/leveldb_value_store.cc

Issue 1428843002: LeveldbValueStore: Deleting db when open fails due to corruption. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: base::File::DeleteFile -> base::DeleteFile Created 5 years, 1 month 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "extensions/browser/value_store/leveldb_value_store.h" 5 #include "extensions/browser/value_store/leveldb_value_store.h"
6 6
7 #include "base/files/file_util.h" 7 #include "base/files/file_util.h"
8 #include "base/json/json_reader.h" 8 #include "base/json/json_reader.h"
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/strings/string_util.h" 11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h" 12 #include "base/strings/stringprintf.h"
13 #include "base/strings/sys_string_conversions.h" 13 #include "base/strings/sys_string_conversions.h"
14 #include "content/public/browser/browser_thread.h" 14 #include "content/public/browser/browser_thread.h"
15 #include "extensions/browser/value_store/value_store_util.h" 15 #include "extensions/browser/value_store/value_store_util.h"
16 #include "third_party/leveldatabase/env_chromium.h" 16 #include "third_party/leveldatabase/env_chromium.h"
17 #include "third_party/leveldatabase/src/include/leveldb/iterator.h" 17 #include "third_party/leveldatabase/src/include/leveldb/iterator.h"
18 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 18 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
19 19
20 namespace util = value_store_util; 20 namespace util = value_store_util;
21 using content::BrowserThread; 21 using content::BrowserThread;
22 22
23 namespace { 23 namespace {
24 24
25 const char kInvalidJson[] = "Invalid JSON"; 25 const char kInvalidJson[] = "Invalid JSON";
26 const char kCannotSerialize[] = "Cannot serialize value to JSON"; 26 const char kCannotSerialize[] = "Cannot serialize value to JSON";
27 27
28 // UMA values used when recovering from a corrupted leveldb.
29 // Do not change/delete these values as you will break reporting for older
30 // copies of Chrome. Only add new values to the end.
31 enum LevelDBCorruptionRecoveryValue {
32 LEVELDB_CORRUPTION_RECOVERY_DELETE_SUCCESS = 0,
33 LEVELDB_CORRUPTION_RECOVERY_DELETE_FAILURE,
34 LEVELDB_CORRUPTION_RECOVERY_MAX
35 };
36
28 // Scoped leveldb snapshot which releases the snapshot on destruction. 37 // Scoped leveldb snapshot which releases the snapshot on destruction.
29 class ScopedSnapshot { 38 class ScopedSnapshot {
30 public: 39 public:
31 explicit ScopedSnapshot(leveldb::DB* db) 40 explicit ScopedSnapshot(leveldb::DB* db)
32 : db_(db), snapshot_(db->GetSnapshot()) {} 41 : db_(db), snapshot_(db->GetSnapshot()) {}
33 42
34 ~ScopedSnapshot() { 43 ~ScopedSnapshot() {
35 db_->ReleaseSnapshot(snapshot_); 44 db_->ReleaseSnapshot(snapshot_);
36 } 45 }
37 46
38 const leveldb::Snapshot* get() { 47 const leveldb::Snapshot* get() {
39 return snapshot_; 48 return snapshot_;
40 } 49 }
41 50
42 private: 51 private:
43 leveldb::DB* db_; 52 leveldb::DB* db_;
44 const leveldb::Snapshot* snapshot_; 53 const leveldb::Snapshot* snapshot_;
45 54
46 DISALLOW_COPY_AND_ASSIGN(ScopedSnapshot); 55 DISALLOW_COPY_AND_ASSIGN(ScopedSnapshot);
47 }; 56 };
48 57
49 } // namespace 58 } // namespace
50 59
51 LeveldbValueStore::LeveldbValueStore(const std::string& uma_client_name, 60 LeveldbValueStore::LeveldbValueStore(const std::string& uma_client_name,
52 const base::FilePath& db_path) 61 const base::FilePath& db_path)
53 : db_path_(db_path), open_histogram_(nullptr) { 62 : db_path_(db_path),
63 open_histogram_(nullptr),
64 corruption_recovery_histogram_(nullptr) {
54 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 65 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
55 66
56 // Used in lieu of UMA_HISTOGRAM_ENUMERATION because the histogram name is 67 // Used in lieu of UMA_HISTOGRAM_ENUMERATION because the histogram name is
57 // not a constant. 68 // not a constant.
58 open_histogram_ = base::LinearHistogram::FactoryGet( 69 open_histogram_ = base::LinearHistogram::FactoryGet(
59 "Extensions.Database.Open." + uma_client_name, 1, 70 "Extensions.Database.Open." + uma_client_name, 1,
60 leveldb_env::LEVELDB_STATUS_MAX, leveldb_env::LEVELDB_STATUS_MAX + 1, 71 leveldb_env::LEVELDB_STATUS_MAX, leveldb_env::LEVELDB_STATUS_MAX + 1,
61 base::Histogram::kUmaTargetedHistogramFlag); 72 base::Histogram::kUmaTargetedHistogramFlag);
73 corruption_recovery_histogram_ = base::LinearHistogram::FactoryGet(
74 "Extensions.Database.CorruptionRecovery." + uma_client_name, 1,
75 LEVELDB_CORRUPTION_RECOVERY_MAX, LEVELDB_CORRUPTION_RECOVERY_MAX + 1,
76 base::Histogram::kUmaTargetedHistogramFlag);
62 } 77 }
63 78
64 LeveldbValueStore::~LeveldbValueStore() { 79 LeveldbValueStore::~LeveldbValueStore() {
65 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 80 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
66 81
67 // Delete the database from disk if it's empty (but only if we managed to 82 // Delete the database from disk if it's empty (but only if we managed to
68 // open it!). This is safe on destruction, assuming that we have exclusive 83 // open it!). This is safe on destruction, assuming that we have exclusive
69 // access to the database. 84 // access to the database.
70 if (db_ && IsEmpty()) 85 if (db_ && IsEmpty())
71 DeleteDbFile(); 86 DeleteDbFile();
(...skipping 262 matching lines...) Expand 10 before | Expand all | Expand 10 after
334 leveldb::Options options; 349 leveldb::Options options;
335 options.max_open_files = 0; // Use minimum. 350 options.max_open_files = 0; // Use minimum.
336 options.create_if_missing = true; 351 options.create_if_missing = true;
337 options.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue; 352 options.reuse_logs = leveldb_env::kDefaultLogReuseOptionValue;
338 353
339 leveldb::DB* db = NULL; 354 leveldb::DB* db = NULL;
340 leveldb::Status status = 355 leveldb::Status status =
341 leveldb::DB::Open(options, db_path_.AsUTF8Unsafe(), &db); 356 leveldb::DB::Open(options, db_path_.AsUTF8Unsafe(), &db);
342 if (open_histogram_) 357 if (open_histogram_)
343 open_histogram_->Add(leveldb_env::GetLevelDBStatusUMAValue(status)); 358 open_histogram_->Add(leveldb_env::GetLevelDBStatusUMAValue(status));
359 if (status.IsCorruption()) {
360 // We do not currently recover from corrupted databases, so completely
Devlin 2015/10/29 17:57:26 We do try to recover. See ValueStore::Restore().
cmumford 2015/10/29 22:34:22 Yes, it appears as though ValueStoreFrontend::Back
Devlin 2015/10/30 20:13:17 We try to restore when a call fails - this is in s
361 // delete it to avoid future open failures.
362 if (base::DeleteFile(db_path_, true /* recursive */))
363 corruption_recovery_histogram_->Add(
364 LEVELDB_CORRUPTION_RECOVERY_DELETE_SUCCESS);
365 else
366 corruption_recovery_histogram_->Add(
367 LEVELDB_CORRUPTION_RECOVERY_DELETE_FAILURE);
368 }
344 if (!status.ok()) 369 if (!status.ok())
345 return ToValueStoreError(status, util::NoKey()); 370 return ToValueStoreError(status, util::NoKey());
346 371
347 CHECK(db); 372 CHECK(db);
348 db_.reset(db); 373 db_.reset(db);
349 return util::NoError(); 374 return util::NoError();
350 } 375 }
351 376
352 scoped_ptr<ValueStore::Error> LeveldbValueStore::ReadFromDb( 377 scoped_ptr<ValueStore::Error> LeveldbValueStore::ReadFromDb(
353 leveldb::ReadOptions options, 378 leveldb::ReadOptions options,
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
443 CHECK(!status.IsNotFound()); // not an error 468 CHECK(!status.IsNotFound()); // not an error
444 469
445 std::string message = status.ToString(); 470 std::string message = status.ToString();
446 // The message may contain |db_path_|, which may be considered sensitive 471 // The message may contain |db_path_|, which may be considered sensitive
447 // data, and those strings are passed to the extension, so strip it out. 472 // data, and those strings are passed to the extension, so strip it out.
448 base::ReplaceSubstringsAfterOffset( 473 base::ReplaceSubstringsAfterOffset(
449 &message, 0u, db_path_.AsUTF8Unsafe(), "..."); 474 &message, 0u, db_path_.AsUTF8Unsafe(), "...");
450 475
451 return Error::Create(CORRUPTION, message, key.Pass()); 476 return Error::Create(CORRUPTION, message, key.Pass());
452 } 477 }
OLDNEW
« no previous file with comments | « extensions/browser/value_store/leveldb_value_store.h ('k') | tools/metrics/histograms/histograms.xml » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698