IDBError MemoryIDBBackingStore::generateKeyNumber(const IDBResourceIdentifier& transactionIdentifier, uint64_t objectStoreIdentifier, uint64_t& keyNumber) { LOG(IndexedDB, "MemoryIDBBackingStore::generateKeyNumber"); ASSERT(objectStoreIdentifier); ASSERT_UNUSED(transactionIdentifier, m_transactions.contains(transactionIdentifier)); ASSERT_UNUSED(transactionIdentifier, m_transactions.get(transactionIdentifier)->isWriting()); MemoryObjectStore* objectStore = m_objectStoresByIdentifier.get(objectStoreIdentifier); RELEASE_ASSERT(objectStore); keyNumber = objectStore->currentKeyGeneratorValue(); objectStore->setKeyGeneratorValue(keyNumber + 1); return IDBError(); }
void IDBServer::deleteDatabase(const IDBRequestData& requestData) { LOG(IndexedDB, "IDBServer::deleteDatabase - %s", requestData.databaseIdentifier().debugString().utf8().data()); auto connection = m_connectionMap.get(requestData.requestIdentifier().connectionIdentifier()); if (!connection) { // If the connection back to the client is gone, there's no way to delete the database as // well as no way to message back failure. return; } // FIXME: During bringup of modern IDB, the database deletion is a no-op, and is // immediately reported back to the WebProcess as failure. auto result = IDBResultData::error(requestData.requestIdentifier(), IDBError(IDBExceptionCode::Unknown)); connection->didDeleteDatabase(result); }
IDBError MemoryObjectStore::createIndex(MemoryBackingStoreTransaction& transaction, const IDBIndexInfo& info) { LOG(IndexedDB, "MemoryObjectStore::createIndex"); if (!m_writeTransaction || !m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction) return IDBError(IDBExceptionCode::ConstraintError); ASSERT(!m_indexesByIdentifier.contains(info.identifier())); auto index = MemoryIndex::create(info); m_info.addExistingIndex(info); transaction.addNewIndex(*index); registerIndex(WTF::move(index)); return { }; }
IDBError MemoryObjectStore::createIndex(MemoryBackingStoreTransaction& transaction, const IDBIndexInfo& info) { LOG(IndexedDB, "MemoryObjectStore::createIndex"); if (!m_writeTransaction || !m_writeTransaction->isVersionChange() || m_writeTransaction != &transaction) return IDBError(IDBDatabaseException::ConstraintError); ASSERT(!m_indexesByIdentifier.contains(info.identifier())); auto index = MemoryIndex::create(info, *this); // If there was an error populating the new index, then the current records in the object store violate its contraints auto error = populateIndexWithExistingRecords(*index); if (!error.isNull()) return error; m_info.addExistingIndex(info); transaction.addNewIndex(*index); registerIndex(WTFMove(index)); return { }; }
IDBError MemoryIDBBackingStore::openCursor(const IDBResourceIdentifier& transactionIdentifier, const IDBCursorInfo& info, IDBGetResult& outData) { LOG(IndexedDB, "MemoryIDBBackingStore::openCursor"); ASSERT(!MemoryCursor::cursorForIdentifier(info.identifier())); if (!m_transactions.contains(transactionIdentifier)) return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store transaction found in which to open a cursor")); switch (info.cursorSource()) { case IndexedDB::CursorSource::ObjectStore: { auto* objectStore = m_objectStoresByIdentifier.get(info.sourceIdentifier()); if (!objectStore) return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found")); MemoryCursor* cursor = objectStore->maybeOpenCursor(info); if (!cursor) return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("Could not create object store cursor in backing store")); cursor->currentData(outData); break; } case IndexedDB::CursorSource::Index: auto* objectStore = m_objectStoresByIdentifier.get(info.objectStoreIdentifier()); if (!objectStore) return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store object store found")); auto* index = objectStore->indexForIdentifier(info.sourceIdentifier()); if (!index) return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("No backing store index found")); MemoryCursor* cursor = index->maybeOpenCursor(info); if (!cursor) return IDBError(IDBDatabaseException::UnknownError, ASCIILiteral("Could not create index cursor in backing store")); cursor->currentData(outData); break; } return { }; }
void UniqueIDBDatabase::handleOpenDatabaseOperations() { ASSERT(isMainThread()); LOG(IndexedDB, "(main) UniqueIDBDatabase::handleOpenDatabaseOperations"); // If a version change transaction is currently in progress, no new connections can be opened right now. // We will try again later. if (m_versionChangeDatabaseConnection) return; auto operation = m_pendingOpenDatabaseOperations.takeFirst(); // 3.3.1 Opening a database // If requested version is undefined, then let requested version be 1 if db was created in the previous step, // or the current version of db otherwise. uint64_t requestedVersion = operation->requestData().requestedVersion(); if (!requestedVersion) requestedVersion = m_databaseInfo->version() ? m_databaseInfo->version() : 1; // 3.3.1 Opening a database // If the database version higher than the requested version, abort these steps and return a VersionError. if (requestedVersion < m_databaseInfo->version()) { auto result = IDBResultData::error(operation->requestData().requestIdentifier(), IDBError(IDBExceptionCode::VersionError)); operation->connection().didOpenDatabase(result); return; } Ref<UniqueIDBDatabaseConnection> connection = UniqueIDBDatabaseConnection::create(*this, operation->connection()); UniqueIDBDatabaseConnection* rawConnection = &connection.get(); if (requestedVersion == m_databaseInfo->version()) { addOpenDatabaseConnection(WTF::move(connection)); auto result = IDBResultData::openDatabaseSuccess(operation->requestData().requestIdentifier(), *rawConnection); operation->connection().didOpenDatabase(result); return; } ASSERT(!m_versionChangeOperation); ASSERT(!m_versionChangeDatabaseConnection); m_versionChangeOperation = adoptRef(operation.leakRef()); m_versionChangeDatabaseConnection = rawConnection; // 3.3.7 "versionchange" transaction steps // If there's no other open connections to this database, the version change process can begin immediately. if (!hasAnyOpenConnections()) { startVersionChangeTransaction(); return; } // Otherwise we have to notify all those open connections and wait for them to close. notifyConnectionsOfVersionChange(); }