ClangRefactoring: Make the indexer more robust

We check now if the database is busy. This should not be happen but better
be careful.

Change-Id: I8b667ff183368977991974ea1fe7fcde837e968a
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
This commit is contained in:
Marco Bubke
2019-07-10 14:03:38 +02:00
parent 4526a02e31
commit 2eb4050acb
2 changed files with 57 additions and 44 deletions

View File

@@ -91,12 +91,31 @@ void SymbolIndexer::updateProjectParts(ProjectPartContainers &&projectParts)
updateProjectPart(std::move(projectPart)); updateProjectPart(std::move(projectPart));
} }
namespace {
void store(SymbolStorageInterface &symbolStorage,
BuildDependenciesStorageInterface &buildDependencyStorage,
Sqlite::TransactionInterface &transactionInterface,
SymbolsCollectorInterface &symbolsCollector)
{
try {
Sqlite::ImmediateTransaction transaction{transactionInterface};
buildDependencyStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
transaction.commit();
} catch (const Sqlite::StatementIsBusy &) {
store(symbolStorage, buildDependencyStorage, transactionInterface, symbolsCollector);
}
}
} // namespace
void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart) void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
{ {
ProjectPartId projectPartId = projectPart.projectPartId; ProjectPartId projectPartId = projectPart.projectPartId;
std::vector<SymbolIndexerTask> symbolIndexerTask; std::vector<SymbolIndexerTask> symbolIndexerTask;
symbolIndexerTask.reserve(projectPart.sourcePathIds.size()); symbolIndexerTask.reserve(projectPart.sourcePathIds.size());
for (FilePathId sourcePathId : projectPart.sourcePathIds) { for (FilePathId sourcePathId : projectPart.sourcePathIds) {
SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps( SourceTimeStamps dependentTimeStamps = m_buildDependencyStorage.fetchIncludedIndexingTimeStamps(
sourcePathId); sourcePathId);
@@ -117,27 +136,28 @@ void SymbolIndexer::updateProjectPart(ProjectPartContainer &&projectPart)
preIncludeSearchPath}; preIncludeSearchPath};
symbolsCollector.setFile(sourcePathId, commandLineBuilder.commandLine); symbolsCollector.setFile(sourcePathId, commandLineBuilder.commandLine);
return symbolsCollector.collectSymbols();
};
auto store = [&] { return symbolsCollector.collectSymbols();
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(
symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
transaction.commit();
}; };
const PchPaths pchPaths = m_precompiledHeaderStorage.fetchPrecompiledHeaders( const PchPaths pchPaths = m_precompiledHeaderStorage.fetchPrecompiledHeaders(
projectPart.projectPartId); projectPart.projectPartId);
if (pchPaths.projectPchPath.size() && collect(pchPaths.projectPchPath)) { if (pchPaths.projectPchPath.size() && collect(pchPaths.projectPchPath)) {
store(); store(m_symbolStorage,
m_buildDependencyStorage,
m_transactionInterface,
symbolsCollector);
} else if (pchPaths.systemPchPath.size() && collect(pchPaths.systemPchPath)) { } else if (pchPaths.systemPchPath.size() && collect(pchPaths.systemPchPath)) {
store(); store(m_symbolStorage,
m_buildDependencyStorage,
m_transactionInterface,
symbolsCollector);
} else if (collect({})) { } else if (collect({})) {
store(); store(m_symbolStorage,
m_buildDependencyStorage,
m_transactionInterface,
symbolsCollector);
} }
}; };
@@ -196,23 +216,15 @@ void SymbolIndexer::updateChangedPath(FilePathId filePathId,
return symbolsCollector.collectSymbols(); return symbolsCollector.collectSymbols();
}; };
auto store = [&] {
Sqlite::ImmediateTransaction transaction{m_transactionInterface};
m_buildDependencyStorage.insertOrUpdateIndexingTimeStamps(symbolsCollector.fileStatuses());
m_symbolStorage.addSymbolsAndSourceLocations(symbolsCollector.symbols(),
symbolsCollector.sourceLocations());
transaction.commit();
};
const PchPaths pchPaths = m_precompiledHeaderStorage.fetchPrecompiledHeaders( const PchPaths pchPaths = m_precompiledHeaderStorage.fetchPrecompiledHeaders(
optionalArtefact->projectPartId); optionalArtefact->projectPartId);
if (pchPaths.projectPchPath.size() && collect(pchPaths.projectPchPath)) { if (pchPaths.projectPchPath.size() && collect(pchPaths.projectPchPath)) {
store(); store(m_symbolStorage, m_buildDependencyStorage, m_transactionInterface, symbolsCollector);
} else if (pchPaths.systemPchPath.size() && collect(pchPaths.systemPchPath)) { } else if (pchPaths.systemPchPath.size() && collect(pchPaths.systemPchPath)) {
store(); store(m_symbolStorage, m_buildDependencyStorage, m_transactionInterface, symbolsCollector);
} else if (collect({})) { } else if (collect({})) {
store(); store(m_symbolStorage, m_buildDependencyStorage, m_transactionInterface, symbolsCollector);
} }
}; };

