indexed_db_cursor.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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 saved_cursor_.reset(); 112 const size_t max_size_estimate = 10 * 1024 * 1024; 113 size_t size_estimate = 0; 114 115 for (int i = 0; i < number_to_fetch; ++i) { 116 if (!cursor_ || !cursor_->Continue()) { 117 cursor_.reset(); 118 break; 119 } 120 121 if (i == 0) { 122 // First prefetched result is always used, so that's the position 123 // a cursor should be reset to if the prefetch is invalidated. 124 saved_cursor_.reset(cursor_->Clone()); 125 } 126 127 found_keys.push_back(cursor_->key()); 128 found_primary_keys.push_back(cursor_->primary_key()); 129 130 switch (cursor_type_) { 131 case indexed_db::CURSOR_KEY_ONLY: 132 found_values.push_back(std::string()); 133 break; 134 case indexed_db::CURSOR_KEY_AND_VALUE: { 135 std::string value; 136 value.swap(*cursor_->value()); 137 size_estimate += value.size(); 138 found_values.push_back(value); 139 break; 140 } 141 default: 142 NOTREACHED(); 143 } 144 size_estimate += cursor_->key().size_estimate(); 145 size_estimate += cursor_->primary_key().size_estimate(); 146 147 if (size_estimate > max_size_estimate) 148 break; 149 } 150 151 if (!found_keys.size()) { 152 callbacks->OnSuccess(static_cast<std::string*>(NULL)); 153 return; 154 } 155 156 callbacks->OnSuccessWithPrefetch( 157 found_keys, found_primary_keys, found_values); 158} 159 160void IndexedDBCursor::PrefetchReset(int used_prefetches, 161 int /* unused_prefetches */) { 162 IDB_TRACE("IndexedDBCursor::PrefetchReset"); 163 cursor_.swap(saved_cursor_); 164 saved_cursor_.reset(); 165 166 if (closed_) 167 return; 168 if (cursor_) { 169 // First prefetched result is always used. 170 DCHECK_GT(used_prefetches, 0); 171 for (int i = 0; i < used_prefetches - 1; ++i) { 172 bool ok = cursor_->Continue(); 173 DCHECK(ok); 174 } 175 } 176} 177 178void IndexedDBCursor::Close() { 179 IDB_TRACE("IndexedDBCursor::Close"); 180 closed_ = true; 181 cursor_.reset(); 182 saved_cursor_.reset(); 183} 184 185} // namespace content 186