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