| 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 "content/browser/leveldb_wrapper_impl.h" | 5 #include "content/browser/leveldb_wrapper_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/threading/thread_task_runner_handle.h" | 8 #include "base/threading/thread_task_runner_handle.h" |
| 9 #include "components/leveldb/public/cpp/util.h" | 9 #include "components/leveldb/public/cpp/util.h" |
| 10 #include "content/public/browser/browser_thread.h" | 10 #include "content/public/browser/browser_thread.h" |
| 11 | 11 |
| 12 namespace content { | 12 namespace content { |
| 13 | 13 |
| 14 void LevelDBWrapperImpl::Delegate::MigrateData( |
| 15 base::OnceCallback<void(std::unique_ptr<ValueMap>)> callback) { |
| 16 std::move(callback).Run(nullptr); |
| 17 } |
| 18 |
| 14 bool LevelDBWrapperImpl::s_aggressive_flushing_enabled_ = false; | 19 bool LevelDBWrapperImpl::s_aggressive_flushing_enabled_ = false; |
| 15 | 20 |
| 16 LevelDBWrapperImpl::RateLimiter::RateLimiter(size_t desired_rate, | 21 LevelDBWrapperImpl::RateLimiter::RateLimiter(size_t desired_rate, |
| 17 base::TimeDelta time_quantum) | 22 base::TimeDelta time_quantum) |
| 18 : rate_(desired_rate), samples_(0), time_quantum_(time_quantum) { | 23 : rate_(desired_rate), samples_(0), time_quantum_(time_quantum) { |
| 19 DCHECK_GT(desired_rate, 0ul); | 24 DCHECK_GT(desired_rate, 0ul); |
| 20 } | 25 } |
| 21 | 26 |
| 22 base::TimeDelta LevelDBWrapperImpl::RateLimiter::ComputeTimeNeeded() const { | 27 base::TimeDelta LevelDBWrapperImpl::RateLimiter::ComputeTimeNeeded() const { |
| 23 return time_quantum_ * (samples_ / rate_); | 28 return time_quantum_ * (samples_ / rate_); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 34 LevelDBWrapperImpl::CommitBatch::CommitBatch() : clear_all_first(false) {} | 39 LevelDBWrapperImpl::CommitBatch::CommitBatch() : clear_all_first(false) {} |
| 35 LevelDBWrapperImpl::CommitBatch::~CommitBatch() {} | 40 LevelDBWrapperImpl::CommitBatch::~CommitBatch() {} |
| 36 | 41 |
| 37 LevelDBWrapperImpl::LevelDBWrapperImpl( | 42 LevelDBWrapperImpl::LevelDBWrapperImpl( |
| 38 leveldb::mojom::LevelDBDatabase* database, | 43 leveldb::mojom::LevelDBDatabase* database, |
| 39 const std::string& prefix, | 44 const std::string& prefix, |
| 40 size_t max_size, | 45 size_t max_size, |
| 41 base::TimeDelta default_commit_delay, | 46 base::TimeDelta default_commit_delay, |
| 42 int max_bytes_per_hour, | 47 int max_bytes_per_hour, |
| 43 int max_commits_per_hour, | 48 int max_commits_per_hour, |
| 44 const base::Closure& no_bindings_callback, | 49 Delegate* delegate) |
| 45 const PrepareToCommitCallback& prepare_to_commit_callback) | |
| 46 : prefix_(leveldb::StdStringToUint8Vector(prefix)), | 50 : prefix_(leveldb::StdStringToUint8Vector(prefix)), |
| 47 no_bindings_callback_(no_bindings_callback), | 51 delegate_(delegate), |
| 48 prepare_to_commit_callback_(prepare_to_commit_callback), | |
| 49 database_(database), | 52 database_(database), |
| 50 bytes_used_(0), | 53 bytes_used_(0), |
| 51 max_size_(max_size), | 54 max_size_(max_size), |
| 52 start_time_(base::TimeTicks::Now()), | 55 start_time_(base::TimeTicks::Now()), |
| 53 default_commit_delay_(default_commit_delay), | 56 default_commit_delay_(default_commit_delay), |
| 54 data_rate_limiter_(max_bytes_per_hour, base::TimeDelta::FromHours(1)), | 57 data_rate_limiter_(max_bytes_per_hour, base::TimeDelta::FromHours(1)), |
| 55 commit_rate_limiter_(max_commits_per_hour, base::TimeDelta::FromHours(1)), | 58 commit_rate_limiter_(max_commits_per_hour, base::TimeDelta::FromHours(1)), |
| 56 weak_ptr_factory_(this) { | 59 weak_ptr_factory_(this) { |
| 57 bindings_.set_connection_error_handler(base::Bind( | 60 bindings_.set_connection_error_handler(base::Bind( |
| 58 &LevelDBWrapperImpl::OnConnectionError, base::Unretained(this))); | 61 &LevelDBWrapperImpl::OnConnectionError, base::Unretained(this))); |
| (...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 } | 247 } |
| 245 } | 248 } |
| 246 | 249 |
| 247 void LevelDBWrapperImpl::OnConnectionError() { | 250 void LevelDBWrapperImpl::OnConnectionError() { |
| 248 if (!bindings_.empty()) | 251 if (!bindings_.empty()) |
| 249 return; | 252 return; |
| 250 // If any tasks are waiting for load to complete, delay calling the | 253 // If any tasks are waiting for load to complete, delay calling the |
| 251 // no_bindings_callback_ until all those tasks have completed. | 254 // no_bindings_callback_ until all those tasks have completed. |
| 252 if (!on_load_complete_tasks_.empty()) | 255 if (!on_load_complete_tasks_.empty()) |
| 253 return; | 256 return; |
| 254 no_bindings_callback_.Run(); | 257 delegate_->OnNoBindings(); |
| 255 } | 258 } |
| 256 | 259 |
| 257 void LevelDBWrapperImpl::LoadMap(const base::Closure& completion_callback) { | 260 void LevelDBWrapperImpl::LoadMap(const base::Closure& completion_callback) { |
| 258 DCHECK(!map_); | 261 DCHECK(!map_); |
| 259 on_load_complete_tasks_.push_back(completion_callback); | 262 on_load_complete_tasks_.push_back(completion_callback); |
| 260 if (on_load_complete_tasks_.size() > 1) | 263 if (on_load_complete_tasks_.size() > 1) |
| 261 return; | 264 return; |
| 262 | 265 |
| 263 if (!database_) { | 266 if (!database_) { |
| 264 OnLoadComplete(leveldb::mojom::DatabaseError::IO_ERROR, | 267 OnMapLoaded(leveldb::mojom::DatabaseError::IO_ERROR, |
| 265 std::vector<leveldb::mojom::KeyValuePtr>()); | 268 std::vector<leveldb::mojom::KeyValuePtr>()); |
| 266 return; | 269 return; |
| 267 } | 270 } |
| 268 | 271 |
| 269 // TODO(michaeln): Import from sqlite localstorage db. | 272 // TODO(michaeln): Import from sqlite localstorage db. |
| 270 database_->GetPrefixed(prefix_, | 273 database_->GetPrefixed(prefix_, base::Bind(&LevelDBWrapperImpl::OnMapLoaded, |
| 271 base::Bind(&LevelDBWrapperImpl::OnLoadComplete, | 274 weak_ptr_factory_.GetWeakPtr())); |
| 272 weak_ptr_factory_.GetWeakPtr())); | |
| 273 } | 275 } |
| 274 | 276 |
| 275 void LevelDBWrapperImpl::OnLoadComplete( | 277 void LevelDBWrapperImpl::OnMapLoaded( |
| 276 leveldb::mojom::DatabaseError status, | 278 leveldb::mojom::DatabaseError status, |
| 277 std::vector<leveldb::mojom::KeyValuePtr> data) { | 279 std::vector<leveldb::mojom::KeyValuePtr> data) { |
| 278 DCHECK(!map_); | 280 DCHECK(!map_); |
| 281 |
| 282 if (data.empty() && status == leveldb::mojom::DatabaseError::OK) { |
| 283 delegate_->MigrateData( |
| 284 base::BindOnce(&LevelDBWrapperImpl::OnGotMigrationData, |
| 285 weak_ptr_factory_.GetWeakPtr())); |
| 286 return; |
| 287 } |
| 288 |
| 279 map_.reset(new ValueMap); | 289 map_.reset(new ValueMap); |
| 280 bytes_used_ = 0; | 290 bytes_used_ = 0; |
| 281 for (auto& it : data) { | 291 for (auto& it : data) { |
| 282 DCHECK_GE(it->key.size(), prefix_.size()); | 292 DCHECK_GE(it->key.size(), prefix_.size()); |
| 283 (*map_)[std::vector<uint8_t>(it->key.begin() + prefix_.size(), | 293 (*map_)[std::vector<uint8_t>(it->key.begin() + prefix_.size(), |
| 284 it->key.end())] = it->value; | 294 it->key.end())] = it->value; |
| 285 bytes_used_ += it->key.size() - prefix_.size() + it->value.size(); | 295 bytes_used_ += it->key.size() - prefix_.size() + it->value.size(); |
| 286 } | 296 } |
| 287 | 297 |
| 288 // We proceed without using a backing store, nothing will be persisted but the | 298 // We proceed without using a backing store, nothing will be persisted but the |
| 289 // class is functional for the lifetime of the object. | 299 // class is functional for the lifetime of the object. |
| 290 // TODO(michaeln): Uma here or in the DB file? | 300 // TODO(michaeln): Uma here or in the DB file? |
| 291 if (status != leveldb::mojom::DatabaseError::OK) | 301 if (status != leveldb::mojom::DatabaseError::OK) |
| 292 database_ = nullptr; | 302 database_ = nullptr; |
| 293 | 303 |
| 304 OnLoadComplete(); |
| 305 } |
| 306 |
| 307 void LevelDBWrapperImpl::OnGotMigrationData(std::unique_ptr<ValueMap> data) { |
| 308 map_ = data ? std::move(data) : base::MakeUnique<ValueMap>(); |
| 309 bytes_used_ = 0; |
| 310 for (const auto& it : *map_) |
| 311 bytes_used_ += it.first.size() + it.second.size(); |
| 312 |
| 313 if (database_ && !empty()) { |
| 314 CreateCommitBatchIfNeeded(); |
| 315 for (const auto& it : *map_) |
| 316 commit_batch_->changed_keys.insert(it.first); |
| 317 CommitChanges(); |
| 318 } |
| 319 |
| 320 OnLoadComplete(); |
| 321 } |
| 322 |
| 323 void LevelDBWrapperImpl::OnLoadComplete() { |
| 294 std::vector<base::Closure> tasks; | 324 std::vector<base::Closure> tasks; |
| 295 on_load_complete_tasks_.swap(tasks); | 325 on_load_complete_tasks_.swap(tasks); |
| 296 for (auto& task : tasks) | 326 for (auto& task : tasks) |
| 297 task.Run(); | 327 task.Run(); |
| 298 | 328 |
| 299 // We might need to call the no_bindings_callback_ here if bindings became | 329 // We might need to call the no_bindings_callback_ here if bindings became |
| 300 // empty while waiting for load to complete. | 330 // empty while waiting for load to complete. |
| 301 if (bindings_.empty()) | 331 if (bindings_.empty()) |
| 302 no_bindings_callback_.Run(); | 332 delegate_->OnNoBindings(); |
| 303 } | 333 } |
| 304 | 334 |
| 305 void LevelDBWrapperImpl::CreateCommitBatchIfNeeded() { | 335 void LevelDBWrapperImpl::CreateCommitBatchIfNeeded() { |
| 306 if (commit_batch_) | 336 if (commit_batch_) |
| 307 return; | 337 return; |
| 308 | 338 |
| 309 commit_batch_.reset(new CommitBatch()); | 339 commit_batch_.reset(new CommitBatch()); |
| 310 BrowserThread::PostAfterStartupTask( | 340 BrowserThread::PostAfterStartupTask( |
| 311 FROM_HERE, base::ThreadTaskRunnerHandle::Get(), | 341 FROM_HERE, base::ThreadTaskRunnerHandle::Get(), |
| 312 base::Bind(&LevelDBWrapperImpl::StartCommitTimer, | 342 base::Bind(&LevelDBWrapperImpl::StartCommitTimer, |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 345 void LevelDBWrapperImpl::CommitChanges() { | 375 void LevelDBWrapperImpl::CommitChanges() { |
| 346 DCHECK(database_); | 376 DCHECK(database_); |
| 347 DCHECK(map_); | 377 DCHECK(map_); |
| 348 if (!commit_batch_) | 378 if (!commit_batch_) |
| 349 return; | 379 return; |
| 350 | 380 |
| 351 commit_rate_limiter_.add_samples(1); | 381 commit_rate_limiter_.add_samples(1); |
| 352 | 382 |
| 353 // Commit all our changes in a single batch. | 383 // Commit all our changes in a single batch. |
| 354 std::vector<leveldb::mojom::BatchedOperationPtr> operations = | 384 std::vector<leveldb::mojom::BatchedOperationPtr> operations = |
| 355 prepare_to_commit_callback_.Run(*this); | 385 delegate_->PrepareToCommit(); |
| 356 if (commit_batch_->clear_all_first) { | 386 if (commit_batch_->clear_all_first) { |
| 357 leveldb::mojom::BatchedOperationPtr item = | 387 leveldb::mojom::BatchedOperationPtr item = |
| 358 leveldb::mojom::BatchedOperation::New(); | 388 leveldb::mojom::BatchedOperation::New(); |
| 359 item->type = leveldb::mojom::BatchOperationType::DELETE_PREFIXED_KEY; | 389 item->type = leveldb::mojom::BatchOperationType::DELETE_PREFIXED_KEY; |
| 360 item->key = prefix_; | 390 item->key = prefix_; |
| 361 operations.push_back(std::move(item)); | 391 operations.push_back(std::move(item)); |
| 362 } | 392 } |
| 363 size_t data_size = 0; | 393 size_t data_size = 0; |
| 364 for (const auto& key: commit_batch_->changed_keys) { | 394 for (const auto& key: commit_batch_->changed_keys) { |
| 365 data_size += key.size(); | 395 data_size += key.size(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 388 // will run during a clean shutdown. We need that to avoid dataloss. | 418 // will run during a clean shutdown. We need that to avoid dataloss. |
| 389 database_->Write(std::move(operations), | 419 database_->Write(std::move(operations), |
| 390 base::Bind(&LevelDBWrapperImpl::OnCommitComplete, | 420 base::Bind(&LevelDBWrapperImpl::OnCommitComplete, |
| 391 weak_ptr_factory_.GetWeakPtr())); | 421 weak_ptr_factory_.GetWeakPtr())); |
| 392 } | 422 } |
| 393 | 423 |
| 394 void LevelDBWrapperImpl::OnCommitComplete(leveldb::mojom::DatabaseError error) { | 424 void LevelDBWrapperImpl::OnCommitComplete(leveldb::mojom::DatabaseError error) { |
| 395 // TODO(michaeln): What if it fails, uma here or in the DB class? | 425 // TODO(michaeln): What if it fails, uma here or in the DB class? |
| 396 --commit_batches_in_flight_; | 426 --commit_batches_in_flight_; |
| 397 StartCommitTimer(); | 427 StartCommitTimer(); |
| 428 delegate_->DidCommit(error); |
| 398 } | 429 } |
| 399 | 430 |
| 400 } // namespace content | 431 } // namespace content |
| OLD | NEW |