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"
10 #include "base/logging.h"
11 #include "content/browser/indexed_db/indexed_db_callbacks.h"
12 #include "content/browser/indexed_db/indexed_db_database_error.h"
13 #include "content/browser/indexed_db/indexed_db_tracing.h"
14 #include "content/browser/indexed_db/indexed_db_transaction.h"
15 #include "content/browser/indexed_db/indexed_db_value.h"
19 IndexedDBCursor::IndexedDBCursor(
20 scoped_ptr
<IndexedDBBackingStore::Cursor
> cursor
,
21 indexed_db::CursorType cursor_type
,
22 blink::WebIDBTaskType task_type
,
23 IndexedDBTransaction
* transaction
)
24 : task_type_(task_type
),
25 cursor_type_(cursor_type
),
26 transaction_(transaction
),
27 cursor_(cursor
.Pass()),
29 transaction_
->RegisterOpenCursor(this);
32 IndexedDBCursor::~IndexedDBCursor() {
33 transaction_
->UnregisterOpenCursor(this);
36 void IndexedDBCursor::Continue(scoped_ptr
<IndexedDBKey
> key
,
37 scoped_ptr
<IndexedDBKey
> primary_key
,
38 scoped_refptr
<IndexedDBCallbacks
> callbacks
) {
39 IDB_TRACE("IndexedDBCursor::Continue");
41 transaction_
->ScheduleTask(
43 base::Bind(&IndexedDBCursor::CursorIterationOperation
,
46 base::Passed(&primary_key
),
50 void IndexedDBCursor::Advance(uint32 count
,
51 scoped_refptr
<IndexedDBCallbacks
> callbacks
) {
52 IDB_TRACE("IndexedDBCursor::Advance");
54 transaction_
->ScheduleTask(
57 &IndexedDBCursor::CursorAdvanceOperation
, this, count
, callbacks
));
60 void IndexedDBCursor::CursorAdvanceOperation(
62 scoped_refptr
<IndexedDBCallbacks
> callbacks
,
63 IndexedDBTransaction
* /*transaction*/) {
64 IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation");
66 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
67 // properly fail, caller will not know why, and any corruption
69 if (!cursor_
|| !cursor_
->Advance(count
, &s
)) {
71 callbacks
->OnSuccess(static_cast<IndexedDBValue
*>(NULL
));
75 callbacks
->OnSuccess(key(), primary_key(), Value());
78 void IndexedDBCursor::CursorIterationOperation(
79 scoped_ptr
<IndexedDBKey
> key
,
80 scoped_ptr
<IndexedDBKey
> primary_key
,
81 scoped_refptr
<IndexedDBCallbacks
> callbacks
,
82 IndexedDBTransaction
* /*transaction*/) {
83 IDB_TRACE("IndexedDBCursor::CursorIterationOperation");
85 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
86 // properly fail, caller will not know why, and any corruption
88 if (!cursor_
|| !cursor_
->Continue(key
.get(),
90 IndexedDBBackingStore::Cursor::SEEK
,
93 callbacks
->OnSuccess(static_cast<IndexedDBValue
*>(NULL
));
97 callbacks
->OnSuccess(this->key(), this->primary_key(), Value());
100 void IndexedDBCursor::PrefetchContinue(
102 scoped_refptr
<IndexedDBCallbacks
> callbacks
) {
103 IDB_TRACE("IndexedDBCursor::PrefetchContinue");
105 transaction_
->ScheduleTask(
107 base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation
,
113 void IndexedDBCursor::CursorPrefetchIterationOperation(
115 scoped_refptr
<IndexedDBCallbacks
> callbacks
,
116 IndexedDBTransaction
* /*transaction*/) {
117 IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation");
119 std::vector
<IndexedDBKey
> found_keys
;
120 std::vector
<IndexedDBKey
> found_primary_keys
;
121 std::vector
<IndexedDBValue
> found_values
;
123 saved_cursor_
.reset();
124 const size_t max_size_estimate
= 10 * 1024 * 1024;
125 size_t size_estimate
= 0;
128 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
129 // properly fail, caller will not know why, and any corruption
131 for (int i
= 0; i
< number_to_fetch
; ++i
) {
132 if (!cursor_
|| !cursor_
->Continue(&s
)) {
138 // First prefetched result is always used, so that's the position
139 // a cursor should be reset to if the prefetch is invalidated.
140 saved_cursor_
.reset(cursor_
->Clone());
143 found_keys
.push_back(cursor_
->key());
144 found_primary_keys
.push_back(cursor_
->primary_key());
146 switch (cursor_type_
) {
147 case indexed_db::CURSOR_KEY_ONLY
:
148 found_values
.push_back(IndexedDBValue());
150 case indexed_db::CURSOR_KEY_AND_VALUE
: {
151 IndexedDBValue value
;
152 value
.swap(*cursor_
->value());
153 size_estimate
+= value
.SizeEstimate();
154 found_values
.push_back(value
);
160 size_estimate
+= cursor_
->key().size_estimate();
161 size_estimate
+= cursor_
->primary_key().size_estimate();
163 if (size_estimate
> max_size_estimate
)
167 if (!found_keys
.size()) {
168 callbacks
->OnSuccess(static_cast<IndexedDBValue
*>(NULL
));
172 callbacks
->OnSuccessWithPrefetch(
173 found_keys
, found_primary_keys
, &found_values
);
176 leveldb::Status
IndexedDBCursor::PrefetchReset(int used_prefetches
,
177 int /* unused_prefetches */) {
178 IDB_TRACE("IndexedDBCursor::PrefetchReset");
179 cursor_
.swap(saved_cursor_
);
180 saved_cursor_
.reset();
186 // First prefetched result is always used.
187 DCHECK_GT(used_prefetches
, 0);
188 for (int i
= 0; i
< used_prefetches
- 1; ++i
) {
189 bool ok
= cursor_
->Continue(&s
);
197 void IndexedDBCursor::Close() {
198 IDB_TRACE("IndexedDBCursor::Close");
201 saved_cursor_
.reset();
204 } // namespace content