forked from OSchip/llvm-project
114 lines
3.5 KiB
C++
114 lines
3.5 KiB
C++
//===-- BackgroundRebuild.cpp - when to rebuild thei background index -----===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "index/BackgroundRebuild.h"
|
|
#include "index/FileIndex.h"
|
|
#include "support/Logger.h"
|
|
#include "support/Trace.h"
|
|
|
|
#include <atomic>
|
|
#include <chrono>
|
|
#include <condition_variable>
|
|
#include <memory>
|
|
#include <mutex>
|
|
#include <numeric>
|
|
#include <queue>
|
|
#include <random>
|
|
#include <string>
|
|
#include <thread>
|
|
|
|
namespace clang {
|
|
namespace clangd {
|
|
|
|
bool BackgroundIndexRebuilder::enoughTUsToRebuild() const {
|
|
if (!ActiveVersion) // never built
|
|
return IndexedTUs == TUsBeforeFirstBuild; // use low threshold
|
|
// rebuild if we've reached the (higher) threshold
|
|
return IndexedTUs >= IndexedTUsAtLastRebuild + TUsBeforeRebuild;
|
|
}
|
|
|
|
void BackgroundIndexRebuilder::indexedTU() {
|
|
maybeRebuild("after indexing enough files", [this] {
|
|
++IndexedTUs;
|
|
if (Loading)
|
|
return false; // rebuild once loading finishes
|
|
if (ActiveVersion != StartedVersion) // currently building
|
|
return false; // no urgency, avoid overlapping builds
|
|
return enoughTUsToRebuild();
|
|
});
|
|
}
|
|
|
|
void BackgroundIndexRebuilder::idle() {
|
|
maybeRebuild("when background indexer is idle", [this] {
|
|
// rebuild if there's anything new in the index.
|
|
// (even if currently rebuilding! this ensures eventual completeness)
|
|
return IndexedTUs > IndexedTUsAtLastRebuild;
|
|
});
|
|
}
|
|
|
|
void BackgroundIndexRebuilder::startLoading() {
|
|
std::lock_guard<std::mutex> Lock(Mu);
|
|
if (!Loading)
|
|
LoadedShards = 0;
|
|
++Loading;
|
|
}
|
|
void BackgroundIndexRebuilder::loadedShard(size_t ShardCount) {
|
|
std::lock_guard<std::mutex> Lock(Mu);
|
|
assert(Loading);
|
|
LoadedShards += ShardCount;
|
|
}
|
|
void BackgroundIndexRebuilder::doneLoading() {
|
|
maybeRebuild("after loading index from disk", [this] {
|
|
assert(Loading);
|
|
--Loading;
|
|
if (Loading) // was loading multiple batches concurrently
|
|
return false; // rebuild once the last batch is done.
|
|
// Rebuild if we loaded any shards, or if we stopped an indexedTU rebuild.
|
|
return LoadedShards > 0 || enoughTUsToRebuild();
|
|
});
|
|
}
|
|
|
|
void BackgroundIndexRebuilder::shutdown() {
|
|
std::lock_guard<std::mutex> Lock(Mu);
|
|
ShouldStop = true;
|
|
}
|
|
|
|
void BackgroundIndexRebuilder::maybeRebuild(const char *Reason,
|
|
std::function<bool()> Check) {
|
|
unsigned BuildVersion = 0;
|
|
{
|
|
std::lock_guard<std::mutex> Lock(Mu);
|
|
if (!ShouldStop && Check()) {
|
|
BuildVersion = ++StartedVersion;
|
|
IndexedTUsAtLastRebuild = IndexedTUs;
|
|
}
|
|
}
|
|
if (BuildVersion) {
|
|
std::unique_ptr<SymbolIndex> NewIndex;
|
|
{
|
|
vlog("BackgroundIndex: building version {0} {1}", BuildVersion, Reason);
|
|
trace::Span Tracer("RebuildBackgroundIndex");
|
|
SPAN_ATTACH(Tracer, "reason", Reason);
|
|
NewIndex = Source->buildIndex(IndexType::Heavy, DuplicateHandling::Merge);
|
|
}
|
|
{
|
|
std::lock_guard<std::mutex> Lock(Mu);
|
|
// Guard against rebuild finishing in the wrong order.
|
|
if (BuildVersion > ActiveVersion) {
|
|
ActiveVersion = BuildVersion;
|
|
vlog("BackgroundIndex: serving version {0} ({1} bytes)", BuildVersion,
|
|
NewIndex->estimateMemoryUsage());
|
|
Target->reset(std::move(NewIndex));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
} // namespace clangd
|
|
} // namespace clang
|