indexed_db_cursor.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
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::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 87void 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 95void 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 108void 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 123void 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 133void 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 185void 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 200void IndexedDBCursor::Close() { 201 IDB_TRACE("IndexedDBCursor::Close"); 202 closed_ = true; 203 cursor_.reset(); 204 saved_cursor_.reset(); 205} 206 207} // namespace content 208