- add sources.
[platform/framework/web/crosswalk.git] / src / content / browser / indexed_db / indexed_db_cursor.cc
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
14 namespace content {
15
16 IndexedDBCursor::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
29 IndexedDBCursor::~IndexedDBCursor() {
30   transaction_->UnregisterOpenCursor(this);
31 }
32
33 void 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
45 void 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
55 void 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
69 void 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
84 void 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
97 void 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
151 void 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
166 void IndexedDBCursor::Close() {
167   IDB_TRACE("IndexedDBCursor::Close");
168   closed_ = true;
169   cursor_.reset();
170   saved_cursor_.reset();
171 }
172
173 }  // namespace content