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