annotate clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp @ 221:79ff65ed7e25

LLVM12 Original
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 15 Jun 2021 19:15:29 +0900
parents 0572611fdcc8
children c4bab56944e8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //== BackgroundIndexStorage.cpp - Provide caching support to BackgroundIndex ==/
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8
anatofuz
parents:
diff changeset
9 #include "GlobalCompilationDatabase.h"
anatofuz
parents:
diff changeset
10 #include "index/Background.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
11 #include "support/Logger.h"
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
12 #include "support/Path.h"
150
anatofuz
parents:
diff changeset
13 #include "llvm/ADT/Optional.h"
anatofuz
parents:
diff changeset
14 #include "llvm/ADT/STLExtras.h"
anatofuz
parents:
diff changeset
15 #include "llvm/ADT/ScopeExit.h"
anatofuz
parents:
diff changeset
16 #include "llvm/ADT/SmallString.h"
anatofuz
parents:
diff changeset
17 #include "llvm/ADT/SmallVector.h"
anatofuz
parents:
diff changeset
18 #include "llvm/ADT/StringRef.h"
anatofuz
parents:
diff changeset
19 #include "llvm/Support/Error.h"
anatofuz
parents:
diff changeset
20 #include "llvm/Support/FileSystem.h"
anatofuz
parents:
diff changeset
21 #include "llvm/Support/FileUtilities.h"
anatofuz
parents:
diff changeset
22 #include "llvm/Support/MemoryBuffer.h"
anatofuz
parents:
diff changeset
23 #include "llvm/Support/Path.h"
anatofuz
parents:
diff changeset
24 #include <functional>
anatofuz
parents:
diff changeset
25
anatofuz
parents:
diff changeset
26 namespace clang {
anatofuz
parents:
diff changeset
27 namespace clangd {
anatofuz
parents:
diff changeset
28 namespace {
anatofuz
parents:
diff changeset
29
anatofuz
parents:
diff changeset
30 std::string getShardPathFromFilePath(llvm::StringRef ShardRoot,
anatofuz
parents:
diff changeset
31 llvm::StringRef FilePath) {
anatofuz
parents:
diff changeset
32 llvm::SmallString<128> ShardRootSS(ShardRoot);
anatofuz
parents:
diff changeset
33 llvm::sys::path::append(ShardRootSS, llvm::sys::path::filename(FilePath) +
anatofuz
parents:
diff changeset
34 "." + llvm::toHex(digest(FilePath)) +
anatofuz
parents:
diff changeset
35 ".idx");
anatofuz
parents:
diff changeset
36 return std::string(ShardRootSS.str());
anatofuz
parents:
diff changeset
37 }
anatofuz
parents:
diff changeset
38
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
39 // Uses disk as a storage for index shards.
150
anatofuz
parents:
diff changeset
40 class DiskBackedIndexStorage : public BackgroundIndexStorage {
anatofuz
parents:
diff changeset
41 std::string DiskShardRoot;
anatofuz
parents:
diff changeset
42
anatofuz
parents:
diff changeset
43 public:
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
44 // Creates `DiskShardRoot` and any parents during construction.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
45 DiskBackedIndexStorage(llvm::StringRef Directory) : DiskShardRoot(Directory) {
150
anatofuz
parents:
diff changeset
46 std::error_code OK;
anatofuz
parents:
diff changeset
47 std::error_code EC = llvm::sys::fs::create_directories(DiskShardRoot);
anatofuz
parents:
diff changeset
48 if (EC != OK) {
anatofuz
parents:
diff changeset
49 elog("Failed to create directory {0} for index storage: {1}",
anatofuz
parents:
diff changeset
50 DiskShardRoot, EC.message());
anatofuz
parents:
diff changeset
51 }
anatofuz
parents:
diff changeset
52 }
anatofuz
parents:
diff changeset
53
anatofuz
parents:
diff changeset
54 std::unique_ptr<IndexFileIn>
anatofuz
parents:
diff changeset
55 loadShard(llvm::StringRef ShardIdentifier) const override {
anatofuz
parents:
diff changeset
56 const std::string ShardPath =
anatofuz
parents:
diff changeset
57 getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
anatofuz
parents:
diff changeset
58 auto Buffer = llvm::MemoryBuffer::getFile(ShardPath);
anatofuz
parents:
diff changeset
59 if (!Buffer)
anatofuz
parents:
diff changeset
60 return nullptr;
anatofuz
parents:
diff changeset
61 if (auto I = readIndexFile(Buffer->get()->getBuffer()))
anatofuz
parents:
diff changeset
62 return std::make_unique<IndexFileIn>(std::move(*I));
anatofuz
parents:
diff changeset
63 else
anatofuz
parents:
diff changeset
64 elog("Error while reading shard {0}: {1}", ShardIdentifier,
anatofuz
parents:
diff changeset
65 I.takeError());
anatofuz
parents:
diff changeset
66 return nullptr;
anatofuz
parents:
diff changeset
67 }
anatofuz
parents:
diff changeset
68
anatofuz
parents:
diff changeset
69 llvm::Error storeShard(llvm::StringRef ShardIdentifier,
anatofuz
parents:
diff changeset
70 IndexFileOut Shard) const override {
anatofuz
parents:
diff changeset
71 auto ShardPath = getShardPathFromFilePath(DiskShardRoot, ShardIdentifier);
anatofuz
parents:
diff changeset
72 return llvm::writeFileAtomically(ShardPath + ".tmp.%%%%%%%%", ShardPath,
anatofuz
parents:
diff changeset
73 [&Shard](llvm::raw_ostream &OS) {
anatofuz
parents:
diff changeset
74 OS << Shard;
anatofuz
parents:
diff changeset
75 return llvm::Error::success();
anatofuz
parents:
diff changeset
76 });
anatofuz
parents:
diff changeset
77 }
anatofuz
parents:
diff changeset
78 };
anatofuz
parents:
diff changeset
79
anatofuz
parents:
diff changeset
80 // Doesn't persist index shards anywhere (used when the CDB dir is unknown).
anatofuz
parents:
diff changeset
81 // We could consider indexing into ~/.clangd/ or so instead.
anatofuz
parents:
diff changeset
82 class NullStorage : public BackgroundIndexStorage {
anatofuz
parents:
diff changeset
83 public:
anatofuz
parents:
diff changeset
84 std::unique_ptr<IndexFileIn>
anatofuz
parents:
diff changeset
85 loadShard(llvm::StringRef ShardIdentifier) const override {
anatofuz
parents:
diff changeset
86 return nullptr;
anatofuz
parents:
diff changeset
87 }
anatofuz
parents:
diff changeset
88
anatofuz
parents:
diff changeset
89 llvm::Error storeShard(llvm::StringRef ShardIdentifier,
anatofuz
parents:
diff changeset
90 IndexFileOut Shard) const override {
anatofuz
parents:
diff changeset
91 vlog("Couldn't find project for {0}, indexing in-memory only",
anatofuz
parents:
diff changeset
92 ShardIdentifier);
anatofuz
parents:
diff changeset
93 return llvm::Error::success();
anatofuz
parents:
diff changeset
94 }
anatofuz
parents:
diff changeset
95 };
anatofuz
parents:
diff changeset
96
anatofuz
parents:
diff changeset
97 // Creates and owns IndexStorages for multiple CDBs.
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
98 // When a CDB root is found, shards are stored in $ROOT/.cache/clangd/index/.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
99 // When no root is found, the fallback path is ~/.cache/clangd/index/.
150
anatofuz
parents:
diff changeset
100 class DiskBackedIndexStorageManager {
anatofuz
parents:
diff changeset
101 public:
anatofuz
parents:
diff changeset
102 DiskBackedIndexStorageManager(
anatofuz
parents:
diff changeset
103 std::function<llvm::Optional<ProjectInfo>(PathRef)> GetProjectInfo)
anatofuz
parents:
diff changeset
104 : IndexStorageMapMu(std::make_unique<std::mutex>()),
anatofuz
parents:
diff changeset
105 GetProjectInfo(std::move(GetProjectInfo)) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
106 llvm::SmallString<128> FallbackDir;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
107 if (llvm::sys::path::cache_directory(FallbackDir))
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
108 llvm::sys::path::append(FallbackDir, "clangd", "index");
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
109 this->FallbackDir = FallbackDir.str().str();
150
anatofuz
parents:
diff changeset
110 }
anatofuz
parents:
diff changeset
111
anatofuz
parents:
diff changeset
112 // Creates or fetches to storage from cache for the specified project.
anatofuz
parents:
diff changeset
113 BackgroundIndexStorage *operator()(PathRef File) {
anatofuz
parents:
diff changeset
114 std::lock_guard<std::mutex> Lock(*IndexStorageMapMu);
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
115 llvm::SmallString<128> StorageDir(FallbackDir);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
116 if (auto PI = GetProjectInfo(File)) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
117 StorageDir = PI->SourceRoot;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
118 llvm::sys::path::append(StorageDir, ".cache", "clangd", "index");
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
119 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
120 auto &IndexStorage = IndexStorageMap[StorageDir];
150
anatofuz
parents:
diff changeset
121 if (!IndexStorage)
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
122 IndexStorage = create(StorageDir);
150
anatofuz
parents:
diff changeset
123 return IndexStorage.get();
anatofuz
parents:
diff changeset
124 }
anatofuz
parents:
diff changeset
125
anatofuz
parents:
diff changeset
126 private:
anatofuz
parents:
diff changeset
127 std::unique_ptr<BackgroundIndexStorage> create(PathRef CDBDirectory) {
anatofuz
parents:
diff changeset
128 if (CDBDirectory.empty()) {
anatofuz
parents:
diff changeset
129 elog("Tried to create storage for empty directory!");
anatofuz
parents:
diff changeset
130 return std::make_unique<NullStorage>();
anatofuz
parents:
diff changeset
131 }
anatofuz
parents:
diff changeset
132 return std::make_unique<DiskBackedIndexStorage>(CDBDirectory);
anatofuz
parents:
diff changeset
133 }
anatofuz
parents:
diff changeset
134
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
135 Path FallbackDir;
150
anatofuz
parents:
diff changeset
136
anatofuz
parents:
diff changeset
137 llvm::StringMap<std::unique_ptr<BackgroundIndexStorage>> IndexStorageMap;
anatofuz
parents:
diff changeset
138 std::unique_ptr<std::mutex> IndexStorageMapMu;
anatofuz
parents:
diff changeset
139
anatofuz
parents:
diff changeset
140 std::function<llvm::Optional<ProjectInfo>(PathRef)> GetProjectInfo;
anatofuz
parents:
diff changeset
141 };
anatofuz
parents:
diff changeset
142
anatofuz
parents:
diff changeset
143 } // namespace
anatofuz
parents:
diff changeset
144
anatofuz
parents:
diff changeset
145 BackgroundIndexStorage::Factory
anatofuz
parents:
diff changeset
146 BackgroundIndexStorage::createDiskBackedStorageFactory(
anatofuz
parents:
diff changeset
147 std::function<llvm::Optional<ProjectInfo>(PathRef)> GetProjectInfo) {
anatofuz
parents:
diff changeset
148 return DiskBackedIndexStorageManager(std::move(GetProjectInfo));
anatofuz
parents:
diff changeset
149 }
anatofuz
parents:
diff changeset
150
anatofuz
parents:
diff changeset
151 } // namespace clangd
anatofuz
parents:
diff changeset
152 } // namespace clang