diff --git a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h index c7fd859ac9f..26bc59d9e50 100644 --- a/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h +++ b/src/tools/clangpchmanagerbackend/source/precompiledheaderstorage.h @@ -144,10 +144,18 @@ public: FilePath fetchPrecompiledHeader(ProjectPartId projectPartId) const { - auto value = getPrecompiledHeader.template value(projectPartId.projectPathId); + try { + Sqlite::DeferredTransaction transaction{database}; - if (value) - return *value; + auto value = getPrecompiledHeader.template value(projectPartId.projectPathId); + + if (value) + return *value; + + transaction.commit(); + } catch (const Sqlite::StatementIsBusy) { + return fetchPrecompiledHeader(projectPartId); + } return FilePath(""); } diff --git a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp index 2fa2480a37f..cb47b6f5d28 100644 --- a/src/tools/clangrefactoringbackend/source/symbolindexer.cpp +++ b/src/tools/clangrefactoringbackend/source/symbolindexer.cpp @@ -90,13 +90,9 @@ void SymbolIndexer::updateProjectParts(ProjectPartContainers &&projectParts) void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart) { - Sqlite::DeferredTransaction transaction{m_transactionInterface}; - ProjectPartId projectPartId = projectPart.projectPartId; const FilePath pchPath = m_precompiledHeaderStorage.fetchPrecompiledHeader(projectPartId); - transaction.commit(); - using Builder = CommandLineBuilder; Builder commandLineBuilder{ projectPart, projectPart.toolChainArguments, InputFileType::Source, {}, {}, pchPath}; @@ -157,17 +153,16 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId, optionalArtefact = m_projectPartsStorage.fetchProjectPartArtefact(filePathId); if (!optionalArtefact) return; + transaction.commit(); const FilePath pchPath = m_precompiledHeaderStorage.fetchPrecompiledHeader( optionalArtefact->projectPartId); - transaction.commit(); - SourceTimeStamps dependentTimeStamps = m_symbolStorage.fetchIncludedIndexingTimeStamps(filePathId); const ProjectPartArtefact &artefact = *optionalArtefact; - CommandLineBuilder - builder{artefact, artefact.toolChainArguments, InputFileType::Source, {}, {}, pchPath}; + CommandLineBuilder builder{ + artefact, artefact.toolChainArguments, InputFileType::Source, {}, {}, pchPath}; auto indexing = [arguments = builder.commandLine, filePathId, this]( SymbolsCollectorInterface &symbolsCollector) { diff --git a/tests/unit/unittest/precompiledheaderstorage-test.cpp b/tests/unit/unittest/precompiledheaderstorage-test.cpp index c900350c218..fed3e52093a 100644 --- a/tests/unit/unittest/precompiledheaderstorage-test.cpp +++ b/tests/unit/unittest/precompiledheaderstorage-test.cpp @@ -250,7 +250,24 @@ TEST_F(PrecompiledHeaderStorage, FetchSystemPrecompiledHeaderReturnsNullOptional TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderCallsValueInStatement) { + EXPECT_CALL(database, deferredBegin()); EXPECT_CALL(getPrecompiledHeader, valueReturnFilePath(Eq(25))); + EXPECT_CALL(database, commit()); + + storage.fetchPrecompiledHeader(25); +} + +TEST_F(PrecompiledHeaderStorage, FetchPrecompiledHeaderIsBusy) +{ + InSequence s; + + EXPECT_CALL(database, deferredBegin()); + EXPECT_CALL(getPrecompiledHeader, valueReturnFilePath(Eq(25))) + .WillOnce(Throw(Sqlite::StatementIsBusy{""})); + EXPECT_CALL(database, rollback()); + EXPECT_CALL(database, deferredBegin()); + EXPECT_CALL(getPrecompiledHeader, valueReturnFilePath(Eq(25))); + EXPECT_CALL(database, commit()); storage.fetchPrecompiledHeader(25); } @@ -271,4 +288,4 @@ TEST_F(PrecompiledHeaderStorage, FetchEmptyPrecompiledHeader) ASSERT_THAT(path, IsEmpty()); } -} +} // namespace diff --git a/tests/unit/unittest/symbolindexer-test.cpp b/tests/unit/unittest/symbolindexer-test.cpp index 6d0ebb63bc2..673ef1b4caa 100644 --- a/tests/unit/unittest/symbolindexer-test.cpp +++ b/tests/unit/unittest/symbolindexer-test.cpp @@ -439,9 +439,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrder) { InSequence s; - EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()); EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(projectPart1.projectPartId))); - EXPECT_CALL(mockSqliteTransactionBackend, commit()); EXPECT_CALL(mockCollector, setFile(main1PathId, ElementsAre("clang++", @@ -479,9 +477,7 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsInOrderButGetsAnErrorForCollectingS { InSequence s; - EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()); EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(projectPart1.projectPartId))); - EXPECT_CALL(mockSqliteTransactionBackend, commit()); EXPECT_CALL(mockCollector, setFile(main1PathId, ElementsAre("clang++", @@ -647,8 +643,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrder) EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) .WillOnce(Return(artefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))); EXPECT_CALL(mockSqliteTransactionBackend, commit()); + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))); EXPECT_CALL(mockCollector, setFile(Eq(sourceFileIds[0]), ElementsAre("clang++", @@ -689,8 +685,8 @@ TEST_F(SymbolIndexer, HandleEmptyOptionalArtifactInUpdateChangedPath) EXPECT_CALL(mockSqliteTransactionBackend, deferredBegin()); EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(sourceFileIds[0])) .WillOnce(Return(nullArtefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(_)).Times(0); EXPECT_CALL(mockSqliteTransactionBackend, commit()).Times(0); + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(_)).Times(0); EXPECT_CALL(mockCollector, setFile(_, _)).Times(0); EXPECT_CALL(mockCollector, collectSymbols()).Times(0); EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin()).Times(0); @@ -708,8 +704,8 @@ TEST_F(SymbolIndexer, UpdateChangedPathCallsInOrderButGetsAnErrorForCollectingSy EXPECT_CALL(mockProjectPartsStorage, fetchProjectPartArtefact(TypedEq(sourceFileIds[0]))) .WillOnce(Return(artefact)); - EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))); EXPECT_CALL(mockSqliteTransactionBackend, commit()); + EXPECT_CALL(mockPrecompiledHeaderStorage, fetchPrecompiledHeader(Eq(artefact.projectPartId))); EXPECT_CALL(mockCollector, setFile(Eq(sourceFileIds[0]), ElementsAre("clang++",