diff options
Diffstat (limited to 'content')
-rw-r--r-- | content/browser/in_process_webkit/indexed_db_browsertest.cc | 4 | ||||
-rw-r--r-- | content/browser/in_process_webkit/indexed_db_callbacks.cc | 25 | ||||
-rw-r--r-- | content/browser/in_process_webkit/indexed_db_callbacks.h | 4 | ||||
-rw-r--r-- | content/browser/in_process_webkit/indexed_db_dispatcher_host.cc | 28 | ||||
-rw-r--r-- | content/browser/in_process_webkit/indexed_db_dispatcher_host.h | 6 | ||||
-rw-r--r-- | content/common/indexed_db_messages.h | 19 | ||||
-rw-r--r-- | content/renderer/indexed_db_dispatcher.cc | 67 | ||||
-rw-r--r-- | content/renderer/indexed_db_dispatcher.h | 18 | ||||
-rw-r--r-- | content/renderer/renderer_webidbcursor_impl.cc | 100 | ||||
-rw-r--r-- | content/renderer/renderer_webidbcursor_impl.h | 31 |
10 files changed, 301 insertions, 1 deletions
diff --git a/content/browser/in_process_webkit/indexed_db_browsertest.cc b/content/browser/in_process_webkit/indexed_db_browsertest.cc index c849a18..759efda 100644 --- a/content/browser/in_process_webkit/indexed_db_browsertest.cc +++ b/content/browser/in_process_webkit/indexed_db_browsertest.cc @@ -69,6 +69,10 @@ IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorTestIncognito) { true /* incognito */); } +IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, CursorPrefetch) { + SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("cursor_prefetch.html")))); +} + // Flaky: http://crbug.com/70773 IN_PROC_BROWSER_TEST_F(IndexedDBBrowserTest, DISABLED_IndexTest) { SimpleTest(testUrl(FilePath(FILE_PATH_LITERAL("index_test.html")))); diff --git a/content/browser/in_process_webkit/indexed_db_callbacks.cc b/content/browser/in_process_webkit/indexed_db_callbacks.cc index 70e79ef..969a430 100644 --- a/content/browser/in_process_webkit/indexed_db_callbacks.cc +++ b/content/browser/in_process_webkit/indexed_db_callbacks.cc @@ -59,6 +59,31 @@ void IndexedDBCallbacks<WebKit::WebIDBCursor>::onSuccessWithContinuation() { content::SerializedScriptValue(idb_cursor->value()))); } +void IndexedDBCallbacks<WebKit::WebIDBCursor>::onSuccessWithPrefetch( + const WebKit::WebVector<WebKit::WebIDBKey>& keys, + const WebKit::WebVector<WebKit::WebIDBKey>& primaryKeys, + const WebKit::WebVector<WebKit::WebSerializedScriptValue>& values) { + DCHECK(cursor_id_ != -1); + + std::vector<IndexedDBKey> msgKeys; + std::vector<IndexedDBKey> msgPrimaryKeys; + std::vector<content::SerializedScriptValue> msgValues; + + for (size_t i = 0; i < keys.size(); ++i) { + msgKeys.push_back(IndexedDBKey(keys[i])); + msgPrimaryKeys.push_back(IndexedDBKey(primaryKeys[i])); + msgValues.push_back(content::SerializedScriptValue(values[i])); + } + + dispatcher_host()->Send( + new IndexedDBMsg_CallbacksSuccessCursorPrefetch( + response_id(), + cursor_id_, + msgKeys, + msgPrimaryKeys, + msgValues)); +} + void IndexedDBCallbacks<WebKit::WebIDBKey>::onSuccess( const WebKit::WebIDBKey& value) { dispatcher_host()->Send( diff --git a/content/browser/in_process_webkit/indexed_db_callbacks.h b/content/browser/in_process_webkit/indexed_db_callbacks.h index 085bfa4..de9edaf 100644 --- a/content/browser/in_process_webkit/indexed_db_callbacks.h +++ b/content/browser/in_process_webkit/indexed_db_callbacks.h @@ -93,6 +93,10 @@ class IndexedDBCallbacks<WebKit::WebIDBCursor> virtual void onSuccess(WebKit::WebIDBCursor* idb_object); virtual void onSuccess(const WebKit::WebSerializedScriptValue& value); virtual void onSuccessWithContinuation(); + virtual void onSuccessWithPrefetch( + const WebKit::WebVector<WebKit::WebIDBKey>& keys, + const WebKit::WebVector<WebKit::WebIDBKey>& primaryKeys, + const WebKit::WebVector<WebKit::WebSerializedScriptValue>& values); private: // The id of the cursor this callback concerns, or -1 if the cursor diff --git a/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc b/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc index e4abb51..f521667 100644 --- a/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc +++ b/content/browser/in_process_webkit/indexed_db_dispatcher_host.cc @@ -886,6 +886,8 @@ bool IndexedDBDispatcherHost::CursorDispatcherHost::OnMessageReceived( IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDirection, OnDirection) IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorUpdate, OnUpdate) IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorContinue, OnContinue) + IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetch, OnPrefetch) + IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorPrefetchReset, OnPrefetchReset) IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDelete, OnDelete) IPC_MESSAGE_HANDLER(IndexedDBHostMsg_CursorDestroyed, OnDestroyed) IPC_MESSAGE_UNHANDLED(handled = false) @@ -967,6 +969,32 @@ void IndexedDBDispatcherHost::CursorDispatcherHost::OnContinue( cursor_id), *ec); } +void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetch( + int32 cursor_id, + int32 response_id, + int n, + WebKit::WebExceptionCode* ec) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); + WebIDBCursor* idb_cursor = parent_->GetOrTerminateProcess(&map_, cursor_id); + if (!idb_cursor) + return; + + *ec = 0; + idb_cursor->prefetchContinue( + n, new IndexedDBCallbacks<WebIDBCursor>(parent_, response_id, + cursor_id), *ec); +} + +void IndexedDBDispatcherHost::CursorDispatcherHost::OnPrefetchReset( + int32 cursor_id, int used_prefetches, int unused_prefetches) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::WEBKIT)); + WebIDBCursor* idb_cursor = parent_->GetOrTerminateProcess(&map_, cursor_id); + if (!idb_cursor) + return; + + idb_cursor->prefetchReset(used_prefetches, unused_prefetches); +} + void IndexedDBDispatcherHost::CursorDispatcherHost::OnDelete( int32 cursor_id, int32 response_id, diff --git a/content/browser/in_process_webkit/indexed_db_dispatcher_host.h b/content/browser/in_process_webkit/indexed_db_dispatcher_host.h index 4ee03b9..88bff96 100644 --- a/content/browser/in_process_webkit/indexed_db_dispatcher_host.h +++ b/content/browser/in_process_webkit/indexed_db_dispatcher_host.h @@ -238,6 +238,12 @@ class IndexedDBDispatcherHost : public BrowserMessageFilter { int32 response_id, const IndexedDBKey& key, WebKit::WebExceptionCode* ec); + void OnPrefetch(int32 idb_cursor_id, + int32 response_id, + int n, + WebKit::WebExceptionCode* ec); + void OnPrefetchReset(int32 idb_cursor_id, int used_prefetches, + int unused_prefetches); void OnDelete(int32 idb_object_store_id, int32 response_id, WebKit::WebExceptionCode* ec); diff --git a/content/common/indexed_db_messages.h b/content/common/indexed_db_messages.h index 118106e..31a0974 100644 --- a/content/common/indexed_db_messages.h +++ b/content/common/indexed_db_messages.h @@ -147,6 +147,12 @@ IPC_MESSAGE_CONTROL5(IndexedDBMsg_CallbacksSuccessCursorContinue, IndexedDBKey /* key */, IndexedDBKey /* primary key */, content::SerializedScriptValue /* script_value */) +IPC_MESSAGE_CONTROL5(IndexedDBMsg_CallbacksSuccessCursorPrefetch, + int32 /* response_id */, + int32 /* cursor_id */, + std::vector<IndexedDBKey> /* keys */, + std::vector<IndexedDBKey> /* primary keys */, + std::vector<content::SerializedScriptValue> /* values */) IPC_MESSAGE_CONTROL2(IndexedDBMsg_CallbacksSuccessIDBDatabase, int32 /* response_id */, int32 /* idb_database_id */) @@ -200,6 +206,19 @@ IPC_SYNC_MESSAGE_CONTROL3_1(IndexedDBHostMsg_CursorContinue, IndexedDBKey, /* key */ WebKit::WebExceptionCode /* ec */) +// WebIDBCursor::prefetchContinue() message. +IPC_SYNC_MESSAGE_CONTROL3_1(IndexedDBHostMsg_CursorPrefetch, + int32, /* idb_cursor_id */ + int32, /* response_id */ + int32, /* n */ + WebKit::WebExceptionCode /* ec */) + +// WebIDBCursor::prefetchReset() message. +IPC_SYNC_MESSAGE_CONTROL3_0(IndexedDBHostMsg_CursorPrefetchReset, + int32, /* idb_cursor_id */ + int32, /* used_prefetches */ + int32 /* used_prefetches */) + // WebIDBCursor::remove() message. IPC_SYNC_MESSAGE_CONTROL2_1(IndexedDBHostMsg_CursorDelete, int32, /* idb_cursor_id */ diff --git a/content/renderer/indexed_db_dispatcher.cc b/content/renderer/indexed_db_dispatcher.cc index 8b3ddda..2308e8b 100644 --- a/content/renderer/indexed_db_dispatcher.cc +++ b/content/renderer/indexed_db_dispatcher.cc @@ -44,6 +44,8 @@ bool IndexedDBDispatcher::OnMessageReceived(const IPC::Message& msg) { OnSuccessOpenCursor) IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorContinue, OnSuccessCursorContinue) + IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessCursorPrefetch, + OnSuccessCursorPrefetch) IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIDBDatabase, OnSuccessIDBDatabase) IPC_MESSAGE_HANDLER(IndexedDBMsg_CallbacksSuccessIndexedDBKey, @@ -74,6 +76,7 @@ void IndexedDBDispatcher::RequestIDBCursorUpdate( WebIDBCallbacks* callbacks_ptr, int32 idb_cursor_id, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); @@ -88,6 +91,9 @@ void IndexedDBDispatcher::RequestIDBCursorContinue( WebIDBCallbacks* callbacks_ptr, int32 idb_cursor_id, WebExceptionCode* ec) { + // Reset all cursor prefetch caches except for this cursor. + ResetCursorPrefetchCaches(idb_cursor_id); + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); @@ -97,10 +103,32 @@ void IndexedDBDispatcher::RequestIDBCursorContinue( pending_callbacks_.Remove(response_id); } +void IndexedDBDispatcher::RequestIDBCursorPrefetch( + int n, + WebIDBCallbacks* callbacks_ptr, + int32 idb_cursor_id, + WebExceptionCode* ec) { + scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); + + int32 response_id = pending_callbacks_.Add(callbacks.release()); + RenderThreadImpl::current()->Send( + new IndexedDBHostMsg_CursorPrefetch(idb_cursor_id, response_id, n, ec)); + if (*ec) + pending_callbacks_.Remove(response_id); +} + +void IndexedDBDispatcher::RequestIDBCursorPrefetchReset( + int used_prefetches, int unused_prefetches, int32 idb_cursor_id) { + RenderThreadImpl::current()->Send( + new IndexedDBHostMsg_CursorPrefetchReset(idb_cursor_id, used_prefetches, + unused_prefetches)); +} + void IndexedDBDispatcher::RequestIDBCursorDelete( WebIDBCallbacks* callbacks_ptr, int32 idb_cursor_id, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); @@ -114,6 +142,7 @@ void IndexedDBDispatcher::RequestIDBFactoryOpen( WebIDBCallbacks* callbacks_ptr, const string16& origin, WebFrame* web_frame) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); if (!web_frame) @@ -133,6 +162,7 @@ void IndexedDBDispatcher::RequestIDBFactoryGetDatabaseNames( WebIDBCallbacks* callbacks_ptr, const string16& origin, WebFrame* web_frame) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); if (!web_frame) @@ -152,6 +182,7 @@ void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase( WebIDBCallbacks* callbacks_ptr, const string16& origin, WebFrame* web_frame) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); if (!web_frame) @@ -168,6 +199,7 @@ void IndexedDBDispatcher::RequestIDBFactoryDeleteDatabase( } void IndexedDBDispatcher::RequestIDBDatabaseClose(int32 idb_database_id) { + ResetCursorPrefetchCaches(); Send(new IndexedDBHostMsg_DatabaseClose(idb_database_id)); pending_database_callbacks_.Remove(idb_database_id); } @@ -175,6 +207,7 @@ void IndexedDBDispatcher::RequestIDBDatabaseClose(int32 idb_database_id) { void IndexedDBDispatcher::RequestIDBDatabaseOpen( WebIDBDatabaseCallbacks* callbacks_ptr, int32 idb_database_id) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBDatabaseCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_database_callbacks_.Add(callbacks.release()); @@ -186,6 +219,7 @@ void IndexedDBDispatcher::RequestIDBDatabaseSetVersion( WebIDBCallbacks* callbacks_ptr, int32 idb_database_id, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); @@ -202,6 +236,7 @@ void IndexedDBDispatcher::RequestIDBIndexOpenObjectCursor( int32 idb_index_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); IndexedDBHostMsg_IndexOpenCursor_Params params; params.response_id = pending_callbacks_.Add(callbacks.release()); @@ -224,6 +259,7 @@ void IndexedDBDispatcher::RequestIDBIndexOpenKeyCursor( int32 idb_index_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); IndexedDBHostMsg_IndexOpenCursor_Params params; params.response_id = pending_callbacks_.Add(callbacks.release()); @@ -247,6 +283,7 @@ void IndexedDBDispatcher::RequestIDBIndexGetObject( int32 idb_index_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); Send(new IndexedDBHostMsg_IndexGetObject(idb_index_id, response_id, key, @@ -261,6 +298,7 @@ void IndexedDBDispatcher::RequestIDBIndexGetKey( int32 idb_index_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); Send(new IndexedDBHostMsg_IndexGetKey( @@ -276,6 +314,7 @@ void IndexedDBDispatcher::RequestIDBObjectStoreGet( int32 idb_object_store_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); @@ -294,6 +333,7 @@ void IndexedDBDispatcher::RequestIDBObjectStorePut( int32 idb_object_store_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); IndexedDBHostMsg_ObjectStorePut_Params params; params.idb_object_store_id = idb_object_store_id; @@ -313,6 +353,7 @@ void IndexedDBDispatcher::RequestIDBObjectStoreDelete( int32 idb_object_store_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); @@ -327,6 +368,7 @@ void IndexedDBDispatcher::RequestIDBObjectStoreClear( int32 idb_object_store_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); int32 response_id = pending_callbacks_.Add(callbacks.release()); @@ -343,6 +385,7 @@ void IndexedDBDispatcher::RequestIDBObjectStoreOpenCursor( int32 idb_object_store_id, const WebIDBTransaction& transaction, WebExceptionCode* ec) { + ResetCursorPrefetchCaches(); scoped_ptr<WebIDBCallbacks> callbacks(callbacks_ptr); IndexedDBHostMsg_ObjectStoreOpenCursor_Params params; params.response_id = pending_callbacks_.Add(callbacks.release()); @@ -458,6 +501,21 @@ void IndexedDBDispatcher::OnSuccessCursorContinue( pending_callbacks_.Remove(response_id); } +void IndexedDBDispatcher::OnSuccessCursorPrefetch( + int32 response_id, + int32 cursor_id, + const std::vector<IndexedDBKey>& keys, + const std::vector<IndexedDBKey>& primary_keys, + const std::vector<content::SerializedScriptValue>& values) { + RendererWebIDBCursorImpl* cursor = cursors_[cursor_id]; + DCHECK(cursor); + cursor->SetPrefetchData(keys, primary_keys, values); + + WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); + cursor->CachedContinue(callbacks); + pending_callbacks_.Remove(response_id); +} + void IndexedDBDispatcher::OnBlocked(int32 response_id) { WebIDBCallbacks* callbacks = pending_callbacks_.Lookup(response_id); callbacks->onBlocked(); @@ -500,3 +558,12 @@ void IndexedDBDispatcher::OnVersionChange(int32 database_id, return; callbacks->onVersionChange(newVersion); } + +void IndexedDBDispatcher::ResetCursorPrefetchCaches(int32 exception_cursor_id) { + typedef std::map<int32, RendererWebIDBCursorImpl*>::iterator Iterator; + for (Iterator i = cursors_.begin(); i != cursors_.end(); ++i) { + if (i->first == exception_cursor_id) + continue; + i->second->ResetPrefetchCache(); + } +} diff --git a/content/renderer/indexed_db_dispatcher.h b/content/renderer/indexed_db_dispatcher.h index d2b3f1a..6f7deef 100644 --- a/content/renderer/indexed_db_dispatcher.h +++ b/content/renderer/indexed_db_dispatcher.h @@ -70,6 +70,15 @@ class IndexedDBDispatcher : public IPC::Channel::Listener { int32 idb_cursor_id, WebKit::WebExceptionCode* ec); + void RequestIDBCursorPrefetch( + int n, + WebKit::WebIDBCallbacks* callbacks_ptr, + int32 idb_cursor_id, + WebKit::WebExceptionCode* ec); + + void RequestIDBCursorPrefetchReset(int used_prefetches, int unused_prefetches, + int32 idb_cursor_id); + void RequestIDBCursorDelete( WebKit::WebIDBCallbacks* callbacks_ptr, int32 idb_cursor_id, @@ -174,6 +183,12 @@ class IndexedDBDispatcher : public IPC::Channel::Listener { const IndexedDBKey& key, const IndexedDBKey& primary_key, const content::SerializedScriptValue& value); + void OnSuccessCursorPrefetch( + int32 response_id, + int32 cursor_id, + const std::vector<IndexedDBKey>& keys, + const std::vector<IndexedDBKey>& primary_keys, + const std::vector<content::SerializedScriptValue>& values); void OnSuccessStringList(int32 response_id, const std::vector<string16>& value); void OnSuccessSerializedScriptValue( @@ -185,6 +200,9 @@ class IndexedDBDispatcher : public IPC::Channel::Listener { void OnComplete(int32 transaction_id); void OnVersionChange(int32 database_id, const string16& newVersion); + // Reset cursor prefetch caches for all cursors except exception_cursor_id. + void ResetCursorPrefetchCaches(int32 exception_cursor_id = -1); + // Careful! WebIDBCallbacks wraps non-threadsafe data types. It must be // destroyed and used on the same thread it was created on. IDMap<WebKit::WebIDBCallbacks, IDMapOwnPointer> pending_callbacks_; diff --git a/content/renderer/renderer_webidbcursor_impl.cc b/content/renderer/renderer_webidbcursor_impl.cc index 5ba7820..58113ad 100644 --- a/content/renderer/renderer_webidbcursor_impl.cc +++ b/content/renderer/renderer_webidbcursor_impl.cc @@ -14,7 +14,11 @@ using WebKit::WebIDBKey; using WebKit::WebSerializedScriptValue; RendererWebIDBCursorImpl::RendererWebIDBCursorImpl(int32 idb_cursor_id) - : idb_cursor_id_(idb_cursor_id) { + : idb_cursor_id_(idb_cursor_id), + continue_count_(0), + used_prefetches_(0), + pending_onsuccess_callbacks_(0), + prefetch_amount_(kMinPrefetchAmount) { } RendererWebIDBCursorImpl::~RendererWebIDBCursorImpl() { @@ -62,6 +66,34 @@ void RendererWebIDBCursorImpl::continueFunction(const WebIDBKey& key, WebExceptionCode& ec) { IndexedDBDispatcher* dispatcher = RenderThreadImpl::current()->indexed_db_dispatcher(); + + if (key.type() == WebIDBKey::InvalidType) { + // No key, so this would qualify for a prefetch. + ++continue_count_; + + if (!prefetch_keys_.empty()) { + // We have a prefetch cache, so serve the result from that. + CachedContinue(callbacks); + return; + } + + if (continue_count_ > kPrefetchContinueThreshold) { + // Request pre-fetch. + dispatcher->RequestIDBCursorPrefetch(prefetch_amount_, callbacks, + idb_cursor_id_, &ec); + + // Increase prefetch_amount_ exponentially. + prefetch_amount_ *= 2; + if (prefetch_amount_ > kMaxPrefetchAmount) + prefetch_amount_ = kMaxPrefetchAmount; + + return; + } + } else { + // Key argument supplied. We couldn't prefetch this. + ResetPrefetchCache(); + } + dispatcher->RequestIDBCursorContinue(IndexedDBKey(key), callbacks, idb_cursor_id_, &ec); } @@ -73,6 +105,20 @@ void RendererWebIDBCursorImpl::deleteFunction(WebIDBCallbacks* callbacks, dispatcher->RequestIDBCursorDelete(callbacks, idb_cursor_id_, &ec); } +void RendererWebIDBCursorImpl::postSuccessHandlerCallback() +{ + pending_onsuccess_callbacks_--; + + // If the onsuccess callback called continue() on the cursor again, + // and that continue was served by the prefetch cache, then + // pending_onsuccess_callbacks_ would be incremented. + // If not, it means the callback did something else, or nothing at all, + // in which case we need to reset the cache. + + if (pending_onsuccess_callbacks_ == 0) + ResetPrefetchCache(); +} + void RendererWebIDBCursorImpl::SetKeyAndValue( const IndexedDBKey& key, const IndexedDBKey& primary_key, @@ -81,3 +127,55 @@ void RendererWebIDBCursorImpl::SetKeyAndValue( primary_key_ = primary_key; value_ = value; } + +void RendererWebIDBCursorImpl::SetPrefetchData( + const std::vector<IndexedDBKey>& keys, + const std::vector<IndexedDBKey>& primary_keys, + const std::vector<content::SerializedScriptValue>& values) { + prefetch_keys_.assign(keys.begin(), keys.end()); + prefetch_primary_keys_.assign(primary_keys.begin(), primary_keys.end()); + prefetch_values_.assign(values.begin(), values.end()); + + used_prefetches_ = 0; + pending_onsuccess_callbacks_ = 0; +} + +void RendererWebIDBCursorImpl::CachedContinue( + WebKit::WebIDBCallbacks* callbacks) { + DCHECK(prefetch_keys_.size() > 0); + DCHECK(prefetch_primary_keys_.size() == prefetch_keys_.size()); + DCHECK(prefetch_values_.size() == prefetch_keys_.size()); + + key_ = prefetch_keys_.front(); + primary_key_ = prefetch_primary_keys_.front(); + value_ = prefetch_values_.front(); + + prefetch_keys_.pop_front(); + prefetch_primary_keys_.pop_front(); + prefetch_values_.pop_front(); + used_prefetches_++; + + pending_onsuccess_callbacks_++; + callbacks->onSuccessWithContinuation(); +} + +void RendererWebIDBCursorImpl::ResetPrefetchCache() { + continue_count_ = 0; + prefetch_amount_ = kMinPrefetchAmount; + + if (!prefetch_keys_.size()) { + // No prefetch cache, so no need to reset the cursor in the back-end. + return; + } + + IndexedDBDispatcher* dispatcher = + RenderThreadImpl::current()->indexed_db_dispatcher(); + dispatcher->RequestIDBCursorPrefetchReset(used_prefetches_, + prefetch_keys_.size(), + idb_cursor_id_); + prefetch_keys_.clear(); + prefetch_primary_keys_.clear(); + prefetch_values_.clear(); + + pending_onsuccess_callbacks_ = 0; +} diff --git a/content/renderer/renderer_webidbcursor_impl.h b/content/renderer/renderer_webidbcursor_impl.h index fbca6b2..b033990 100644 --- a/content/renderer/renderer_webidbcursor_impl.h +++ b/content/renderer/renderer_webidbcursor_impl.h @@ -5,6 +5,8 @@ #ifndef CONTENT_RENDERER_RENDERER_WEBIDBCURSOR_IMPL_H_ #define CONTENT_RENDERER_RENDERER_WEBIDBCURSOR_IMPL_H_ +#include <deque> + #include "base/basictypes.h" #include "content/common/indexed_db_key.h" #include "content/public/common/serialized_script_value.h" @@ -30,15 +32,44 @@ class RendererWebIDBCursorImpl : public WebKit::WebIDBCursor { WebKit::WebExceptionCode& ec); virtual void deleteFunction(WebKit::WebIDBCallbacks* callback, WebKit::WebExceptionCode& ec); + virtual void postSuccessHandlerCallback(); void SetKeyAndValue(const IndexedDBKey& key, const IndexedDBKey& primary_key, const content::SerializedScriptValue& value); + void SetPrefetchData( + const std::vector<IndexedDBKey>& keys, + const std::vector<IndexedDBKey>& primary_keys, + const std::vector<content::SerializedScriptValue>& values); + + void CachedContinue(WebKit::WebIDBCallbacks* callbacks); + void ResetPrefetchCache(); private: int32 idb_cursor_id_; IndexedDBKey key_; IndexedDBKey primary_key_; content::SerializedScriptValue value_; + + // Prefetch cache. + std::deque<IndexedDBKey> prefetch_keys_; + std::deque<IndexedDBKey> prefetch_primary_keys_; + std::deque<content::SerializedScriptValue> prefetch_values_; + + // Number of continue calls that would qualify for a pre-fetch. + int continue_count_; + + // Number of items used from the last prefetch. + int used_prefetches_; + + // Number of onsuccess handlers we are waiting for. + int pending_onsuccess_callbacks_; + + // Number of items to request in next prefetch. + int prefetch_amount_; + + enum { kPrefetchContinueThreshold = 2 }; + enum { kMinPrefetchAmount = 5 }; + enum { kMaxPrefetchAmount = 100 }; }; #endif // CONTENT_RENDERER_RENDERER_WEBIDBCURSOR_IMPL_H_ |