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

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

Issue 15659013: Revert "Migrate the IndexedDB backend from Blink to Chromium" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
6
7 #include "base/logging.h"
8 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
9 #include "content/browser/indexed_db/leveldb/leveldb_slice.h"
10 #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h"
11 #include "third_party/leveldatabase/src/include/leveldb/db.h"
12
13 namespace content {
14
15 scoped_refptr<LevelDBTransaction> LevelDBTransaction::Create(
16 LevelDBDatabase* db) {
17 return make_scoped_refptr(new LevelDBTransaction(db));
18 }
19
20 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db)
21 : db_(db), snapshot_(db), comparator_(db->Comparator()), finished_(false) {
22 tree_.abstractor().comparator_ = comparator_;
23 }
24
25 LevelDBTransaction::AVLTreeNode::AVLTreeNode() {}
26 LevelDBTransaction::AVLTreeNode::~AVLTreeNode() {}
27
28 void LevelDBTransaction::ClearTree() {
29 TreeType::Iterator iterator;
30 iterator.start_iter_least(tree_);
31
32 std::vector<AVLTreeNode*> nodes;
33
34 while (*iterator) {
35 nodes.push_back(*iterator);
36 ++iterator;
37 }
38 tree_.purge();
39
40 for (size_t i = 0; i < nodes.size(); ++i)
41 delete nodes[i];
42 }
43
44 LevelDBTransaction::~LevelDBTransaction() { ClearTree(); }
45
46 static void InitVector(const LevelDBSlice& slice, std::vector<char>* vector) {
47 vector->clear();
48 vector->insert(vector->end(), slice.begin(), slice.end());
49 }
50
51 void LevelDBTransaction::Set(const LevelDBSlice& key,
52 const std::vector<char>& value,
53 bool deleted) {
54 DCHECK(!finished_);
55 bool new_node = false;
56 AVLTreeNode* node = tree_.search(key);
57
58 if (!node) {
59 node = new AVLTreeNode;
60 InitVector(key, &node->key);
61 tree_.insert(node);
62 new_node = true;
63 }
64 node->value = value;
65 node->deleted = deleted;
66
67 if (new_node)
68 NotifyIteratorsOfTreeChange();
69 }
70
71 void LevelDBTransaction::Put(const LevelDBSlice& key,
72 const std::vector<char>& value) {
73 Set(key, value, false);
74 }
75
76 void LevelDBTransaction::Remove(const LevelDBSlice& key) {
77 Set(key, std::vector<char>(), true);
78 }
79
80 bool LevelDBTransaction::Get(const LevelDBSlice& key,
81 std::vector<char>& value,
82 bool& found) {
83 found = false;
84 DCHECK(!finished_);
85 AVLTreeNode* node = tree_.search(key);
86
87 if (node) {
88 if (node->deleted)
89 return true;
90
91 value = node->value;
92 found = true;
93 return true;
94 }
95
96 bool ok = db_->Get(key, value, found, &snapshot_);
97 if (!ok) {
98 DCHECK(!found);
99 return false;
100 }
101 return true;
102 }
103
104 bool LevelDBTransaction::Commit() {
105 DCHECK(!finished_);
106
107 if (tree_.is_empty()) {
108 finished_ = true;
109 return true;
110 }
111
112 scoped_ptr<LevelDBWriteBatch> write_batch = LevelDBWriteBatch::Create();
113
114 TreeType::Iterator iterator;
115 iterator.start_iter_least(tree_);
116
117 while (*iterator) {
118 AVLTreeNode* node = *iterator;
119 if (!node->deleted)
120 write_batch->Put(LevelDBSlice(node->key), LevelDBSlice(node->value));
121 else
122 write_batch->Remove(LevelDBSlice(node->key));
123 ++iterator;
124 }
125
126 if (!db_->Write(*write_batch))
127 return false;
128
129 ClearTree();
130 finished_ = true;
131 return true;
132 }
133
134 void LevelDBTransaction::Rollback() {
135 DCHECK(!finished_);
136 finished_ = true;
137 ClearTree();
138 }
139
140 scoped_ptr<LevelDBIterator> LevelDBTransaction::CreateIterator() {
141 return TransactionIterator::Create(this).PassAs<LevelDBIterator>();
142 }
143
144 scoped_ptr<LevelDBTransaction::TreeIterator>
145 LevelDBTransaction::TreeIterator::Create(LevelDBTransaction* transaction) {
146 return make_scoped_ptr(new TreeIterator(transaction));
147 }
148
149 bool LevelDBTransaction::TreeIterator::IsValid() const { return !!*iterator_; }
150
151 void LevelDBTransaction::TreeIterator::SeekToLast() {
152 iterator_.start_iter_greatest(*tree_);
153 if (IsValid())
154 key_ = (*iterator_)->key;
155 }
156
157 void LevelDBTransaction::TreeIterator::Seek(const LevelDBSlice& target) {
158 iterator_.start_iter(*tree_, target, TreeType::EQUAL);
159 if (!IsValid())
160 iterator_.start_iter(*tree_, target, TreeType::GREATER);
161
162 if (IsValid())
163 key_ = (*iterator_)->key;
164 }
165
166 void LevelDBTransaction::TreeIterator::Next() {
167 DCHECK(IsValid());
168 ++iterator_;
169 if (IsValid()) {
170 DCHECK(transaction_->comparator_->Compare(LevelDBSlice((*iterator_)->key),
171 LevelDBSlice(key_)) >
172 0);
173 (void) transaction_;
174 key_ = (*iterator_)->key;
175 }
176 }
177
178 void LevelDBTransaction::TreeIterator::Prev() {
179 DCHECK(IsValid());
180 --iterator_;
181 if (IsValid()) {
182 DCHECK(tree_->abstractor().comparator_->Compare(
183 LevelDBSlice((*iterator_)->key), LevelDBSlice(key_)) <
184 0);
185 key_ = (*iterator_)->key;
186 }
187 }
188
189 LevelDBSlice LevelDBTransaction::TreeIterator::Key() const {
190 DCHECK(IsValid());
191 return LevelDBSlice(key_);
192 }
193
194 LevelDBSlice LevelDBTransaction::TreeIterator::Value() const {
195 DCHECK(IsValid());
196 DCHECK(!IsDeleted());
197 return LevelDBSlice((*iterator_)->value);
198 }
199
200 bool LevelDBTransaction::TreeIterator::IsDeleted() const {
201 DCHECK(IsValid());
202 return (*iterator_)->deleted;
203 }
204
205 void LevelDBTransaction::TreeIterator::Reset() {
206 DCHECK(IsValid());
207 iterator_.start_iter(*tree_, LevelDBSlice(key_), TreeType::EQUAL);
208 DCHECK(IsValid());
209 }
210
211 LevelDBTransaction::TreeIterator::~TreeIterator() {}
212
213 LevelDBTransaction::TreeIterator::TreeIterator(LevelDBTransaction* transaction)
214 : tree_(&transaction->tree_), transaction_(transaction) {}
215
216 scoped_ptr<LevelDBTransaction::TransactionIterator>
217 LevelDBTransaction::TransactionIterator::Create(
218 scoped_refptr<LevelDBTransaction> transaction) {
219 return make_scoped_ptr(new TransactionIterator(transaction));
220 }
221
222 LevelDBTransaction::TransactionIterator::TransactionIterator(
223 scoped_refptr<LevelDBTransaction> transaction)
224 : transaction_(transaction),
225 comparator_(transaction_->comparator_),
226 tree_iterator_(TreeIterator::Create(transaction_.get())),
227 db_iterator_(transaction_->db_->CreateIterator(&transaction_->snapshot_)),
228 current_(0),
229 direction_(FORWARD),
230 tree_changed_(false) {
231 transaction_->RegisterIterator(this);
232 }
233
234 LevelDBTransaction::TransactionIterator::~TransactionIterator() {
235 transaction_->UnregisterIterator(this);
236 }
237
238 bool LevelDBTransaction::TransactionIterator::IsValid() const {
239 return !!current_;
240 }
241
242 void LevelDBTransaction::TransactionIterator::SeekToLast() {
243 tree_iterator_->SeekToLast();
244 db_iterator_->SeekToLast();
245 direction_ = REVERSE;
246
247 HandleConflictsAndDeletes();
248 SetCurrentIteratorToLargestKey();
249 }
250
251 void LevelDBTransaction::TransactionIterator::Seek(const LevelDBSlice& target) {
252 tree_iterator_->Seek(target);
253 db_iterator_->Seek(target);
254 direction_ = FORWARD;
255
256 HandleConflictsAndDeletes();
257 SetCurrentIteratorToSmallestKey();
258 }
259
260 void LevelDBTransaction::TransactionIterator::Next() {
261 DCHECK(IsValid());
262 if (tree_changed_)
263 RefreshTreeIterator();
264
265 if (direction_ != FORWARD) {
266 // Ensure the non-current iterator is positioned after Key().
267
268 LevelDBIterator* non_current =
269 (current_ == db_iterator_.get()) ? tree_iterator_.get()
270 : db_iterator_.get();
271
272 non_current->Seek(Key());
273 if (non_current->IsValid() &&
274 !comparator_->Compare(non_current->Key(), Key()))
275 non_current->Next(); // Take an extra step so the non-current key is
276 // strictly greater than Key().
277
278 DCHECK(!non_current->IsValid() ||
279 comparator_->Compare(non_current->Key(), Key()) > 0);
280
281 direction_ = FORWARD;
282 }
283
284 current_->Next();
285 HandleConflictsAndDeletes();
286 SetCurrentIteratorToSmallestKey();
287 }
288
289 void LevelDBTransaction::TransactionIterator::Prev() {
290 DCHECK(IsValid());
291 if (tree_changed_)
292 RefreshTreeIterator();
293
294 if (direction_ != REVERSE) {
295 // Ensure the non-current iterator is positioned before Key().
296
297 LevelDBIterator* non_current =
298 (current_ == db_iterator_.get()) ? tree_iterator_.get()
299 : db_iterator_.get();
300
301 non_current->Seek(Key());
302 if (non_current->IsValid()) {
303 // Iterator is at first entry >= Key().
304 // Step back once to entry < key.
305 // This is why we don't check for the keys being the same before
306 // stepping, like we do in Next() above.
307 non_current->Prev();
308 } else {
309 non_current->SeekToLast(); // Iterator has no entries >= Key(). Position
310 // at last entry.
311 }
312 DCHECK(!non_current->IsValid() ||
313 comparator_->Compare(non_current->Key(), Key()) < 0);
314
315 direction_ = REVERSE;
316 }
317
318 current_->Prev();
319 HandleConflictsAndDeletes();
320 SetCurrentIteratorToLargestKey();
321 }
322
323 LevelDBSlice LevelDBTransaction::TransactionIterator::Key() const {
324 DCHECK(IsValid());
325 if (tree_changed_)
326 RefreshTreeIterator();
327 return current_->Key();
328 }
329
330 LevelDBSlice LevelDBTransaction::TransactionIterator::Value() const {
331 DCHECK(IsValid());
332 if (tree_changed_)
333 RefreshTreeIterator();
334 return current_->Value();
335 }
336
337 void LevelDBTransaction::TransactionIterator::TreeChanged() {
338 tree_changed_ = true;
339 }
340
341 void LevelDBTransaction::TransactionIterator::RefreshTreeIterator() const {
342 DCHECK(tree_changed_);
343
344 tree_changed_ = false;
345
346 if (tree_iterator_->IsValid() && tree_iterator_.get() == current_) {
347 tree_iterator_->Reset();
348 return;
349 }
350
351 if (db_iterator_->IsValid()) {
352
353 // There could be new nodes in the tree that we should iterate over.
354
355 if (direction_ == FORWARD) {
356 // Try to seek tree iterator to something greater than the db iterator.
357 tree_iterator_->Seek(db_iterator_->Key());
358 if (tree_iterator_->IsValid() &&
359 !comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key()))
360 tree_iterator_->Next(); // If equal, take another step so the tree
361 // iterator is strictly greater.
362 } else {
363 // If going backward, seek to a key less than the db iterator.
364 DCHECK_EQ(REVERSE, direction_);
365 tree_iterator_->Seek(db_iterator_->Key());
366 if (tree_iterator_->IsValid())
367 tree_iterator_->Prev();
368 }
369 }
370 }
371
372 bool LevelDBTransaction::TransactionIterator::TreeIteratorIsLower() const {
373 return comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key()) < 0;
374 }
375
376 bool LevelDBTransaction::TransactionIterator::TreeIteratorIsHigher() const {
377 return comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key()) > 0;
378 }
379
380 void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() {
381 bool loop = true;
382
383 while (loop) {
384 loop = false;
385
386 if (tree_iterator_->IsValid() && db_iterator_->IsValid() &&
387 !comparator_->Compare(tree_iterator_->Key(), db_iterator_->Key())) {
388 // For equal keys, the tree iterator takes precedence, so move the
389 // database iterator another step.
390 if (direction_ == FORWARD)
391 db_iterator_->Next();
392 else
393 db_iterator_->Prev();
394 }
395
396 // Skip over delete markers in the tree iterator until it catches up with
397 // the db iterator.
398 if (tree_iterator_->IsValid() && tree_iterator_->IsDeleted()) {
399 if (direction_ == FORWARD &&
400 (!db_iterator_->IsValid() || TreeIteratorIsLower())) {
401 tree_iterator_->Next();
402 loop = true;
403 } else if (direction_ == REVERSE &&
404 (!db_iterator_->IsValid() || TreeIteratorIsHigher())) {
405 tree_iterator_->Prev();
406 loop = true;
407 }
408 }
409 }
410 }
411
412 void
413 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() {
414 LevelDBIterator* smallest = 0;
415
416 if (tree_iterator_->IsValid())
417 smallest = tree_iterator_.get();
418
419 if (db_iterator_->IsValid()) {
420 if (!smallest ||
421 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0)
422 smallest = db_iterator_.get();
423 }
424
425 current_ = smallest;
426 }
427
428 void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() {
429 LevelDBIterator* largest = 0;
430
431 if (tree_iterator_->IsValid())
432 largest = tree_iterator_.get();
433
434 if (db_iterator_->IsValid()) {
435 if (!largest ||
436 comparator_->Compare(db_iterator_->Key(), largest->Key()) > 0)
437 largest = db_iterator_.get();
438 }
439
440 current_ = largest;
441 }
442
443 void LevelDBTransaction::RegisterIterator(TransactionIterator* iterator) {
444 DCHECK(iterators_.find(iterator) == iterators_.end());
445 iterators_.insert(iterator);
446 }
447
448 void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) {
449 DCHECK(iterators_.find(iterator) != iterators_.end());
450 iterators_.erase(iterator);
451 }
452
453 void LevelDBTransaction::NotifyIteratorsOfTreeChange() {
454 for (std::set<TransactionIterator*>::iterator i = iterators_.begin();
455 i != iterators_.end();
456 ++i) {
457 TransactionIterator* transaction_iterator = *i;
458 transaction_iterator->TreeChanged();
459 }
460 }
461
462 scoped_ptr<LevelDBWriteOnlyTransaction> LevelDBWriteOnlyTransaction::Create(
463 LevelDBDatabase* db) {
464 return make_scoped_ptr(new LevelDBWriteOnlyTransaction(db));
465 }
466
467 LevelDBWriteOnlyTransaction::LevelDBWriteOnlyTransaction(LevelDBDatabase* db)
468 : db_(db), write_batch_(LevelDBWriteBatch::Create()), finished_(false) {}
469
470 LevelDBWriteOnlyTransaction::~LevelDBWriteOnlyTransaction() {
471 write_batch_->Clear();
472 }
473
474 void LevelDBWriteOnlyTransaction::Remove(const LevelDBSlice& key) {
475 DCHECK(!finished_);
476 write_batch_->Remove(key);
477 }
478
479 bool LevelDBWriteOnlyTransaction::Commit() {
480 DCHECK(!finished_);
481
482 if (!db_->Write(*write_batch_))
483 return false;
484
485 finished_ = true;
486 write_batch_->Clear();
487 return true;
488 }
489
490 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/leveldb/leveldb_transaction.h ('k') | content/browser/indexed_db/leveldb/leveldb_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698