Home | History | Annotate | Download | only in indexed_db
      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/indexed_db_cursor.h"
      6 
      7 #include "base/logging.h"
      8 #include "content/browser/indexed_db/indexed_db_callbacks.h"
      9 #include "content/browser/indexed_db/indexed_db_database_error.h"
     10 #include "content/browser/indexed_db/indexed_db_tracing.h"
     11 #include "content/browser/indexed_db/indexed_db_transaction.h"
     12 
     13 namespace content {
     14 
     15 class IndexedDBCursor::CursorIterationOperation
     16     : public IndexedDBTransaction::Operation {
     17  public:
     18   CursorIterationOperation(scoped_refptr<IndexedDBCursor> cursor,
     19                            scoped_ptr<IndexedDBKey> key,
     20                            scoped_refptr<IndexedDBCallbacks> callbacks)
     21       : cursor_(cursor), key_(key.Pass()), callbacks_(callbacks) {}
     22   virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
     23 
     24  private:
     25   scoped_refptr<IndexedDBCursor> cursor_;
     26   scoped_ptr<IndexedDBKey> key_;
     27   scoped_refptr<IndexedDBCallbacks> callbacks_;
     28 };
     29 
     30 class IndexedDBCursor::CursorAdvanceOperation
     31     : public IndexedDBTransaction::Operation {
     32  public:
     33   CursorAdvanceOperation(scoped_refptr<IndexedDBCursor> cursor,
     34                          uint32 count,
     35                          scoped_refptr<IndexedDBCallbacks> callbacks)
     36       : cursor_(cursor), count_(count), callbacks_(callbacks) {}
     37   virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
     38 
     39  private:
     40   scoped_refptr<IndexedDBCursor> cursor_;
     41   uint32 count_;
     42   scoped_refptr<IndexedDBCallbacks> callbacks_;
     43 };
     44 
     45 class IndexedDBCursor::CursorPrefetchIterationOperation
     46     : public IndexedDBTransaction::Operation {
     47  public:
     48   CursorPrefetchIterationOperation(scoped_refptr<IndexedDBCursor> cursor,
     49                                    int number_to_fetch,
     50                                    scoped_refptr<IndexedDBCallbacks> callbacks)
     51       : cursor_(cursor),
     52         number_to_fetch_(number_to_fetch),
     53         callbacks_(callbacks) {}
     54   virtual void Perform(IndexedDBTransaction* transaction) OVERRIDE;
     55 
     56  private:
     57   scoped_refptr<IndexedDBCursor> cursor_;
     58   int number_to_fetch_;
     59   scoped_refptr<IndexedDBCallbacks> callbacks_;
     60 };
     61 
     62 IndexedDBCursor::IndexedDBCursor(
     63     scoped_ptr<IndexedDBBackingStore::Cursor> cursor,
     64     indexed_db::CursorType cursor_type,
     65     IndexedDBDatabase::TaskType task_type,
     66     IndexedDBTransaction* transaction)
     67     : task_type_(task_type),
     68       cursor_type_(cursor_type),
     69       transaction_(transaction),
     70       cursor_(cursor.Pass()),
     71       closed_(false) {
     72   transaction_->RegisterOpenCursor(this);
     73 }
     74 
     75 IndexedDBCursor::~IndexedDBCursor() {
     76   transaction_->UnregisterOpenCursor(this);
     77 }
     78 
     79 void IndexedDBCursor::Continue(scoped_ptr<IndexedDBKey> key,
     80                                scoped_refptr<IndexedDBCallbacks> callbacks) {
     81   IDB_TRACE("IndexedDBCursor::Continue");
     82 
     83   transaction_->ScheduleTask(
     84       task_type_, new CursorIterationOperation(this, key.Pass(), callbacks));
     85 }
     86 
     87 void IndexedDBCursor::Advance(uint32 count,
     88                               scoped_refptr<IndexedDBCallbacks> callbacks) {
     89   IDB_TRACE("IndexedDBCursor::Advance");
     90 
     91   transaction_->ScheduleTask(
     92       new CursorAdvanceOperation(this, count, callbacks));
     93 }
     94 
     95 void IndexedDBCursor::CursorAdvanceOperation::Perform(
     96     IndexedDBTransaction* /*transaction*/) {
     97   IDB_TRACE("CursorAdvanceOperation");
     98   if (!cursor_->cursor_ || !cursor_->cursor_->Advance(count_)) {
     99     cursor_->cursor_.reset();
    100     callbacks_->OnSuccess(static_cast<std::string*>(NULL));
    101     return;
    102   }
    103 
    104   callbacks_->OnSuccess(
    105       cursor_->key(), cursor_->primary_key(), cursor_->Value());
    106 }
    107 
    108 void IndexedDBCursor::CursorIterationOperation::Perform(
    109     IndexedDBTransaction* /*transaction*/) {
    110   IDB_TRACE("CursorIterationOperation");
    111   if (!cursor_->cursor_ ||
    112       !cursor_->cursor_->Continue(key_.get(),
    113                                   IndexedDBBackingStore::Cursor::SEEK)) {
    114     cursor_->cursor_.reset();
    115     callbacks_->OnSuccess(static_cast<std::string*>(NULL));
    116     return;
    117   }
    118 
    119   callbacks_->OnSuccess(
    120       cursor_->key(), cursor_->primary_key(), cursor_->Value());
    121 }
    122 
    123 void IndexedDBCursor::PrefetchContinue(
    124     int number_to_fetch,
    125     scoped_refptr<IndexedDBCallbacks> callbacks) {
    126   IDB_TRACE("IndexedDBCursor::PrefetchContinue");
    127 
    128   transaction_->ScheduleTask(
    129       task_type_,
    130       new CursorPrefetchIterationOperation(this, number_to_fetch, callbacks));
    131 }
    132 
    133 void IndexedDBCursor::CursorPrefetchIterationOperation::Perform(
    134     IndexedDBTransaction* /*transaction*/) {
    135   IDB_TRACE("CursorPrefetchIterationOperation");
    136 
    137   std::vector<IndexedDBKey> found_keys;
    138   std::vector<IndexedDBKey> found_primary_keys;
    139   std::vector<std::string> found_values;
    140 
    141   if (cursor_->cursor_)
    142     cursor_->saved_cursor_.reset(cursor_->cursor_->Clone());
    143   const size_t max_size_estimate = 10 * 1024 * 1024;
    144   size_t size_estimate = 0;
    145 
    146   for (int i = 0; i < number_to_fetch_; ++i) {
    147     if (!cursor_->cursor_ || !cursor_->cursor_->Continue()) {
    148       cursor_->cursor_.reset();
    149       break;
    150     }
    151 
    152     found_keys.push_back(cursor_->cursor_->key());
    153     found_primary_keys.push_back(cursor_->cursor_->primary_key());
    154 
    155     switch (cursor_->cursor_type_) {
    156       case indexed_db::CURSOR_KEY_ONLY:
    157         found_values.push_back(std::string());
    158         break;
    159       case indexed_db::CURSOR_KEY_AND_VALUE: {
    160         std::string value;
    161         value.swap(*cursor_->cursor_->Value());
    162         size_estimate += value.size();
    163         found_values.push_back(value);
    164         break;
    165       }
    166       default:
    167         NOTREACHED();
    168     }
    169     size_estimate += cursor_->cursor_->key().size_estimate();
    170     size_estimate += cursor_->cursor_->primary_key().size_estimate();
    171 
    172     if (size_estimate > max_size_estimate)
    173       break;
    174   }
    175 
    176   if (!found_keys.size()) {
    177     callbacks_->OnSuccess(static_cast<std::string*>(NULL));
    178     return;
    179   }
    180 
    181   callbacks_->OnSuccessWithPrefetch(
    182       found_keys, found_primary_keys, found_values);
    183 }
    184 
    185 void IndexedDBCursor::PrefetchReset(int used_prefetches, int) {
    186   IDB_TRACE("IndexedDBCursor::PrefetchReset");
    187   cursor_.swap(saved_cursor_);
    188   saved_cursor_.reset();
    189 
    190   if (closed_)
    191     return;
    192   if (cursor_) {
    193     for (int i = 0; i < used_prefetches; ++i) {
    194       bool ok = cursor_->Continue();
    195       DCHECK(ok);
    196     }
    197   }
    198 }
    199 
    200 void IndexedDBCursor::Close() {
    201   IDB_TRACE("IndexedDBCursor::Close");
    202   closed_ = true;
    203   cursor_.reset();
    204   saved_cursor_.reset();
    205 }
    206 
    207 }  // namespace content
    208