| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/indexed_db/leveldb/leveldb_transaction.h" | 5 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
| 10 #include "base/time/time.h" | 10 #include "base/time/time.h" |
| (...skipping 23 matching lines...) Expand all Loading... |
| 34 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db) | 34 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db) |
| 35 : db_(db), | 35 : db_(db), |
| 36 snapshot_(db), | 36 snapshot_(db), |
| 37 comparator_(db->Comparator()), | 37 comparator_(db->Comparator()), |
| 38 data_comparator_(comparator_), | 38 data_comparator_(comparator_), |
| 39 data_(data_comparator_) {} | 39 data_(data_comparator_) {} |
| 40 | 40 |
| 41 LevelDBTransaction::Record::Record() {} | 41 LevelDBTransaction::Record::Record() {} |
| 42 LevelDBTransaction::Record::~Record() {} | 42 LevelDBTransaction::Record::~Record() {} |
| 43 | 43 |
| 44 LevelDBTransaction::~LevelDBTransaction() {} | 44 LevelDBTransaction::~LevelDBTransaction() { |
| 45 for (TransactionIterator* iter : iterators_) { |
| 46 db_->NotifyIteratorDestroyed(iter); |
| 47 } |
| 48 } |
| 45 | 49 |
| 46 void LevelDBTransaction::Set(const StringPiece& key, | 50 void LevelDBTransaction::Set(const StringPiece& key, |
| 47 std::string* value, | 51 std::string* value, |
| 48 bool deleted) { | 52 bool deleted) { |
| 49 DCHECK(!finished_); | 53 DCHECK(!finished_); |
| 50 DataType::iterator it = data_.find(key); | 54 DataType::iterator it = data_.find(key); |
| 51 | 55 |
| 52 if (it == data_.end()) { | 56 if (it == data_.end()) { |
| 53 std::unique_ptr<Record> record = base::MakeUnique<Record>(); | 57 std::unique_ptr<Record> record = base::MakeUnique<Record>(); |
| 54 record->key.assign(key.begin(), key.end() - key.begin()); | 58 record->key.assign(key.begin(), key.end() - key.begin()); |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 | 245 |
| 242 LevelDBTransaction::TransactionIterator::~TransactionIterator() { | 246 LevelDBTransaction::TransactionIterator::~TransactionIterator() { |
| 243 transaction_->UnregisterIterator(this); | 247 transaction_->UnregisterIterator(this); |
| 244 } | 248 } |
| 245 | 249 |
| 246 bool LevelDBTransaction::TransactionIterator::IsValid() const { | 250 bool LevelDBTransaction::TransactionIterator::IsValid() const { |
| 247 return !!current_; | 251 return !!current_; |
| 248 } | 252 } |
| 249 | 253 |
| 250 leveldb::Status LevelDBTransaction::TransactionIterator::SeekToLast() { | 254 leveldb::Status LevelDBTransaction::TransactionIterator::SeekToLast() { |
| 255 LoadDBIteratorIfEvicted(); |
| 251 leveldb::Status s = data_iterator_->SeekToLast(); | 256 leveldb::Status s = data_iterator_->SeekToLast(); |
| 252 DCHECK(s.ok()); | 257 DCHECK(s.ok()); |
| 253 s = db_iterator_->SeekToLast(); | 258 s = db_iterator_->SeekToLast(); |
| 254 if (!s.ok()) | 259 if (!s.ok()) |
| 255 return s; | 260 return s; |
| 256 direction_ = REVERSE; | 261 direction_ = REVERSE; |
| 257 | 262 |
| 258 HandleConflictsAndDeletes(); | 263 HandleConflictsAndDeletes(); |
| 259 SetCurrentIteratorToLargestKey(); | 264 SetCurrentIteratorToLargestKey(); |
| 260 return s; | 265 return s; |
| 261 } | 266 } |
| 262 | 267 |
| 263 leveldb::Status LevelDBTransaction::TransactionIterator::Seek( | 268 leveldb::Status LevelDBTransaction::TransactionIterator::Seek( |
| 264 const StringPiece& target) { | 269 const StringPiece& target) { |
| 270 LoadDBIteratorIfEvicted(); |
| 265 leveldb::Status s = data_iterator_->Seek(target); | 271 leveldb::Status s = data_iterator_->Seek(target); |
| 266 DCHECK(s.ok()); | 272 DCHECK(s.ok()); |
| 267 s = db_iterator_->Seek(target); | 273 s = db_iterator_->Seek(target); |
| 268 if (!s.ok()) | 274 if (!s.ok()) |
| 269 return s; | 275 return s; |
| 270 direction_ = FORWARD; | 276 direction_ = FORWARD; |
| 271 | 277 |
| 272 HandleConflictsAndDeletes(); | 278 HandleConflictsAndDeletes(); |
| 273 SetCurrentIteratorToSmallestKey(); | 279 SetCurrentIteratorToSmallestKey(); |
| 274 return s; | 280 return s; |
| 275 } | 281 } |
| 276 | 282 |
| 277 leveldb::Status LevelDBTransaction::TransactionIterator::Next() { | 283 leveldb::Status LevelDBTransaction::TransactionIterator::Next() { |
| 284 LoadDBIteratorIfEvicted(); |
| 278 DCHECK(IsValid()); | 285 DCHECK(IsValid()); |
| 279 if (data_changed_) | 286 if (data_changed_) |
| 280 RefreshDataIterator(); | 287 RefreshDataIterator(); |
| 281 | 288 |
| 282 leveldb::Status s; | 289 leveldb::Status s; |
| 283 if (direction_ != FORWARD) { | 290 if (direction_ != FORWARD) { |
| 284 // Ensure the non-current iterator is positioned after Key(). | 291 // Ensure the non-current iterator is positioned after Key(). |
| 285 | 292 |
| 286 LevelDBIterator* non_current = (current_ == db_iterator_.get()) | 293 LevelDBIterator* non_current = (current_ == db_iterator_.get()) |
| 287 ? data_iterator_.get() | 294 ? data_iterator_.get() |
| (...skipping 16 matching lines...) Expand all Loading... |
| 304 | 311 |
| 305 s = current_->Next(); | 312 s = current_->Next(); |
| 306 if (!s.ok()) | 313 if (!s.ok()) |
| 307 return s; | 314 return s; |
| 308 HandleConflictsAndDeletes(); | 315 HandleConflictsAndDeletes(); |
| 309 SetCurrentIteratorToSmallestKey(); | 316 SetCurrentIteratorToSmallestKey(); |
| 310 return leveldb::Status::OK(); | 317 return leveldb::Status::OK(); |
| 311 } | 318 } |
| 312 | 319 |
| 313 leveldb::Status LevelDBTransaction::TransactionIterator::Prev() { | 320 leveldb::Status LevelDBTransaction::TransactionIterator::Prev() { |
| 321 LoadDBIteratorIfEvicted(); |
| 314 DCHECK(IsValid()); | 322 DCHECK(IsValid()); |
| 315 leveldb::Status s; | 323 leveldb::Status s; |
| 316 if (data_changed_) | 324 if (data_changed_) |
| 317 RefreshDataIterator(); | 325 RefreshDataIterator(); |
| 318 | 326 |
| 319 if (direction_ != REVERSE) { | 327 if (direction_ != REVERSE) { |
| 320 // Ensure the non-current iterator is positioned before Key(). | 328 // Ensure the non-current iterator is positioned before Key(). |
| 321 | 329 |
| 322 LevelDBIterator* non_current = (current_ == db_iterator_.get()) | 330 LevelDBIterator* non_current = (current_ == db_iterator_.get()) |
| 323 ? data_iterator_.get() | 331 ? data_iterator_.get() |
| (...skipping 23 matching lines...) Expand all Loading... |
| 347 return s; | 355 return s; |
| 348 HandleConflictsAndDeletes(); | 356 HandleConflictsAndDeletes(); |
| 349 SetCurrentIteratorToLargestKey(); | 357 SetCurrentIteratorToLargestKey(); |
| 350 return leveldb::Status::OK(); | 358 return leveldb::Status::OK(); |
| 351 } | 359 } |
| 352 | 360 |
| 353 StringPiece LevelDBTransaction::TransactionIterator::Key() const { | 361 StringPiece LevelDBTransaction::TransactionIterator::Key() const { |
| 354 DCHECK(IsValid()); | 362 DCHECK(IsValid()); |
| 355 if (data_changed_) | 363 if (data_changed_) |
| 356 RefreshDataIterator(); | 364 RefreshDataIterator(); |
| 365 if (current_ == db_iterator_.get() && is_evicted_) { |
| 366 return key_after_eviction_; |
| 367 } |
| 357 return current_->Key(); | 368 return current_->Key(); |
| 358 } | 369 } |
| 359 | 370 |
| 360 StringPiece LevelDBTransaction::TransactionIterator::Value() const { | 371 StringPiece LevelDBTransaction::TransactionIterator::Value() const { |
| 361 DCHECK(IsValid()); | 372 DCHECK(IsValid()); |
| 362 if (data_changed_) | 373 if (data_changed_) |
| 363 RefreshDataIterator(); | 374 RefreshDataIterator(); |
| 375 if (current_ == db_iterator_.get()) { |
| 376 const_cast<LevelDBTransaction::TransactionIterator*>(this) |
| 377 ->LoadDBIteratorIfEvicted(); |
| 378 } |
| 364 return current_->Value(); | 379 return current_->Value(); |
| 365 } | 380 } |
| 366 | 381 |
| 382 void LevelDBTransaction::TransactionIterator::EvictWorkingMemory() { |
| 383 DCHECK(!is_evicted_); |
| 384 is_evicted_ = true; |
| 385 key_after_eviction_ = db_iterator_->Key().as_string(); |
| 386 db_iterator_.reset(); |
| 387 } |
| 388 |
| 367 void LevelDBTransaction::TransactionIterator::DataChanged() { | 389 void LevelDBTransaction::TransactionIterator::DataChanged() { |
| 368 data_changed_ = true; | 390 data_changed_ = true; |
| 369 } | 391 } |
| 370 | 392 |
| 371 void LevelDBTransaction::TransactionIterator::Delete() { | 393 void LevelDBTransaction::TransactionIterator::Delete() { |
| 372 DCHECK(IsValid()); | 394 DCHECK(IsValid()); |
| 373 if (current_ == data_iterator_.get()) { | 395 if (current_ == data_iterator_.get()) { |
| 374 data_iterator_->Delete(); | 396 data_iterator_->Delete(); |
| 375 } else { | 397 } else { |
| 376 std::unique_ptr<Record> record = base::MakeUnique<Record>(); | 398 std::unique_ptr<Record> record = base::MakeUnique<Record>(); |
| (...skipping 27 matching lines...) Expand all Loading... |
| 404 // If going backward, seek to a key less than the db iterator. | 426 // If going backward, seek to a key less than the db iterator. |
| 405 DCHECK_EQ(REVERSE, direction_); | 427 DCHECK_EQ(REVERSE, direction_); |
| 406 data_iterator_->Seek(db_iterator_->Key()); | 428 data_iterator_->Seek(db_iterator_->Key()); |
| 407 if (data_iterator_->IsValid()) | 429 if (data_iterator_->IsValid()) |
| 408 data_iterator_->Prev(); | 430 data_iterator_->Prev(); |
| 409 } | 431 } |
| 410 } | 432 } |
| 411 } | 433 } |
| 412 | 434 |
| 413 bool LevelDBTransaction::TransactionIterator::DataIteratorIsLower() const { | 435 bool LevelDBTransaction::TransactionIterator::DataIteratorIsLower() const { |
| 436 DCHECK(!is_evicted_); |
| 414 return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) < 0; | 437 return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) < 0; |
| 415 } | 438 } |
| 416 | 439 |
| 417 bool LevelDBTransaction::TransactionIterator::DataIteratorIsHigher() const { | 440 bool LevelDBTransaction::TransactionIterator::DataIteratorIsHigher() const { |
| 441 DCHECK(!is_evicted_); |
| 418 return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) > 0; | 442 return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) > 0; |
| 419 } | 443 } |
| 420 | 444 |
| 445 void LevelDBTransaction::TransactionIterator::LoadDBIteratorIfEvicted() { |
| 446 transaction_->db_->NotifyIteratorUsed(this); |
| 447 if (!is_evicted_) |
| 448 return; |
| 449 |
| 450 db_iterator_ = transaction_->db_->CreateIterator(&transaction_->snapshot_); |
| 451 db_iterator_->Seek(key_after_eviction_); |
| 452 key_after_eviction_.clear(); |
| 453 is_evicted_ = false; |
| 454 } |
| 455 |
| 421 void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() { | 456 void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() { |
| 457 LoadDBIteratorIfEvicted(); |
| 422 bool loop = true; | 458 bool loop = true; |
| 423 | 459 |
| 424 while (loop) { | 460 while (loop) { |
| 425 loop = false; | 461 loop = false; |
| 426 | 462 |
| 427 if (data_iterator_->IsValid() && db_iterator_->IsValid() && | 463 if (data_iterator_->IsValid() && db_iterator_->IsValid() && |
| 428 !comparator_->Compare(data_iterator_->Key(), db_iterator_->Key())) { | 464 !comparator_->Compare(data_iterator_->Key(), db_iterator_->Key())) { |
| 429 // For equal keys, the data iterator takes precedence, so move the | 465 // For equal keys, the data iterator takes precedence, so move the |
| 430 // database iterator another step. | 466 // database iterator another step. |
| 431 if (direction_ == FORWARD) | 467 if (direction_ == FORWARD) |
| (...skipping 13 matching lines...) Expand all Loading... |
| 445 (!db_iterator_->IsValid() || DataIteratorIsHigher())) { | 481 (!db_iterator_->IsValid() || DataIteratorIsHigher())) { |
| 446 data_iterator_->Prev(); | 482 data_iterator_->Prev(); |
| 447 loop = true; | 483 loop = true; |
| 448 } | 484 } |
| 449 } | 485 } |
| 450 } | 486 } |
| 451 } | 487 } |
| 452 | 488 |
| 453 void | 489 void |
| 454 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() { | 490 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() { |
| 491 DCHECK(!is_evicted_); |
| 455 LevelDBIterator* smallest = nullptr; | 492 LevelDBIterator* smallest = nullptr; |
| 456 | 493 |
| 457 if (data_iterator_->IsValid()) | 494 if (data_iterator_->IsValid()) |
| 458 smallest = data_iterator_.get(); | 495 smallest = data_iterator_.get(); |
| 459 | 496 |
| 460 if (db_iterator_->IsValid()) { | 497 if (db_iterator_->IsValid()) { |
| 461 if (!smallest || | 498 if (!smallest || |
| 462 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0) | 499 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0) |
| 463 smallest = db_iterator_.get(); | 500 smallest = db_iterator_.get(); |
| 464 } | 501 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 482 } | 519 } |
| 483 | 520 |
| 484 void LevelDBTransaction::RegisterIterator(TransactionIterator* iterator) { | 521 void LevelDBTransaction::RegisterIterator(TransactionIterator* iterator) { |
| 485 DCHECK(iterators_.find(iterator) == iterators_.end()); | 522 DCHECK(iterators_.find(iterator) == iterators_.end()); |
| 486 iterators_.insert(iterator); | 523 iterators_.insert(iterator); |
| 487 } | 524 } |
| 488 | 525 |
| 489 void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) { | 526 void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) { |
| 490 DCHECK(iterators_.find(iterator) != iterators_.end()); | 527 DCHECK(iterators_.find(iterator) != iterators_.end()); |
| 491 iterators_.erase(iterator); | 528 iterators_.erase(iterator); |
| 529 db_->NotifyIteratorDestroyed(iterator); |
| 492 } | 530 } |
| 493 | 531 |
| 494 void LevelDBTransaction::NotifyIterators() { | 532 void LevelDBTransaction::NotifyIterators() { |
| 495 for (auto* transaction_iterator : iterators_) | 533 for (auto* transaction_iterator : iterators_) |
| 496 transaction_iterator->DataChanged(); | 534 transaction_iterator->DataChanged(); |
| 497 } | 535 } |
| 498 | 536 |
| 499 std::unique_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create( | 537 std::unique_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create( |
| 500 LevelDBDatabase* db) { | 538 LevelDBDatabase* db) { |
| 501 return base::WrapUnique(new LevelDBDirectTransaction(db)); | 539 return base::WrapUnique(new LevelDBDirectTransaction(db)); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 | 574 |
| 537 leveldb::Status s = db_->Write(*write_batch_); | 575 leveldb::Status s = db_->Write(*write_batch_); |
| 538 if (s.ok()) { | 576 if (s.ok()) { |
| 539 finished_ = true; | 577 finished_ = true; |
| 540 write_batch_->Clear(); | 578 write_batch_->Clear(); |
| 541 } | 579 } |
| 542 return s; | 580 return s; |
| 543 } | 581 } |
| 544 | 582 |
| 545 } // namespace content | 583 } // namespace content |
| OLD | NEW |