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

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: 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 content { 18 namespace content {
19 19
20 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db) 20 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db)
21 : db_(db), 21 : db_(db),
22 snapshot_(db), 22 snapshot_(db),
23 comparator_(db->Comparator()), 23 comparator_(db->Comparator()),
24 data_comparator_(comparator_), 24 data_comparator_(comparator_),
25 data_(data_comparator_), 25 data_(data_comparator_) {}
26 finished_(false) {}
27 26
28 LevelDBTransaction::Record::Record() : deleted(false) {} 27 LevelDBTransaction::Record::Record() {}
29 LevelDBTransaction::Record::~Record() {} 28 LevelDBTransaction::Record::~Record() {}
30 29
31 LevelDBTransaction::~LevelDBTransaction() {} 30 LevelDBTransaction::~LevelDBTransaction() {}
32 31
33 bool LevelDBTransaction::Set(const StringPiece& key, 32 void LevelDBTransaction::Set(const StringPiece& key,
34 std::string* value, 33 std::string* value,
35 bool deleted) { 34 bool deleted) {
36 DCHECK(!finished_); 35 DCHECK(!finished_);
37 DataType::iterator it = data_.find(key); 36 DataType::iterator it = data_.find(key);
38 37
39 if (it == data_.end()) { 38 if (it == data_.end()) {
40 std::unique_ptr<Record> record = base::MakeUnique<Record>(); 39 std::unique_ptr<Record> record = base::MakeUnique<Record>();
41 record->key.assign(key.begin(), key.end() - key.begin()); 40 record->key.assign(key.begin(), key.end() - key.begin());
42 record->value.swap(*value); 41 record->value.swap(*value);
43 record->deleted = deleted; 42 record->deleted = deleted;
44 data_[record->key] = std::move(record); 43 data_[record->key] = std::move(record);
45 NotifyIterators(); 44 NotifyIterators();
46 return false; 45 return;
47 } 46 }
48 bool replaced_deleted_value = it->second->deleted;
49 it->second->value.swap(*value); 47 it->second->value.swap(*value);
50 it->second->deleted = deleted; 48 it->second->deleted = deleted;
51 return replaced_deleted_value;
52 } 49 }
53 50
54 void LevelDBTransaction::Put(const StringPiece& key, std::string* value) { 51 void LevelDBTransaction::Put(const StringPiece& key, std::string* value) {
55 Set(key, value, false); 52 Set(key, value, false);
56 } 53 }
57 54
58 bool LevelDBTransaction::Remove(const StringPiece& key) { 55 void LevelDBTransaction::Remove(const StringPiece& key) {
59 std::string empty; 56 std::string empty;
60 return !Set(key, &empty, true); 57 Set(key, &empty, true);
58 }
59
60 leveldb::Status LevelDBTransaction::RemoveRange(const StringPiece& begin,
61 const StringPiece& end,
62 bool upper_open) {
63 leveldb::Status s;
64 bool dirty = false;
65 {
66 // Scope this iterator so it is deleted before other iterators are
67 // notified.
68 std::unique_ptr<TransactionIterator> it = TransactionIterator::Create(this);
69 for (s = it->Seek(begin);
70 s.ok() && it->IsValid() &&
71 (upper_open ? comparator_->Compare(it->Key(), end) < 0
dmurph 2017/03/01 20:06:35 Can you pull this out into a static helper method?
jsbell 2017/03/01 22:45:25 Done. Feedback welcome!
72 : comparator_->Compare(it->Key(), end) <= 0);
73 s = it->Next()) {
74 if (!it->DeleteData()) {
75 std::unique_ptr<Record> record = base::MakeUnique<Record>();
76 record->key = it->Key().as_string();
77 record->deleted = true;
78 data_[record->key] = std::move(record);
79 }
80 dirty = true;
81 }
82 }
83 if (dirty)
84 NotifyIterators();
85 return s;
61 } 86 }
62 87
63 leveldb::Status LevelDBTransaction::Get(const StringPiece& key, 88 leveldb::Status LevelDBTransaction::Get(const StringPiece& key,
64 std::string* value, 89 std::string* value,
65 bool* found) { 90 bool* found) {
66 *found = false; 91 *found = false;
67 DCHECK(!finished_); 92 DCHECK(!finished_);
68 std::string string_key(key.begin(), key.end() - key.begin()); 93 std::string string_key(key.begin(), key.end() - key.begin());
69 DataType::const_iterator it = data_.find(string_key); 94 DataType::const_iterator it = data_.find(string_key);
70 95
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
171 DCHECK(IsValid()); 196 DCHECK(IsValid());
172 DCHECK(!IsDeleted()); 197 DCHECK(!IsDeleted());
173 return iterator_->second->value; 198 return iterator_->second->value;
174 } 199 }
175 200
176 bool LevelDBTransaction::DataIterator::IsDeleted() const { 201 bool LevelDBTransaction::DataIterator::IsDeleted() const {
177 DCHECK(IsValid()); 202 DCHECK(IsValid());
178 return iterator_->second->deleted; 203 return iterator_->second->deleted;
179 } 204 }
180 205
206 void LevelDBTransaction::DataIterator::Delete() {
207 DCHECK(IsValid());
208 iterator_->second->deleted = true;
209 iterator_->second->value.clear();
210 }
211
181 LevelDBTransaction::DataIterator::~DataIterator() {} 212 LevelDBTransaction::DataIterator::~DataIterator() {}
182 213
183 LevelDBTransaction::DataIterator::DataIterator(LevelDBTransaction* transaction) 214 LevelDBTransaction::DataIterator::DataIterator(LevelDBTransaction* transaction)
184 : data_(&transaction->data_), 215 : data_(&transaction->data_),
185 iterator_(data_->end()) {} 216 iterator_(data_->end()) {}
186 217
187 std::unique_ptr<LevelDBTransaction::TransactionIterator> 218 std::unique_ptr<LevelDBTransaction::TransactionIterator>
188 LevelDBTransaction::TransactionIterator::Create( 219 LevelDBTransaction::TransactionIterator::Create(
189 scoped_refptr<LevelDBTransaction> transaction) { 220 scoped_refptr<LevelDBTransaction> transaction) {
190 return base::WrapUnique(new TransactionIterator(transaction)); 221 return base::WrapUnique(new TransactionIterator(transaction));
191 } 222 }
192 223
193 LevelDBTransaction::TransactionIterator::TransactionIterator( 224 LevelDBTransaction::TransactionIterator::TransactionIterator(
194 scoped_refptr<LevelDBTransaction> transaction) 225 scoped_refptr<LevelDBTransaction> transaction)
195 : transaction_(transaction), 226 : transaction_(transaction),
196 comparator_(transaction_->comparator_), 227 comparator_(transaction_->comparator_),
197 data_iterator_(DataIterator::Create(transaction_.get())), 228 data_iterator_(DataIterator::Create(transaction_.get())),
198 db_iterator_(transaction_->db_->CreateIterator(&transaction_->snapshot_)), 229 db_iterator_(
199 current_(0), 230 transaction_->db_->CreateIterator(&transaction_->snapshot_)) {
200 direction_(FORWARD),
201 data_changed_(false) {
202 transaction_->RegisterIterator(this); 231 transaction_->RegisterIterator(this);
203 } 232 }
204 233
205 LevelDBTransaction::TransactionIterator::~TransactionIterator() { 234 LevelDBTransaction::TransactionIterator::~TransactionIterator() {
206 transaction_->UnregisterIterator(this); 235 transaction_->UnregisterIterator(this);
207 } 236 }
208 237
209 bool LevelDBTransaction::TransactionIterator::IsValid() const { 238 bool LevelDBTransaction::TransactionIterator::IsValid() const {
210 return !!current_; 239 return !!current_;
211 } 240 }
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
324 DCHECK(IsValid()); 353 DCHECK(IsValid());
325 if (data_changed_) 354 if (data_changed_)
326 RefreshDataIterator(); 355 RefreshDataIterator();
327 return current_->Value(); 356 return current_->Value();
328 } 357 }
329 358
330 void LevelDBTransaction::TransactionIterator::DataChanged() { 359 void LevelDBTransaction::TransactionIterator::DataChanged() {
331 data_changed_ = true; 360 data_changed_ = true;
332 } 361 }
333 362
363 bool LevelDBTransaction::TransactionIterator::DeleteData() {
364 DCHECK(IsValid());
365 if (current_ == data_iterator_.get()) {
366 data_iterator_->Delete();
367 return true;
368 }
369 return false;
370 }
371
334 void LevelDBTransaction::TransactionIterator::RefreshDataIterator() const { 372 void LevelDBTransaction::TransactionIterator::RefreshDataIterator() const {
335 DCHECK(data_changed_); 373 DCHECK(data_changed_);
336 374
337 data_changed_ = false; 375 data_changed_ = false;
338 376
339 if (data_iterator_->IsValid() && data_iterator_.get() == current_) { 377 if (data_iterator_->IsValid() && data_iterator_.get() == current_) {
340 return; 378 return;
341 } 379 }
342 380
343 if (db_iterator_->IsValid()) { 381 if (db_iterator_->IsValid()) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
396 (!db_iterator_->IsValid() || DataIteratorIsHigher())) { 434 (!db_iterator_->IsValid() || DataIteratorIsHigher())) {
397 data_iterator_->Prev(); 435 data_iterator_->Prev();
398 loop = true; 436 loop = true;
399 } 437 }
400 } 438 }
401 } 439 }
402 } 440 }
403 441
404 void 442 void
405 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() { 443 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() {
406 LevelDBIterator* smallest = 0; 444 LevelDBIterator* smallest = nullptr;
407 445
408 if (data_iterator_->IsValid()) 446 if (data_iterator_->IsValid())
409 smallest = data_iterator_.get(); 447 smallest = data_iterator_.get();
410 448
411 if (db_iterator_->IsValid()) { 449 if (db_iterator_->IsValid()) {
412 if (!smallest || 450 if (!smallest ||
413 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0) 451 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0)
414 smallest = db_iterator_.get(); 452 smallest = db_iterator_.get();
415 } 453 }
416 454
417 current_ = smallest; 455 current_ = smallest;
418 } 456 }
419 457
420 void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() { 458 void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() {
421 LevelDBIterator* largest = 0; 459 LevelDBIterator* largest = nullptr;
422 460
423 if (data_iterator_->IsValid()) 461 if (data_iterator_->IsValid())
424 largest = data_iterator_.get(); 462 largest = data_iterator_.get();
425 463
426 if (db_iterator_->IsValid()) { 464 if (db_iterator_->IsValid()) {
427 if (!largest || 465 if (!largest ||
428 comparator_->Compare(db_iterator_->Key(), largest->Key()) > 0) 466 comparator_->Compare(db_iterator_->Key(), largest->Key()) > 0)
429 largest = db_iterator_.get(); 467 largest = db_iterator_.get();
430 } 468 }
431 469
(...skipping 14 matching lines...) Expand all
446 for (auto* transaction_iterator : iterators_) 484 for (auto* transaction_iterator : iterators_)
447 transaction_iterator->DataChanged(); 485 transaction_iterator->DataChanged();
448 } 486 }
449 487
450 std::unique_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create( 488 std::unique_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create(
451 LevelDBDatabase* db) { 489 LevelDBDatabase* db) {
452 return base::WrapUnique(new LevelDBDirectTransaction(db)); 490 return base::WrapUnique(new LevelDBDirectTransaction(db));
453 } 491 }
454 492
455 LevelDBDirectTransaction::LevelDBDirectTransaction(LevelDBDatabase* db) 493 LevelDBDirectTransaction::LevelDBDirectTransaction(LevelDBDatabase* db)
456 : db_(db), write_batch_(LevelDBWriteBatch::Create()), finished_(false) {} 494 : db_(db), write_batch_(LevelDBWriteBatch::Create()) {}
457 495
458 LevelDBDirectTransaction::~LevelDBDirectTransaction() { 496 LevelDBDirectTransaction::~LevelDBDirectTransaction() {
459 write_batch_->Clear(); 497 write_batch_->Clear();
460 } 498 }
461 499
462 void LevelDBDirectTransaction::Put(const StringPiece& key, 500 void LevelDBDirectTransaction::Put(const StringPiece& key,
463 const std::string* value) { 501 const std::string* value) {
464 DCHECK(!finished_); 502 DCHECK(!finished_);
465 write_batch_->Put(key, *value); 503 write_batch_->Put(key, *value);
466 } 504 }
(...skipping 20 matching lines...) Expand all
487 525
488 leveldb::Status s = db_->Write(*write_batch_); 526 leveldb::Status s = db_->Write(*write_batch_);
489 if (s.ok()) { 527 if (s.ok()) {
490 finished_ = true; 528 finished_ = true;
491 write_batch_->Clear(); 529 write_batch_->Clear();
492 } 530 }
493 return s; 531 return s;
494 } 532 }
495 533
496 } // namespace content 534 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698