OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/value_store/leveldb_value_store.h" | 5 #include "chrome/browser/value_store/leveldb_value_store.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/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" |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 scoped_ptr<base::Value> next_value; | 262 scoped_ptr<base::Value> next_value; |
263 whole_db.RemoveWithoutPathExpansion(next_key, &next_value); | 263 whole_db.RemoveWithoutPathExpansion(next_key, &next_value); |
264 changes->push_back( | 264 changes->push_back( |
265 ValueStoreChange(next_key, next_value.release(), NULL)); | 265 ValueStoreChange(next_key, next_value.release(), NULL)); |
266 } | 266 } |
267 | 267 |
268 DeleteDbFile(); | 268 DeleteDbFile(); |
269 return MakeWriteResult(changes.Pass()); | 269 return MakeWriteResult(changes.Pass()); |
270 } | 270 } |
271 | 271 |
| 272 bool LeveldbValueStore::Restore() { |
| 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 274 |
| 275 ReadResult result = Get(); |
| 276 std::string previous_key; |
| 277 while (result->IsCorrupted()) { |
| 278 // If we don't have a specific corrupted key, or we've tried and failed to |
| 279 // clear this specific key, or we fail to restore the key, then wipe the |
| 280 // whole database. |
| 281 if (!result->error().key.get() || *result->error().key == previous_key || |
| 282 !RestoreKey(*result->error().key)) { |
| 283 DeleteDbFile(); |
| 284 result = Get(); |
| 285 break; |
| 286 } |
| 287 |
| 288 // Otherwise, re-Get() the database to check if there is still any |
| 289 // corruption. |
| 290 previous_key = *result->error().key; |
| 291 result = Get(); |
| 292 } |
| 293 |
| 294 // If we still have an error, it means we've tried deleting the database file, |
| 295 // and failed. There's nothing more we can do. |
| 296 return !result->IsCorrupted(); |
| 297 } |
| 298 |
| 299 bool LeveldbValueStore::RestoreKey(const std::string& key) { |
| 300 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| 301 |
| 302 ReadResult result = Get(key); |
| 303 if (result->IsCorrupted()) { |
| 304 leveldb::WriteBatch batch; |
| 305 batch.Delete(key); |
| 306 scoped_ptr<ValueStore::Error> error = WriteToDb(&batch); |
| 307 // If we can't delete the key, the restore failed. |
| 308 if (error.get()) |
| 309 return false; |
| 310 result = Get(key); |
| 311 } |
| 312 |
| 313 // The restore succeeded if there is no corruption error. |
| 314 return !result->IsCorrupted(); |
| 315 } |
| 316 |
| 317 bool LeveldbValueStore::WriteToDbForTest(leveldb::WriteBatch* batch) { |
| 318 return !WriteToDb(batch).get(); |
| 319 } |
| 320 |
272 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() { | 321 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() { |
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
274 | 323 |
275 if (db_) | 324 if (db_) |
276 return util::NoError(); | 325 return util::NoError(); |
277 | 326 |
278 leveldb::Options options; | 327 leveldb::Options options; |
279 options.max_open_files = 0; // Use minimum. | 328 options.max_open_files = 0; // Use minimum. |
280 options.create_if_missing = true; | 329 options.create_if_missing = true; |
281 | 330 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
382 CHECK(!status.ok()); | 431 CHECK(!status.ok()); |
383 CHECK(!status.IsNotFound()); // not an error | 432 CHECK(!status.IsNotFound()); // not an error |
384 | 433 |
385 std::string message = status.ToString(); | 434 std::string message = status.ToString(); |
386 // The message may contain |db_path_|, which may be considered sensitive | 435 // The message may contain |db_path_|, which may be considered sensitive |
387 // data, and those strings are passed to the extension, so strip it out. | 436 // data, and those strings are passed to the extension, so strip it out. |
388 ReplaceSubstringsAfterOffset(&message, 0u, db_path_.AsUTF8Unsafe(), "..."); | 437 ReplaceSubstringsAfterOffset(&message, 0u, db_path_.AsUTF8Unsafe(), "..."); |
389 | 438 |
390 return Error::Create(CORRUPTION, message, key.Pass()); | 439 return Error::Create(CORRUPTION, message, key.Pass()); |
391 } | 440 } |
OLD | NEW |