Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "components/leveldb/leveldb_database_impl.h" | 5 #include "components/leveldb/leveldb_database_impl.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <string> | 8 #include <string> |
| 9 | 9 |
| 10 #include "base/optional.h" | |
| 10 #include "base/rand_util.h" | 11 #include "base/rand_util.h" |
| 11 #include "components/leveldb/env_mojo.h" | 12 #include "components/leveldb/env_mojo.h" |
| 12 #include "components/leveldb/public/cpp/util.h" | 13 #include "components/leveldb/public/cpp/util.h" |
| 13 #include "mojo/common/common_type_converters.h" | |
| 14 #include "third_party/leveldatabase/src/include/leveldb/db.h" | 14 #include "third_party/leveldatabase/src/include/leveldb/db.h" |
| 15 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" | 15 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" |
| 16 | 16 |
| 17 namespace leveldb { | 17 namespace leveldb { |
| 18 namespace { | 18 namespace { |
| 19 | 19 |
| 20 template <typename T> | 20 template <typename T> |
| 21 uint64_t GetSafeRandomId(const std::map<uint64_t, T>& m) { | 21 uint64_t GetSafeRandomId(const std::map<uint64_t, T>& m) { |
| 22 // Associate a random unsigned 64 bit handle to |s|, checking for the highly | 22 // Associate a random unsigned 64 bit handle to |s|, checking for the highly |
| 23 // improbable id duplication or castability to null. | 23 // improbable id duplication or castability to null. |
| (...skipping 29 matching lines...) Expand all Loading... | |
| 53 environment_(std::move(environment)), | 53 environment_(std::move(environment)), |
| 54 db_(std::move(db)) {} | 54 db_(std::move(db)) {} |
| 55 | 55 |
| 56 LevelDBDatabaseImpl::~LevelDBDatabaseImpl() { | 56 LevelDBDatabaseImpl::~LevelDBDatabaseImpl() { |
| 57 for (auto& p : iterator_map_) | 57 for (auto& p : iterator_map_) |
| 58 delete p.second; | 58 delete p.second; |
| 59 for (auto& p : snapshot_map_) | 59 for (auto& p : snapshot_map_) |
| 60 db_->ReleaseSnapshot(p.second); | 60 db_->ReleaseSnapshot(p.second); |
| 61 } | 61 } |
| 62 | 62 |
| 63 void LevelDBDatabaseImpl::Put(mojo::Array<uint8_t> key, | 63 void LevelDBDatabaseImpl::Put(const std::vector<uint8_t>& key, |
| 64 mojo::Array<uint8_t> value, | 64 const std::vector<uint8_t>& value, |
| 65 const PutCallback& callback) { | 65 const PutCallback& callback) { |
| 66 leveldb::Status status = | 66 leveldb::Status status = |
| 67 db_->Put(leveldb::WriteOptions(), GetSliceFor(key), GetSliceFor(value)); | 67 db_->Put(leveldb::WriteOptions(), GetSliceFor(key), GetSliceFor(value)); |
| 68 callback.Run(LeveldbStatusToError(status)); | 68 callback.Run(LeveldbStatusToError(status)); |
| 69 } | 69 } |
| 70 | 70 |
| 71 void LevelDBDatabaseImpl::Delete(mojo::Array<uint8_t> key, | 71 void LevelDBDatabaseImpl::Delete(const std::vector<uint8_t>& key, |
| 72 const DeleteCallback& callback) { | 72 const DeleteCallback& callback) { |
| 73 leveldb::Status status = | 73 leveldb::Status status = |
| 74 db_->Delete(leveldb::WriteOptions(), GetSliceFor(key)); | 74 db_->Delete(leveldb::WriteOptions(), GetSliceFor(key)); |
| 75 callback.Run(LeveldbStatusToError(status)); | 75 callback.Run(LeveldbStatusToError(status)); |
| 76 } | 76 } |
| 77 | 77 |
| 78 void LevelDBDatabaseImpl::DeletePrefixed( | 78 void LevelDBDatabaseImpl::DeletePrefixed( |
| 79 mojo::Array<uint8_t> key_prefix, | 79 const std::vector<uint8_t>& key_prefix, |
| 80 const DeletePrefixedCallback& callback) { | 80 const DeletePrefixedCallback& callback) { |
| 81 leveldb::WriteBatch batch; | 81 leveldb::WriteBatch batch; |
| 82 leveldb::Status status = DeletePrefixedHelper( | 82 leveldb::Status status = DeletePrefixedHelper( |
| 83 GetSliceFor(key_prefix), &batch); | 83 GetSliceFor(key_prefix), &batch); |
| 84 if (status.ok()) | 84 if (status.ok()) |
| 85 status = db_->Write(leveldb::WriteOptions(), &batch); | 85 status = db_->Write(leveldb::WriteOptions(), &batch); |
| 86 callback.Run(LeveldbStatusToError(status)); | 86 callback.Run(LeveldbStatusToError(status)); |
| 87 } | 87 } |
| 88 | 88 |
| 89 void LevelDBDatabaseImpl::Write( | 89 void LevelDBDatabaseImpl::Write( |
| 90 mojo::Array<mojom::BatchedOperationPtr> operations, | 90 std::vector<mojom::BatchedOperationPtr> operations, |
| 91 const WriteCallback& callback) { | 91 const WriteCallback& callback) { |
| 92 leveldb::WriteBatch batch; | 92 leveldb::WriteBatch batch; |
| 93 | 93 |
| 94 for (size_t i = 0; i < operations.size(); ++i) { | 94 for (size_t i = 0; i < operations.size(); ++i) { |
| 95 switch (operations[i]->type) { | 95 switch (operations[i]->type) { |
| 96 case mojom::BatchOperationType::PUT_KEY: { | 96 case mojom::BatchOperationType::PUT_KEY: { |
| 97 batch.Put(GetSliceFor(operations[i]->key), | 97 batch.Put(GetSliceFor(operations[i]->key), |
| 98 GetSliceFor(operations[i]->value)); | 98 GetSliceFor(*(operations[i]->value))); |
|
yzshen1
2016/08/26 16:58:40
A malicious sender may send you a null value. And
leonhsl(Using Gerrit)
2016/08/29 06:36:17
Yeah, it is true. Done and thanks. Also confirmed
| |
| 99 break; | 99 break; |
| 100 } | 100 } |
| 101 case mojom::BatchOperationType::DELETE_KEY: { | 101 case mojom::BatchOperationType::DELETE_KEY: { |
| 102 batch.Delete(GetSliceFor(operations[i]->key)); | 102 batch.Delete(GetSliceFor(operations[i]->key)); |
| 103 break; | 103 break; |
| 104 } | 104 } |
| 105 case mojom::BatchOperationType::DELETE_PREFIXED_KEY: { | 105 case mojom::BatchOperationType::DELETE_PREFIXED_KEY: { |
| 106 DeletePrefixedHelper(GetSliceFor(operations[i]->key), &batch); | 106 DeletePrefixedHelper(GetSliceFor(operations[i]->key), &batch); |
| 107 break; | 107 break; |
| 108 } | 108 } |
| 109 } | 109 } |
| 110 } | 110 } |
| 111 | 111 |
| 112 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); | 112 leveldb::Status status = db_->Write(leveldb::WriteOptions(), &batch); |
| 113 callback.Run(LeveldbStatusToError(status)); | 113 callback.Run(LeveldbStatusToError(status)); |
| 114 } | 114 } |
| 115 | 115 |
| 116 void LevelDBDatabaseImpl::Get(mojo::Array<uint8_t> key, | 116 void LevelDBDatabaseImpl::Get(const std::vector<uint8_t>& key, |
| 117 const GetCallback& callback) { | 117 const GetCallback& callback) { |
| 118 std::string value; | 118 std::string value; |
| 119 leveldb::Status status = | 119 leveldb::Status status = |
| 120 db_->Get(leveldb::ReadOptions(), GetSliceFor(key), &value); | 120 db_->Get(leveldb::ReadOptions(), GetSliceFor(key), &value); |
| 121 callback.Run(LeveldbStatusToError(status), mojo::Array<uint8_t>::From(value)); | 121 callback.Run(LeveldbStatusToError(status), StdStringToUint8Vector(value)); |
| 122 } | 122 } |
| 123 | 123 |
| 124 void LevelDBDatabaseImpl::GetPrefixed(mojo::Array<uint8_t> key_prefix, | 124 void LevelDBDatabaseImpl::GetPrefixed(const std::vector<uint8_t>& key_prefix, |
| 125 const GetPrefixedCallback& callback) { | 125 const GetPrefixedCallback& callback) { |
| 126 mojo::Array<mojom::KeyValuePtr> data; | 126 std::vector<mojom::KeyValuePtr> data; |
| 127 leveldb::Status status = ForEachWithPrefix( | 127 leveldb::Status status = ForEachWithPrefix( |
| 128 db_.get(), GetSliceFor(key_prefix), | 128 db_.get(), GetSliceFor(key_prefix), |
| 129 [&data](const leveldb::Slice& key, const leveldb::Slice& value) { | 129 [&data](const leveldb::Slice& key, const leveldb::Slice& value) { |
| 130 mojom::KeyValuePtr kv = mojom::KeyValue::New(); | 130 mojom::KeyValuePtr kv = mojom::KeyValue::New(); |
| 131 kv->key = GetArrayFor(key); | 131 kv->key = GetVectorFor(key); |
| 132 kv->value = GetArrayFor(value); | 132 kv->value = GetVectorFor(value); |
| 133 data.push_back(std::move(kv)); | 133 data.push_back(std::move(kv)); |
| 134 }); | 134 }); |
| 135 callback.Run(LeveldbStatusToError(status), std::move(data)); | 135 callback.Run(LeveldbStatusToError(status), std::move(data)); |
| 136 } | 136 } |
| 137 | 137 |
| 138 void LevelDBDatabaseImpl::GetSnapshot(const GetSnapshotCallback& callback) { | 138 void LevelDBDatabaseImpl::GetSnapshot(const GetSnapshotCallback& callback) { |
| 139 const Snapshot* s = db_->GetSnapshot(); | 139 const Snapshot* s = db_->GetSnapshot(); |
| 140 uint64_t new_id = GetSafeRandomId(snapshot_map_); | 140 uint64_t new_id = GetSafeRandomId(snapshot_map_); |
| 141 snapshot_map_.insert(std::make_pair(new_id, s)); | 141 snapshot_map_.insert(std::make_pair(new_id, s)); |
| 142 callback.Run(new_id); | 142 callback.Run(new_id); |
| 143 } | 143 } |
| 144 | 144 |
| 145 void LevelDBDatabaseImpl::ReleaseSnapshot(uint64_t snapshot_id) { | 145 void LevelDBDatabaseImpl::ReleaseSnapshot(uint64_t snapshot_id) { |
| 146 auto it = snapshot_map_.find(snapshot_id); | 146 auto it = snapshot_map_.find(snapshot_id); |
| 147 if (it != snapshot_map_.end()) { | 147 if (it != snapshot_map_.end()) { |
| 148 db_->ReleaseSnapshot(it->second); | 148 db_->ReleaseSnapshot(it->second); |
| 149 snapshot_map_.erase(it); | 149 snapshot_map_.erase(it); |
| 150 } | 150 } |
| 151 } | 151 } |
| 152 | 152 |
| 153 void LevelDBDatabaseImpl::GetFromSnapshot(uint64_t snapshot_id, | 153 void LevelDBDatabaseImpl::GetFromSnapshot(uint64_t snapshot_id, |
| 154 mojo::Array<uint8_t> key, | 154 const std::vector<uint8_t>& key, |
| 155 const GetCallback& callback) { | 155 const GetCallback& callback) { |
| 156 // If the snapshot id is invalid, send back invalid argument | 156 // If the snapshot id is invalid, send back invalid argument |
| 157 auto it = snapshot_map_.find(snapshot_id); | 157 auto it = snapshot_map_.find(snapshot_id); |
| 158 if (it == snapshot_map_.end()) { | 158 if (it == snapshot_map_.end()) { |
| 159 callback.Run(mojom::DatabaseError::INVALID_ARGUMENT, | 159 callback.Run(mojom::DatabaseError::INVALID_ARGUMENT, |
| 160 mojo::Array<uint8_t>()); | 160 std::vector<uint8_t>()); |
| 161 return; | 161 return; |
| 162 } | 162 } |
| 163 | 163 |
| 164 std::string value; | 164 std::string value; |
| 165 leveldb::ReadOptions options; | 165 leveldb::ReadOptions options; |
| 166 options.snapshot = it->second; | 166 options.snapshot = it->second; |
| 167 leveldb::Status status = db_->Get(options, GetSliceFor(key), &value); | 167 leveldb::Status status = db_->Get(options, GetSliceFor(key), &value); |
| 168 callback.Run(LeveldbStatusToError(status), mojo::Array<uint8_t>::From(value)); | 168 callback.Run(LeveldbStatusToError(status), StdStringToUint8Vector(value)); |
| 169 } | 169 } |
| 170 | 170 |
| 171 void LevelDBDatabaseImpl::NewIterator(const NewIteratorCallback& callback) { | 171 void LevelDBDatabaseImpl::NewIterator(const NewIteratorCallback& callback) { |
| 172 Iterator* iterator = db_->NewIterator(leveldb::ReadOptions()); | 172 Iterator* iterator = db_->NewIterator(leveldb::ReadOptions()); |
| 173 uint64_t new_id = GetSafeRandomId(iterator_map_); | 173 uint64_t new_id = GetSafeRandomId(iterator_map_); |
| 174 iterator_map_.insert(std::make_pair(new_id, iterator)); | 174 iterator_map_.insert(std::make_pair(new_id, iterator)); |
| 175 callback.Run(new_id); | 175 callback.Run(new_id); |
| 176 } | 176 } |
| 177 | 177 |
| 178 void LevelDBDatabaseImpl::NewIteratorFromSnapshot( | 178 void LevelDBDatabaseImpl::NewIteratorFromSnapshot( |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 200 delete it->second; | 200 delete it->second; |
| 201 iterator_map_.erase(it); | 201 iterator_map_.erase(it); |
| 202 } | 202 } |
| 203 } | 203 } |
| 204 | 204 |
| 205 void LevelDBDatabaseImpl::IteratorSeekToFirst( | 205 void LevelDBDatabaseImpl::IteratorSeekToFirst( |
| 206 uint64_t iterator_id, | 206 uint64_t iterator_id, |
| 207 const IteratorSeekToFirstCallback& callback) { | 207 const IteratorSeekToFirstCallback& callback) { |
| 208 auto it = iterator_map_.find(iterator_id); | 208 auto it = iterator_map_.find(iterator_id); |
| 209 if (it == iterator_map_.end()) { | 209 if (it == iterator_map_.end()) { |
| 210 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, nullptr, | 210 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, base::nullopt, |
| 211 nullptr); | 211 base::nullopt); |
| 212 return; | 212 return; |
| 213 } | 213 } |
| 214 | 214 |
| 215 it->second->SeekToFirst(); | 215 it->second->SeekToFirst(); |
| 216 | 216 |
| 217 ReplyToIteratorMessage(it->second, callback); | 217 ReplyToIteratorMessage(it->second, callback); |
| 218 } | 218 } |
| 219 | 219 |
| 220 void LevelDBDatabaseImpl::IteratorSeekToLast( | 220 void LevelDBDatabaseImpl::IteratorSeekToLast( |
| 221 uint64_t iterator_id, | 221 uint64_t iterator_id, |
| 222 const IteratorSeekToLastCallback& callback) { | 222 const IteratorSeekToLastCallback& callback) { |
| 223 auto it = iterator_map_.find(iterator_id); | 223 auto it = iterator_map_.find(iterator_id); |
| 224 if (it == iterator_map_.end()) { | 224 if (it == iterator_map_.end()) { |
| 225 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, nullptr, | 225 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, base::nullopt, |
| 226 nullptr); | 226 base::nullopt); |
| 227 return; | 227 return; |
| 228 } | 228 } |
| 229 | 229 |
| 230 it->second->SeekToLast(); | 230 it->second->SeekToLast(); |
| 231 | 231 |
| 232 ReplyToIteratorMessage(it->second, callback); | 232 ReplyToIteratorMessage(it->second, callback); |
| 233 } | 233 } |
| 234 | 234 |
| 235 void LevelDBDatabaseImpl::IteratorSeek( | 235 void LevelDBDatabaseImpl::IteratorSeek( |
| 236 uint64_t iterator_id, | 236 uint64_t iterator_id, |
| 237 mojo::Array<uint8_t> target, | 237 const std::vector<uint8_t>& target, |
| 238 const IteratorSeekToLastCallback& callback) { | 238 const IteratorSeekToLastCallback& callback) { |
| 239 auto it = iterator_map_.find(iterator_id); | 239 auto it = iterator_map_.find(iterator_id); |
| 240 if (it == iterator_map_.end()) { | 240 if (it == iterator_map_.end()) { |
| 241 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, nullptr, | 241 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, base::nullopt, |
| 242 nullptr); | 242 base::nullopt); |
| 243 return; | 243 return; |
| 244 } | 244 } |
| 245 | 245 |
| 246 it->second->Seek(GetSliceFor(target)); | 246 it->second->Seek(GetSliceFor(target)); |
| 247 | 247 |
| 248 ReplyToIteratorMessage(it->second, callback); | 248 ReplyToIteratorMessage(it->second, callback); |
| 249 } | 249 } |
| 250 | 250 |
| 251 void LevelDBDatabaseImpl::IteratorNext(uint64_t iterator_id, | 251 void LevelDBDatabaseImpl::IteratorNext(uint64_t iterator_id, |
| 252 const IteratorNextCallback& callback) { | 252 const IteratorNextCallback& callback) { |
| 253 auto it = iterator_map_.find(iterator_id); | 253 auto it = iterator_map_.find(iterator_id); |
| 254 if (it == iterator_map_.end()) { | 254 if (it == iterator_map_.end()) { |
| 255 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, nullptr, | 255 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, base::nullopt, |
| 256 nullptr); | 256 base::nullopt); |
| 257 return; | 257 return; |
| 258 } | 258 } |
| 259 | 259 |
| 260 it->second->Next(); | 260 it->second->Next(); |
| 261 | 261 |
| 262 ReplyToIteratorMessage(it->second, callback); | 262 ReplyToIteratorMessage(it->second, callback); |
| 263 } | 263 } |
| 264 | 264 |
| 265 void LevelDBDatabaseImpl::IteratorPrev(uint64_t iterator_id, | 265 void LevelDBDatabaseImpl::IteratorPrev(uint64_t iterator_id, |
| 266 const IteratorPrevCallback& callback) { | 266 const IteratorPrevCallback& callback) { |
| 267 auto it = iterator_map_.find(iterator_id); | 267 auto it = iterator_map_.find(iterator_id); |
| 268 if (it == iterator_map_.end()) { | 268 if (it == iterator_map_.end()) { |
| 269 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, nullptr, | 269 callback.Run(false, mojom::DatabaseError::INVALID_ARGUMENT, base::nullopt, |
| 270 nullptr); | 270 base::nullopt); |
| 271 return; | 271 return; |
| 272 } | 272 } |
| 273 | 273 |
| 274 it->second->Prev(); | 274 it->second->Prev(); |
| 275 | 275 |
| 276 ReplyToIteratorMessage(it->second, callback); | 276 ReplyToIteratorMessage(it->second, callback); |
| 277 } | 277 } |
| 278 | 278 |
| 279 void LevelDBDatabaseImpl::ReplyToIteratorMessage( | 279 void LevelDBDatabaseImpl::ReplyToIteratorMessage( |
| 280 leveldb::Iterator* it, | 280 leveldb::Iterator* it, |
| 281 const IteratorSeekToFirstCallback& callback) { | 281 const IteratorSeekToFirstCallback& callback) { |
| 282 if (!it->Valid()) { | 282 if (!it->Valid()) { |
| 283 callback.Run(false, LeveldbStatusToError(it->status()), nullptr, nullptr); | 283 callback.Run(false, LeveldbStatusToError(it->status()), base::nullopt, |
| 284 base::nullopt); | |
| 284 return; | 285 return; |
| 285 } | 286 } |
| 286 | 287 |
| 287 callback.Run(true, LeveldbStatusToError(it->status()), GetArrayFor(it->key()), | 288 callback.Run(true, LeveldbStatusToError(it->status()), |
| 288 GetArrayFor(it->value())); | 289 GetVectorFor(it->key()), GetVectorFor(it->value())); |
| 289 } | 290 } |
| 290 | 291 |
| 291 leveldb::Status LevelDBDatabaseImpl::DeletePrefixedHelper( | 292 leveldb::Status LevelDBDatabaseImpl::DeletePrefixedHelper( |
| 292 const leveldb::Slice& key_prefix, | 293 const leveldb::Slice& key_prefix, |
| 293 leveldb::WriteBatch* batch) { | 294 leveldb::WriteBatch* batch) { |
| 294 leveldb::Status status = ForEachWithPrefix(db_.get(), key_prefix, | 295 leveldb::Status status = ForEachWithPrefix(db_.get(), key_prefix, |
| 295 [batch](const leveldb::Slice& key, const leveldb::Slice& value) { | 296 [batch](const leveldb::Slice& key, const leveldb::Slice& value) { |
| 296 batch->Delete(key); | 297 batch->Delete(key); |
| 297 }); | 298 }); |
| 298 return status; | 299 return status; |
| 299 } | 300 } |
| 300 | 301 |
| 301 } // namespace leveldb | 302 } // namespace leveldb |
| OLD | NEW |