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.
5 #include "content/browser/indexed_db/leveldb/leveldb_transaction.h"
7 #include "base/logging.h"
8 #include "content/browser/indexed_db/leveldb/leveldb_database.h"
9 #include "content/browser/indexed_db/leveldb/leveldb_write_batch.h"
10 #include "third_party/leveldatabase/src/include/leveldb/db.h"
12 using base::StringPiece;
16 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db)
19 comparator_(db->Comparator()),
20 data_comparator_(comparator_),
21 data_(data_comparator_),
24 LevelDBTransaction::Record::Record() : deleted(false) {}
25 LevelDBTransaction::Record::~Record() {}
27 void LevelDBTransaction::Clear() {
28 for (DataType::iterator it = data_.begin(); it != data_.end(); ++it) {
34 LevelDBTransaction::~LevelDBTransaction() { Clear(); }
36 void LevelDBTransaction::Set(const StringPiece& key,
40 DataType::iterator it = data_.find(key);
42 if (it == data_.end()) {
43 Record* record = new Record();
44 record->key.assign(key.begin(), key.end() - key.begin());
45 record->value.swap(*value);
46 record->deleted = deleted;
47 data_[record->key] = record;
52 it->second->value.swap(*value);
53 it->second->deleted = deleted;
56 void LevelDBTransaction::Put(const StringPiece& key, std::string* value) {
57 Set(key, value, false);
60 void LevelDBTransaction::Remove(const StringPiece& key) {
62 Set(key, &empty, true);
65 leveldb::Status LevelDBTransaction::Get(const StringPiece& key,
70 std::string string_key(key.begin(), key.end() - key.begin());
71 DataType::const_iterator it = data_.find(string_key);
73 if (it != data_.end()) {
74 if (it->second->deleted)
75 return leveldb::Status::OK();
77 *value = it->second->value;
79 return leveldb::Status::OK();
82 leveldb::Status s = db_->Get(key, value, found, &snapshot_);
88 leveldb::Status LevelDBTransaction::Commit() {
93 return leveldb::Status::OK();
96 scoped_ptr<LevelDBWriteBatch> write_batch = LevelDBWriteBatch::Create();
98 for (DataType::iterator iterator = data_.begin(); iterator != data_.end();
100 if (!iterator->second->deleted)
101 write_batch->Put(iterator->first, iterator->second->value);
103 write_batch->Remove(iterator->first);
106 leveldb::Status s = db_->Write(*write_batch);
114 void LevelDBTransaction::Rollback() {
120 scoped_ptr<LevelDBIterator> LevelDBTransaction::CreateIterator() {
121 return TransactionIterator::Create(this).PassAs<LevelDBIterator>();
124 scoped_ptr<LevelDBTransaction::DataIterator>
125 LevelDBTransaction::DataIterator::Create(LevelDBTransaction* transaction) {
126 return make_scoped_ptr(new DataIterator(transaction));
129 bool LevelDBTransaction::DataIterator::IsValid() const {
130 return iterator_ != data_->end();
133 leveldb::Status LevelDBTransaction::DataIterator::SeekToLast() {
134 iterator_ = data_->end();
135 if (iterator_ != data_->begin())
137 return leveldb::Status::OK();
140 leveldb::Status LevelDBTransaction::DataIterator::Seek(
141 const StringPiece& target) {
142 iterator_ = data_->lower_bound(target);
143 return leveldb::Status::OK();
146 leveldb::Status LevelDBTransaction::DataIterator::Next() {
149 return leveldb::Status::OK();
152 leveldb::Status LevelDBTransaction::DataIterator::Prev() {
154 if (iterator_ != data_->begin())
157 iterator_ = data_->end();
158 return leveldb::Status::OK();
161 StringPiece LevelDBTransaction::DataIterator::Key() const {
163 return iterator_->first;
166 StringPiece LevelDBTransaction::DataIterator::Value() const {
168 DCHECK(!IsDeleted());
169 return iterator_->second->value;
172 bool LevelDBTransaction::DataIterator::IsDeleted() const {
174 return iterator_->second->deleted;
177 LevelDBTransaction::DataIterator::~DataIterator() {}
179 LevelDBTransaction::DataIterator::DataIterator(LevelDBTransaction* transaction)
180 : data_(&transaction->data_),
181 iterator_(data_->end()) {}
183 scoped_ptr<LevelDBTransaction::TransactionIterator>
184 LevelDBTransaction::TransactionIterator::Create(
185 scoped_refptr<LevelDBTransaction> transaction) {
186 return make_scoped_ptr(new TransactionIterator(transaction));
189 LevelDBTransaction::TransactionIterator::TransactionIterator(
190 scoped_refptr<LevelDBTransaction> transaction)
191 : transaction_(transaction),
192 comparator_(transaction_->comparator_),
193 data_iterator_(DataIterator::Create(transaction_.get())),
194 db_iterator_(transaction_->db_->CreateIterator(&transaction_->snapshot_)),
197 data_changed_(false) {
198 transaction_->RegisterIterator(this);
201 LevelDBTransaction::TransactionIterator::~TransactionIterator() {
202 transaction_->UnregisterIterator(this);
205 bool LevelDBTransaction::TransactionIterator::IsValid() const {
209 leveldb::Status LevelDBTransaction::TransactionIterator::SeekToLast() {
210 leveldb::Status s = data_iterator_->SeekToLast();
212 s = db_iterator_->SeekToLast();
215 direction_ = REVERSE;
217 HandleConflictsAndDeletes();
218 SetCurrentIteratorToLargestKey();
222 leveldb::Status LevelDBTransaction::TransactionIterator::Seek(
223 const StringPiece& target) {
224 leveldb::Status s = data_iterator_->Seek(target);
226 s = db_iterator_->Seek(target);
229 direction_ = FORWARD;
231 HandleConflictsAndDeletes();
232 SetCurrentIteratorToSmallestKey();
236 leveldb::Status LevelDBTransaction::TransactionIterator::Next() {
239 RefreshDataIterator();
242 if (direction_ != FORWARD) {
243 // Ensure the non-current iterator is positioned after Key().
245 LevelDBIterator* non_current = (current_ == db_iterator_.get())
246 ? data_iterator_.get()
247 : db_iterator_.get();
249 non_current->Seek(Key());
250 if (non_current->IsValid() &&
251 !comparator_->Compare(non_current->Key(), Key())) {
252 // Take an extra step so the non-current key is
253 // strictly greater than Key().
254 s = non_current->Next();
258 DCHECK(!non_current->IsValid() ||
259 comparator_->Compare(non_current->Key(), Key()) > 0);
261 direction_ = FORWARD;
264 s = current_->Next();
267 HandleConflictsAndDeletes();
268 SetCurrentIteratorToSmallestKey();
269 return leveldb::Status::OK();
272 leveldb::Status LevelDBTransaction::TransactionIterator::Prev() {
276 RefreshDataIterator();
278 if (direction_ != REVERSE) {
279 // Ensure the non-current iterator is positioned before Key().
281 LevelDBIterator* non_current = (current_ == db_iterator_.get())
282 ? data_iterator_.get()
283 : db_iterator_.get();
285 s = non_current->Seek(Key());
288 if (non_current->IsValid()) {
289 // Iterator is at first entry >= Key().
290 // Step back once to entry < key.
291 // This is why we don't check for the keys being the same before
292 // stepping, like we do in Next() above.
295 // Iterator has no entries >= Key(). Position at last entry.
296 non_current->SeekToLast();
298 DCHECK(!non_current->IsValid() ||
299 comparator_->Compare(non_current->Key(), Key()) < 0);
301 direction_ = REVERSE;
304 s = current_->Prev();
307 HandleConflictsAndDeletes();
308 SetCurrentIteratorToLargestKey();
309 return leveldb::Status::OK();
312 StringPiece LevelDBTransaction::TransactionIterator::Key() const {
315 RefreshDataIterator();
316 return current_->Key();
319 StringPiece LevelDBTransaction::TransactionIterator::Value() const {
322 RefreshDataIterator();
323 return current_->Value();
326 void LevelDBTransaction::TransactionIterator::DataChanged() {
327 data_changed_ = true;
330 void LevelDBTransaction::TransactionIterator::RefreshDataIterator() const {
331 DCHECK(data_changed_);
333 data_changed_ = false;
335 if (data_iterator_->IsValid() && data_iterator_.get() == current_) {
339 if (db_iterator_->IsValid()) {
340 // There could be new records in data that we should iterate over.
342 if (direction_ == FORWARD) {
343 // Try to seek data iterator to something greater than the db iterator.
344 data_iterator_->Seek(db_iterator_->Key());
345 if (data_iterator_->IsValid() &&
346 !comparator_->Compare(data_iterator_->Key(), db_iterator_->Key())) {
347 // If equal, take another step so the data iterator is strictly greater.
348 data_iterator_->Next();
351 // If going backward, seek to a key less than the db iterator.
352 DCHECK_EQ(REVERSE, direction_);
353 data_iterator_->Seek(db_iterator_->Key());
354 if (data_iterator_->IsValid())
355 data_iterator_->Prev();
360 bool LevelDBTransaction::TransactionIterator::DataIteratorIsLower() const {
361 return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) < 0;
364 bool LevelDBTransaction::TransactionIterator::DataIteratorIsHigher() const {
365 return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) > 0;
368 void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() {
374 if (data_iterator_->IsValid() && db_iterator_->IsValid() &&
375 !comparator_->Compare(data_iterator_->Key(), db_iterator_->Key())) {
376 // For equal keys, the data iterator takes precedence, so move the
377 // database iterator another step.
378 if (direction_ == FORWARD)
379 db_iterator_->Next();
381 db_iterator_->Prev();
384 // Skip over delete markers in the data iterator until it catches up with
386 if (data_iterator_->IsValid() && data_iterator_->IsDeleted()) {
387 if (direction_ == FORWARD &&
388 (!db_iterator_->IsValid() || DataIteratorIsLower())) {
389 data_iterator_->Next();
391 } else if (direction_ == REVERSE &&
392 (!db_iterator_->IsValid() || DataIteratorIsHigher())) {
393 data_iterator_->Prev();
401 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() {
402 LevelDBIterator* smallest = 0;
404 if (data_iterator_->IsValid())
405 smallest = data_iterator_.get();
407 if (db_iterator_->IsValid()) {
409 comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0)
410 smallest = db_iterator_.get();
416 void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() {
417 LevelDBIterator* largest = 0;
419 if (data_iterator_->IsValid())
420 largest = data_iterator_.get();
422 if (db_iterator_->IsValid()) {
424 comparator_->Compare(db_iterator_->Key(), largest->Key()) > 0)
425 largest = db_iterator_.get();
431 void LevelDBTransaction::RegisterIterator(TransactionIterator* iterator) {
432 DCHECK(iterators_.find(iterator) == iterators_.end());
433 iterators_.insert(iterator);
436 void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) {
437 DCHECK(iterators_.find(iterator) != iterators_.end());
438 iterators_.erase(iterator);
441 void LevelDBTransaction::NotifyIterators() {
442 for (std::set<TransactionIterator*>::iterator i = iterators_.begin();
443 i != iterators_.end();
445 TransactionIterator* transaction_iterator = *i;
446 transaction_iterator->DataChanged();
450 scoped_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create(
451 LevelDBDatabase* db) {
452 return make_scoped_ptr(new LevelDBDirectTransaction(db));
455 LevelDBDirectTransaction::LevelDBDirectTransaction(LevelDBDatabase* db)
456 : db_(db), write_batch_(LevelDBWriteBatch::Create()), finished_(false) {}
458 LevelDBDirectTransaction::~LevelDBDirectTransaction() {
459 write_batch_->Clear();
462 void LevelDBDirectTransaction::Put(const StringPiece& key,
463 const std::string* value) {
465 write_batch_->Put(key, *value);
468 leveldb::Status LevelDBDirectTransaction::Get(const StringPiece& key,
474 leveldb::Status s = db_->Get(key, value, found);
475 DCHECK(s.ok() || !*found);
479 void LevelDBDirectTransaction::Remove(const StringPiece& key) {
481 write_batch_->Remove(key);
484 leveldb::Status LevelDBDirectTransaction::Commit() {
487 leveldb::Status s = db_->Write(*write_batch_);
490 write_batch_->Clear();
495 } // namespace content