OLD | NEW |
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_database.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() { |
| 24 db_->OnIteratorDestroyed(this); |
23 } | 25 } |
24 | 26 |
25 LevelDBIteratorImpl::LevelDBIteratorImpl(std::unique_ptr<leveldb::Iterator> it) | 27 LevelDBIteratorImpl::LevelDBIteratorImpl(std::unique_ptr<leveldb::Iterator> it, |
26 : iterator_(std::move(it)) {} | 28 LevelDBDatabase* db, |
| 29 const leveldb::Snapshot* snapshot) |
| 30 : iterator_(std::move(it)), db_(db), snapshot_(snapshot) {} |
27 | 31 |
28 void LevelDBIteratorImpl::CheckStatus() { | 32 leveldb::Status LevelDBIteratorImpl::CheckStatus() { |
| 33 DCHECK(!IsDetached()); |
29 const leveldb::Status& s = iterator_->status(); | 34 const leveldb::Status& s = iterator_->status(); |
30 if (!s.ok()) | 35 if (!s.ok()) |
31 LOG(ERROR) << "LevelDB iterator error: " << s.ToString(); | 36 LOG(ERROR) << "LevelDB iterator error: " << s.ToString(); |
| 37 return s; |
32 } | 38 } |
33 | 39 |
34 bool LevelDBIteratorImpl::IsValid() const { | 40 bool LevelDBIteratorImpl::IsValid() const { |
35 return iterator_->Valid(); | 41 return iterator_state_ == IteratorState::EVICTED_AND_VALID || |
| 42 iterator_->Valid(); |
36 } | 43 } |
37 | 44 |
38 leveldb::Status LevelDBIteratorImpl::SeekToLast() { | 45 leveldb::Status LevelDBIteratorImpl::SeekToLast() { |
| 46 WillUseDBIterator(); |
| 47 DCHECK(iterator_); |
39 iterator_->SeekToLast(); | 48 iterator_->SeekToLast(); |
40 CheckStatus(); | 49 return CheckStatus(); |
41 return iterator_->status(); | |
42 } | 50 } |
43 | 51 |
44 leveldb::Status LevelDBIteratorImpl::Seek(const base::StringPiece& target) { | 52 leveldb::Status LevelDBIteratorImpl::Seek(const base::StringPiece& target) { |
| 53 WillUseDBIterator(); |
| 54 DCHECK(iterator_); |
45 iterator_->Seek(MakeSlice(target)); | 55 iterator_->Seek(MakeSlice(target)); |
46 CheckStatus(); | 56 return CheckStatus(); |
47 return iterator_->status(); | |
48 } | 57 } |
49 | 58 |
50 leveldb::Status LevelDBIteratorImpl::Next() { | 59 leveldb::Status LevelDBIteratorImpl::Next() { |
51 DCHECK(IsValid()); | 60 DCHECK(IsValid()); |
| 61 WillUseDBIterator(); |
| 62 DCHECK(iterator_); |
52 iterator_->Next(); | 63 iterator_->Next(); |
53 CheckStatus(); | 64 return CheckStatus(); |
54 return iterator_->status(); | |
55 } | 65 } |
56 | 66 |
57 leveldb::Status LevelDBIteratorImpl::Prev() { | 67 leveldb::Status LevelDBIteratorImpl::Prev() { |
58 DCHECK(IsValid()); | 68 DCHECK(IsValid()); |
| 69 WillUseDBIterator(); |
| 70 DCHECK(iterator_); |
59 iterator_->Prev(); | 71 iterator_->Prev(); |
60 CheckStatus(); | 72 return CheckStatus(); |
61 return iterator_->status(); | |
62 } | 73 } |
63 | 74 |
64 base::StringPiece LevelDBIteratorImpl::Key() const { | 75 base::StringPiece LevelDBIteratorImpl::Key() const { |
65 DCHECK(IsValid()); | 76 DCHECK(IsValid()); |
| 77 if (IsDetached()) |
| 78 return key_before_eviction_; |
66 return MakeStringPiece(iterator_->key()); | 79 return MakeStringPiece(iterator_->key()); |
67 } | 80 } |
68 | 81 |
69 base::StringPiece LevelDBIteratorImpl::Value() const { | 82 base::StringPiece LevelDBIteratorImpl::Value() const { |
70 DCHECK(IsValid()); | 83 DCHECK(IsValid()); |
| 84 // Always need to update the LRU, so we always call this. Const-cast needed, |
| 85 // as we're implementing a caching layer. |
| 86 LevelDBIteratorImpl* non_const = const_cast<LevelDBIteratorImpl*>(this); |
| 87 non_const->WillUseDBIterator(); |
71 return MakeStringPiece(iterator_->value()); | 88 return MakeStringPiece(iterator_->value()); |
72 } | 89 } |
73 | 90 |
| 91 void LevelDBIteratorImpl::Detach() { |
| 92 DCHECK(!IsDetached()); |
| 93 if (iterator_->Valid()) { |
| 94 iterator_state_ = IteratorState::EVICTED_AND_VALID; |
| 95 key_before_eviction_ = iterator_->key().ToString(); |
| 96 } else { |
| 97 iterator_state_ = IteratorState::EVICTED_AND_INVALID; |
| 98 } |
| 99 iterator_.reset(); |
| 100 } |
| 101 |
| 102 bool LevelDBIteratorImpl::IsDetached() const { |
| 103 return iterator_state_ != IteratorState::ACTIVE; |
| 104 } |
| 105 |
| 106 void LevelDBIteratorImpl::WillUseDBIterator() { |
| 107 db_->OnIteratorUsed(this); |
| 108 if (!IsDetached()) |
| 109 return; |
| 110 |
| 111 iterator_ = db_->CreateLevelDBIterator(snapshot_); |
| 112 if (iterator_state_ == IteratorState::EVICTED_AND_VALID) { |
| 113 iterator_->Seek(key_before_eviction_); |
| 114 key_before_eviction_.clear(); |
| 115 DCHECK(IsValid()); |
| 116 } else { |
| 117 DCHECK(!iterator_->Valid()); |
| 118 } |
| 119 iterator_state_ = IteratorState::ACTIVE; |
| 120 } |
| 121 |
74 } // namespace content | 122 } // namespace content |
OLD | NEW |