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