Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 |
| OLD | NEW |