GPU workaround to simulate Out of Memory errors with large textures
[chromium-blink-merge.git] / content / child / indexed_db / webidbcursor_impl.cc
blob4f458050f824ea7970e6458641e89b1bab71381a
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 <string>
8 #include <vector>
10 #include "content/child/indexed_db/indexed_db_dispatcher.h"
11 #include "content/child/indexed_db/indexed_db_key_builders.h"
12 #include "content/child/thread_safe_sender.h"
13 #include "content/common/indexed_db/indexed_db_messages.h"
15 using blink::WebData;
16 using blink::WebIDBCallbacks;
17 using blink::WebIDBKey;
19 namespace content {
21 WebIDBCursorImpl::WebIDBCursorImpl(int32 ipc_cursor_id,
22 int64 transaction_id,
23 ThreadSafeSender* thread_safe_sender)
24 : ipc_cursor_id_(ipc_cursor_id),
25 transaction_id_(transaction_id),
26 continue_count_(0),
27 used_prefetches_(0),
28 pending_onsuccess_callbacks_(0),
29 prefetch_amount_(kMinPrefetchAmount),
30 thread_safe_sender_(thread_safe_sender) {}
32 WebIDBCursorImpl::~WebIDBCursorImpl() {
33 // It's not possible for there to be pending callbacks that address this
34 // object since inside WebKit, they hold a reference to the object which owns
35 // this object. But, if that ever changed, then we'd need to invalidate
36 // any such pointers.
38 if (ipc_cursor_id_ != kInvalidCursorId) {
39 // Invalid ID used in tests to avoid really sending this message.
40 thread_safe_sender_->Send(
41 new IndexedDBHostMsg_CursorDestroyed(ipc_cursor_id_));
43 IndexedDBDispatcher* dispatcher =
44 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
45 dispatcher->CursorDestroyed(ipc_cursor_id_);
48 void WebIDBCursorImpl::advance(unsigned long count,
49 WebIDBCallbacks* callbacks_ptr) {
50 IndexedDBDispatcher* dispatcher =
51 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
52 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
53 if (count <= prefetch_keys_.size()) {
54 CachedAdvance(count, callbacks.get());
55 return;
57 ResetPrefetchCache();
58 dispatcher->RequestIDBCursorAdvance(
59 count, callbacks.release(), ipc_cursor_id_, transaction_id_);
62 void WebIDBCursorImpl::continueFunction(const WebIDBKey& key,
63 WebIDBCallbacks* callbacks_ptr) {
64 continueFunction(key, WebIDBKey::createNull(), callbacks_ptr);
67 void WebIDBCursorImpl::continueFunction(const WebIDBKey& key,
68 const WebIDBKey& primary_key,
69 WebIDBCallbacks* callbacks_ptr) {
70 IndexedDBDispatcher* dispatcher =
71 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
72 scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr);
74 if (key.keyType() == blink::WebIDBKeyTypeNull &&
75 primary_key.keyType() == blink::WebIDBKeyTypeNull) {
76 // No key(s), so this would qualify for a prefetch.
77 ++continue_count_;
79 if (!prefetch_keys_.empty()) {
80 // We have a prefetch cache, so serve the result from that.
81 CachedContinue(callbacks.get());
82 return;
85 if (continue_count_ > kPrefetchContinueThreshold) {
86 // Request pre-fetch.
87 ++pending_onsuccess_callbacks_;
88 dispatcher->RequestIDBCursorPrefetch(
89 prefetch_amount_, callbacks.release(), ipc_cursor_id_);
91 // Increase prefetch_amount_ exponentially.
92 prefetch_amount_ *= 2;
93 if (prefetch_amount_ > kMaxPrefetchAmount)
94 prefetch_amount_ = kMaxPrefetchAmount;
96 return;
98 } else {
99 // Key argument supplied. We couldn't prefetch this.
100 ResetPrefetchCache();
103 dispatcher->RequestIDBCursorContinue(IndexedDBKeyBuilder::Build(key),
104 IndexedDBKeyBuilder::Build(primary_key),
105 callbacks.release(),
106 ipc_cursor_id_,
107 transaction_id_);
110 void WebIDBCursorImpl::postSuccessHandlerCallback() {
111 pending_onsuccess_callbacks_--;
113 // If the onsuccess callback called continue()/advance() on the cursor
114 // again, and that request was served by the prefetch cache, then
115 // pending_onsuccess_callbacks_ would be incremented. If not, it means the
116 // callback did something else, or nothing at all, in which case we need to
117 // reset the cache.
119 if (pending_onsuccess_callbacks_ == 0)
120 ResetPrefetchCache();
123 void WebIDBCursorImpl::SetPrefetchData(
124 const std::vector<IndexedDBKey>& keys,
125 const std::vector<IndexedDBKey>& primary_keys,
126 const std::vector<WebData>& values,
127 const std::vector<blink::WebVector<blink::WebBlobInfo> >& blob_info) {
128 prefetch_keys_.assign(keys.begin(), keys.end());
129 prefetch_primary_keys_.assign(primary_keys.begin(), primary_keys.end());
130 prefetch_values_.assign(values.begin(), values.end());
131 prefetch_blob_info_.assign(blob_info.begin(), blob_info.end());
133 used_prefetches_ = 0;
134 pending_onsuccess_callbacks_ = 0;
137 void WebIDBCursorImpl::CachedAdvance(unsigned long count,
138 WebIDBCallbacks* callbacks) {
139 DCHECK_GE(prefetch_keys_.size(), count);
140 DCHECK_EQ(prefetch_primary_keys_.size(), prefetch_keys_.size());
141 DCHECK_EQ(prefetch_values_.size(), prefetch_keys_.size());
142 DCHECK_EQ(prefetch_blob_info_.size(), prefetch_keys_.size());
144 while (count > 1) {
145 prefetch_keys_.pop_front();
146 prefetch_primary_keys_.pop_front();
147 prefetch_values_.pop_front();
148 prefetch_blob_info_.pop_front();
149 ++used_prefetches_;
150 --count;
153 CachedContinue(callbacks);
156 void WebIDBCursorImpl::CachedContinue(WebIDBCallbacks* callbacks) {
157 DCHECK_GT(prefetch_keys_.size(), 0ul);
158 DCHECK_EQ(prefetch_primary_keys_.size(), prefetch_keys_.size());
159 DCHECK_EQ(prefetch_values_.size(), prefetch_keys_.size());
160 DCHECK_EQ(prefetch_blob_info_.size(), prefetch_keys_.size());
162 IndexedDBKey key = prefetch_keys_.front();
163 IndexedDBKey primary_key = prefetch_primary_keys_.front();
164 WebData value = prefetch_values_.front();
165 blink::WebVector<blink::WebBlobInfo> blob_info = prefetch_blob_info_.front();
167 prefetch_keys_.pop_front();
168 prefetch_primary_keys_.pop_front();
169 prefetch_values_.pop_front();
170 prefetch_blob_info_.pop_front();
171 ++used_prefetches_;
173 ++pending_onsuccess_callbacks_;
175 if (!continue_count_) {
176 // The cache was invalidated by a call to ResetPrefetchCache()
177 // after the RequestIDBCursorPrefetch() was made. Now that the
178 // initiating continue() call has been satisfied, discard
179 // the rest of the cache.
180 ResetPrefetchCache();
183 callbacks->onSuccess(WebIDBKeyBuilder::Build(key),
184 WebIDBKeyBuilder::Build(primary_key),
185 value,
186 blob_info);
189 void WebIDBCursorImpl::ResetPrefetchCache() {
190 continue_count_ = 0;
191 prefetch_amount_ = kMinPrefetchAmount;
193 if (!prefetch_keys_.size()) {
194 // No prefetch cache, so no need to reset the cursor in the back-end.
195 return;
198 // Ack any unused blobs.
199 std::vector<std::string> uuids;
200 for (const auto& blobs : prefetch_blob_info_) {
201 for (size_t i = 0, size = blobs.size(); i < size; ++i)
202 uuids.push_back(blobs[i].uuid().latin1());
204 if (!uuids.empty())
205 thread_safe_sender_->Send(new IndexedDBHostMsg_AckReceivedBlobs(uuids));
207 // Reset the back-end cursor.
208 IndexedDBDispatcher* dispatcher =
209 IndexedDBDispatcher::ThreadSpecificInstance(thread_safe_sender_.get());
210 dispatcher->RequestIDBCursorPrefetchReset(
211 used_prefetches_, prefetch_keys_.size(), ipc_cursor_id_);
213 // Reset the prefetch cache.
214 prefetch_keys_.clear();
215 prefetch_primary_keys_.clear();
216 prefetch_values_.clear();
217 prefetch_blob_info_.clear();
219 pending_onsuccess_callbacks_ = 0;
222 } // namespace content