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->HasError() && result->error().code == CORRUPTION) { | |
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->HasError() && result->error().code == CORRUPTION); | |
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->HasError() && result->error().code == CORRUPTION) { | |
not at google - send to devlin
2014/02/14 19:35:56
all my talk of making corruption a switch... turns
Devlin
2014/02/18 23:55:22
Done.
| |
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->HasError() && result->error().code == CORRUPTION); | |
not at google - send to devlin
2014/02/14 19:35:56
return !result->HasError() || result->error().code
Devlin
2014/02/18 23:55:22
Done.
| |
315 } | |
316 | |
317 bool LeveldbValueStore::WriteToDbForTest(leveldb::WriteBatch* batch) { | |
318 scoped_ptr<ValueStore::Error> error = WriteToDb(batch); | |
not at google - send to devlin
2014/02/14 19:35:56
inline this
Devlin
2014/02/18 23:55:22
Done.
| |
319 return !error.get(); | |
320 } | |
321 | |
272 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() { | 322 scoped_ptr<ValueStore::Error> LeveldbValueStore::EnsureDbIsOpen() { |
273 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
274 | 324 |
275 if (db_) | 325 if (db_) |
276 return util::NoError(); | 326 return util::NoError(); |
277 | 327 |
278 leveldb::Options options; | 328 leveldb::Options options; |
279 options.max_open_files = 0; // Use minimum. | 329 options.max_open_files = 0; // Use minimum. |
280 options.create_if_missing = true; | 330 options.create_if_missing = true; |
281 | 331 |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
382 CHECK(!status.ok()); | 432 CHECK(!status.ok()); |
383 CHECK(!status.IsNotFound()); // not an error | 433 CHECK(!status.IsNotFound()); // not an error |
384 | 434 |
385 std::string message = status.ToString(); | 435 std::string message = status.ToString(); |
386 // The message may contain |db_path_|, which may be considered sensitive | 436 // 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. | 437 // data, and those strings are passed to the extension, so strip it out. |
388 ReplaceSubstringsAfterOffset(&message, 0u, db_path_.AsUTF8Unsafe(), "..."); | 438 ReplaceSubstringsAfterOffset(&message, 0u, db_path_.AsUTF8Unsafe(), "..."); |
389 | 439 |
390 return Error::Create(CORRUPTION, message, key.Pass()); | 440 return Error::Create(CORRUPTION, message, key.Pass()); |
391 } | 441 } |
OLD | NEW |