IndexedDBFactory now ForceCloses databases.
[chromium-blink-merge.git] / content / child / indexed_db / webidbcursor_impl.cc
blob50f7ebf0409b640cb0732d79064fefc5dfb09063
1 // Copyright 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/child/indexed_db/webidbcursor_impl.h"
7 #include <vector>
9 #include "content/child/indexed_db/indexed_db_dispatcher.h"
10 #include "content/child/indexed_db/indexed_db_key_builders.h"
11 #include "content/child/thread_safe_sender.h"
12 #include "content/common/indexed_db/indexed_db_messages.h"
14 using blink::WebData;
15 using blink::WebIDBCallbacks;
16 using blink::WebIDBKey;
18 namespace content {
20 WebIDBCursorImpl::WebIDBCursorImpl(int32 ipc_cursor_id,
21 ThreadSafeSender* thread_safe_sender)
22 : ipc_cursor_id_(ipc_cursor_id),
23 continue_count_(0),
24 used_prefetches_(0),
25 pending_onsuccess_callbacks_(0),
26 prefetch_amount_(kMinPrefetchAmount),
27 thread_safe_sender_(thread_safe_sender) {}
29 WebIDBCursorImpl::~WebIDBCursorImpl() {
30 // It's not possible for there to be pending callbacks that address this
31 // object since inside WebKit, they hold a reference to the object which owns
32 // this object. But, if that ever changed, then we'd need to invalidate
33 // any such pointers.
35 if (ipc_cursor_id_ != kInvalidCursorId) {
36 // Invalid ID used in tests to avoid really sending this message.
37 thread_safe_sender_->Send(
38 new IndexedDBHostMsg_CursorDestroyed(ipc_cursor_id_));
40 IndexedDBDispatcher* dispatcher =
41 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
42 dispatcher->CursorDestroyed(ipc_cursor_id_);
45 void WebIDBCursorImpl::advance(unsigned long count,
46 WebIDBCallbacks* callbacks_ptr) {
47 IndexedDBDispatcher* dispatcher =
48 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
49 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
50 if (count <= prefetch_keys_.size()) {
51 CachedAdvance(count, callbacks.get());
52 return;
54 ResetPrefetchCache();
55 dispatcher->RequestIDBCursorAdvance(
56 count, callbacks.release(), ipc_cursor_id_);
59 void WebIDBCursorImpl::continueFunction(const WebIDBKey& key,
60 WebIDBCallbacks* callbacks_ptr) {
61 continueFunction(key, WebIDBKey::createNull(), callbacks_ptr);
64 void WebIDBCursorImpl::continueFunction(const WebIDBKey& key,
65 const WebIDBKey& primary_key,
66 WebIDBCallbacks* callbacks_ptr) {
67 IndexedDBDispatcher* dispatcher =
68 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
69 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
71 if (key.keyType() == blink::WebIDBKeyTypeNull &&
72 primary_key.keyType() == blink::WebIDBKeyTypeNull) {
73 // No key(s), so this would qualify for a prefetch.
74 ++continue_count_;
76 if (!prefetch_keys_.empty()) {
77 // We have a prefetch cache, so serve the result from that.
78 CachedContinue(callbacks.get());
79 return;
82 if (continue_count_ > kPrefetchContinueThreshold) {
83 // Request pre-fetch.
84 ++pending_onsuccess_callbacks_;
85 dispatcher->RequestIDBCursorPrefetch(
86 prefetch_amount_, callbacks.release(), ipc_cursor_id_);
88 // Increase prefetch_amount_ exponentially.
89 prefetch_amount_ *= 2;
90 if (prefetch_amount_ > kMaxPrefetchAmount)
91 prefetch_amount_ = kMaxPrefetchAmount;
93 return;
95 } else {
96 // Key argument supplied. We couldn't prefetch this.
97 ResetPrefetchCache();
100 dispatcher->RequestIDBCursorContinue(IndexedDBKeyBuilder::Build(key),
101 IndexedDBKeyBuilder::Build(primary_key),
102 callbacks.release(),
103 ipc_cursor_id_);
106 void WebIDBCursorImpl::postSuccessHandlerCallback() {
107 pending_onsuccess_callbacks_--;
109 // If the onsuccess callback called continue()/advance() on the cursor
110 // again, and that request was served by the prefetch cache, then
111 // pending_onsuccess_callbacks_ would be incremented. If not, it means the
112 // callback did something else, or nothing at all, in which case we need to
113 // reset the cache.
115 if (pending_onsuccess_callbacks_ == 0)
116 ResetPrefetchCache();
119 void WebIDBCursorImpl::SetPrefetchData(
120 const std::vector<IndexedDBKey>& keys,
121 const std::vector<IndexedDBKey>& primary_keys,
122 const std::vector<WebData>& values) {
123 prefetch_keys_.assign(keys.begin(), keys.end());
124 prefetch_primary_keys_.assign(primary_keys.begin(), primary_keys.end());
125 prefetch_values_.assign(values.begin(), values.end());
127 used_prefetches_ = 0;
128 pending_onsuccess_callbacks_ = 0;
131 void WebIDBCursorImpl::CachedAdvance(unsigned long count,
132 WebIDBCallbacks* callbacks) {
133 DCHECK_GE(prefetch_keys_.size(), count);
134 DCHECK_EQ(prefetch_primary_keys_.size(), prefetch_keys_.size());
135 DCHECK_EQ(prefetch_values_.size(), prefetch_keys_.size());
137 while (count > 1) {
138 prefetch_keys_.pop_front();
139 prefetch_primary_keys_.pop_front();
140 prefetch_values_.pop_front();
141 ++used_prefetches_;
142 --count;
145 CachedContinue(callbacks);
148 void WebIDBCursorImpl::CachedContinue(WebIDBCallbacks* callbacks) {
149 DCHECK_GT(prefetch_keys_.size(), 0ul);
150 DCHECK_EQ(prefetch_primary_keys_.size(), prefetch_keys_.size());
151 DCHECK_EQ(prefetch_values_.size(), prefetch_keys_.size());
153 IndexedDBKey key = prefetch_keys_.front();
154 IndexedDBKey primary_key = prefetch_primary_keys_.front();
155 WebData value = prefetch_values_.front();
157 prefetch_keys_.pop_front();
158 prefetch_primary_keys_.pop_front();
159 prefetch_values_.pop_front();
160 ++used_prefetches_;
162 ++pending_onsuccess_callbacks_;
164 if (!continue_count_) {
165 // The cache was invalidated by a call to ResetPrefetchCache()
166 // after the RequestIDBCursorPrefetch() was made. Now that the
167 // initiating continue() call has been satisfied, discard
168 // the rest of the cache.
169 ResetPrefetchCache();
172 callbacks->onSuccess(WebIDBKeyBuilder::Build(key),
173 WebIDBKeyBuilder::Build(primary_key),
174 value);
177 void WebIDBCursorImpl::ResetPrefetchCache() {
178 continue_count_ = 0;
179 prefetch_amount_ = kMinPrefetchAmount;
181 if (!prefetch_keys_.size()) {
182 // No prefetch cache, so no need to reset the cursor in the back-end.
183 return;
186 IndexedDBDispatcher* dispatcher =
187 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
188 dispatcher->RequestIDBCursorPrefetchReset(
189 used_prefetches_, prefetch_keys_.size(), ipc_cursor_id_);
190 prefetch_keys_.clear();
191 prefetch_primary_keys_.clear();
192 prefetch_values_.clear();
194 pending_onsuccess_callbacks_ = 0;
197 } // namespace content