Index: content/browser/leveldb_wrapper_impl.cc |
diff --git a/content/browser/leveldb_wrapper_impl.cc b/content/browser/leveldb_wrapper_impl.cc |
index 623b728e19ee4db7d4e0e0ddfabc869489736c26..dbc129959fea76404316c642295022883f825caa 100644 |
--- a/content/browser/leveldb_wrapper_impl.cc |
+++ b/content/browser/leveldb_wrapper_impl.cc |
@@ -5,16 +5,20 @@ |
#include "content/browser/leveldb_wrapper_impl.h" |
#include "base/bind.h" |
+#include "mojo/common/common_type_converters.h" |
namespace content { |
LevelDBWrapperImpl::LevelDBWrapperImpl( |
leveldb::LevelDBDatabase* database, |
const std::string& prefix, |
+ size_t max_size, |
const base::Closure& no_bindings_callback) |
: prefix_(prefix), |
no_bindings_callback_(no_bindings_callback), |
- database_(database) { |
+ database_(database), |
+ bytes_used_(0), |
+ max_size_(max_size) { |
bindings_.set_connection_error_handler(base::Bind( |
&LevelDBWrapperImpl::OnConnectionError, base::Unretained(this))); |
} |
@@ -25,41 +29,98 @@ void LevelDBWrapperImpl::Bind(LevelDBWrapperRequest request) { |
LevelDBWrapperImpl::~LevelDBWrapperImpl() {} |
+void LevelDBWrapperImpl::AddObserver(LevelDBObserverPtr observer) { |
+ observers_.AddInterfacePtr(std::move(observer)); |
+} |
+ |
void LevelDBWrapperImpl::Put(mojo::Array<uint8_t> key, |
mojo::Array<uint8_t> value, |
const mojo::String& source, |
const PutCallback& callback) { |
- NOTIMPLEMENTED(); |
- callback.Run(leveldb::DatabaseError::NOT_SUPPORTED); |
+ bool has_old_item = false; |
+ mojo::Array<uint8_t> old_value; |
+ size_t old_item_size = 0; |
+ auto found = map_.find(key); |
+ if (found != map_.end()) { |
+ old_value = std::move(found->second); |
+ old_item_size = key.size() + old_value.size(); |
+ has_old_item = true; |
+ } |
+ size_t new_item_size = key.size() + value.size(); |
+ size_t new_bytes_used = bytes_used_ - old_item_size + new_item_size; |
+ |
+ // Only check quota if the size is increasing, this allows |
+ // shrinking changes to pre-existing maps that are over budget. |
+ if (new_item_size > old_item_size && new_bytes_used > max_size_) { |
+ callback.Run(false); |
+ return; |
+ } |
+ |
+ map_[key.Clone()] = value.Clone(); |
+ bytes_used_ = new_bytes_used; |
+ if (!has_old_item) { |
+ // We added a new key/value pair. |
+ observers_.ForAllPtrs( |
+ [&key, &value, &source](LevelDBObserver* observer) { |
+ observer->KeyAdded(key.Clone(), value.Clone(), source); |
michaeln
2016/03/29 22:20:46
like we've talked about, the repeated cloning is n
|
+ }); |
+ } else { |
+ // We changed the value for an existing key. |
+ observers_.ForAllPtrs( |
+ [&key, &value, &source, &old_value](LevelDBObserver* observer) { |
+ observer->KeyChanged( |
+ key.Clone(), value.Clone(), old_value.Clone(), source); |
+ }); |
+ } |
+ callback.Run(true); |
} |
void LevelDBWrapperImpl::Delete(mojo::Array<uint8_t> key, |
const mojo::String& source, |
const DeleteCallback& callback) { |
- NOTIMPLEMENTED(); |
- callback.Run(leveldb::DatabaseError::NOT_SUPPORTED); |
-} |
+ auto found = map_.find(key); |
+ if (found == map_.end()) { |
+ callback.Run(true); |
+ return; |
+ } |
-void LevelDBWrapperImpl::DeleteAll(LevelDBObserverPtr observer, |
- const mojo::String& source, |
- const DeleteAllCallback& callback) { |
- // TODO(jam): store observer and call it when changes occur. |
- NOTIMPLEMENTED(); |
- callback.Run(leveldb::DatabaseError::NOT_SUPPORTED); |
+ mojo::Array<uint8_t> old_value = std::move(found->second); |
+ map_.erase(found); |
+ bytes_used_ -= key.size() + old_value.size(); |
+ observers_.ForAllPtrs( |
+ [&key, &source, &old_value](LevelDBObserver* observer) { |
+ observer->KeyDeleted( |
+ key.Clone(), old_value.Clone(), source); |
+ }); |
+ callback.Run(true); |
} |
-void LevelDBWrapperImpl::Get(mojo::Array<uint8_t> key, |
michaeln
2016/03/29 22:20:46
we don't have a use for this method in the localst
jam
2016/03/30 17:15:16
it doesn't harm to keep it there, so let's not rem
michaeln
2016/03/30 21:57:01
Done.
The comment about general purpose'ness is a
|
- const GetCallback& callback) { |
- NOTIMPLEMENTED(); |
- callback.Run(leveldb::DatabaseError::NOT_SUPPORTED, mojo::Array<uint8_t>()); |
+void LevelDBWrapperImpl::DeleteAll(const mojo::String& source, |
+ const DeleteAllCallback& callback) { |
+ map_.clear(); |
+ bytes_used_ = 0; |
+ observers_.ForAllPtrs( |
+ [&source](LevelDBObserver* observer) { |
+ observer->AllDeleted(source); |
+ }); |
+ callback.Run(true); |
} |
-void LevelDBWrapperImpl::GetAll(LevelDBObserverPtr observer, |
+void LevelDBWrapperImpl::GetAll(uint64_t request_id, |
const GetAllCallback& callback) { |
- // TODO(jam): store observer and call it when changes occur. |
- NOTIMPLEMENTED(); |
- callback.Run(leveldb::DatabaseError::NOT_SUPPORTED, |
- mojo::Array<KeyValuePtr>()); |
+ |
+ mojo::Array<KeyValuePtr> all(map_.size()); |
+ for (const auto& it : map_) { |
+ KeyValuePtr kv = KeyValue::New(); |
+ kv->key = it.first.Clone(); |
+ kv->value = it.second.Clone(); |
+ all.push_back(std::move(kv)); |
+ } |
+ callback.Run(leveldb::DatabaseError::OK, std::move(all)); |
+ observers_.ForAllPtrs( |
+ [request_id](LevelDBObserver* observer) { |
+ observer->GetAllComplete(request_id); |
+ }); |
} |
void LevelDBWrapperImpl::OnConnectionError() { |