13 #include "llvm/ADT/Optional.h" 14 #include "llvm/ADT/STLExtras.h" 15 #include "llvm/ADT/ScopeExit.h" 16 #include "llvm/ADT/SmallString.h" 17 #include "llvm/ADT/SmallVector.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/Support/Error.h" 20 #include "llvm/Support/FileSystem.h" 21 #include "llvm/Support/FileUtilities.h" 22 #include "llvm/Support/MemoryBuffer.h" 23 #include "llvm/Support/Path.h" 30 std::string getShardPathFromFilePath(llvm::StringRef ShardRoot,
31 llvm::StringRef FilePath) {
32 llvm::SmallString<128> ShardRootSS(ShardRoot);
33 llvm::sys::path::append(ShardRootSS, llvm::sys::path::filename(FilePath) +
34 "." + llvm::toHex(
digest(FilePath)) +
36 return ShardRootSS.str();
41 class DiskBackedIndexStorage :
public BackgroundIndexStorage {
42 std::string DiskShardRoot;
47 DiskBackedIndexStorage(llvm::StringRef
Directory) {
48 llvm::SmallString<128> CDBDirectory(Directory);
49 llvm::sys::path::append(CDBDirectory,
".clangd",
"index");
50 DiskShardRoot = CDBDirectory.str();
52 std::error_code EC = llvm::sys::fs::create_directories(DiskShardRoot);
54 elog(
"Failed to create directory {0} for index storage: {1}",
55 DiskShardRoot, EC.message());
59 std::unique_ptr<IndexFileIn>
60 loadShard(llvm::StringRef ShardIdentifier)
const override {
61 const std::string ShardPath =
62 getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
63 auto Buffer = llvm::MemoryBuffer::getFile(ShardPath);
67 return std::make_unique<IndexFileIn>(std::move(*I));
69 elog(
"Error while reading shard {0}: {1}", ShardIdentifier,
74 llvm::Error storeShard(llvm::StringRef ShardIdentifier,
75 IndexFileOut Shard)
const override {
76 auto ShardPath = getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
77 return llvm::writeFileAtomically(ShardPath +
".tmp.%%%%%%%%", ShardPath,
78 [&Shard](llvm::raw_ostream &OS) {
80 return llvm::Error::success();
87 class NullStorage :
public BackgroundIndexStorage {
89 std::unique_ptr<IndexFileIn>
90 loadShard(llvm::StringRef ShardIdentifier)
const override {
94 llvm::Error storeShard(llvm::StringRef ShardIdentifier,
95 IndexFileOut Shard)
const override {
96 vlog(
"Couldn't find project for {0}, indexing in-memory only",
98 return llvm::Error::success();
103 class DiskBackedIndexStorageManager {
105 DiskBackedIndexStorageManager(
106 std::function<llvm::Optional<ProjectInfo>(
PathRef)> GetProjectInfo)
107 : IndexStorageMapMu(std::make_unique<std::mutex>()),
108 GetProjectInfo(std::move(GetProjectInfo)) {
109 llvm::SmallString<128> HomeDir;
110 llvm::sys::path::home_directory(HomeDir);
111 this->HomeDir = HomeDir.str().str();
116 std::lock_guard<std::mutex> Lock(*IndexStorageMapMu);
117 Path CDBDirectory = HomeDir;
118 if (
auto PI = GetProjectInfo(File))
119 CDBDirectory = PI->SourceRoot;
120 auto &IndexStorage = IndexStorageMap[CDBDirectory];
122 IndexStorage = create(CDBDirectory);
123 return IndexStorage.get();
127 std::unique_ptr<BackgroundIndexStorage> create(
PathRef CDBDirectory) {
128 if (CDBDirectory.empty()) {
129 elog(
"Tried to create storage for empty directory!");
130 return std::make_unique<NullStorage>();
132 return std::make_unique<DiskBackedIndexStorage>(CDBDirectory);
137 llvm::StringMap<std::unique_ptr<BackgroundIndexStorage>> IndexStorageMap;
138 std::unique_ptr<std::mutex> IndexStorageMapMu;
140 std::function<llvm::Optional<ProjectInfo>(
PathRef)> GetProjectInfo;
147 std::function<llvm::Optional<ProjectInfo>(
PathRef)> GetProjectInfo) {
148 return DiskBackedIndexStorageManager(std::move(GetProjectInfo));
llvm::unique_function< BackgroundIndexStorage *(PathRef)> Factory
static Factory createDiskBackedStorageFactory(std::function< llvm::Optional< ProjectInfo >(PathRef)> GetProjectInfo)
llvm::StringRef PathRef
A typedef to represent a ref to file path.
llvm::Expected< IndexFileIn > readIndexFile(llvm::StringRef Data)
void vlog(const char *Fmt, Ts &&... Vals)
void elog(const char *Fmt, Ts &&... Vals)
std::string Path
A typedef to represent a file path.
llvm::StringRef Directory
FileDigest digest(llvm::StringRef Content)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//