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 | |
321 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() { | 272 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() { |
322 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
323 | 274 |
324 if (db_) | 275 if (db_) |
325 return util::NoError(); | 276 return util::NoError(); |
326 | 277 |
327 leveldb::Options options; | 278 leveldb::Options options; |
328 options.max_open_files = 0; // Use minimum. | 279 options.max_open_files = 0; // Use minimum. |
329 options.create_if_missing = true; | 280 options.create_if_missing = true; |
330 | 281 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 CHECK(!status.ok()); | 382 CHECK(!status.ok()); |
432 CHECK(!status.IsNotFound()); // not an error | 383 CHECK(!status.IsNotFound()); // not an error |
433 | 384 |
434 std::string message = status.ToString(); | 385 std::string message = status.ToString(); |
435 // The message may contain |db_path_|, which may be considered sensitive | 386 // The message may contain |db_path_|, which may be considered sensitive |
436 // data, and those strings are passed to the extension, so strip it out. | 387 // data, and those strings are passed to the extension, so strip it out. |
437 ReplaceSubstringsAfterOffset(&message, 0u, db_path_.AsUTF8Unsafe(), "..."); | 388 ReplaceSubstringsAfterOffset(&message, 0u, db_path_.AsUTF8Unsafe(), "..."); |
438 | 389 |
439 return Error::Create(CORRUPTION, message, key.Pass()); | 390 return Error::Create(CORRUPTION, message, key.Pass()); |
440 } | 391 } |
OLD | NEW |