Diff
Modified: trunk/Source/WebCore/ChangeLog (256620 => 256621)
--- trunk/Source/WebCore/ChangeLog 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/ChangeLog 2020-02-14 18:08:03 UTC (rev 256621)
@@ -1,3 +1,126 @@
+2020-02-14 Sihui Liu <sihui_...@apple.com>
+
+ IndexedDB: prefetch cursor records on client side
+ https://bugs.webkit.org/show_bug.cgi?id=207602
+ <rdar://problem/58483927>
+
+ Reviewed by Brady Eidson.
+
+ Cache cursor records on client side and use those records for iterate operations.
+
+ This makes cursor continue/advance tests in PerformanceTests/IndexedDB/basics ~3x faster.
+
+ * Headers.cmake:
+
+ * Modules/indexeddb/IDBCursor.cpp:
+ (WebCore::IDBCursor::setGetResult): Record the ID of TransactionOperation that updates cached record.
+ (WebCore::IDBCursor::iterateWithPrefetchedRecords): IDBCursor uses cached records for iterate opertaions if
+ there is no write operation between last cached records update and current iteration operation.
+ (WebCore::IDBCursor::clearPrefetchedRecords):
+ * Modules/indexeddb/IDBCursor.h:
+
+ * Modules/indexeddb/IDBGetResult.cpp:
+ (WebCore::IDBGetResult::isolatedCopy):
+ * Modules/indexeddb/IDBGetResult.h:
+ (WebCore::IDBGetResult::IDBGetResult):
+ (WebCore::IDBGetResult::prefetchedRecords const):
+ (WebCore::IDBGetResult::encode const):
+ (WebCore::IDBGetResult::decode):
+
+ * Modules/indexeddb/IDBRequest.cpp: Record corresponding TransactionOperation ID in request.
+ (WebCore::IDBRequest::didOpenOrIterateCursor):
+ * Modules/indexeddb/IDBRequest.h:
+ (WebCore::IDBRequest::pendingCursor const):
+ (WebCore::IDBRequest::setTransactionOperationID):
+
+ * Modules/indexeddb/IDBTransaction.cpp: If a cursor iterate request can be handled with cached records,
+ IDBClient does not need to send request to IDBServer and wait for response. But requests before that iterate
+ request may need to wait server to answer, and spec requires to handle requests in order. Therefore, we now keep
+ all the results in m_transactionOperationResultMap and handle them according to the ordering in
+ m_transactionOperationsInProgressQueue.
+ (WebCore::IDBTransaction::abortInProgressOperations):
+ (WebCore::IDBTransaction::removeRequest): Because result of a cursor request can be answered sooner, it is
+ possible that in finishedDispatchEventForRequest, m_currentlyCompletingRequest (which is a cursor request) is
+ set to nullptr, and then it is set back to the same cursor request in handleOperationsCompletedOnServer right
+ after. This happens in dispatchEvent of the cursor request, where request would remove itself from request list
+ of transaction at the end.
+ In this case, when request list becomes empty, transaction may commit automatically. But transaction should not
+ because that request is still valid as m_currentlyCompletingRequest and should not be removed from list.
+ (WebCore::IDBTransaction::scheduleOperation):
+ (WebCore::IDBTransaction::operationCompletedOnServer):
+ (WebCore::IDBTransaction::handleOperationsCompletedOnServer): All requests were sent to IDBServer and the
+ response/result ordering would naturally be the same as request order. Now that results can be created in both
+ IDBClient and IDBServer, we no longer handle requests using m_completedOnServerQueue.
+ (WebCore::IDBTransaction::createObjectStore): Mark as write operation to track last write operation.
+ (WebCore::IDBTransaction::renameObjectStore): Ditto.
+ (WebCore::IDBTransaction::createIndex): Ditto.
+ (WebCore::IDBTransaction::renameIndex): Ditto.
+ (WebCore::IDBTransaction::requestDeleteRecord): Ditto.
+ (WebCore::IDBTransaction::requestClearObjectStore): Ditto.
+ (WebCore::IDBTransaction::requestPutOrAdd): Ditto.
+ (WebCore::IDBTransaction::deleteObjectStore): Ditto.
+ (WebCore::IDBTransaction::deleteIndex): Ditto.
+ (WebCore::IDBTransaction::iterateCursorOnServer): Only use cached records if the request does not specify target
+ key. If cursor is iterated successfully with cache, send a message to IDBServer to notify about the progress.
+ Otherwise, fall back to depend on IDBServer to answer the request.
+ (WebCore::IDBTransaction::generateOperationID): TransactionOperation ID is unique in a transaction.
+ * Modules/indexeddb/IDBTransaction.h:
+
+ * Modules/indexeddb/IndexedDB.h:
+ * Modules/indexeddb/client/IDBConnectionProxy.cpp:
+ (WebCore::IDBClient::IDBConnectionProxy::iterateCursor): Don't track result of TransactionOperation in
+ IDBConnectionProxy if TransactionOperation does not need a reply from IDBServer.
+
+ * Modules/indexeddb/client/TransactionOperation.cpp:
+ (WebCore::IDBClient::TransactionOperation::TransactionOperation):
+ * Modules/indexeddb/client/TransactionOperation.h: Add ID to TransactionOperation.
+ (WebCore::IDBClient::TransactionOperation::operationID const):
+ (WebCore::IDBClient::TransactionOperation::TransactionOperation):
+
+ * Modules/indexeddb/server/IDBBackingStore.h: remove prefetchCursor as it is not used now.
+ * Modules/indexeddb/server/MemoryIDBBackingStore.h: Ditto. Also this patch only deals with prefetching in
+ persistent store.
+ * Modules/indexeddb/server/MemoryIDBBackingStore.h:
+ * Modules/indexeddb/server/SQLiteIDBBackingStore.cpp:
+ (WebCore::IDBServer::SQLiteIDBBackingStore::createIndex):
+ (WebCore::IDBServer::SQLiteIDBBackingStore::getAllIndexRecords):
+ (WebCore::IDBServer::SQLiteIDBBackingStore::getIndexRecord):
+ (WebCore::IDBServer::SQLiteIDBBackingStore::iterateCursor): Only prefetch at when request needs to be answered.
+ (WebCore::IDBServer::SQLiteIDBBackingStore::prefetchCursor): Deleted.
+ * Modules/indexeddb/server/SQLiteIDBBackingStore.h:
+
+ * Modules/indexeddb/server/SQLiteIDBCursor.cpp:
+ (WebCore::IDBServer::SQLiteIDBCursor::currentData): Provide an option to include prefetched records in result.
+ (WebCore::IDBServer::SQLiteIDBCursor::objectStoreRecordsChanged): Reset count to prefetch when there is a
+ change. This is used with increaseCountToPrefetch to make prefetch adaptive.
+ (WebCore::IDBServer::SQLiteIDBCursor::objectStoreRecordsChanged):
+ (WebCore::IDBServer::SQLiteIDBCursor::prefetchOneRecord):
+ (WebCore::IDBServer::SQLiteIDBCursor::increaseCountToPrefetch):
+ (WebCore::IDBServer::SQLiteIDBCursor::prefetch): Count to prefetch is decided by SQLiteCursor now.
+ (WebCore::IDBServer::SQLiteIDBCursor::internalFetchNextRecord):
+ (WebCore::IDBServer::SQLiteIDBCursor::currentValue const):
+ * Modules/indexeddb/server/SQLiteIDBCursor.h:
+
+ * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
+ (WebCore::IDBServer::UniqueIDBDatabase::iterateCursor): Move call to prefetch cursor to SQLiteIDBBackingStore.
+ (WebCore::IDBServer::UniqueIDBDatabase::prefetchCursor): Deleted.
+ * Modules/indexeddb/server/UniqueIDBDatabase.h:
+ * Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp:
+ (WebCore::IDBServer::UniqueIDBDatabaseTransaction::iterateCursor):
+
+ * Modules/indexeddb/shared/IDBCursorRecord.h: Stop using pointer for IDBValue for easier encoding and decoding.
+ (WebCore::IDBCursorRecord::size const):
+ (WebCore::IDBCursorRecord::isolatedCopy const):
+
+ * Modules/indexeddb/shared/IDBIterateCursorData.cpp:
+ (WebCore::IDBIterateCursorData::isolatedCopy const):
+ * Modules/indexeddb/shared/IDBIterateCursorData.h: Add an option to let IDBServer know whether it should answer
+ the cursor request.
+ (WebCore::IDBIterateCursorData::encode const):
+ (WebCore::IDBIterateCursorData::decode):
+
+ * WebCore.xcodeproj/project.pbxproj:
+
2020-02-14 Charles Turner <ctur...@igalia.com>
[GStreamer][EME] Fix warnings in LOG_DISABLED build
Modified: trunk/Source/WebCore/Headers.cmake (256620 => 256621)
--- trunk/Source/WebCore/Headers.cmake 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Headers.cmake 2020-02-14 18:08:03 UTC (rev 256621)
@@ -68,6 +68,7 @@
Modules/indexeddb/server/UniqueIDBDatabaseTransaction.h
Modules/indexeddb/shared/IDBCursorInfo.h
+ Modules/indexeddb/shared/IDBCursorRecord.h
Modules/indexeddb/shared/IDBDatabaseInfo.h
Modules/indexeddb/shared/IDBError.h
Modules/indexeddb/shared/IDBGetAllRecordsData.h
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -312,7 +312,7 @@
return request;
}
-bool IDBCursor::setGetResult(IDBRequest& request, const IDBGetResult& getResult)
+bool IDBCursor::setGetResult(IDBRequest& request, const IDBGetResult& getResult, uint64_t operationID)
{
LOG(IndexedDB, "IDBCursor::setGetResult - current key %s", getResult.keyData().loggingString().substring(0, 100).utf8().data());
ASSERT(canCurrentThreadAccessThreadLocalData(effectiveObjectStore().transaction().database().originThread()));
@@ -349,6 +349,13 @@
m_keyPath = getResult.keyPath();
}
+ auto prefetchedRecords = getResult.prefetchedRecords();
+ if (!prefetchedRecords.isEmpty()) {
+ for (auto& record : prefetchedRecords)
+ m_prefetchedRecords.append(record);
+ m_prefetchOperationID = operationID;
+ }
+
m_gotValue = true;
return true;
}
@@ -360,6 +367,26 @@
m_valueWrapper.clear();
}
+Optional<IDBGetResult> IDBCursor::iterateWithPrefetchedRecords(unsigned count, uint64_t lastWriteOperationID)
+{
+ unsigned step = count > 0 ? count : 1;
+ if (step > m_prefetchedRecords.size() || m_prefetchOperationID <= lastWriteOperationID)
+ return WTF::nullopt;
+
+ while (--step)
+ m_prefetchedRecords.removeFirst();
+
+ auto record = m_prefetchedRecords.takeFirst();
+
+ LOG(IndexedDB, "IDBTransaction::iterateWithPrefetchedRecords consumes %u records", count > 0 ? count : 1);
+ return IDBGetResult(record.key, record.primaryKey, IDBValue(record.value), effectiveObjectStore().keyPath());
+}
+
+void IDBCursor::clearPrefetchedRecords()
+{
+ m_prefetchedRecords.clear();
+}
+
} // namespace WebCore
#endif // ENABLE(INDEXED_DATABASE)
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBCursor.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -81,10 +81,13 @@
void clearWrappers();
IDBRequest* request() { return m_request.get(); }
- bool setGetResult(IDBRequest&, const IDBGetResult&);
+ bool setGetResult(IDBRequest&, const IDBGetResult&, uint64_t operationID);
virtual bool isKeyCursorWithValue() const { return false; }
+ Optional<IDBGetResult> iterateWithPrefetchedRecords(unsigned count, uint64_t lastWriteOperationID);
+ void clearPrefetchedRecords();
+
protected:
IDBCursor(IDBObjectStore&, const IDBCursorInfo&);
IDBCursor(IDBIndex&, const IDBCursorInfo&);
@@ -113,6 +116,9 @@
JSValueInWrappedObject m_keyWrapper;
JSValueInWrappedObject m_primaryKeyWrapper;
JSValueInWrappedObject m_valueWrapper;
+
+ Deque<IDBCursorRecord> m_prefetchedRecords;
+ uint64_t m_prefetchOperationID { 0 };
};
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -55,6 +55,7 @@
destination.m_primaryKeyData = source.m_primaryKeyData.isolatedCopy();
destination.m_keyPath = WebCore::isolatedCopy(source.m_keyPath);
destination.m_isDefined = source.m_isDefined;
+ destination.m_prefetchedRecords = source.m_prefetchedRecords.isolatedCopy();
}
void IDBGetResult::setValue(IDBValue&& value)
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBGetResult.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -27,6 +27,7 @@
#if ENABLE(INDEXED_DATABASE)
+#include "IDBCursorRecord.h"
#include "IDBKey.h"
#include "IDBKeyData.h"
#include "IDBKeyPath.h"
@@ -76,6 +77,15 @@
{
}
+ IDBGetResult(const IDBKeyData& keyData, const IDBKeyData& primaryKeyData, IDBValue&& value, const Optional<IDBKeyPath>& keyPath, Vector<IDBCursorRecord>&& prefetechedRecords)
+ : m_value(WTFMove(value))
+ , m_keyData(keyData)
+ , m_primaryKeyData(primaryKeyData)
+ , m_keyPath(keyPath)
+ , m_prefetchedRecords(WTFMove(prefetechedRecords))
+ {
+ }
+
enum IsolatedCopyTag { IsolatedCopy };
IDBGetResult(const IDBGetResult&, IsolatedCopyTag);
@@ -87,6 +97,7 @@
const IDBKeyData& keyData() const { return m_keyData; }
const IDBKeyData& primaryKeyData() const { return m_primaryKeyData; }
const Optional<IDBKeyPath>& keyPath() const { return m_keyPath; }
+ const Vector<IDBCursorRecord>& prefetchedRecords() const { return m_prefetchedRecords; }
bool isDefined() const { return m_isDefined; }
template<class Encoder> void encode(Encoder&) const;
@@ -101,6 +112,7 @@
IDBKeyData m_keyData;
IDBKeyData m_primaryKeyData;
Optional<IDBKeyPath> m_keyPath;
+ Vector<IDBCursorRecord> m_prefetchedRecords;
bool m_isDefined { true };
};
@@ -107,7 +119,7 @@
template<class Encoder>
void IDBGetResult::encode(Encoder& encoder) const
{
- encoder << m_keyData << m_primaryKeyData << m_keyPath << m_isDefined << m_value;
+ encoder << m_keyData << m_primaryKeyData << m_keyPath << m_isDefined << m_value << m_prefetchedRecords;
}
template<class Decoder>
@@ -137,6 +149,12 @@
return false;
result.m_value = WTFMove(*value);
+ Optional<Vector<IDBCursorRecord>> prefetchedRecords;
+ decoder >> prefetchedRecords;
+ if (!prefetchedRecords)
+ return false;
+ result.m_prefetchedRecords = WTFMove(*prefetchedRecords);
+
return true;
}
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBRequest.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -499,7 +499,7 @@
m_resultWrapper = { };
if (resultData.type() == IDBResultType::IterateCursorSuccess || resultData.type() == IDBResultType::OpenCursorSuccess) {
- if (m_pendingCursor->setGetResult(*this, resultData.getResult()) && m_cursorWrapper)
+ if (m_pendingCursor->setGetResult(*this, resultData.getResult(), m_currentTransactionOperationID) && m_cursorWrapper)
m_resultWrapper = m_cursorWrapper;
if (resultData.getResult().isDefined())
m_result = m_pendingCursor;
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBRequest.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -118,7 +118,7 @@
void willIterateCursor(IDBCursor&);
void didOpenOrIterateCursor(const IDBResultData&);
- const IDBCursor* pendingCursor() const { return m_pendingCursor.get(); }
+ IDBCursor* pendingCursor() const { return m_pendingCursor ? m_pendingCursor.get() : nullptr; }
void setSource(IDBCursor&);
void setVersionChangeTransaction(IDBTransaction&);
@@ -127,6 +127,8 @@
bool hasPendingActivity() const final;
+ void setTransactionOperationID(uint64_t transactionOperationID) { m_currentTransactionOperationID = transactionOperationID; }
+
protected:
IDBRequest(ScriptExecutionContext&, IDBClient::IDBConnectionProxy&);
@@ -191,6 +193,8 @@
bool m_dispatchingEvent { false };
bool m_hasUncaughtException { false };
+
+ uint64_t m_currentTransactionOperationID { 0 };
};
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -272,16 +272,8 @@
operation->doComplete(IDBResultData::error(operation->identifier(), error));
}
- Vector<RefPtr<IDBClient::TransactionOperation>> completedOnServerAbortVector;
- completedOnServerAbortVector.reserveInitialCapacity(m_completedOnServerQueue.size());
- while (!m_completedOnServerQueue.isEmpty())
- completedOnServerAbortVector.uncheckedAppend(m_completedOnServerQueue.takeFirst().first);
+ m_transactionOperationResultMap.clear();
- for (auto& operation : completedOnServerAbortVector) {
- m_currentlyCompletingRequest = nullptr;
- operation->doComplete(IDBResultData::error(operation->identifier(), error));
- }
-
m_currentlyCompletingRequest = nullptr;
connectionProxy().forgetActiveOperations(inProgressAbortVector);
}
@@ -376,16 +368,22 @@
void IDBTransaction::removeRequest(IDBRequest& request)
{
ASSERT(canCurrentThreadAccessThreadLocalData(m_database->originThread()));
+ if (m_currentlyCompletingRequest == &request)
+ return;
+
m_openRequests.remove(&request);
autoCommit();
}
-void IDBTransaction::scheduleOperation(Ref<IDBClient::TransactionOperation>&& operation)
+void IDBTransaction::scheduleOperation(Ref<IDBClient::TransactionOperation>&& operation, IsWriteOperation isWriteOperation)
{
ASSERT(!m_transactionOperationMap.contains(operation->identifier()));
ASSERT(canCurrentThreadAccessThreadLocalData(m_database->originThread()));
+ if (isWriteOperation == IsWriteOperation::Yes)
+ m_lastWriteOperationID = operation->operationID();
+
auto identifier = operation->identifier();
m_pendingTransactionOperationQueue.append(operation.copyRef());
m_transactionOperationMap.set(identifier, WTFMove(operation));
@@ -398,8 +396,11 @@
ASSERT(canCurrentThreadAccessThreadLocalData(m_database->originThread()));
ASSERT(canCurrentThreadAccessThreadLocalData(operation.originThread()));
- m_completedOnServerQueue.append({ &operation, data });
+ if (!m_transactionOperationMap.contains(operation.identifier()))
+ return;
+ m_transactionOperationResultMap.set(&operation, IDBResultData(data));
+
if (!m_currentlyCompletingRequest)
handleOperationsCompletedOnServer();
}
@@ -406,12 +407,15 @@
void IDBTransaction::handleOperationsCompletedOnServer()
{
- LOG(IndexedDB, "IDBTransaction::completedOperationTimerFired (%p)", this);
+ LOG(IndexedDB, "IDBTransaction::handleOperationsCompletedOnServer");
ASSERT(canCurrentThreadAccessThreadLocalData(m_database->originThread()));
- while (!m_completedOnServerQueue.isEmpty() && !m_currentlyCompletingRequest) {
- auto iterator = m_completedOnServerQueue.takeFirst();
- iterator.first->doComplete(iterator.second);
+ while (!m_transactionOperationsInProgressQueue.isEmpty() && !m_currentlyCompletingRequest) {
+ RefPtr<IDBClient::TransactionOperation> currentOperation = m_transactionOperationsInProgressQueue.first();
+ if (!m_transactionOperationResultMap.contains(currentOperation))
+ return;
+
+ currentOperation->doComplete(m_transactionOperationResultMap.take(currentOperation));
}
}
@@ -622,7 +626,7 @@
protectedThis->didCreateObjectStoreOnServer(result);
}, [protectedThis = makeRef(*this), info = info.isolatedCopy()] (auto& operation) {
protectedThis->createObjectStoreOnServer(operation, info);
- }));
+ }), IsWriteOperation::Yes);
return *rawObjectStore;
}
@@ -664,7 +668,7 @@
protectedThis->didRenameObjectStoreOnServer(result);
}, [protectedThis = makeRef(*this), objectStoreIdentifier, newName = newName.isolatedCopy()] (auto& operation) {
protectedThis->renameObjectStoreOnServer(operation, objectStoreIdentifier, newName);
- }));
+ }), IsWriteOperation::Yes);
m_referencedObjectStores.set(newName, m_referencedObjectStores.take(objectStore.info().name()));
}
@@ -699,7 +703,7 @@
protectedThis->didCreateIndexOnServer(result);
}, [protectedThis = makeRef(*this), info = info.isolatedCopy()] (auto& operation) {
protectedThis->createIndexOnServer(operation, info);
- }));
+ }), IsWriteOperation::Yes);
return makeUnique<IDBIndex>(*scriptExecutionContext(), info, objectStore);
}
@@ -753,7 +757,7 @@
protectedThis->didRenameIndexOnServer(result);
}, [protectedThis = makeRef(*this), objectStoreIdentifier, indexIdentifier, newName = newName.isolatedCopy()] (auto& operation) {
protectedThis->renameIndexOnServer(operation, objectStoreIdentifier, indexIdentifier, newName);
- }));
+ }), IsWriteOperation::Yes);
}
void IDBTransaction::renameIndexOnServer(IDBClient::TransactionOperation& operation, const uint64_t& objectStoreIdentifier, const uint64_t& indexIdentifier, const String& newName)
@@ -852,7 +856,23 @@
{
LOG(IndexedDB, "IDBTransaction::iterateCursorOnServer");
ASSERT(canCurrentThreadAccessThreadLocalData(m_database->originThread()));
+ ASSERT(operation.idbRequest());
+ auto* cursor = operation.idbRequest()->pendingCursor();
+ ASSERT(cursor);
+
+ if (data.keyData.isNull() && data.primaryKeyData.isNull()) {
+ if (auto getResult = cursor->iterateWithPrefetchedRecords(data.count, m_lastWriteOperationID)) {
+ auto result = IDBResultData::iterateCursorSuccess(operation.identifier(), getResult.value());
+ m_database->connectionProxy().iterateCursor(operation, { data.keyData, data.primaryKeyData, data.count, IndexedDB::CursorIterateOption::DoNotReply });
+ operationCompletedOnServer(result, operation);
+ return;
+ }
+ }
+
+ cursor->clearPrefetchedRecords();
+
+ ASSERT(data.option == IndexedDB::CursorIterateOption::Reply);
m_database->connectionProxy().iterateCursor(operation, data);
}
@@ -1126,7 +1146,7 @@
protectedThis->didDeleteRecordOnServer(request.get(), result);
}, [protectedThis = makeRef(*this), range = range.isolatedCopy()] (auto& operation) {
protectedThis->deleteRecordOnServer(operation, range);
- }));
+ }), IsWriteOperation::Yes);
return request;
}
@@ -1165,7 +1185,7 @@
protectedThis->didClearObjectStoreOnServer(request.get(), result);
}, [protectedThis = makeRef(*this), objectStoreIdentifier] (auto& operation) {
protectedThis->clearObjectStoreOnServer(operation, objectStoreIdentifier);
- }));
+ }), IsWriteOperation::Yes);
return request;
}
@@ -1205,7 +1225,7 @@
protectedThis->didPutOrAddOnServer(request.get(), result);
}, [protectedThis = makeRef(*this), key, value = makeRef(value), overwriteMode] (auto& operation) {
protectedThis->putOrAddOnServer(operation, key.get(), value.ptr(), overwriteMode);
- }));
+ }), IsWriteOperation::Yes);
return request;
}
@@ -1293,7 +1313,7 @@
protectedThis->didDeleteObjectStoreOnServer(result);
}, [protectedThis = makeRef(*this), objectStoreName = objectStoreName.isolatedCopy()] (auto& operation) {
protectedThis->deleteObjectStoreOnServer(operation, objectStoreName);
- }));
+ }), IsWriteOperation::Yes);
}
void IDBTransaction::deleteObjectStoreOnServer(IDBClient::TransactionOperation& operation, const String& objectStoreName)
@@ -1323,7 +1343,7 @@
protectedThis->didDeleteIndexOnServer(result);
}, [protectedThis = makeRef(*this), objectStoreIdentifier, indexName = indexName.isolatedCopy()] (auto& operation) {
protectedThis->deleteIndexOnServer(operation, objectStoreIdentifier, indexName);
- }));
+ }), IsWriteOperation::Yes);
}
void IDBTransaction::deleteIndexOnServer(IDBClient::TransactionOperation& operation, const uint64_t& objectStoreIdentifier, const String& indexName)
@@ -1474,6 +1494,12 @@
commit();
}
+uint64_t IDBTransaction::generateOperationID()
+{
+ static std::atomic<uint64_t> currentOperationID(1);
+ return currentOperationID += 1;
+}
+
} // namespace WebCore
#endif // ENABLE(INDEXED_DATABASE)
Modified: trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IDBTransaction.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -71,6 +71,8 @@
static Ref<IDBTransaction> create(IDBDatabase&, const IDBTransactionInfo&);
static Ref<IDBTransaction> create(IDBDatabase&, const IDBTransactionInfo&, IDBOpenDBRequest&);
+ static uint64_t generateOperationID();
+
WEBCORE_EXPORT ~IDBTransaction() final;
// IDBTransaction IDL
@@ -165,7 +167,8 @@
void finishAbortOrCommit();
void abortInProgressOperations(const IDBError&);
- void scheduleOperation(Ref<IDBClient::TransactionOperation>&&);
+ enum class IsWriteOperation : bool { No, Yes };
+ void scheduleOperation(Ref<IDBClient::TransactionOperation>&&, IsWriteOperation = IsWriteOperation::No);
void handleOperationsCompletedOnServer();
void handlePendingOperations();
void autoCommit();
@@ -244,8 +247,8 @@
Deque<RefPtr<IDBClient::TransactionOperation>> m_pendingTransactionOperationQueue;
Deque<IDBClient::TransactionOperation*> m_transactionOperationsInProgressQueue;
- Deque<std::pair<RefPtr<IDBClient::TransactionOperation>, IDBResultData>> m_completedOnServerQueue;
Deque<RefPtr<IDBClient::TransactionOperation>> m_abortQueue;
+ HashMap<RefPtr<IDBClient::TransactionOperation>, IDBResultData> m_transactionOperationResultMap;
HashMap<IDBResourceIdentifier, RefPtr<IDBClient::TransactionOperation>> m_transactionOperationMap;
@@ -258,6 +261,8 @@
bool m_contextStopped { false };
bool m_didDispatchAbortOrCommit { false };
+
+ uint64_t m_lastWriteOperationID { 0 };
};
class TransactionActivator {
Modified: trunk/Source/WebCore/Modules/indexeddb/IndexedDB.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/IndexedDB.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/IndexedDB.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -106,6 +106,11 @@
enum class ConnectionClosedOnBehalfOfServer : bool { No, Yes };
+enum class CursorIterateOption {
+ DoNotReply,
+ Reply,
+};
+
} // namespace IndexedDB
} // namespace WebCore
Modified: trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/client/IDBConnectionProxy.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -238,7 +238,8 @@
void IDBConnectionProxy::iterateCursor(TransactionOperation& operation, const IDBIterateCursorData& data)
{
const IDBRequestData requestData { operation };
- saveOperation(operation);
+ if (data.option != IndexedDB::CursorIterateOption::DoNotReply)
+ saveOperation(operation);
callConnectionOnMainThread(&IDBConnectionToServer::iterateCursor, requestData, data);
}
Modified: trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -44,6 +44,7 @@
if (auto* cursor = request.pendingCursor())
m_cursorIdentifier = makeUnique<IDBResourceIdentifier>(cursor->info().identifier());
+ request.setTransactionOperationID(m_operationID);
m_idbRequest = &request;
}
Modified: trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/client/TransactionOperation.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -112,10 +112,13 @@
bool nextRequestCanGoToServer() const { return m_nextRequestCanGoToServer && m_idbRequest; }
void setNextRequestCanGoToServer(bool nextRequestCanGoToServer) { m_nextRequestCanGoToServer = nextRequestCanGoToServer; }
+ uint64_t operationID() const { return m_operationID; }
+
protected:
TransactionOperation(IDBTransaction& transaction)
: m_transaction(transaction)
, m_identifier(transaction.connectionProxy())
+ , m_operationID(transaction.generateOperationID())
{
}
@@ -142,6 +145,8 @@
RefPtr<IDBRequest> m_idbRequest;
bool m_nextRequestCanGoToServer { true };
bool m_didComplete { false };
+
+ uint64_t m_operationID { 0 };
};
class TransactionOperationImpl final : public TransactionOperation {
Modified: trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -85,7 +85,6 @@
virtual IDBError maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber) = 0;
virtual IDBError openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&, IDBGetResult& outResult) = 0;
virtual IDBError iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBIterateCursorData&, IDBGetResult& outResult) = 0;
- virtual bool prefetchCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier) = 0;
virtual IDBObjectStoreInfo* infoForObjectStore(uint64_t objectStoreIdentifier) = 0;
virtual void deleteBackingStore() = 0;
Modified: trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -74,7 +74,6 @@
IDBError maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber) final;
IDBError openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&, IDBGetResult& outResult) final;
IDBError iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBIterateCursorData&, IDBGetResult& outResult) final;
- bool prefetchCursor(const IDBResourceIdentifier&, const IDBResourceIdentifier&) final { return false; }
IDBObjectStoreInfo* infoForObjectStore(uint64_t objectStoreIdentifier) final;
void deleteBackingStore() final;
Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -1366,8 +1366,8 @@
while (!cursor->currentKey().isNull()) {
auto& key = cursor->currentKey();
- auto* value = cursor->currentValue();
- ThreadSafeDataBuffer valueBuffer = value ? value->data() : ThreadSafeDataBuffer();
+ auto value = cursor->currentValue();
+ ThreadSafeDataBuffer valueBuffer = value.data();
ASSERT(cursor->currentRecordRowID());
@@ -2354,7 +2354,7 @@
IDBKeyData keyCopy = cursor->currentPrimaryKey();
result.addKey(WTFMove(keyCopy));
if (getAllRecordsData.getAllType == IndexedDB::GetAllType::Values)
- result.addValue(cursor->currentValue() ? *cursor->currentValue() : IDBValue());
+ result.addValue(IDBValue(cursor->currentValue()));
++currentCount;
cursor->advance(1);
@@ -2401,7 +2401,7 @@
else {
auto* objectStoreInfo = infoForObjectStore(objectStoreID);
ASSERT(objectStoreInfo);
- getResult = { cursor->currentPrimaryKey(), cursor->currentPrimaryKey(), cursor->currentValue() ? *cursor->currentValue() : IDBValue(), objectStoreInfo->keyPath() };
+ getResult = { cursor->currentPrimaryKey(), cursor->currentPrimaryKey(), IDBValue(cursor->currentValue()), objectStoreInfo->keyPath() };
}
}
@@ -2721,26 +2721,18 @@
}
}
- auto* objectStoreInfo = infoForObjectStore(cursor->objectStoreID());
- ASSERT(objectStoreInfo);
- cursor->currentData(result, objectStoreInfo->keyPath());
- return IDBError { };
-}
+ if (data.option == IndexedDB::CursorIterateOption::Reply) {
+ auto* objectStoreInfo = infoForObjectStore(cursor->objectStoreID());
+ ASSERT(objectStoreInfo);
-bool SQLiteIDBBackingStore::prefetchCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier)
-{
- LOG(IndexedDB, "SQLiteIDBBackingStore::prefetchCursor");
+ bool shouldPrefetch = key.isNull() && primaryKey.isNull();
+ if (shouldPrefetch)
+ cursor->prefetch();
- ASSERT(m_sqliteDB);
- ASSERT(m_sqliteDB->isOpen());
+ cursor->currentData(result, objectStoreInfo->keyPath(), shouldPrefetch ? SQLiteIDBCursor::ShouldIncludePrefetchedRecords::Yes : SQLiteIDBCursor::ShouldIncludePrefetchedRecords::No);
+ }
- auto* cursor = m_cursors.get(cursorIdentifier);
- if (!cursor || !cursor->transaction() || !cursor->transaction()->inProgress())
- return false;
-
- ASSERT_UNUSED(transactionIdentifier, cursor->transaction()->transactionIdentifier() == transactionIdentifier);
-
- return cursor->prefetch();
+ return IDBError { };
}
IDBObjectStoreInfo* SQLiteIDBBackingStore::infoForObjectStore(uint64_t objectStoreIdentifier)
Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -80,7 +80,6 @@
IDBError maybeUpdateKeyGeneratorNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, double newKeyNumber) final;
IDBError openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo&, IDBGetResult& outResult) final;
IDBError iterateCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, const IDBIterateCursorData&, IDBGetResult& outResult) final;
- bool prefetchCursor(const IDBResourceIdentifier&, const IDBResourceIdentifier&) final;
IDBObjectStoreInfo* infoForObjectStore(uint64_t objectStoreIdentifier) final;
void deleteBackingStore() final;
Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -42,8 +42,8 @@
namespace WebCore {
namespace IDBServer {
-static const size_t prefetchLimit = 128;
-static const size_t prefetchSizeLimit = 8 * MB;
+static const size_t prefetchLimit = 256;
+static const size_t prefetchSizeLimit = 1 * MB;
std::unique_ptr<SQLiteIDBCursor> SQLiteIDBCursor::maybeCreate(SQLiteIDBTransaction& transaction, const IDBCursorInfo& info)
{
@@ -102,7 +102,7 @@
m_transaction->closeCursor(*this);
}
-void SQLiteIDBCursor::currentData(IDBGetResult& result, const Optional<IDBKeyPath>& keyPath)
+void SQLiteIDBCursor::currentData(IDBGetResult& result, const Optional<IDBKeyPath>& keyPath, ShouldIncludePrefetchedRecords shouldIncludePrefetchedRecords)
{
ASSERT(!m_fetchedRecords.isEmpty());
@@ -113,7 +113,25 @@
return;
}
- result = { currentRecord.record.key, currentRecord.record.primaryKey, currentRecord.record.value ? *currentRecord.record.value : IDBValue(), keyPath};
+ if (shouldIncludePrefetchedRecords == ShouldIncludePrefetchedRecords::No) {
+ result = { currentRecord.record.key, currentRecord.record.primaryKey, IDBValue(currentRecord.record.value), keyPath };
+ return;
+ }
+
+ Vector<IDBCursorRecord> prefetchedRecords;
+ prefetchedRecords.reserveCapacity(m_fetchedRecords.size());
+ for (auto& record : m_fetchedRecords) {
+ if (record.isTerminalRecord())
+ break;
+
+ prefetchedRecords.append(record.record);
+ }
+
+ // First record will be returned as current record.
+ if (!prefetchedRecords.isEmpty())
+ prefetchedRecords.remove(0);
+
+ result = { currentRecord.record.key, currentRecord.record.primaryKey, IDBValue(currentRecord.record.value), keyPath, WTFMove(prefetchedRecords) };
}
static String buildPreIndexStatement(bool isDirectionNext)
@@ -263,6 +281,8 @@
// We also need to throw away any fetched records as they may no longer be valid.
m_fetchedRecords.clear();
m_fetchedRecordsSize = 0;
+
+ m_prefetchCount = 0;
}
void SQLiteIDBCursor::resetAndRebindStatement()
@@ -359,19 +379,34 @@
return true;
}
-bool SQLiteIDBCursor::prefetch()
+bool SQLiteIDBCursor::prefetchOneRecord()
{
- LOG(IndexedDB, "SQLiteIDBCursor::prefetch() - Cursor already has %zu fetched records", m_fetchedRecords.size());
+ LOG(IndexedDB, "SQLiteIDBCursor::prefetchOneRecord() - Cursor already has %zu fetched records", m_fetchedRecords.size());
if (m_fetchedRecordsSize >= prefetchSizeLimit || m_fetchedRecords.isEmpty() || m_fetchedRecords.size() >= prefetchLimit || m_fetchedRecords.last().isTerminalRecord())
return false;
m_currentKeyForUniqueness = m_fetchedRecords.last().record.key;
- fetch();
- return m_fetchedRecords.size() < prefetchLimit && m_fetchedRecordsSize < prefetchSizeLimit;
+ return fetch() && m_fetchedRecords.size() < prefetchLimit && m_fetchedRecordsSize < prefetchSizeLimit;
}
+void SQLiteIDBCursor::increaseCountToPrefetch()
+{
+ m_prefetchCount = m_prefetchCount ? m_prefetchCount * 2 : 1;
+}
+
+bool SQLiteIDBCursor::prefetch()
+{
+ for (unsigned i = 0; i < m_prefetchCount; ++i) {
+ if (!prefetchOneRecord())
+ return false;
+ }
+
+ increaseCountToPrefetch();
+ return true;
+}
+
bool SQLiteIDBCursor::advance(uint64_t count)
{
LOG(IndexedDB, "SQLiteIDBCursor::advance() - Count %" PRIu64 ", %zu fetched records", count, m_fetchedRecords.size());
@@ -488,7 +523,7 @@
ASSERT(!m_fetchedRecords.isEmpty());
ASSERT(!m_fetchedRecords.last().isTerminalRecord());
- record.record.value = nullptr;
+ record.record.value = { };
auto& database = m_transaction->sqliteTransaction()->database();
SQLiteStatement* statement = nullptr;
@@ -546,7 +581,7 @@
}
if (m_cursorType == IndexedDB::CursorType::KeyAndValue)
- record.record.value = makeUnique<IDBValue>(ThreadSafeDataBuffer::create(WTFMove(keyData)), blobURLs, blobFilePaths);
+ record.record.value = { ThreadSafeDataBuffer::create(WTFMove(keyData)), blobURLs, blobFilePaths };
} else {
if (!deserializeIDBKeyData(keyData.data(), keyData.size(), record.record.primaryKey)) {
LOG_ERROR("Unable to deserialize value data from database while advancing index cursor");
@@ -572,7 +607,7 @@
if (result == SQLITE_ROW) {
m_cachedObjectStoreStatement->getColumnBlobAsVector(0, keyData);
- record.record.value = makeUnique<IDBValue>(ThreadSafeDataBuffer::create(WTFMove(keyData)));
+ record.record.value = { ThreadSafeDataBuffer::create(WTFMove(keyData)) };
} else if (result == SQLITE_DONE) {
// This indicates that the record we're trying to retrieve has been removed from the object store.
// Skip over it.
@@ -645,10 +680,10 @@
return m_fetchedRecords.first().record.primaryKey;
}
-IDBValue* SQLiteIDBCursor::currentValue() const
+const IDBValue& SQLiteIDBCursor::currentValue() const
{
ASSERT(!m_fetchedRecords.isEmpty());
- return m_fetchedRecords.first().record.value.get();
+ return m_fetchedRecords.first().record.value;
}
bool SQLiteIDBCursor::didComplete() const
Modified: trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBCursor.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -66,10 +66,11 @@
const IDBKeyData& currentKey() const;
const IDBKeyData& currentPrimaryKey() const;
- IDBValue* currentValue() const;
+ const IDBValue& currentValue() const;
bool advance(uint64_t count);
bool iterate(const IDBKeyData& targetKey, const IDBKeyData& targetPrimaryKey);
+ bool prefetchOneRecord();
bool prefetch();
bool didComplete() const;
@@ -77,7 +78,8 @@
void objectStoreRecordsChanged();
- void currentData(IDBGetResult&, const Optional<IDBKeyPath>&);
+ enum class ShouldIncludePrefetchedRecords { No, Yes };
+ void currentData(IDBGetResult&, const Optional<IDBKeyPath>&, ShouldIncludePrefetchedRecords = ShouldIncludePrefetchedRecords::No);
private:
bool establishStatement();
@@ -109,6 +111,8 @@
bool isDirectionNext() const { return m_cursorDirection == IndexedDB::CursorDirection::Next || m_cursorDirection == IndexedDB::CursorDirection::Nextunique; }
+ void increaseCountToPrefetch();
+
SQLiteIDBTransaction* m_transaction;
IDBResourceIdentifier m_cursorIdentifier;
int64_t m_objectStoreID;
@@ -133,6 +137,8 @@
int64_t m_boundID { 0 };
bool m_backingStoreCursor { false };
+
+ unsigned m_prefetchCount { 0 };
};
} // namespace IDBServer
Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -854,24 +854,8 @@
auto error = m_backingStore->iterateCursor(transactionIdentifier, cursorIdentifier, data, result);
callback(error, result);
-
- if (error.isNull())
- prefetchCursor(transactionIdentifier, cursorIdentifier, data.count ? data.count : 1);
}
-void UniqueIDBDatabase::prefetchCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBResourceIdentifier& cursorIdentifier, uint64_t step)
-{
- LOG(IndexedDB, "UniqueIDBDatabase::prefetchCursor");
-
- ASSERT(!isMainThread());
-
- uint64_t countToPrefetch = step * 2;
- while (countToPrefetch --) {
- if (!m_backingStore->prefetchCursor(transactionIdentifier, cursorIdentifier))
- return;
- }
-}
-
void UniqueIDBDatabase::commitTransaction(UniqueIDBDatabaseTransaction& transaction, ErrorCallback callback)
{
ASSERT(!isMainThread());
Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -142,8 +142,6 @@
void clearTransactionsOnConnection(UniqueIDBDatabaseConnection&);
- void prefetchCursor(const IDBResourceIdentifier&, const IDBResourceIdentifier&, uint64_t step);
-
IDBServer& m_server;
IDBDatabaseIdentifier m_identifier;
Modified: trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabaseTransaction.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -374,9 +374,12 @@
auto database = m_databaseConnection->database();
ASSERT(database);
- database->iterateCursor(requestData, data, [this, requestData](auto& error, const IDBGetResult& result) {
+ database->iterateCursor(requestData, data, [this, requestData, option = data.option](auto& error, const IDBGetResult& result) {
LOG(IndexedDB, "UniqueIDBDatabaseTransaction::iterateCursor (callback)");
+ if (option == IndexedDB::CursorIterateOption::DoNotReply)
+ return;
+
if (error.isNull())
m_databaseConnection->connectionToClient().didIterateCursor(IDBResultData::iterateCursorSuccess(requestData.requestIdentifier(), result));
else
Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBCursorRecord.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBCursorRecord.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBCursorRecord.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -35,12 +35,13 @@
struct IDBCursorRecord {
IDBKeyData key;
IDBKeyData primaryKey;
- std::unique_ptr<IDBValue> value;
+ IDBValue value;
template<class Encoder> void encode(Encoder&) const;
template<class Decoder> static bool decode(Decoder&, IDBCursorRecord&);
- size_t size() const { return key.size() + primaryKey.size() + (value ? value->size() : 0); }
+ IDBCursorRecord isolatedCopy() const;
+ size_t size() const { return key.size() + primaryKey.size() + value.size(); }
};
template<class Encoder>
@@ -64,6 +65,11 @@
return true;
}
+inline IDBCursorRecord IDBCursorRecord::isolatedCopy() const
+{
+ return { key.isolatedCopy(), primaryKey.isolatedCopy(), value.isolatedCopy() };
+}
+
} // namespace WebCore
#endif // ENABLE(INDEXED_DATABASE)
Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.cpp (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.cpp 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.cpp 2020-02-14 18:08:03 UTC (rev 256621)
@@ -33,7 +33,7 @@
IDBIterateCursorData IDBIterateCursorData::isolatedCopy() const
{
- return { keyData.isolatedCopy(), primaryKeyData.isolatedCopy(), count };
+ return { keyData.isolatedCopy(), primaryKeyData.isolatedCopy(), count, option };
}
#if !LOG_DISABLED
Modified: trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.h (256620 => 256621)
--- trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.h 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/Modules/indexeddb/shared/IDBIterateCursorData.h 2020-02-14 18:08:03 UTC (rev 256621)
@@ -35,6 +35,7 @@
IDBKeyData keyData;
IDBKeyData primaryKeyData;
unsigned count;
+ IndexedDB::CursorIterateOption option { IndexedDB::CursorIterateOption::Reply };
WEBCORE_EXPORT IDBIterateCursorData isolatedCopy() const;
@@ -50,6 +51,7 @@
void IDBIterateCursorData::encode(Encoder& encoder) const
{
encoder << keyData << primaryKeyData << static_cast<uint64_t>(count);
+ encoder.encodeEnum(option);
}
template<class Decoder>
@@ -73,9 +75,11 @@
if (count > std::numeric_limits<unsigned>::max())
return false;
-
iteratorCursorData.count = static_cast<unsigned>(count);
+ if (!decoder.decodeEnum(iteratorCursorData.option))
+ return false;
+
return true;
}
Modified: trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj (256620 => 256621)
--- trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-02-14 18:05:04 UTC (rev 256620)
+++ trunk/Source/WebCore/WebCore.xcodeproj/project.pbxproj 2020-02-14 18:08:03 UTC (rev 256621)
@@ -1399,7 +1399,7 @@
510D4A34103165EE0049EA54 /* SocketStreamError.h in Headers */ = {isa = PBXBuildFile; fileRef = 510D4A2E103165EE0049EA54 /* SocketStreamError.h */; settings = {ATTRIBUTES = (Private, ); }; };
510D4A37103165EE0049EA54 /* SocketStreamHandle.h in Headers */ = {isa = PBXBuildFile; fileRef = 510D4A31103165EE0049EA54 /* SocketStreamHandle.h */; settings = {ATTRIBUTES = (Private, ); }; };
510D4A38103165EE0049EA54 /* SocketStreamHandleClient.h in Headers */ = {isa = PBXBuildFile; fileRef = 510D4A32103165EE0049EA54 /* SocketStreamHandleClient.h */; settings = {ATTRIBUTES = (Private, ); }; };
- 5110FCFC1E03641D006F8D0B /* IDBCursorRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 5110FCFB1E0362A5006F8D0B /* IDBCursorRecord.h */; };
+ 5110FCFC1E03641D006F8D0B /* IDBCursorRecord.h in Headers */ = {isa = PBXBuildFile; fileRef = 5110FCFB1E0362A5006F8D0B /* IDBCursorRecord.h */; settings = {ATTRIBUTES = (Private, ); }; };
511EC1281C50AACA0032F983 /* IDBSerialization.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC1261C50AA570032F983 /* IDBSerialization.h */; };
511EC12C1C50ABBF0032F983 /* SQLiteIDBTransaction.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC12A1C50ABBA0032F983 /* SQLiteIDBTransaction.h */; };
511EC1301C50ABF50032F983 /* SQLiteIDBCursor.h in Headers */ = {isa = PBXBuildFile; fileRef = 511EC12E1C50ABEC0032F983 /* SQLiteIDBCursor.h */; };