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

Side by Side Diff: content/browser/indexed_db/leveldb/leveldb_transaction.cc

Issue 2719023007: IndexedDB: Optimize range deletion operations (e.g. clearing a store) (Closed)
Patch Set: Review feedback: docs and refactors Created 3 years, 9 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 unified diff | Download patch
OLDNEW
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"
11 #include "content/browser/indexed_db/indexed_db_tracing.h" 11 #include "content/browser/indexed_db/indexed_db_tracing.h"
12 #include "content/browser/indexed_db/leveldb/leveldb_database.h" 12 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
13 #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h" 13 #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h"
14 #include "third_party/leveldatabase/src/include/leveldb/db.h" 14 #include "third_party/leveldatabase/src/include/leveldb/db.h"
15 15
16 using base::StringPiece; 16 using base::StringPiece;
17 17
18 namespace {
19
20 // Tests if the given key is before the end of a range, which
21 // may have an open (exclusive) or closed (inclusive) bound.
22 bool IsKeyBeforeEndOfRange(const content::LevelDBComparator* comparator,
23 const StringPiece& key,
24 const StringPiece& end,
25 bool open) {
26 return (open ? comparator->Compare(key, end) < 0
27 : comparator->Compare(key, end) <= 0);
28 }
29
30 } // namespace
31
18 namespace content { 32 namespace content {
19 33
20 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db) 34 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db)
21 : db_(db), 35 : db_(db),
22 snapshot_(db), 36 snapshot_(db),
23 comparator_(db->Comparator()), 37 comparator_(db->Comparator()),
24 data_comparator_(comparator_), 38 data_comparator_(comparator_),
25 data_(data_comparator_), 39 data_(data_comparator_) {}
26 finished_(false) {}
27 40
28 LevelDBTransaction::Record::Record() : deleted(false) {} 41 LevelDBTransaction::Record::Record() {}
29 LevelDBTransaction::Record::~Record() {} 42 LevelDBTransaction::Record::~Record() {}
30 43
31 LevelDBTransaction::~LevelDBTransaction() {} 44 LevelDBTransaction::~LevelDBTransaction() {}
32 45
33 bool LevelDBTransaction::Set(const StringPiece& key, 46 void LevelDBTransaction::Set(const StringPiece& key,
34 std::string* value, 47 std::string* value,
35 bool deleted) { 48 bool deleted) {
36 DCHECK(!finished_); 49 DCHECK(!finished_);
37 DataType::iterator it = data_.find(key); 50 DataType::iterator it = data_.find(key);
38 51
39 if (it == data_.end()) { 52 if (it == data_.end()) {
40 std::unique_ptr<Record> record = base::MakeUnique<Record>(); 53 std::unique_ptr<Record> record = base::MakeUnique<Record>();
41 record->key.assign(key.begin(), key.end() - key.begin()); 54 record->key.assign(key.begin(), key.end() - key.begin());
42 record->value.swap(*value); 55 record->value.swap(*value);
43 record->deleted = deleted; 56 record->deleted = deleted;
44 data_[record->key] = std::move(record); 57 data_[record->key] = std::move(record);
45 NotifyIterators(); 58 NotifyIterators();
46 return false; 59 return;
47 } 60 }
48 bool replaced_deleted_value = it->second->deleted;
49 it->second->value.swap(*value); 61 it->second->value.swap(*value);
50 it->second->deleted = deleted; 62 it->second->deleted = deleted;
51 return replaced_deleted_value;
52 } 63 }
53 64
54 void LevelDBTransaction::Put(const StringPiece& key, std::string* value) { 65 void LevelDBTransaction::Put(const StringPiece& key, std::string* value) {
55 Set(key, value, false); 66 Set(key, value, false);
56 } 67 }
57 68
58 bool LevelDBTransaction::Remove(const StringPiece& key) { 69 void LevelDBTransaction::Remove(const StringPiece& key) {
59 std::string empty; 70 std::string empty;
60 return !Set(key, &empty, true); 71 Set(key, &empty, true);
72 }
73
74 leveldb::Status LevelDBTransaction::RemoveRange(const StringPiece& begin,
75 const StringPiece& end,
76 bool upper_open) {
77 leveldb::Status s;
78 bool dirty = false;
79 {
80 // Scope this iterator so it is deleted before other iterators are
81 // notified.
82 std::unique_ptr<TransactionIterator> it = TransactionIterator::Create(this);
83 for (s = it->Seek(begin);
84 s.ok() && it->IsValid() &&
85 IsKeyBeforeEndOfRange(comparator_, it->Key(), end, upper_open);
86 s = it->Next()) {
87 it->Delete();
88 dirty = true;
89 }
90 }
91 if (dirty)
92 NotifyIterators();
93 return s;
61 } 94 }
62 95
63 leveldb::Status LevelDBTransaction::Get(const StringPiece& key, 96 leveldb::Status LevelDBTransaction::Get(const StringPiece& key,
64 std::string* value, 97 std::string* value,
65 bool* found) { 98 bool* found) {
66 *found = false; 99 *found = false;
67 DCHECK(!finished_); 100 DCHECK(!finished_);
68 std::string string_key(key.begin(), key.end() - key.begin()); 101 std::string string_key(key.begin(), key.end() - key.begin());
69 DataType::const_iterator it = data_.find(string_key); 102 DataType::const_iterator it = data_.find(string_key);
70 103
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 DCHECK(IsValid()); 204 DCHECK(IsValid());
172 DCHECK(!IsDeleted()); 205 DCHECK(!IsDeleted());
173 return iterator_->second->value; 206 return iterator_->second->value;
174 } 207 }
175 208
176 bool LevelDBTransaction::DataIterator::IsDeleted() const { 209 bool LevelDBTransaction::DataIterator::IsDeleted() const {
177 DCHECK(IsValid()); 210 DCHECK(IsValid());
178 return iterator_->second->deleted; 211 return iterator_->second->deleted;
179 } 212 }
180 213
214 void LevelDBTransaction::DataIterator::Delete() {
215 DCHECK(IsValid());
216 iterator_->second->deleted = true;
217 iterator_->second->value.clear();
218 }
219
181 LevelDBTransaction::DataIterator::~DataIterator() {} 220 LevelDBTransaction::DataIterator::~DataIterator() {}
182 221
183 LevelDBTransaction::DataIterator::DataIterator(LevelDBTransaction* transaction) 222 LevelDBTransaction::DataIterator::DataIterator(LevelDBTransaction* transaction)
184 : data_(&transaction->data_), 223 : data_(&transaction->data_),
185 iterator_(data_->end()) {} 224 iterator_(data_->end()) {}
186 225
187 std::unique_ptr<LevelDBTransaction::TransactionIterator> 226 std::unique_ptr<LevelDBTransaction::TransactionIterator>
188 LevelDBTransaction::TransactionIterator::Create( 227 LevelDBTransaction::TransactionIterator::Create(
189 scoped_refptr<LevelDBTransaction> transaction) { 228 scoped_refptr<LevelDBTransaction> transaction) {
190 return base::WrapUnique(new TransactionIterator(transaction)); 229 return base::WrapUnique(new TransactionIterator(transaction));
191 } 230 }
192 231
193 LevelDBTransaction::TransactionIterator::TransactionIterator( 232 LevelDBTransaction::TransactionIterator::TransactionIterator(
194 scoped_refptr<LevelDBTransaction> transaction) 233 scoped_refptr<LevelDBTransaction> transaction)
195 : transaction_(transaction), 234 : transaction_(transaction),
196 comparator_(transaction_->comparator_), 235 comparator_(transaction_->comparator_),
197 data_iterator_(DataIterator::Create(transaction_.get())), 236 data_iterator_(DataIterator::Create(transaction_.get())),
198 db_iterator_(transaction_->db_->CreateIterator(&transaction_->snapshot_)), 237 db_iterator_(
199 current_(0), 238 transaction_->db_->CreateIterator(&transaction_->snapshot_)) {
200 direction_(FORWARD),
201 data_changed_(false) {
202 transaction_->RegisterIterator(this); 239 transaction_->RegisterIterator(this);
203 } 240 }
204 241
205 LevelDBTransaction::TransactionIterator::~TransactionIterator() { 242 LevelDBTransaction::TransactionIterator::~TransactionIterator() {
206 transaction_->UnregisterIterator(this); 243 transaction_->UnregisterIterator(this);
207 } 244 }
208 245
209 bool LevelDBTransaction::TransactionIterator::IsValid() const { 246 bool LevelDBTransaction::TransactionIterator::IsValid() const {
210 return !!current_; 247 return !!current_;
211 } 248 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 DCHECK(IsValid()); 361 DCHECK(IsValid());
325 if (data_changed_) 362 if (data_changed_)
326 RefreshDataIterator(); 363 RefreshDataIterator();
327 return current_->Value(); 364 return current_->Value();
328 } 365 }
329 366
330 void LevelDBTransaction::TransactionIterator::DataChanged() { 367 void LevelDBTransaction::TransactionIterator::DataChanged() {
331 data_changed_ = true; 368 data_changed_ = true;
332 } 369 }
333 370
371 void LevelDBTransaction::TransactionIterator::Delete() {
372 DCHECK(IsValid());
373 if (current_ == data_iterator_.get()) {
374 data_iterator_->Delete();
375 } else {
376 std::unique_ptr<Record> record = base::MakeUnique<Record>();
377 record->key = Key().as_string();
378 record->deleted = true;
379 transaction_->data_[record->key] = std::move(record);
380 }
381 }
382
334 void LevelDBTransaction::TransactionIterator::RefreshDataIterator() const { 383 void LevelDBTransaction::TransactionIterator::RefreshDataIterator() const {
335 DCHECK(data_changed_); 384 DCHECK(data_changed_);
336 385
337 data_changed_ = false; 386 data_changed_ = false;
338 387
339 if (data_iterator_->IsValid() && data_iterator_.get() == current_) { 388 if (data_iterator_->IsValid() && data_iterator_.get() == current_) {
340 return; 389 return;
341 } 390 }
342 391
343 if (db_iterator_->IsValid()) { 392 if (db_iterator_->IsValid()) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 (!db_iterator_->IsValid() || DataIteratorIsHigher())) { 445 (!db_iterator_->IsValid() || DataIteratorIsHigher())) {
397 data_iterator_->Prev(); 446 data_iterator_->Prev();
398 loop = true; 447 loop = true;
399 } 448 }
400 } 449 }
401 } 450 }
402 } 451 }
403 452
404 void 453 void
405 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() { 454 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() {
406 LevelDBIterator* smallest = 0; 455 LevelDBIterator* smallest = nullptr;
407 456
408 if (data_iterator_->IsValid()) 457 if (data_iterator_->IsValid())
409 smallest = data_iterator_.get(); 458 smallest = data_iterator_.get();
410 459
411 if (db_iterator_->IsValid()) { 460 if (db_iterator_->IsValid()) {
412 if (!smallest || 461 if (!smallest ||
413 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0) 462 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0)
414 smallest = db_iterator_.get(); 463 smallest = db_iterator_.get();
415 } 464 }
416 465
417 current_ = smallest; 466 current_ = smallest;
418 } 467 }
419 468
420 void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() { 469 void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() {
421 LevelDBIterator* largest = 0; 470 LevelDBIterator* largest = nullptr;
422 471
423 if (data_iterator_->IsValid()) 472 if (data_iterator_->IsValid())
424 largest = data_iterator_.get(); 473 largest = data_iterator_.get();
425 474
426 if (db_iterator_->IsValid()) { 475 if (db_iterator_->IsValid()) {
427 if (!largest || 476 if (!largest ||
428 comparator_->Compare(db_iterator_->Key(), largest->Key()) > 0) 477 comparator_->Compare(db_iterator_->Key(), largest->Key()) > 0)
429 largest = db_iterator_.get(); 478 largest = db_iterator_.get();
430 } 479 }
431 480
(...skipping 14 matching lines...) Expand all
446 for (auto* transaction_iterator : iterators_) 495 for (auto* transaction_iterator : iterators_)
447 transaction_iterator->DataChanged(); 496 transaction_iterator->DataChanged();
448 } 497 }
449 498
450 std::unique_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create( 499 std::unique_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create(
451 LevelDBDatabase* db) { 500 LevelDBDatabase* db) {
452 return base::WrapUnique(new LevelDBDirectTransaction(db)); 501 return base::WrapUnique(new LevelDBDirectTransaction(db));
453 } 502 }
454 503
455 LevelDBDirectTransaction::LevelDBDirectTransaction(LevelDBDatabase* db) 504 LevelDBDirectTransaction::LevelDBDirectTransaction(LevelDBDatabase* db)
456 : db_(db), write_batch_(LevelDBWriteBatch::Create()), finished_(false) {} 505 : db_(db), write_batch_(LevelDBWriteBatch::Create()) {}
457 506
458 LevelDBDirectTransaction::~LevelDBDirectTransaction() { 507 LevelDBDirectTransaction::~LevelDBDirectTransaction() {
459 write_batch_->Clear(); 508 write_batch_->Clear();
460 } 509 }
461 510
462 void LevelDBDirectTransaction::Put(const StringPiece& key, 511 void LevelDBDirectTransaction::Put(const StringPiece& key,
463 const std::string* value) { 512 const std::string* value) {
464 DCHECK(!finished_); 513 DCHECK(!finished_);
465 write_batch_->Put(key, *value); 514 write_batch_->Put(key, *value);
466 } 515 }
(...skipping 20 matching lines...) Expand all
487 536
488 leveldb::Status s = db_->Write(*write_batch_); 537 leveldb::Status s = db_->Write(*write_batch_);
489 if (s.ok()) { 538 if (s.ok()) {
490 finished_ = true; 539 finished_ = true;
491 write_batch_->Clear(); 540 write_batch_->Clear();
492 } 541 }
493 return s; 542 return s;
494 } 543 }
495 544
496 } // namespace content 545 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698