indexed_db_cursor.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 13namespace content { 14 15class 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 30class 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 45class 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 62IndexedDBCursor::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 75IndexedDBCursor::~IndexedDBCursor() { 76 transaction_->UnregisterOpenCursor(this); 77} 78 79void IndexedDBCursor::ContinueFunction( 80 scoped_ptr<IndexedDBKey> key, 81 scoped_refptr<IndexedDBCallbacks> callbacks) { 82 IDB_TRACE("IndexedDBCursor::Continue"); 83 84 transaction_->ScheduleTask( 85 task_type_, new CursorIterationOperation(this, key.Pass(), callbacks)); 86} 87 88void IndexedDBCursor::Advance(uint32 count, 89 scoped_refptr<IndexedDBCallbacks> callbacks) { 90 IDB_TRACE("IndexedDBCursor::Advance"); 91 92 transaction_->ScheduleTask( 93 new CursorAdvanceOperation(this, count, callbacks)); 94} 95 96void IndexedDBCursor::CursorAdvanceOperation::Perform( 97 IndexedDBTransaction* /*transaction*/) { 98 IDB_TRACE("CursorAdvanceOperation"); 99 if (!cursor_->cursor_ || !cursor_->cursor_->Advance(count_)) { 100 cursor_->cursor_.reset(); 101 callbacks_->OnSuccess(static_cast<std::vector<char>*>(NULL)); 102 return; 103 } 104 105 callbacks_->OnSuccess( 106 cursor_->key(), cursor_->primary_key(), cursor_->Value()); 107} 108 109void IndexedDBCursor::CursorIterationOperation::Perform( 110 IndexedDBTransaction* /*transaction*/) { 111 IDB_TRACE("CursorIterationOperation"); 112 if (!cursor_->cursor_ || 113 !cursor_->cursor_->ContinueFunction( 114 key_.get(), IndexedDBBackingStore::Cursor::SEEK)) { 115 cursor_->cursor_.reset(); 116 callbacks_->OnSuccess(static_cast<std::vector<char>*>(NULL)); 117 return; 118 } 119 120 callbacks_->OnSuccess( 121 cursor_->key(), cursor_->primary_key(), cursor_->Value()); 122} 123 124void IndexedDBCursor::PrefetchContinue( 125 int number_to_fetch, 126 scoped_refptr<IndexedDBCallbacks> callbacks) { 127 IDB_TRACE("IndexedDBCursor::PrefetchContinue"); 128 129 transaction_->ScheduleTask( 130 task_type_, 131 new CursorPrefetchIterationOperation(this, number_to_fetch, callbacks)); 132} 133 134void IndexedDBCursor::CursorPrefetchIterationOperation::Perform( 135 IndexedDBTransaction* /*transaction*/) { 136 IDB_TRACE("CursorPrefetchIterationOperation"); 137 138 std::vector<IndexedDBKey> found_keys; 139 std::vector<IndexedDBKey> found_primary_keys; 140 std::vector<std::vector<char> > found_values; 141 142 if (cursor_->cursor_) 143 cursor_->saved_cursor_.reset(cursor_->cursor_->Clone()); 144 const size_t max_size_estimate = 10 * 1024 * 1024; 145 size_t size_estimate = 0; 146 147 for (int i = 0; i < number_to_fetch_; ++i) { 148 if (!cursor_->cursor_ || !cursor_->cursor_->ContinueFunction()) { 149 cursor_->cursor_.reset(); 150 break; 151 } 152 153 found_keys.push_back(cursor_->cursor_->key()); 154 found_primary_keys.push_back(cursor_->cursor_->primary_key()); 155 156 switch (cursor_->cursor_type_) { 157 case indexed_db::CURSOR_KEY_ONLY: 158 found_values.push_back(std::vector<char>()); 159 break; 160 case indexed_db::CURSOR_KEY_AND_VALUE: { 161 std::vector<char> value; 162 value.swap(*cursor_->cursor_->Value()); 163 size_estimate += value.size(); 164 found_values.push_back(value); 165 break; 166 } 167 default: 168 NOTREACHED(); 169 } 170 size_estimate += cursor_->cursor_->key().size_estimate(); 171 size_estimate += cursor_->cursor_->primary_key().size_estimate(); 172 173 if (size_estimate > max_size_estimate) 174 break; 175 } 176 177 if (!found_keys.size()) { 178 callbacks_->OnSuccess(static_cast<std::vector<char>*>(NULL)); 179 return; 180 } 181 182 callbacks_->OnSuccessWithPrefetch( 183 found_keys, found_primary_keys, found_values); 184} 185 186void IndexedDBCursor::PrefetchReset(int used_prefetches, int) { 187 IDB_TRACE("IndexedDBCursor::PrefetchReset"); 188 cursor_.swap(saved_cursor_); 189 saved_cursor_.reset(); 190 191 if (closed_) 192 return; 193 if (cursor_) { 194 for (int i = 0; i < used_prefetches; ++i) { 195 bool ok = cursor_->ContinueFunction(); 196 DCHECK(ok); 197 } 198 } 199} 200 201void IndexedDBCursor::Close() { 202 IDB_TRACE("IndexedDBCursor::Close"); 203 closed_ = true; 204 cursor_.reset(); 205 saved_cursor_.reset(); 206} 207 208} // namespace content 209