View File

@@ -39,9 +39,10 @@
#include <filepathcaching.h> #include <filepathcaching.h>
#include <filestatuscache.h> #include <filestatuscache.h>
#include <processormanager.h>
#include <projectpartcontainer.h> #include <projectpartcontainer.h>
#include <refactoringdatabaseinitializer.h> #include <refactoringdatabaseinitializer.h>
#include <processormanager.h> #include <sqliteexception.h>
#include <symbolindexer.h> #include <symbolindexer.h>
#include <symbolindexertaskqueue.h> #include <symbolindexertaskqueue.h>
#include <taskscheduler.h> #include <taskscheduler.h>
@@ -868,29 +869,29 @@ TEST_F(SymbolIndexer, UpdateProjectPartsCallsGetsNoPchPathsAndHasErrors)
TEST_F(SymbolIndexer, UpdateProjectPartsFetchIncludedIndexingTimeStamps) TEST_F(SymbolIndexer, UpdateProjectPartsFetchIncludedIndexingTimeStamps)
{ {
InSequence s; InSequence s;
ProjectPartContainer projectPart{1,
{"-Wno-pragma-once-outside-header"},
{{"BAR", "1", 1}, {"FOO", "1", 2}},
Utils::clone(systemIncludeSearchPaths),
Utils::clone(projectIncludeSearchPaths),
{header1PathId},
{main1PathId, main2PathId},
Utils::Language::Cxx,
Utils::LanguageVersion::CXX14,
Utils::LanguageExtension::None};
EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main1PathId))) EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
.WillOnce(Return(dependentSourceTimeStamps1));
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps1));
EXPECT_CALL(mockBuildDependenciesStorage, fetchIncludedIndexingTimeStamps(Eq(main2PathId)))
.WillOnce(Return(dependentSourceTimeStamps2));
EXPECT_CALL(mockModifiedTimeChecker, isUpToDate(dependentSourceTimeStamps2));
EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses1)); EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses1));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses1)); EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(_));
EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses2)); EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(_, _));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(fileStatuses2)); EXPECT_CALL(mockSqliteTransactionBackend, commit());
indexer.updateProjectParts({projectPart}); indexer.updateProjectParts({projectPart1});
}
TEST_F(SymbolIndexer, UpdateProjectPartsIsBusyInStoringData)
{
InSequence s;
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin())
.WillOnce(Throw(Sqlite::StatementIsBusy{""}));
EXPECT_CALL(mockSqliteTransactionBackend, immediateBegin());
EXPECT_CALL(mockCollector, fileStatuses()).WillRepeatedly(ReturnRef(fileStatuses1));
EXPECT_CALL(mockBuildDependenciesStorage, insertOrUpdateIndexingTimeStamps(_));
EXPECT_CALL(mockSymbolStorage, addSymbolsAndSourceLocations(_, _));
EXPECT_CALL(mockSqliteTransactionBackend, commit());
indexer.updateProjectParts({projectPart1});
} }
TEST_F(SymbolIndexer, DependentSourceAreNotUpToDate) TEST_F(SymbolIndexer, DependentSourceAreNotUpToDate)