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

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

Issue 17462005: IndexedDB: Replace transaction's AVLTree with std::map (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased; store node pointers in map to avoid copies Created 7 years, 4 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 | Annotate | Revision Log
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 "content/browser/indexed_db/leveldb/leveldb_database.h" 8 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
9 #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h" 9 #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h"
10 #include "third_party/leveldatabase/src/include/leveldb/db.h" 10 #include "third_party/leveldatabase/src/include/leveldb/db.h"
11 11
12 using base::StringPiece; 12 using base::StringPiece;
13 13
14 namespace content { 14 namespace content {
15 15
16 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db) 16 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db)
17 : db_(db), snapshot_(db), comparator_(db->Comparator()), finished_(false) { 17 : db_(db),
18 tree_.abstractor().comparator_ = comparator_; 18 snapshot_(db),
19 } 19 comparator_(db->Comparator()),
20 tree_comparator_(comparator_),
21 tree_(tree_comparator_),
22 finished_(false) {}
20 23
21 LevelDBTransaction::AVLTreeNode::AVLTreeNode() {} 24 LevelDBTransaction::TreeNode::TreeNode() : deleted(false) {}
22 LevelDBTransaction::AVLTreeNode::~AVLTreeNode() {} 25 LevelDBTransaction::TreeNode::~TreeNode() {}
23 26
24 void LevelDBTransaction::ClearTree() { 27 void LevelDBTransaction::ClearTree() {
25 TreeType::Iterator iterator; 28 for (TreeType::iterator it = tree_.begin(); it != tree_.end(); ++it) {
26 iterator.StartIterLeast(&tree_); 29 delete it->second;
27
28 std::vector<AVLTreeNode*> nodes;
29
30 while (*iterator) {
31 nodes.push_back(*iterator);
32 ++iterator;
33 } 30 }
34 tree_.Purge(); 31 tree_.clear();
35
36 for (size_t i = 0; i < nodes.size(); ++i)
37 delete nodes[i];
38 } 32 }
39 33
40 LevelDBTransaction::~LevelDBTransaction() { ClearTree(); } 34 LevelDBTransaction::~LevelDBTransaction() { ClearTree(); }
41 35
42 void LevelDBTransaction::Set(const StringPiece& key, 36 void LevelDBTransaction::Set(const StringPiece& key,
43 std::string* value, 37 std::string* value,
44 bool deleted) { 38 bool deleted) {
45 DCHECK(!finished_); 39 DCHECK(!finished_);
46 bool new_node = false; 40 std::string string_key(key.begin(), key.end() - key.begin());
47 AVLTreeNode* node = tree_.Search(key); 41 TreeType::iterator it = tree_.find(string_key);
48 42
49 if (!node) { 43 if (it == tree_.end()) {
50 node = new AVLTreeNode; 44 TreeNode* node = new TreeNode();
51 node->key = key.as_string(); 45 node->value.swap(*value);
52 tree_.Insert(node); 46 node->deleted = deleted;
53 new_node = true; 47 tree_[string_key] = node;
48 NotifyIteratorsOfTreeChange();
49 return;
54 } 50 }
55 node->value.swap(*value);
56 node->deleted = deleted;
57 51
58 if (new_node) 52 it->second->value.swap(*value);
59 NotifyIteratorsOfTreeChange(); 53 it->second->deleted = deleted;
60 } 54 }
61 55
62 void LevelDBTransaction::Put(const StringPiece& key, std::string* value) { 56 void LevelDBTransaction::Put(const StringPiece& key, std::string* value) {
63 Set(key, value, false); 57 Set(key, value, false);
64 } 58 }
65 59
66 void LevelDBTransaction::Remove(const StringPiece& key) { 60 void LevelDBTransaction::Remove(const StringPiece& key) {
67 std::string empty; 61 std::string empty;
68 Set(key, &empty, true); 62 Set(key, &empty, true);
69 } 63 }
70 64
71 bool LevelDBTransaction::Get(const StringPiece& key, 65 bool LevelDBTransaction::Get(const StringPiece& key,
72 std::string* value, 66 std::string* value,
73 bool* found) { 67 bool* found) {
74 *found = false; 68 *found = false;
75 DCHECK(!finished_); 69 DCHECK(!finished_);
76 AVLTreeNode* node = tree_.Search(key); 70 std::string string_key(key.begin(), key.end() - key.begin());
alecflett 2013/09/10 16:46:40 Not that this is particularly expensive, but can y
jsbell 2013/09/10 17:00:06 StringPiece doesn't own its storage, and map::find
jsbell 2013/09/10 21:29:36 That turned out to be tricky due to upstream calle
71 TreeType::const_iterator it = tree_.find(string_key);
77 72
78 if (node) { 73 if (it != tree_.end()) {
79 if (node->deleted) 74 if (it->second->deleted)
80 return true; 75 return true;
81 76
82 *value = node->value; 77 *value = it->second->value;
alecflett 2013/09/10 16:46:40 it's too bad there's no way to swap or something h
jsbell 2013/09/10 17:00:06 Nope, since the the storage is owned by the tree a
83 *found = true; 78 *found = true;
84 return true; 79 return true;
85 } 80 }
86 81
87 bool ok = db_->Get(key, value, found, &snapshot_); 82 bool ok = db_->Get(key, value, found, &snapshot_);
alecflett 2013/09/10 16:46:40 I guess you'd have to propagate the stringpiece st
jsbell 2013/09/10 17:00:06 ... but if key is passed in as a string that's not
88 if (!ok) { 83 if (!ok) {
89 DCHECK(!*found); 84 DCHECK(!*found);
90 return false; 85 return false;
91 } 86 }
92 return true; 87 return true;
93 } 88 }
94 89
95 bool LevelDBTransaction::Commit() { 90 bool LevelDBTransaction::Commit() {
96 DCHECK(!finished_); 91 DCHECK(!finished_);
97 92
98 if (tree_.IsEmpty()) { 93 if (tree_.empty()) {
99 finished_ = true; 94 finished_ = true;
100 return true; 95 return true;
101 } 96 }
102 97
103 scoped_ptr<LevelDBWriteBatch> write_batch = LevelDBWriteBatch::Create(); 98 scoped_ptr<LevelDBWriteBatch> write_batch = LevelDBWriteBatch::Create();
104 99
105 TreeType::Iterator iterator; 100 for (TreeType::iterator iterator = tree_.begin(); iterator != tree_.end();
106 iterator.StartIterLeast(&tree_); 101 ++iterator) {
107 102 if (!iterator->second->deleted)
108 while (*iterator) { 103 write_batch->Put(iterator->first, iterator->second->value);
109 AVLTreeNode* node = *iterator;
110 if (!node->deleted)
111 write_batch->Put(node->key, node->value);
112 else 104 else
113 write_batch->Remove(node->key); 105 write_batch->Remove(iterator->first);
114 ++iterator;
115 } 106 }
116 107
117 if (!db_->Write(*write_batch)) 108 if (!db_->Write(*write_batch))
118 return false; 109 return false;
119 110
120 ClearTree(); 111 ClearTree();
121 finished_ = true; 112 finished_ = true;
122 return true; 113 return true;
123 } 114 }
124 115
125 void LevelDBTransaction::Rollback() { 116 void LevelDBTransaction::Rollback() {
126 DCHECK(!finished_); 117 DCHECK(!finished_);
127 finished_ = true; 118 finished_ = true;
128 ClearTree(); 119 ClearTree();
129 } 120 }
130 121
131 scoped_ptr<LevelDBIterator> LevelDBTransaction::CreateIterator() { 122 scoped_ptr<LevelDBIterator> LevelDBTransaction::CreateIterator() {
132 return TransactionIterator::Create(this).PassAs<LevelDBIterator>(); 123 return TransactionIterator::Create(this).PassAs<LevelDBIterator>();
133 } 124 }
134 125
135 scoped_ptr<LevelDBTransaction::TreeIterator> 126 scoped_ptr<LevelDBTransaction::TreeIterator>
136 LevelDBTransaction::TreeIterator::Create(LevelDBTransaction* transaction) { 127 LevelDBTransaction::TreeIterator::Create(LevelDBTransaction* transaction) {
137 return make_scoped_ptr(new TreeIterator(transaction)); 128 return make_scoped_ptr(new TreeIterator(transaction));
138 } 129 }
139 130
140 bool LevelDBTransaction::TreeIterator::IsValid() const { return !!*iterator_; } 131 bool LevelDBTransaction::TreeIterator::IsValid() const {
132 return iterator_ != tree_->end();
133 }
141 134
142 void LevelDBTransaction::TreeIterator::SeekToLast() { 135 void LevelDBTransaction::TreeIterator::SeekToLast() {
143 iterator_.StartIterGreatest(tree_); 136 iterator_ = tree_->end();
137 if (iterator_ != tree_->begin())
138 --iterator_;
139
144 if (IsValid()) 140 if (IsValid())
145 key_ = (*iterator_)->key; 141 key_ = iterator_->first;
146 } 142 }
147 143
148 void LevelDBTransaction::TreeIterator::Seek(const StringPiece& target) { 144 void LevelDBTransaction::TreeIterator::Seek(const StringPiece& target) {
149 iterator_.StartIter(tree_, target, TreeType::EQUAL); 145 std::string key(target.begin(), target.end() - target.begin());
alecflett 2013/09/10 16:46:40 copying on a seek seems bad?
jsbell 2013/09/10 17:00:06 I'll look at changing this API here to take a cons
150 if (!IsValid()) 146
151 iterator_.StartIter(tree_, target, TreeType::GREATER); 147 iterator_ = tree_->find(key);
148 if (!IsValid()) {
149 TreeNode dummy;
ericu 2013/09/10 01:00:41 How about map::lower_bound or map::equal_range?
jsbell 2013/09/10 17:00:06 lower_bound should work - it looks like exactly wh
150 std::pair<TreeType::iterator, bool> position =
151 tree_->insert(make_pair(key, &dummy));
152 iterator_ = position.first;
153 ++iterator_;
154 tree_->erase(position.first);
155 }
152 156
153 if (IsValid()) 157 if (IsValid())
154 key_ = (*iterator_)->key; 158 key_ = iterator_->first;
155 } 159 }
156 160
157 void LevelDBTransaction::TreeIterator::Next() { 161 void LevelDBTransaction::TreeIterator::Next() {
158 DCHECK(IsValid()); 162 DCHECK(IsValid());
159 ++iterator_; 163 ++iterator_;
160 if (IsValid()) { 164 if (IsValid()) {
161 DCHECK_GE(transaction_->comparator_->Compare((*iterator_)->key, key_), 0); 165 DCHECK_GE(transaction_->comparator_->Compare(iterator_->first, key_), 0);
162 key_ = (*iterator_)->key; 166 key_ = iterator_->first;
163 } 167 }
164 } 168 }
165 169
166 void LevelDBTransaction::TreeIterator::Prev() { 170 void LevelDBTransaction::TreeIterator::Prev() {
167 DCHECK(IsValid()); 171 DCHECK(IsValid());
168 --iterator_; 172 if (iterator_ != tree_->begin())
173 --iterator_;
174 else
175 iterator_ = tree_->end();
169 if (IsValid()) { 176 if (IsValid()) {
170 DCHECK_LT(tree_->abstractor().comparator_->Compare((*iterator_)->key, key_), 177 DCHECK_LT(transaction_->comparator_->Compare(iterator_->first, key_), 0);
171 0); 178 key_ = iterator_->first;
172 key_ = (*iterator_)->key;
173 } 179 }
174 } 180 }
175 181
176 StringPiece LevelDBTransaction::TreeIterator::Key() const { 182 StringPiece LevelDBTransaction::TreeIterator::Key() const {
177 DCHECK(IsValid()); 183 DCHECK(IsValid());
178 return key_; 184 return key_;
179 } 185 }
180 186
181 StringPiece LevelDBTransaction::TreeIterator::Value() const { 187 StringPiece LevelDBTransaction::TreeIterator::Value() const {
182 DCHECK(IsValid()); 188 DCHECK(IsValid());
183 DCHECK(!IsDeleted()); 189 DCHECK(!IsDeleted());
184 return (*iterator_)->value; 190 return iterator_->second->value;
185 } 191 }
186 192
187 bool LevelDBTransaction::TreeIterator::IsDeleted() const { 193 bool LevelDBTransaction::TreeIterator::IsDeleted() const {
188 DCHECK(IsValid()); 194 DCHECK(IsValid());
189 return (*iterator_)->deleted; 195 return iterator_->second->deleted;
190 } 196 }
191 197
192 void LevelDBTransaction::TreeIterator::Reset() { 198 void LevelDBTransaction::TreeIterator::Reset() {
193 DCHECK(IsValid()); 199 DCHECK(IsValid());
194 iterator_.StartIter(tree_, key_, TreeType::EQUAL); 200 iterator_ = tree_->find(key_);
195 DCHECK(IsValid()); 201 DCHECK(IsValid());
196 } 202 }
197 203
198 LevelDBTransaction::TreeIterator::~TreeIterator() {} 204 LevelDBTransaction::TreeIterator::~TreeIterator() {}
199 205
200 LevelDBTransaction::TreeIterator::TreeIterator(LevelDBTransaction* transaction) 206 LevelDBTransaction::TreeIterator::TreeIterator(LevelDBTransaction* transaction)
201 : tree_(&transaction->tree_), transaction_(transaction) {} 207 : tree_(&transaction->tree_),
208 iterator_(tree_->end()),
209 transaction_(transaction) {}
202 210
203 scoped_ptr<LevelDBTransaction::TransactionIterator> 211 scoped_ptr<LevelDBTransaction::TransactionIterator>
204 LevelDBTransaction::TransactionIterator::Create( 212 LevelDBTransaction::TransactionIterator::Create(
205 scoped_refptr<LevelDBTransaction> transaction) { 213 scoped_refptr<LevelDBTransaction> transaction) {
206 return make_scoped_ptr(new TransactionIterator(transaction)); 214 return make_scoped_ptr(new TransactionIterator(transaction));
207 } 215 }
208 216
209 LevelDBTransaction::TransactionIterator::TransactionIterator( 217 LevelDBTransaction::TransactionIterator::TransactionIterator(
210 scoped_refptr<LevelDBTransaction> transaction) 218 scoped_refptr<LevelDBTransaction> transaction)
211 : transaction_(transaction), 219 : transaction_(transaction),
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
467 475
468 if (!db_->Write(*write_batch_)) 476 if (!db_->Write(*write_batch_))
469 return false; 477 return false;
470 478
471 finished_ = true; 479 finished_ = true;
472 write_batch_->Clear(); 480 write_batch_->Clear();
473 return true; 481 return true;
474 } 482 }
475 483
476 } // namespace content 484 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698