void Team::dump( StatementCache & db ) { Statement & insert = db.get( "INSERT INTO TEAM VALUES(?,?,?,NULL)" ); insert.reset(); insert.bind( 1, this->location->getX() ); insert.bind( 2, this->location->getY() ); insert.bind( 3, this->faction ); insert.step(); }
nsresult DOMStorageDBThread::DBOperation::Perform(DOMStorageDBThread* aThread) { nsresult rv; switch (mType) { case opPreload: case opPreloadUrgent: { // Already loaded? if (mCache->Loaded()) { break; } StatementCache* statements; if (MOZ_UNLIKELY(NS_IsMainThread())) { statements = &aThread->mReaderStatements; } else { statements = &aThread->mWorkerStatements; } // OFFSET is an optimization when we have to do a sync load // and cache has already loaded some parts asynchronously. // It skips keys we have already loaded. nsCOMPtr<mozIStorageStatement> stmt = statements->GetCachedStatement( "SELECT key, value FROM webappsstore2 " "WHERE scope = :scope ORDER BY key " "LIMIT -1 OFFSET :offset"); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), mCache->Scope()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("offset"), static_cast<int32_t>(mCache->LoadedCount())); NS_ENSURE_SUCCESS(rv, rv); bool exists; while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&exists)) && exists) { nsAutoString key; rv = stmt->GetString(0, key); NS_ENSURE_SUCCESS(rv, rv); nsAutoString value; rv = stmt->GetString(1, value); NS_ENSURE_SUCCESS(rv, rv); if (!mCache->LoadItem(key, value)) { break; } } mCache->LoadDone(NS_OK); break; } case opGetUsage: { nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "SELECT SUM(LENGTH(key) + LENGTH(value)) FROM webappsstore2" " WHERE scope LIKE :scope" ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), mUsage->Scope() + NS_LITERAL_CSTRING("%")); NS_ENSURE_SUCCESS(rv, rv); bool exists; rv = stmt->ExecuteStep(&exists); NS_ENSURE_SUCCESS(rv, rv); int64_t usage = 0; if (exists) { rv = stmt->GetInt64(0, &usage); NS_ENSURE_SUCCESS(rv, rv); } mUsage->LoadUsage(usage); break; } case opAddItem: case opUpdateItem: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "INSERT OR REPLACE INTO webappsstore2 (scope, key, value) " "VALUES (:scope, :key, :value) " ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), mCache->Scope()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindStringByName(NS_LITERAL_CSTRING("key"), mKey); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindStringByName(NS_LITERAL_CSTRING("value"), mValue); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); aThread->mScopesHavingData.PutEntry(Scope()); break; } case opRemoveItem: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2 " "WHERE scope = :scope " "AND key = :key " ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), mCache->Scope()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindStringByName(NS_LITERAL_CSTRING("key"), mKey); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); break; } case opClear: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2 " "WHERE scope = :scope" ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), mCache->Scope()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); aThread->mScopesHavingData.RemoveEntry(Scope()); break; } case opClearAll: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2" ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); aThread->mScopesHavingData.Clear(); break; } case opClearMatchingScope: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2" " WHERE scope GLOB :scope" ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), mScope + NS_LITERAL_CSTRING("*")); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); break; } default: NS_ERROR("Unknown task type"); break; } return NS_OK; }
nsresult DOMStorageDBThread::DBOperation::Perform(DOMStorageDBThread* aThread) { nsresult rv; switch (mType) { case opPreload: case opPreloadUrgent: { // Already loaded? if (mCache->Loaded()) { break; } StatementCache* statements; if (MOZ_UNLIKELY(NS_IsMainThread())) { statements = &aThread->mReaderStatements; } else { statements = &aThread->mWorkerStatements; } // OFFSET is an optimization when we have to do a sync load // and cache has already loaded some parts asynchronously. // It skips keys we have already loaded. nsCOMPtr<mozIStorageStatement> stmt = statements->GetCachedStatement( "SELECT key, value FROM webappsstore2 " "WHERE originAttributes = :originAttributes AND originKey = :originKey " "ORDER BY key LIMIT -1 OFFSET :offset"); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("originAttributes"), mCache->OriginSuffix()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("originKey"), mCache->OriginNoSuffix()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindInt32ByName(NS_LITERAL_CSTRING("offset"), static_cast<int32_t>(mCache->LoadedCount())); NS_ENSURE_SUCCESS(rv, rv); bool exists; while (NS_SUCCEEDED(rv = stmt->ExecuteStep(&exists)) && exists) { nsAutoString key; rv = stmt->GetString(0, key); NS_ENSURE_SUCCESS(rv, rv); nsAutoString value; rv = stmt->GetString(1, value); NS_ENSURE_SUCCESS(rv, rv); if (!mCache->LoadItem(key, value)) { break; } } mCache->LoadDone(NS_OK); break; } case opGetUsage: { nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "SELECT SUM(LENGTH(key) + LENGTH(value)) FROM webappsstore2 " "WHERE (originAttributes || ':' || originKey) LIKE :usageOrigin" ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("usageOrigin"), mUsage->OriginScope()); NS_ENSURE_SUCCESS(rv, rv); bool exists; rv = stmt->ExecuteStep(&exists); NS_ENSURE_SUCCESS(rv, rv); int64_t usage = 0; if (exists) { rv = stmt->GetInt64(0, &usage); NS_ENSURE_SUCCESS(rv, rv); } mUsage->LoadUsage(usage); break; } case opAddItem: case opUpdateItem: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "INSERT OR REPLACE INTO webappsstore2 (originAttributes, originKey, scope, key, value) " "VALUES (:originAttributes, :originKey, :scope, :key, :value) " ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("originAttributes"), mCache->OriginSuffix()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("originKey"), mCache->OriginNoSuffix()); NS_ENSURE_SUCCESS(rv, rv); // Filling the 'scope' column just for downgrade compatibility reasons rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), Scheme0Scope(mCache)); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindStringByName(NS_LITERAL_CSTRING("key"), mKey); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindStringByName(NS_LITERAL_CSTRING("value"), mValue); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); MonitorAutoLock monitor(aThread->mThreadObserver->GetMonitor()); aThread->mOriginsHavingData.PutEntry(Origin()); break; } case opRemoveItem: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2 " "WHERE originAttributes = :originAttributes AND originKey = :originKey " "AND key = :key " ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("originAttributes"), mCache->OriginSuffix()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("originKey"), mCache->OriginNoSuffix()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindStringByName(NS_LITERAL_CSTRING("key"), mKey); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); break; } case opClear: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2 " "WHERE originAttributes = :originAttributes AND originKey = :originKey" ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("originAttributes"), mCache->OriginSuffix()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("originKey"), mCache->OriginNoSuffix()); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); MonitorAutoLock monitor(aThread->mThreadObserver->GetMonitor()); aThread->mOriginsHavingData.RemoveEntry(Origin()); break; } case opClearAll: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2" ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); MonitorAutoLock monitor(aThread->mThreadObserver->GetMonitor()); aThread->mOriginsHavingData.Clear(); break; } case opClearMatchingOrigin: { MOZ_ASSERT(!NS_IsMainThread()); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2" " WHERE originKey GLOB :scope" ); NS_ENSURE_STATE(stmt); mozStorageStatementScoper scope(stmt); rv = stmt->BindUTF8StringByName(NS_LITERAL_CSTRING("scope"), mOrigin + NS_LITERAL_CSTRING("*")); NS_ENSURE_SUCCESS(rv, rv); rv = stmt->Execute(); NS_ENSURE_SUCCESS(rv, rv); // No need to selectively clear mOriginsHavingData here. That hashtable only // prevents preload for scopes with no data. Leaving a false record in it has // a negligible effect on performance. break; } case opClearMatchingOriginAttributes: { MOZ_ASSERT(!NS_IsMainThread()); // Register the ORIGIN_ATTRS_PATTERN_MATCH function, initialized with the pattern nsCOMPtr<mozIStorageFunction> patternMatchFunction( new OriginAttrsPatternMatchSQLFunction(mOriginPattern)); rv = aThread->mWorkerConnection->CreateFunction( NS_LITERAL_CSTRING("ORIGIN_ATTRS_PATTERN_MATCH"), 1, patternMatchFunction); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<mozIStorageStatement> stmt = aThread->mWorkerStatements.GetCachedStatement( "DELETE FROM webappsstore2" " WHERE ORIGIN_ATTRS_PATTERN_MATCH(originAttributes)" ); if (stmt) { mozStorageStatementScoper scope(stmt); rv = stmt->Execute(); } else { rv = NS_ERROR_UNEXPECTED; } // Always remove the function aThread->mWorkerConnection->RemoveFunction( NS_LITERAL_CSTRING("ORIGIN_ATTRS_PATTERN_MATCH")); NS_ENSURE_SUCCESS(rv, rv); // No need to selectively clear mOriginsHavingData here. That hashtable only // prevents preload for scopes with no data. Leaving a false record in it has // a negligible effect on performance. break; } default: NS_ERROR("Unknown task type"); break; } return NS_OK; }