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.
5 #include "content/browser/indexed_db/indexed_db_cursor.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 #include "content/browser/indexed_db/indexed_db_value.h"
17 IndexedDBCursor::IndexedDBCursor(
18 scoped_ptr
<IndexedDBBackingStore::Cursor
> cursor
,
19 indexed_db::CursorType cursor_type
,
20 IndexedDBDatabase::TaskType task_type
,
21 IndexedDBTransaction
* transaction
)
22 : task_type_(task_type
),
23 cursor_type_(cursor_type
),
24 transaction_(transaction
),
25 cursor_(cursor
.Pass()),
27 transaction_
->RegisterOpenCursor(this);
30 IndexedDBCursor::~IndexedDBCursor() {
31 transaction_
->UnregisterOpenCursor(this);
34 void IndexedDBCursor::Continue(scoped_ptr
<IndexedDBKey
> key
,
35 scoped_ptr
<IndexedDBKey
> primary_key
,
36 scoped_refptr
<IndexedDBCallbacks
> callbacks
) {
37 IDB_TRACE("IndexedDBCursor::Continue");
39 transaction_
->ScheduleTask(
41 base::Bind(&IndexedDBCursor::CursorIterationOperation
,
44 base::Passed(&primary_key
),
48 void IndexedDBCursor::Advance(uint32 count
,
49 scoped_refptr
<IndexedDBCallbacks
> callbacks
) {
50 IDB_TRACE("IndexedDBCursor::Advance");
52 transaction_
->ScheduleTask(
55 &IndexedDBCursor::CursorAdvanceOperation
, this, count
, callbacks
));
58 void IndexedDBCursor::CursorAdvanceOperation(
60 scoped_refptr
<IndexedDBCallbacks
> callbacks
,
61 IndexedDBTransaction
* /*transaction*/) {
62 IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation");
64 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
65 // properly fail, caller will not know why, and any corruption
67 if (!cursor_
|| !cursor_
->Advance(count
, &s
)) {
69 callbacks
->OnSuccess(static_cast<IndexedDBValue
*>(NULL
));
73 callbacks
->OnSuccess(key(), primary_key(), Value());
76 void IndexedDBCursor::CursorIterationOperation(
77 scoped_ptr
<IndexedDBKey
> key
,
78 scoped_ptr
<IndexedDBKey
> primary_key
,
79 scoped_refptr
<IndexedDBCallbacks
> callbacks
,
80 IndexedDBTransaction
* /*transaction*/) {
81 IDB_TRACE("IndexedDBCursor::CursorIterationOperation");
83 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
84 // properly fail, caller will not know why, and any corruption
86 if (!cursor_
|| !cursor_
->Continue(key
.get(),
88 IndexedDBBackingStore::Cursor::SEEK
,
91 callbacks
->OnSuccess(static_cast<IndexedDBValue
*>(NULL
));
95 callbacks
->OnSuccess(this->key(), this->primary_key(), Value());
98 void IndexedDBCursor::PrefetchContinue(
100 scoped_refptr
<IndexedDBCallbacks
> callbacks
) {
101 IDB_TRACE("IndexedDBCursor::PrefetchContinue");
103 transaction_
->ScheduleTask(
105 base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation
,
111 void IndexedDBCursor::CursorPrefetchIterationOperation(
113 scoped_refptr
<IndexedDBCallbacks
> callbacks
,
114 IndexedDBTransaction
* /*transaction*/) {
115 IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation");
117 std::vector
<IndexedDBKey
> found_keys
;
118 std::vector
<IndexedDBKey
> found_primary_keys
;
119 std::vector
<IndexedDBValue
> found_values
;
121 saved_cursor_
.reset();
122 const size_t max_size_estimate
= 10 * 1024 * 1024;
123 size_t size_estimate
= 0;
126 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
127 // properly fail, caller will not know why, and any corruption
129 for (int i
= 0; i
< number_to_fetch
; ++i
) {
130 if (!cursor_
|| !cursor_
->Continue(&s
)) {
136 // First prefetched result is always used, so that's the position
137 // a cursor should be reset to if the prefetch is invalidated.
138 saved_cursor_
.reset(cursor_
->Clone());
141 found_keys
.push_back(cursor_
->key());
142 found_primary_keys
.push_back(cursor_
->primary_key());
144 switch (cursor_type_
) {
145 case indexed_db::CURSOR_KEY_ONLY
:
146 found_values
.push_back(IndexedDBValue());
148 case indexed_db::CURSOR_KEY_AND_VALUE
: {
149 IndexedDBValue value
;
150 value
.swap(*cursor_
->value());
151 size_estimate
+= value
.SizeEstimate();
152 found_values
.push_back(value
);
158 size_estimate
+= cursor_
->key().size_estimate();
159 size_estimate
+= cursor_
->primary_key().size_estimate();
161 if (size_estimate
> max_size_estimate
)
165 if (!found_keys
.size()) {
166 callbacks
->OnSuccess(static_cast<IndexedDBValue
*>(NULL
));
170 callbacks
->OnSuccessWithPrefetch(
171 found_keys
, found_primary_keys
, found_values
);
174 leveldb::Status
IndexedDBCursor::PrefetchReset(int used_prefetches
,
175 int /* unused_prefetches */) {
176 IDB_TRACE("IndexedDBCursor::PrefetchReset");
177 cursor_
.swap(saved_cursor_
);
178 saved_cursor_
.reset();
184 // First prefetched result is always used.
185 DCHECK_GT(used_prefetches
, 0);
186 for (int i
= 0; i
< used_prefetches
- 1; ++i
) {
187 bool ok
= cursor_
->Continue(&s
);
195 void IndexedDBCursor::Close() {
196 IDB_TRACE("IndexedDBCursor::Close");
199 saved_cursor_
.reset();
202 } // namespace content