Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / indexed_db / leveldb / leveldb_transaction.cc
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