Home | History | Annotate | Download | only in leveldb
      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_write_batch.h"
     10 #include "third_party/leveldatabase/src/include/leveldb/db.h"
     11 
     12 using base::StringPiece;
     13 
     14 namespace content {
     15 
     16 LevelDBTransaction::LevelDBTransaction(LevelDBDatabase* db)
     17     : db_(db),
     18       snapshot_(db),
     19       comparator_(db->Comparator()),
     20       data_comparator_(comparator_),
     21       data_(data_comparator_),
     22       finished_(false) {}
     23 
     24 LevelDBTransaction::Record::Record() : deleted(false) {}
     25 LevelDBTransaction::Record::~Record() {}
     26 
     27 void LevelDBTransaction::Clear() {
     28   for (DataType::iterator it = data_.begin(); it != data_.end(); ++it) {
     29     delete it->second;
     30   }
     31   data_.clear();
     32 }
     33 
     34 LevelDBTransaction::~LevelDBTransaction() { Clear(); }
     35 
     36 void LevelDBTransaction::Set(const StringPiece& key,
     37                              std::string* value,
     38                              bool deleted) {
     39   DCHECK(!finished_);
     40   DataType::iterator it = data_.find(key);
     41 
     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;
     48     NotifyIterators();
     49     return;
     50   }
     51 
     52   it->second->value.swap(*value);
     53   it->second->deleted = deleted;
     54 }
     55 
     56 void LevelDBTransaction::Put(const StringPiece& key, std::string* value) {
     57   Set(key, value, false);
     58 }
     59 
     60 void LevelDBTransaction::Remove(const StringPiece& key) {
     61   std::string empty;
     62   Set(key, &empty, true);
     63 }
     64 
     65 leveldb::Status LevelDBTransaction::Get(const StringPiece& key,
     66                                         std::string* value,
     67                                         bool* found) {
     68   *found = false;
     69   DCHECK(!finished_);
     70   std::string string_key(key.begin(), key.end() - key.begin());
     71   DataType::const_iterator it = data_.find(string_key);
     72 
     73   if (it != data_.end()) {
     74     if (it->second->deleted)
     75       return leveldb::Status::OK();
     76 
     77     *value = it->second->value;
     78     *found = true;
     79     return leveldb::Status::OK();
     80   }
     81 
     82   leveldb::Status s = db_->Get(key, value, found, &snapshot_);
     83   if (!s.ok())
     84     DCHECK(!*found);
     85   return s;
     86 }
     87 
     88 leveldb::Status LevelDBTransaction::Commit() {
     89   DCHECK(!finished_);
     90 
     91   if (data_.empty()) {
     92     finished_ = true;
     93     return leveldb::Status::OK();
     94   }
     95 
     96   scoped_ptr<LevelDBWriteBatch> write_batch = LevelDBWriteBatch::Create();
     97 
     98   for (DataType::iterator iterator = data_.begin(); iterator != data_.end();
     99        ++iterator) {
    100     if (!iterator->second->deleted)
    101       write_batch->Put(iterator->first, iterator->second->value);
    102     else
    103       write_batch->Remove(iterator->first);
    104   }
    105 
    106   leveldb::Status s = db_->Write(*write_batch);
    107   if (s.ok()) {
    108     Clear();
    109     finished_ = true;
    110   }
    111   return s;
    112 }
    113 
    114 void LevelDBTransaction::Rollback() {
    115   DCHECK(!finished_);
    116   finished_ = true;
    117   Clear();
    118 }
    119 
    120 scoped_ptr<LevelDBIterator> LevelDBTransaction::CreateIterator() {
    121   return TransactionIterator::Create(this).PassAs<LevelDBIterator>();
    122 }
    123 
    124 scoped_ptr<LevelDBTransaction::DataIterator>
    125 LevelDBTransaction::DataIterator::Create(LevelDBTransaction* transaction) {
    126   return make_scoped_ptr(new DataIterator(transaction));
    127 }
    128 
    129 bool LevelDBTransaction::DataIterator::IsValid() const {
    130   return iterator_ != data_->end();
    131 }
    132 
    133 leveldb::Status LevelDBTransaction::DataIterator::SeekToLast() {
    134   iterator_ = data_->end();
    135   if (iterator_ != data_->begin())
    136     --iterator_;
    137   return leveldb::Status::OK();
    138 }
    139 
    140 leveldb::Status LevelDBTransaction::DataIterator::Seek(
    141     const StringPiece& target) {
    142   iterator_ = data_->lower_bound(target);
    143   return leveldb::Status::OK();
    144 }
    145 
    146 leveldb::Status LevelDBTransaction::DataIterator::Next() {
    147   DCHECK(IsValid());
    148   ++iterator_;
    149   return leveldb::Status::OK();
    150 }
    151 
    152 leveldb::Status LevelDBTransaction::DataIterator::Prev() {
    153   DCHECK(IsValid());
    154   if (iterator_ != data_->begin())
    155     --iterator_;
    156   else
    157     iterator_ = data_->end();
    158   return leveldb::Status::OK();
    159 }
    160 
    161 StringPiece LevelDBTransaction::DataIterator::Key() const {
    162   DCHECK(IsValid());
    163   return iterator_->first;
    164 }
    165 
    166 StringPiece LevelDBTransaction::DataIterator::Value() const {
    167   DCHECK(IsValid());
    168   DCHECK(!IsDeleted());
    169   return iterator_->second->value;
    170 }
    171 
    172 bool LevelDBTransaction::DataIterator::IsDeleted() const {
    173   DCHECK(IsValid());
    174   return iterator_->second->deleted;
    175 }
    176 
    177 LevelDBTransaction::DataIterator::~DataIterator() {}
    178 
    179 LevelDBTransaction::DataIterator::DataIterator(LevelDBTransaction* transaction)
    180     : data_(&transaction->data_),
    181       iterator_(data_->end()) {}
    182 
    183 scoped_ptr<LevelDBTransaction::TransactionIterator>
    184 LevelDBTransaction::TransactionIterator::Create(
    185     scoped_refptr<LevelDBTransaction> transaction) {
    186   return make_scoped_ptr(new TransactionIterator(transaction));
    187 }
    188 
    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_)),
    195       current_(0),
    196       direction_(FORWARD),
    197       data_changed_(false) {
    198   transaction_->RegisterIterator(this);
    199 }
    200 
    201 LevelDBTransaction::TransactionIterator::~TransactionIterator() {
    202   transaction_->UnregisterIterator(this);
    203 }
    204 
    205 bool LevelDBTransaction::TransactionIterator::IsValid() const {
    206   return !!current_;
    207 }
    208 
    209 leveldb::Status LevelDBTransaction::TransactionIterator::SeekToLast() {
    210   leveldb::Status s = data_iterator_->SeekToLast();
    211   DCHECK(s.ok());
    212   s = db_iterator_->SeekToLast();
    213   if (!s.ok())
    214     return s;
    215   direction_ = REVERSE;
    216 
    217   HandleConflictsAndDeletes();
    218   SetCurrentIteratorToLargestKey();
    219   return s;
    220 }
    221 
    222 leveldb::Status LevelDBTransaction::TransactionIterator::Seek(
    223     const StringPiece& target) {
    224   leveldb::Status s = data_iterator_->Seek(target);
    225   DCHECK(s.ok());
    226   s = db_iterator_->Seek(target);
    227   if (!s.ok())
    228     return s;
    229   direction_ = FORWARD;
    230 
    231   HandleConflictsAndDeletes();
    232   SetCurrentIteratorToSmallestKey();
    233   return s;
    234 }
    235 
    236 leveldb::Status LevelDBTransaction::TransactionIterator::Next() {
    237   DCHECK(IsValid());
    238   if (data_changed_)
    239     RefreshDataIterator();
    240 
    241   leveldb::Status s;
    242   if (direction_ != FORWARD) {
    243     // Ensure the non-current iterator is positioned after Key().
    244 
    245     LevelDBIterator* non_current = (current_ == db_iterator_.get())
    246                                        ? data_iterator_.get()
    247                                        : db_iterator_.get();
    248 
    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();
    255       if (!s.ok())
    256         return s;
    257     }
    258     DCHECK(!non_current->IsValid() ||
    259            comparator_->Compare(non_current->Key(), Key()) > 0);
    260 
    261     direction_ = FORWARD;
    262   }
    263 
    264   s = current_->Next();
    265   if (!s.ok())
    266     return s;
    267   HandleConflictsAndDeletes();
    268   SetCurrentIteratorToSmallestKey();
    269   return leveldb::Status::OK();
    270 }
    271 
    272 leveldb::Status LevelDBTransaction::TransactionIterator::Prev() {
    273   DCHECK(IsValid());
    274   leveldb::Status s;
    275   if (data_changed_)
    276     RefreshDataIterator();
    277 
    278   if (direction_ != REVERSE) {
    279     // Ensure the non-current iterator is positioned before Key().
    280 
    281     LevelDBIterator* non_current = (current_ == db_iterator_.get())
    282                                        ? data_iterator_.get()
    283                                        : db_iterator_.get();
    284 
    285     s = non_current->Seek(Key());
    286     if (!s.ok())
    287       return s;
    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.
    293       non_current->Prev();
    294     } else {
    295       // Iterator has no entries >= Key(). Position at last entry.
    296       non_current->SeekToLast();
    297     }
    298     DCHECK(!non_current->IsValid() ||
    299            comparator_->Compare(non_current->Key(), Key()) < 0);
    300 
    301     direction_ = REVERSE;
    302   }
    303 
    304   s = current_->Prev();
    305   if (!s.ok())
    306     return s;
    307   HandleConflictsAndDeletes();
    308   SetCurrentIteratorToLargestKey();
    309   return leveldb::Status::OK();
    310 }
    311 
    312 StringPiece LevelDBTransaction::TransactionIterator::Key() const {
    313   DCHECK(IsValid());
    314   if (data_changed_)
    315     RefreshDataIterator();
    316   return current_->Key();
    317 }
    318 
    319 StringPiece LevelDBTransaction::TransactionIterator::Value() const {
    320   DCHECK(IsValid());
    321   if (data_changed_)
    322     RefreshDataIterator();
    323   return current_->Value();
    324 }
    325 
    326 void LevelDBTransaction::TransactionIterator::DataChanged() {
    327   data_changed_ = true;
    328 }
    329 
    330 void LevelDBTransaction::TransactionIterator::RefreshDataIterator() const {
    331   DCHECK(data_changed_);
    332 
    333   data_changed_ = false;
    334 
    335   if (data_iterator_->IsValid() && data_iterator_.get() == current_) {
    336     return;
    337   }
    338 
    339   if (db_iterator_->IsValid()) {
    340     // There could be new records in data that we should iterate over.
    341 
    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();
    349       }
    350     } else {
    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();
    356     }
    357   }
    358 }
    359 
    360 bool LevelDBTransaction::TransactionIterator::DataIteratorIsLower() const {
    361   return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) < 0;
    362 }
    363 
    364 bool LevelDBTransaction::TransactionIterator::DataIteratorIsHigher() const {
    365   return comparator_->Compare(data_iterator_->Key(), db_iterator_->Key()) > 0;
    366 }
    367 
    368 void LevelDBTransaction::TransactionIterator::HandleConflictsAndDeletes() {
    369   bool loop = true;
    370 
    371   while (loop) {
    372     loop = false;
    373 
    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();
    380       else
    381         db_iterator_->Prev();
    382     }
    383 
    384     // Skip over delete markers in the data iterator until it catches up with
    385     // the db iterator.
    386     if (data_iterator_->IsValid() && data_iterator_->IsDeleted()) {
    387       if (direction_ == FORWARD &&
    388           (!db_iterator_->IsValid() || DataIteratorIsLower())) {
    389         data_iterator_->Next();
    390         loop = true;
    391       } else if (direction_ == REVERSE &&
    392                  (!db_iterator_->IsValid() || DataIteratorIsHigher())) {
    393         data_iterator_->Prev();
    394         loop = true;
    395       }
    396     }
    397   }
    398 }
    399 
    400 void
    401 LevelDBTransaction::TransactionIterator::SetCurrentIteratorToSmallestKey() {
    402   LevelDBIterator* smallest = 0;
    403 
    404   if (data_iterator_->IsValid())
    405     smallest = data_iterator_.get();
    406 
    407   if (db_iterator_->IsValid()) {
    408     if (!smallest ||
    409         comparator_->Compare(db_iterator_->Key(), smallest->Key()) < 0)
    410       smallest = db_iterator_.get();
    411   }
    412 
    413   current_ = smallest;
    414 }
    415 
    416 void LevelDBTransaction::TransactionIterator::SetCurrentIteratorToLargestKey() {
    417   LevelDBIterator* largest = 0;
    418 
    419   if (data_iterator_->IsValid())
    420     largest = data_iterator_.get();
    421 
    422   if (db_iterator_->IsValid()) {
    423     if (!largest ||
    424         comparator_->Compare(db_iterator_->Key(), largest->Key()) > 0)
    425       largest = db_iterator_.get();
    426   }
    427 
    428   current_ = largest;
    429 }
    430 
    431 void LevelDBTransaction::RegisterIterator(TransactionIterator* iterator) {
    432   DCHECK(iterators_.find(iterator) == iterators_.end());
    433   iterators_.insert(iterator);
    434 }
    435 
    436 void LevelDBTransaction::UnregisterIterator(TransactionIterator* iterator) {
    437   DCHECK(iterators_.find(iterator) != iterators_.end());
    438   iterators_.erase(iterator);
    439 }
    440 
    441 void LevelDBTransaction::NotifyIterators() {
    442   for (std::set<TransactionIterator*>::iterator i = iterators_.begin();
    443        i != iterators_.end();
    444        ++i) {
    445     TransactionIterator* transaction_iterator = *i;
    446     transaction_iterator->DataChanged();
    447   }
    448 }
    449 
    450 scoped_ptr<LevelDBDirectTransaction> LevelDBDirectTransaction::Create(
    451     LevelDBDatabase* db) {
    452   return make_scoped_ptr(new LevelDBDirectTransaction(db));
    453 }
    454 
    455 LevelDBDirectTransaction::LevelDBDirectTransaction(LevelDBDatabase* db)
    456     : db_(db), write_batch_(LevelDBWriteBatch::Create()), finished_(false) {}
    457 
    458 LevelDBDirectTransaction::~LevelDBDirectTransaction() {
    459   write_batch_->Clear();
    460 }
    461 
    462 void LevelDBDirectTransaction::Put(const StringPiece& key,
    463                                    const std::string* value) {
    464   DCHECK(!finished_);
    465   write_batch_->Put(key, *value);
    466 }
    467 
    468 leveldb::Status LevelDBDirectTransaction::Get(const StringPiece& key,
    469                                               std::string* value,
    470                                               bool* found) {
    471   *found = false;
    472   DCHECK(!finished_);
    473 
    474   leveldb::Status s = db_->Get(key, value, found);
    475   DCHECK(s.ok() || !*found);
    476   return s;
    477 }
    478 
    479 void LevelDBDirectTransaction::Remove(const StringPiece& key) {
    480   DCHECK(!finished_);
    481   write_batch_->Remove(key);
    482 }
    483 
    484 leveldb::Status LevelDBDirectTransaction::Commit() {
    485   DCHECK(!finished_);
    486 
    487   leveldb::Status s = db_->Write(*write_batch_);
    488   if (s.ok()) {
    489     finished_ = true;
    490     write_batch_->Clear();
    491   }
    492   return s;
    493 }
    494 
    495 }  // namespace content
    496