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

Unified Diff: chrome/browser/value_store/leveldb_value_store.cc

Issue 10964010: Revert 157723 - Revert 157713 - Make database failures in LeveldbValueStore more descriptive. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/browser/value_store/leveldb_value_store.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/browser/value_store/leveldb_value_store.cc
===================================================================
--- chrome/browser/value_store/leveldb_value_store.cc (revision 157723)
+++ chrome/browser/value_store/leveldb_value_store.cc (working copy)
@@ -8,6 +8,7 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
+#include "base/stringprintf.h"
#include "base/sys_string_conversions.h"
#include "content/public/browser/browser_thread.h"
#include "third_party/leveldatabase/src/include/leveldb/iterator.h"
@@ -17,9 +18,40 @@
namespace {
-// Generic error message on failure.
-const char kGenericOnFailureMessage[] = "Failure accessing database";
+const char* kInvalidJson = "Invalid JSON";
+ValueStore::ReadResult ReadFailure(const std::string& action,
+ const std::string& reason) {
+ CHECK_NE("", reason);
+ return ValueStore::MakeReadResult(base::StringPrintf(
+ "Failure to %s: %s", action.c_str(), reason.c_str()));
+}
+
+ValueStore::ReadResult ReadFailureForKey(const std::string& action,
+ const std::string& key,
+ const std::string& reason) {
+ CHECK_NE("", reason);
+ return ValueStore::MakeReadResult(base::StringPrintf(
+ "Failure to %s for key %s: %s",
+ action.c_str(), key.c_str(), reason.c_str()));
+}
+
+ValueStore::WriteResult WriteFailure(const std::string& action,
+ const std::string& reason) {
+ CHECK_NE("", reason);
+ return ValueStore::MakeWriteResult(base::StringPrintf(
+ "Failure to %s: %s", action.c_str(), reason.c_str()));
+}
+
+ValueStore::WriteResult WriteFailureForKey(const std::string& action,
+ const std::string& key,
+ const std::string& reason) {
+ CHECK_NE("", reason);
+ return ValueStore::MakeWriteResult(base::StringPrintf(
+ "Failure to %s for key %s: %s",
+ action.c_str(), key.c_str(), reason.c_str()));
+}
+
// Scoped leveldb snapshot which releases the snapshot on destruction.
class ScopedSnapshot {
public:
@@ -105,23 +137,24 @@
return 0;
}
-ValueStore::ReadResult LeveldbValueStore::Get(
- const std::string& key) {
+ValueStore::ReadResult LeveldbValueStore::Get(const std::string& key) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
scoped_ptr<Value> setting;
- if (!ReadFromDb(leveldb::ReadOptions(), key, &setting)) {
- return MakeReadResult(kGenericOnFailureMessage);
- }
+ std::string error = ReadFromDb(leveldb::ReadOptions(), key, &setting);
+ if (!error.empty())
+ return ReadFailureForKey("get", key, error);
+
DictionaryValue* settings = new DictionaryValue();
- if (setting.get()) {
+ if (setting.get())
settings->SetWithoutPathExpansion(key, setting.release());
- }
return MakeReadResult(settings);
}
ValueStore::ReadResult LeveldbValueStore::Get(
const std::vector<std::string>& keys) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
leveldb::ReadOptions options;
scoped_ptr<DictionaryValue> settings(new DictionaryValue());
@@ -132,12 +165,11 @@
for (std::vector<std::string>::const_iterator it = keys.begin();
it != keys.end(); ++it) {
scoped_ptr<Value> setting;
- if (!ReadFromDb(options, *it, &setting)) {
- return MakeReadResult(kGenericOnFailureMessage);
- }
- if (setting.get()) {
+ std::string error = ReadFromDb(options, *it, &setting);
+ if (!error.empty())
+ return ReadFailureForKey("get multiple items", *it, error);
+ if (setting.get())
settings->SetWithoutPathExpansion(*it, setting.release());
- }
}
return MakeReadResult(settings.release());
@@ -145,6 +177,7 @@
ValueStore::ReadResult LeveldbValueStore::Get() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
+
base::JSONReader json_reader;
leveldb::ReadOptions options = leveldb::ReadOptions();
// All interaction with the db is done on the same thread, so snapshotting
@@ -155,20 +188,23 @@
options.snapshot = snapshot.get();
scoped_ptr<leveldb::Iterator> it(db_->NewIterator(options));
for (it->SeekToFirst(); it->Valid(); it->Next()) {
+ std::string key = it->key().ToString();
Value* value = json_reader.ReadToValue(it->value().ToString());
- if (value != NULL) {
- settings->SetWithoutPathExpansion(it->key().ToString(), value);
- } else {
+ if (value == NULL) {
// TODO(kalman): clear the offending non-JSON value from the database.
- LOG(ERROR) << "Invalid JSON: " << it->value().ToString();
+ return ReadFailureForKey("get all", key, kInvalidJson);
}
+ settings->SetWithoutPathExpansion(key, value);
}
- if (!it->status().ok()) {
- LOG(ERROR) << "DB iteration failed: " << it->status().ToString();
- return MakeReadResult(kGenericOnFailureMessage);
+ if (it->status().IsNotFound()) {
+ NOTREACHED() << "IsNotFound() but iterating over all keys?!";
+ return MakeReadResult(settings.release());
}
+ if (!it->status().ok())
+ return ReadFailure("get all items", it->status().ToString());
+
return MakeReadResult(settings.release());
}
@@ -178,8 +214,15 @@
leveldb::WriteBatch batch;
scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList());
- AddToBatch(options, key, value, &batch, changes.get());
- return WriteToDb(&batch, changes.Pass());
+ std::string read_error =
+ AddToBatch(options, key, value, &batch, changes.get());
+ if (!read_error.empty())
+ return WriteFailureForKey("find changes to set", key, read_error);
+
+ std::string write_error = WriteToDb(&batch);
+ if (!write_error.empty())
+ return WriteFailureForKey("set", key, write_error);
+ return MakeWriteResult(changes.release());
}
ValueStore::WriteResult LeveldbValueStore::Set(
@@ -190,19 +233,24 @@
scoped_ptr<ValueStoreChangeList> changes(new ValueStoreChangeList());
for (DictionaryValue::Iterator it(settings); it.HasNext(); it.Advance()) {
- if (!AddToBatch(options, it.key(), it.value(), &batch, changes.get()))
- return MakeWriteResult(kGenericOnFailureMessage);
+ std::string read_error =
+ AddToBatch(options, it.key(), it.value(), &batch, changes.get());
+ if (!read_error.empty()) {
+ return WriteFailureForKey("find changes to set multiple items",
+ it.key(),
+ read_error);
+ }
}
- return WriteToDb(&batch, changes.Pass());
+ std::string write_error = WriteToDb(&batch);
+ if (!write_error.empty())
+ return WriteFailure("set multiple items", write_error);
+ return MakeWriteResult(changes.release());
}
-ValueStore::WriteResult LeveldbValueStore::Remove(
- const std::string& key) {
+ValueStore::WriteResult LeveldbValueStore::Remove(const std::string& key) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
- std::vector<std::string> keys;
- keys.push_back(key);
- return Remove(keys);
+ return Remove(std::vector<std::string>(1, key));
}
ValueStore::WriteResult LeveldbValueStore::Remove(
@@ -215,23 +263,23 @@
for (std::vector<std::string>::const_iterator it = keys.begin();
it != keys.end(); ++it) {
scoped_ptr<Value> old_value;
- if (!ReadFromDb(leveldb::ReadOptions(), *it, &old_value)) {
- return MakeWriteResult(kGenericOnFailureMessage);
+ std::string read_error =
+ ReadFromDb(leveldb::ReadOptions(), *it, &old_value);
+ if (!read_error.empty()) {
+ return WriteFailureForKey("find changes to remove multiple items",
+ *it,
+ read_error);
}
if (old_value.get()) {
- changes->push_back(
- ValueStoreChange(*it, old_value.release(), NULL));
+ changes->push_back(ValueStoreChange(*it, old_value.release(), NULL));
batch.Delete(*it);
}
}
leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
- if (!status.ok() && !status.IsNotFound()) {
- LOG(WARNING) << "DB batch delete failed: " << status.ToString();
- return MakeWriteResult(kGenericOnFailureMessage);
- }
-
+ if (!status.ok() && !status.IsNotFound())
+ return WriteFailure("remove multiple items", status.ToString());
return MakeWriteResult(changes.release());
}
@@ -251,29 +299,30 @@
const std::string key = it->key().ToString();
const std::string old_value_json = it->value().ToString();
Value* old_value = base::JSONReader().ReadToValue(old_value_json);
- if (old_value) {
- changes->push_back(ValueStoreChange(key, old_value, NULL));
- } else {
- LOG(ERROR) << "Invalid JSON in database: " << old_value_json;
+ if (!old_value) {
+ // TODO: delete the bad JSON.
+ return WriteFailureForKey("find changes to clear", key, kInvalidJson);
}
+ changes->push_back(ValueStoreChange(key, old_value, NULL));
batch.Delete(key);
}
- if (!it->status().ok()) {
- LOG(WARNING) << "Clear iteration failed: " << it->status().ToString();
- return MakeWriteResult(kGenericOnFailureMessage);
- }
+ if (it->status().IsNotFound())
+ NOTREACHED() << "IsNotFound() but clearing?!";
+ else if (!it->status().ok())
+ return WriteFailure("find changes to clear", it->status().ToString());
leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch);
- if (!status.ok() && !status.IsNotFound()) {
- LOG(WARNING) << "Clear failed: " << status.ToString();
- return MakeWriteResult(kGenericOnFailureMessage);
+ if (status.IsNotFound()) {
+ NOTREACHED() << "IsNotFound() but clearing?!";
+ return MakeWriteResult(changes.release());
}
-
+ if (!status.ok())
+ return WriteFailure("clear", status.ToString());
return MakeWriteResult(changes.release());
}
-bool LeveldbValueStore::ReadFromDb(
+std::string LeveldbValueStore::ReadFromDb(
leveldb::ReadOptions options,
const std::string& key,
scoped_ptr<Value>* setting) {
@@ -284,26 +333,24 @@
if (s.IsNotFound()) {
// Despite there being no value, it was still a success.
- return true;
+ // Check this first because ok() is false on IsNotFound.
+ return "";
}
- if (!s.ok()) {
- LOG(ERROR) << "Error reading from database: " << s.ToString();
- return false;
- }
+ if (!s.ok())
+ return s.ToString();
Value* value = base::JSONReader().ReadToValue(value_as_json);
if (value == NULL) {
// TODO(kalman): clear the offending non-JSON value from the database.
- LOG(ERROR) << "Invalid JSON in database: " << value_as_json;
- return false;
+ return kInvalidJson;
}
setting->reset(value);
- return true;
+ return "";
}
-bool LeveldbValueStore::AddToBatch(
+std::string LeveldbValueStore::AddToBatch(
ValueStore::WriteOptions options,
const std::string& key,
const base::Value& value,
@@ -311,8 +358,9 @@
ValueStoreChangeList* changes) {
scoped_ptr<Value> old_value;
if (!(options & NO_CHECK_OLD_VALUE)) {
- if (!ReadFromDb(leveldb::ReadOptions(), key, &old_value))
- return false;
+ std::string error = ReadFromDb(leveldb::ReadOptions(), key, &old_value);
+ if (!error.empty())
+ return error;
}
if (!old_value.get() || !old_value->Equals(&value)) {
@@ -325,19 +373,16 @@
batch->Put(key, value_as_json);
}
- return true;
+ return "";
}
-ValueStore::WriteResult LeveldbValueStore::WriteToDb(
- leveldb::WriteBatch* batch,
- scoped_ptr<ValueStoreChangeList> changes) {
+std::string LeveldbValueStore::WriteToDb(leveldb::WriteBatch* batch) {
leveldb::Status status = db_->Write(leveldb::WriteOptions(), batch);
- if (!status.ok()) {
- LOG(WARNING) << "DB batch write failed: " << status.ToString();
- return MakeWriteResult(kGenericOnFailureMessage);
+ if (status.IsNotFound()) {
+ NOTREACHED() << "IsNotFound() but writing?!";
+ return "";
}
-
- return MakeWriteResult(changes.release());
+ return status.ok() ? "" : status.ToString();
}
bool LeveldbValueStore::IsEmpty() {
« no previous file with comments | « chrome/browser/value_store/leveldb_value_store.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698