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

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

Issue 2760163002: [IndexedDB] Pool and evict leveldb iterators, to save memory (Closed)
Patch Set: comments 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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_iterator_impl.h" 5 #include "content/browser/indexed_db/leveldb/leveldb_iterator_impl.h"
6 6
7 #include <memory> 7 #include <memory>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "content/browser/indexed_db/leveldb/leveldb_iterator_pool_controller.h"
11 12
12 static leveldb::Slice MakeSlice(const base::StringPiece& s) { 13 static leveldb::Slice MakeSlice(const base::StringPiece& s) {
13 return leveldb::Slice(s.begin(), s.size()); 14 return leveldb::Slice(s.begin(), s.size());
14 } 15 }
15 16
16 static base::StringPiece MakeStringPiece(const leveldb::Slice& s) { 17 static base::StringPiece MakeStringPiece(const leveldb::Slice& s) {
17 return base::StringPiece(s.data(), s.size()); 18 return base::StringPiece(s.data(), s.size());
18 } 19 }
19 20
20 namespace content { 21 namespace content {
21 22
22 LevelDBIteratorImpl::~LevelDBIteratorImpl() { 23 LevelDBIteratorImpl::~LevelDBIteratorImpl() {
23 } 24 }
24 25
25 LevelDBIteratorImpl::LevelDBIteratorImpl(std::unique_ptr<leveldb::Iterator> it) 26 LevelDBIteratorImpl::LevelDBIteratorImpl(
26 : iterator_(std::move(it)) {} 27 std::unique_ptr<leveldb::Iterator> it,
28 LevelDBIteratorPoolController* pool_controller,
29 const leveldb::Snapshot* snapshot)
30 : iterator_(std::move(it)),
31 pool_controller_(pool_controller),
32 snapshot_(snapshot) {}
27 33
28 void LevelDBIteratorImpl::CheckStatus() { 34 void LevelDBIteratorImpl::CheckStatus() {
35 DCHECK_EQ(iterator_state_, IteratorState::ACTIVE);
29 const leveldb::Status& s = iterator_->status(); 36 const leveldb::Status& s = iterator_->status();
30 if (!s.ok()) 37 if (!s.ok())
31 LOG(ERROR) << "LevelDB iterator error: " << s.ToString(); 38 LOG(ERROR) << "LevelDB iterator error: " << s.ToString();
32 } 39 }
33 40
34 bool LevelDBIteratorImpl::IsValid() const { 41 bool LevelDBIteratorImpl::IsValid() const {
35 return iterator_->Valid(); 42 return iterator_state_ == IteratorState::EVICTED_AND_VALID ||
43 iterator_->Valid();
36 } 44 }
37 45
38 leveldb::Status LevelDBIteratorImpl::SeekToLast() { 46 leveldb::Status LevelDBIteratorImpl::SeekToLast() {
47 RecordUsage();
48 RestoreDBIteratorIfEvicted();
39 iterator_->SeekToLast(); 49 iterator_->SeekToLast();
40 CheckStatus(); 50 CheckStatus();
41 return iterator_->status(); 51 return iterator_->status();
42 } 52 }
43 53
44 leveldb::Status LevelDBIteratorImpl::Seek(const base::StringPiece& target) { 54 leveldb::Status LevelDBIteratorImpl::Seek(const base::StringPiece& target) {
55 RecordUsage();
56 RestoreDBIteratorIfEvicted();
45 iterator_->Seek(MakeSlice(target)); 57 iterator_->Seek(MakeSlice(target));
46 CheckStatus(); 58 CheckStatus();
47 return iterator_->status(); 59 return iterator_->status();
48 } 60 }
49 61
50 leveldb::Status LevelDBIteratorImpl::Next() { 62 leveldb::Status LevelDBIteratorImpl::Next() {
51 DCHECK(IsValid()); 63 DCHECK(IsValid());
64 RecordUsage();
65 RestoreDBIteratorIfEvicted();
52 iterator_->Next(); 66 iterator_->Next();
53 CheckStatus(); 67 CheckStatus();
54 return iterator_->status(); 68 return iterator_->status();
55 } 69 }
56 70
57 leveldb::Status LevelDBIteratorImpl::Prev() { 71 leveldb::Status LevelDBIteratorImpl::Prev() {
58 DCHECK(IsValid()); 72 DCHECK(IsValid());
73 RecordUsage();
74 RestoreDBIteratorIfEvicted();
59 iterator_->Prev(); 75 iterator_->Prev();
60 CheckStatus(); 76 CheckStatus();
61 return iterator_->status(); 77 return iterator_->status();
62 } 78 }
63 79
64 base::StringPiece LevelDBIteratorImpl::Key() const { 80 base::StringPiece LevelDBIteratorImpl::Key() const {
65 DCHECK(IsValid()); 81 DCHECK(IsValid());
66 return MakeStringPiece(iterator_->key()); 82 return MakeStringPiece(iterator_->key());
jsbell 2017/03/23 21:48:21 Doesn't this need to use key_before_eviction_ if e
dmurph 2017/03/23 22:48:46 Ah! Thanks for catching this. Didn't transfer in r
67 } 83 }
68 84
69 base::StringPiece LevelDBIteratorImpl::Value() const { 85 base::StringPiece LevelDBIteratorImpl::Value() const {
70 DCHECK(IsValid()); 86 DCHECK(IsValid());
87 // Always need to update the LRU, so we always call this. Const-cast needed,
88 // as we're dealing with a caching layer.
jsbell 2017/03/23 21:48:21 Can you see if making iterator_state_, key_before_
dmurph 2017/03/23 22:48:47 Since this would require making all member variabl
89 LevelDBIteratorImpl* non_const = const_cast<LevelDBIteratorImpl*>(this);
90 non_const->RecordUsage();
91 non_const->RestoreDBIteratorIfEvicted();
71 return MakeStringPiece(iterator_->value()); 92 return MakeStringPiece(iterator_->value());
72 } 93 }
73 94
95 void LevelDBIteratorImpl::PurgeMemory() {
96 DCHECK_EQ(iterator_state_, IteratorState::ACTIVE);
97 if (iterator_->Valid()) {
98 iterator_state_ = IteratorState::EVICTED_AND_VALID;
99 key_before_eviction_ = iterator_->key().ToString();
100 } else {
101 iterator_state_ = IteratorState::EVICTED_AND_INVALID;
102 }
103 iterator_.reset();
104 }
105
106 bool LevelDBIteratorImpl::IsEvicted() const {
107 return iterator_state_ != IteratorState::ACTIVE;
108 }
109
110 void LevelDBIteratorImpl::RecordUsage() {
111 pool_controller_->NotifyIteratorUsed(this);
112 }
113
114 void LevelDBIteratorImpl::RestoreDBIteratorIfEvicted() {
115 if (iterator_state_ == IteratorState::ACTIVE)
116 return;
117
118 iterator_ = pool_controller_->CreateLevelDBIterator(snapshot_);
119 if (iterator_state_ == IteratorState::EVICTED_AND_VALID) {
120 iterator_->Seek(key_before_eviction_);
121 key_before_eviction_.clear();
122 DCHECK(IsValid());
123 }
jsbell 2017/03/23 21:48:21 else clause that DCHECK(!IsValid()) ?
dmurph 2017/03/23 22:48:47 tautology - we have to be in state EVICTED_AND_INV
jsbell 2017/03/24 00:30:21 Oops - I meant DCHECK(!iterator_->Valid())
124 iterator_state_ = IteratorState::ACTIVE;
125 }
126
74 } // namespace content 127 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698