1 //===--- GlobalCompilationDatabase.cpp ---------------------------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "GlobalCompilationDatabase.h"
10 #include "Config.h"
11 #include "FS.h"
12 #include "SourceCode.h"
13 #include "support/Logger.h"
14 #include "support/Path.h"
15 #include "support/Threading.h"
16 #include "support/ThreadsafeFS.h"
17 #include "clang/Frontend/CompilerInvocation.h"
18 #include "clang/Tooling/ArgumentsAdjusters.h"
19 #include "clang/Tooling/CompilationDatabase.h"
20 #include "clang/Tooling/CompilationDatabasePluginRegistry.h"
21 #include "clang/Tooling/JSONCompilationDatabase.h"
22 #include "llvm/ADT/None.h"
23 #include "llvm/ADT/Optional.h"
24 #include "llvm/ADT/PointerIntPair.h"
25 #include "llvm/ADT/STLExtras.h"
26 #include "llvm/ADT/ScopeExit.h"
27 #include "llvm/ADT/SmallString.h"
28 #include "llvm/ADT/StringMap.h"
29 #include "llvm/Support/FileSystem.h"
30 #include "llvm/Support/FileUtilities.h"
31 #include "llvm/Support/Path.h"
32 #include "llvm/Support/Program.h"
33 #include "llvm/Support/VirtualFileSystem.h"
34 #include <atomic>
35 #include <chrono>
36 #include <condition_variable>
37 #include <mutex>
38 #include <string>
39 #include <tuple>
40 #include <vector>
41 
42 namespace clang {
43 namespace clangd {
44 namespace {
45 
46 // Variant of parent_path that operates only on absolute paths.
47 PathRef absoluteParent(PathRef Path) {
48   assert(llvm::sys::path::is_absolute(Path));
49 #if defined(_WIN32)
50   // llvm::sys says "C:\" is absolute, and its parent is "C:" which is relative.
51   // This unhelpful behavior seems to have been inherited from boost.
52   if (llvm::sys::path::relative_path(Path).empty()) {
53     return PathRef();
54   }
55 #endif
56   PathRef Result = llvm::sys::path::parent_path(Path);
57   assert(Result.empty() || llvm::sys::path::is_absolute(Result));
58   return Result;
59 }
60 
61 // Runs the given action on all parent directories of filename, starting from
62 // deepest directory and going up to root. Stops whenever action succeeds.
63 void actOnAllParentDirectories(PathRef FileName,
64                                llvm::function_ref<bool(PathRef)> Action) {
65   for (auto Path = absoluteParent(FileName); !Path.empty() && !Action(Path);
66        Path = absoluteParent(Path))
67     ;
68 }
69 
70 } // namespace
71 
72 tooling::CompileCommand
73 GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
74   std::vector<std::string> Argv = {"clang"};
75   // Clang treats .h files as C by default and files without extension as linker
76   // input, resulting in unhelpful diagnostics.
77   // Parsing as Objective C++ is friendly to more cases.
78   auto FileExtension = llvm::sys::path::extension(File);
79   if (FileExtension.empty() || FileExtension == ".h")
80     Argv.push_back("-xobjective-c++-header");
81   Argv.push_back(std::string(File));
82   tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
83                               llvm::sys::path::filename(File), std::move(Argv),
84                               /*Output=*/"");
85   Cmd.Heuristic = "clangd fallback";
86   return Cmd;
87 }
88 
89 // Loads and caches the CDB from a single directory.
90 //
91 // This class is threadsafe, which is to say we have independent locks for each
92 // directory we're searching for a CDB.
93 // Loading is deferred until first access.
94 //
95 // The DirectoryBasedCDB keeps a map from path => DirectoryCache.
96 // Typical usage is to:
97 //  - 1) determine all the paths that might be searched
98 //  - 2) acquire the map lock and get-or-create all the DirectoryCache entries
99 //  - 3) release the map lock and query the caches as desired
100 class DirectoryBasedGlobalCompilationDatabase::DirectoryCache {
101   using stopwatch = std::chrono::steady_clock;
102 
103   // CachedFile is used to read a CDB file on disk (e.g. compile_commands.json).
104   // It specializes in being able to quickly bail out if the file is unchanged,
105   // which is the common case.
106   // Internally, it stores file metadata so a stat() can verify it's unchanged.
107   // We don't actually cache the content as it's not needed - if the file is
108   // unchanged then the previous CDB is valid.
109   struct CachedFile {
110     CachedFile(llvm::StringRef Parent, llvm::StringRef Rel) {
111       llvm::SmallString<256> Path = Parent;
112       llvm::sys::path::append(Path, Rel);
113       this->Path = Path.str().str();
114     }
115     std::string Path;
116     size_t Size = NoFileCached;
117     llvm::sys::TimePoint<> ModifiedTime;
118     FileDigest ContentHash;
119 
120     static constexpr size_t NoFileCached = -1;
121 
122     struct LoadResult {
123       enum {
124         FileNotFound,
125         TransientError,
126         FoundSameData,
127         FoundNewData,
128       } Result;
129       std::unique_ptr<llvm::MemoryBuffer> Buffer; // Set only if FoundNewData
130     };
131 
132     LoadResult load(llvm::vfs::FileSystem &FS, bool HasOldData);
133   };
134 
135   // If we've looked for a CDB here and found none, the time when that happened.
136   // (Atomics make it possible for get() to return without taking a lock)
137   std::atomic<stopwatch::rep> NoCDBAt = {
138       stopwatch::time_point::min().time_since_epoch().count()};
139 
140   // Guards the following cache state.
141   std::mutex Mu;
142   // When was the cache last known to be in sync with disk state?
143   stopwatch::time_point CachePopulatedAt = stopwatch::time_point::min();
144   // Whether a new CDB has been loaded but not broadcast yet.
145   bool NeedsBroadcast = false;
146   // Last loaded CDB, meaningful if CachePopulatedAt was ever set.
147   // shared_ptr so we can overwrite this when callers are still using the CDB.
148   std::shared_ptr<tooling::CompilationDatabase> CDB;
149   // File metadata for the CDB files we support tracking directly.
150   CachedFile CompileCommandsJson;
151   CachedFile BuildCompileCommandsJson;
152   CachedFile CompileFlagsTxt;
153   // CachedFile member corresponding to CDB.
154   //   CDB  | ACF  | Scenario
155   //   null | null | no CDB found, or initial empty cache
156   //   set  | null | CDB was loaded via generic plugin interface
157   //   null | set  | found known CDB file, but parsing it failed
158   //   set  | set  | CDB was parsed from a known file
159   CachedFile *ActiveCachedFile = nullptr;
160 
161 public:
162   DirectoryCache(llvm::StringRef Path)
163       : CompileCommandsJson(Path, "compile_commands.json"),
164         BuildCompileCommandsJson(Path, "build/compile_commands.json"),
165         CompileFlagsTxt(Path, "compile_flags.txt"), Path(Path) {
166     assert(llvm::sys::path::is_absolute(Path));
167   }
168 
169   // Absolute canonical path that we're the cache for. (Not case-folded).
170   const std::string Path;
171 
172   // Get the CDB associated with this directory.
173   // ShouldBroadcast:
174   //  - as input, signals whether the caller is willing to broadcast a
175   //    newly-discovered CDB. (e.g. to trigger background indexing)
176   //  - as output, signals whether the caller should do so.
177   // (If a new CDB is discovered and ShouldBroadcast is false, we mark the
178   // CDB as needing broadcast, and broadcast it next time we can).
179   std::shared_ptr<const tooling::CompilationDatabase>
180   get(const ThreadsafeFS &TFS, bool &ShouldBroadcast,
181       stopwatch::time_point FreshTime, stopwatch::time_point FreshTimeMissing) {
182     // Fast path for common case without taking lock.
183     if (stopwatch::time_point(stopwatch::duration(NoCDBAt.load())) >
184         FreshTimeMissing) {
185       ShouldBroadcast = false;
186       return nullptr;
187     }
188 
189     std::lock_guard<std::mutex> Lock(Mu);
190     auto RequestBroadcast = llvm::make_scope_exit([&, OldCDB(CDB.get())] {
191       // If we loaded a new CDB, it should be broadcast at some point.
192       if (CDB != nullptr && CDB.get() != OldCDB)
193         NeedsBroadcast = true;
194       else if (CDB == nullptr) // nothing to broadcast anymore!
195         NeedsBroadcast = false;
196       // If we have something to broadcast, then do so iff allowed.
197       if (!ShouldBroadcast)
198         return;
199       ShouldBroadcast = NeedsBroadcast;
200       NeedsBroadcast = false;
201     });
202 
203     // If our cache is valid, serve from it.
204     if (CachePopulatedAt > FreshTime)
205       return CDB;
206 
207     if (/*MayCache=*/load(*TFS.view(/*CWD=*/llvm::None))) {
208       // Use new timestamp, as loading may be slow.
209       CachePopulatedAt = stopwatch::now();
210       NoCDBAt.store((CDB ? stopwatch::time_point::min() : CachePopulatedAt)
211                         .time_since_epoch()
212                         .count());
213     }
214 
215     return CDB;
216   }
217 
218 private:
219   // Updates `CDB` from disk state. Returns false on failure.
220   bool load(llvm::vfs::FileSystem &FS);
221 };
222 
223 DirectoryBasedGlobalCompilationDatabase::DirectoryCache::CachedFile::LoadResult
224 DirectoryBasedGlobalCompilationDatabase::DirectoryCache::CachedFile::load(
225     llvm::vfs::FileSystem &FS, bool HasOldData) {
226   auto Stat = FS.status(Path);
227   if (!Stat || !Stat->isRegularFile()) {
228     Size = NoFileCached;
229     ContentHash = {};
230     return {LoadResult::FileNotFound, nullptr};
231   }
232   // If both the size and mtime match, presume unchanged without reading.
233   if (HasOldData && Stat->getLastModificationTime() == ModifiedTime &&
234       Stat->getSize() == Size)
235     return {LoadResult::FoundSameData, nullptr};
236   auto Buf = FS.getBufferForFile(Path);
237   if (!Buf || (*Buf)->getBufferSize() != Stat->getSize()) {
238     // Don't clear the cache - possible we're seeing inconsistent size as the
239     // file is being recreated. If it ends up identical later, great!
240     //
241     // This isn't a complete solution: if we see a partial file but stat/read
242     // agree on its size, we're ultimately going to have spurious CDB reloads.
243     // May be worth fixing if generators don't write atomically (CMake does).
244     elog("Failed to read {0}: {1}", Path,
245          Buf ? "size changed" : Buf.getError().message());
246     return {LoadResult::TransientError, nullptr};
247   }
248 
249   FileDigest NewContentHash = digest((*Buf)->getBuffer());
250   if (HasOldData && NewContentHash == ContentHash) {
251     // mtime changed but data is the same: avoid rebuilding the CDB.
252     ModifiedTime = Stat->getLastModificationTime();
253     return {LoadResult::FoundSameData, nullptr};
254   }
255 
256   Size = (*Buf)->getBufferSize();
257   ModifiedTime = Stat->getLastModificationTime();
258   ContentHash = NewContentHash;
259   return {LoadResult::FoundNewData, std::move(*Buf)};
260 }
261 
262 // Adapt CDB-loading functions to a common interface for DirectoryCache::load().
263 static std::unique_ptr<tooling::CompilationDatabase>
264 parseJSON(PathRef Path, llvm::StringRef Data, std::string &Error) {
265   if (auto CDB = tooling::JSONCompilationDatabase::loadFromBuffer(
266           Data, Error, tooling::JSONCommandLineSyntax::AutoDetect)) {
267     // FS used for expanding response files.
268     // FIXME: ExpandResponseFilesDatabase appears not to provide the usual
269     // thread-safety guarantees, as the access to FS is not locked!
270     // For now, use the real FS, which is known to be threadsafe (if we don't
271     // use/change working directory, which ExpandResponseFilesDatabase doesn't).
272     auto FS = llvm::vfs::getRealFileSystem();
273     return tooling::inferTargetAndDriverMode(
274         tooling::inferMissingCompileCommands(
275             expandResponseFiles(std::move(CDB), std::move(FS))));
276   }
277   return nullptr;
278 }
279 static std::unique_ptr<tooling::CompilationDatabase>
280 parseFixed(PathRef Path, llvm::StringRef Data, std::string &Error) {
281   return tooling::FixedCompilationDatabase::loadFromBuffer(
282       llvm::sys::path::parent_path(Path), Data, Error);
283 }
284 
285 bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load(
286     llvm::vfs::FileSystem &FS) {
287   dlog("Probing directory {0}", Path);
288   std::string Error;
289 
290   // Load from the specially-supported compilation databases (JSON + Fixed).
291   // For these, we know the files they read and cache their metadata so we can
292   // cheaply validate whether they've changed, and hot-reload if they have.
293   // (As a bonus, these are also VFS-clean)!
294   struct CDBFile {
295     CachedFile *File;
296     // Wrapper for {Fixed,JSON}CompilationDatabase::loadFromBuffer.
297     llvm::function_ref<std::unique_ptr<tooling::CompilationDatabase>(
298         PathRef,
299         /*Data*/ llvm::StringRef,
300         /*ErrorMsg*/ std::string &)>
301         Parser;
302   };
303   for (const auto &Entry : {CDBFile{&CompileCommandsJson, parseJSON},
304                             CDBFile{&BuildCompileCommandsJson, parseJSON},
305                             CDBFile{&CompileFlagsTxt, parseFixed}}) {
306     bool Active = ActiveCachedFile == Entry.File;
307     auto Loaded = Entry.File->load(FS, Active);
308     switch (Loaded.Result) {
309     case CachedFile::LoadResult::FileNotFound:
310       if (Active) {
311         log("Unloaded compilation database from {0}", Entry.File->Path);
312         ActiveCachedFile = nullptr;
313         CDB = nullptr;
314       }
315       // Continue looking at other candidates.
316       break;
317     case CachedFile::LoadResult::TransientError:
318       // File existed but we couldn't read it. Reuse the cache, retry later.
319       return false; // Load again next time.
320     case CachedFile::LoadResult::FoundSameData:
321       assert(Active && "CachedFile may not return 'same data' if !HasOldData");
322       // This is the critical file, and it hasn't changed.
323       return true;
324     case CachedFile::LoadResult::FoundNewData:
325       // We have a new CDB!
326       CDB = Entry.Parser(Entry.File->Path, Loaded.Buffer->getBuffer(), Error);
327       if (CDB)
328         log("{0} compilation database from {1}", Active ? "Reloaded" : "Loaded",
329             Entry.File->Path);
330       else
331         elog("Failed to load compilation database from {0}: {1}",
332              Entry.File->Path, Error);
333       ActiveCachedFile = Entry.File;
334       return true;
335     }
336   }
337 
338   // Fall back to generic handling of compilation databases.
339   // We don't know what files they read, so can't efficiently check whether
340   // they need to be reloaded. So we never do that.
341   // FIXME: the interface doesn't provide a way to virtualize FS access.
342 
343   // Don't try these more than once. If we've scanned before, we're done.
344   if (CachePopulatedAt > stopwatch::time_point::min())
345     return true;
346   for (const auto &Entry :
347        tooling::CompilationDatabasePluginRegistry::entries()) {
348     // Avoid duplicating the special cases handled above.
349     if (Entry.getName() == "fixed-compilation-database" ||
350         Entry.getName() == "json-compilation-database")
351       continue;
352     auto Plugin = Entry.instantiate();
353     if (auto CDB = Plugin->loadFromDirectory(Path, Error)) {
354       log("Loaded compilation database from {0} with plugin {1}", Path,
355           Entry.getName());
356       this->CDB = std::move(CDB);
357       return true;
358     }
359     // Don't log Error here, it's usually just "couldn't find <file>".
360   }
361   dlog("No compilation database at {0}", Path);
362   return true;
363 }
364 
365 DirectoryBasedGlobalCompilationDatabase::
366     DirectoryBasedGlobalCompilationDatabase(const Options &Opts)
367     : Opts(Opts), Broadcaster(std::make_unique<BroadcastThread>(*this)) {
368   if (!this->Opts.ContextProvider)
369     this->Opts.ContextProvider = [](llvm::StringRef) {
370       return Context::current().clone();
371     };
372 }
373 
374 DirectoryBasedGlobalCompilationDatabase::
375     ~DirectoryBasedGlobalCompilationDatabase() = default;
376 
377 llvm::Optional<tooling::CompileCommand>
378 DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const {
379   CDBLookupRequest Req;
380   Req.FileName = File;
381   Req.ShouldBroadcast = true;
382   auto Now = std::chrono::steady_clock::now();
383   Req.FreshTime = Now - Opts.RevalidateAfter;
384   Req.FreshTimeMissing = Now - Opts.RevalidateMissingAfter;
385 
386   auto Res = lookupCDB(Req);
387   if (!Res) {
388     log("Failed to find compilation database for {0}", File);
389     return llvm::None;
390   }
391 
392   auto Candidates = Res->CDB->getCompileCommands(File);
393   if (!Candidates.empty())
394     return std::move(Candidates.front());
395 
396   return None;
397 }
398 
399 std::vector<DirectoryBasedGlobalCompilationDatabase::DirectoryCache *>
400 DirectoryBasedGlobalCompilationDatabase::getDirectoryCaches(
401     llvm::ArrayRef<llvm::StringRef> Dirs) const {
402   std::vector<std::string> FoldedDirs;
403   FoldedDirs.reserve(Dirs.size());
404   for (const auto &Dir : Dirs) {
405 #ifndef NDEBUG
406     if (!llvm::sys::path::is_absolute(Dir))
407       elog("Trying to cache CDB for relative {0}");
408 #endif
409     FoldedDirs.push_back(maybeCaseFoldPath(Dir));
410   }
411 
412   std::vector<DirectoryCache *> Ret;
413   Ret.reserve(Dirs.size());
414 
415   std::lock_guard<std::mutex> Lock(DirCachesMutex);
416   for (unsigned I = 0; I < Dirs.size(); ++I)
417     Ret.push_back(&DirCaches.try_emplace(FoldedDirs[I], Dirs[I]).first->second);
418   return Ret;
419 }
420 
421 llvm::Optional<DirectoryBasedGlobalCompilationDatabase::CDBLookupResult>
422 DirectoryBasedGlobalCompilationDatabase::lookupCDB(
423     CDBLookupRequest Request) const {
424   assert(llvm::sys::path::is_absolute(Request.FileName) &&
425          "path must be absolute");
426 
427   std::string Storage;
428   std::vector<llvm::StringRef> SearchDirs;
429   if (Opts.CompileCommandsDir) // FIXME: unify this case with config.
430     SearchDirs = {Opts.CompileCommandsDir.getValue()};
431   else {
432     WithContext WithProvidedContext(Opts.ContextProvider(Request.FileName));
433     const auto &Spec = Config::current().CompileFlags.CDBSearch;
434     switch (Spec.Policy) {
435     case Config::CDBSearchSpec::NoCDBSearch:
436       return llvm::None;
437     case Config::CDBSearchSpec::FixedDir:
438       Storage = Spec.FixedCDBPath.getValue();
439       SearchDirs = {Storage};
440       break;
441     case Config::CDBSearchSpec::Ancestors:
442       // Traverse the canonical version to prevent false positives. i.e.:
443       // src/build/../a.cc can detect a CDB in /src/build if not
444       // canonicalized.
445       Storage = removeDots(Request.FileName);
446       actOnAllParentDirectories(Storage, [&](llvm::StringRef Dir) {
447         SearchDirs.push_back(Dir);
448         return false;
449       });
450     }
451   }
452 
453   std::shared_ptr<const tooling::CompilationDatabase> CDB = nullptr;
454   bool ShouldBroadcast = false;
455   DirectoryCache *DirCache = nullptr;
456   for (DirectoryCache *Candidate : getDirectoryCaches(SearchDirs)) {
457     bool CandidateShouldBroadcast = Request.ShouldBroadcast;
458     if ((CDB = Candidate->get(Opts.TFS, CandidateShouldBroadcast,
459                               Request.FreshTime, Request.FreshTimeMissing))) {
460       DirCache = Candidate;
461       ShouldBroadcast = CandidateShouldBroadcast;
462       break;
463     }
464   }
465 
466   if (!CDB)
467     return llvm::None;
468 
469   CDBLookupResult Result;
470   Result.CDB = std::move(CDB);
471   Result.PI.SourceRoot = DirCache->Path;
472 
473   if (ShouldBroadcast)
474     broadcastCDB(Result);
475   return Result;
476 }
477 
478 // The broadcast thread announces files with new compile commands to the world.
479 // Primarily this is used to enqueue them for background indexing.
480 //
481 // It's on a separate thread because:
482 //  - otherwise it would block the first parse of the initial file
483 //  - we need to enumerate all files in the CDB, of which there are many
484 //  - we (will) have to evaluate config for every file in the CDB, which is slow
485 class DirectoryBasedGlobalCompilationDatabase::BroadcastThread {
486   class Filter;
487   DirectoryBasedGlobalCompilationDatabase &Parent;
488 
489   std::mutex Mu;
490   std::condition_variable CV;
491   // Shutdown flag (CV is notified after writing).
492   // This is atomic so that broadcasts can also observe it and abort early.
493   std::atomic<bool> ShouldStop = {false};
494   struct Task {
495     CDBLookupResult Lookup;
496     Context Ctx;
497   };
498   std::deque<Task> Queue;
499   llvm::Optional<Task> ActiveTask;
500   std::thread Thread; // Must be last member.
501 
502   // Thread body: this is just the basic queue procesing boilerplate.
503   void run() {
504     std::unique_lock<std::mutex> Lock(Mu);
505     while (true) {
506       bool Stopping = false;
507       CV.wait(Lock, [&] {
508         return (Stopping = ShouldStop.load(std::memory_order_acquire)) ||
509                !Queue.empty();
510       });
511       if (Stopping) {
512         Queue.clear();
513         CV.notify_all();
514         return;
515       }
516       ActiveTask = std::move(Queue.front());
517       Queue.pop_front();
518 
519       Lock.unlock();
520       {
521         WithContext WithCtx(std::move(ActiveTask->Ctx));
522         process(ActiveTask->Lookup);
523       }
524       Lock.lock();
525       ActiveTask.reset();
526       CV.notify_all();
527     }
528   }
529 
530   // Inspects a new CDB and broadcasts the files it owns.
531   void process(const CDBLookupResult &T);
532 
533 public:
534   BroadcastThread(DirectoryBasedGlobalCompilationDatabase &Parent)
535       : Parent(Parent), Thread([this] { run(); }) {}
536 
537   void enqueue(CDBLookupResult Lookup) {
538     {
539       assert(!Lookup.PI.SourceRoot.empty());
540       std::lock_guard<std::mutex> Lock(Mu);
541       // New CDB takes precedence over any queued one for the same directory.
542       llvm::erase_if(Queue, [&](const Task &T) {
543         return T.Lookup.PI.SourceRoot == Lookup.PI.SourceRoot;
544       });
545       Queue.push_back({std::move(Lookup), Context::current().clone()});
546     }
547     CV.notify_all();
548   }
549 
550   bool blockUntilIdle(Deadline Timeout) {
551     std::unique_lock<std::mutex> Lock(Mu);
552     return wait(Lock, CV, Timeout,
553                 [&] { return Queue.empty() && !ActiveTask.hasValue(); });
554   }
555 
556   ~BroadcastThread() {
557     {
558       std::lock_guard<std::mutex> Lock(Mu);
559       ShouldStop.store(true, std::memory_order_release);
560     }
561     CV.notify_all();
562     Thread.join();
563   }
564 };
565 
566 // The DirBasedCDB associates each file with a specific CDB.
567 // When a CDB is discovered, it may claim to describe files that we associate
568 // with a different CDB. We do not want to broadcast discovery of these, and
569 // trigger background indexing of them.
570 //
571 // We must filter the list, and check whether they are associated with this CDB.
572 // This class attempts to do so efficiently.
573 //
574 // Roughly, it:
575 //  - loads the config for each file, and determines the relevant search path
576 //  - gathers all directories that are part of any search path
577 //  - (lazily) checks for a CDB in each such directory at most once
578 //  - walks the search path for each file and determines whether to include it.
579 class DirectoryBasedGlobalCompilationDatabase::BroadcastThread::Filter {
580   llvm::StringRef ThisDir;
581   DirectoryBasedGlobalCompilationDatabase &Parent;
582 
583   // Keep track of all directories we might check for CDBs.
584   struct DirInfo {
585     DirectoryCache *Cache = nullptr;
586     enum { Unknown, Missing, TargetCDB, OtherCDB } State = Unknown;
587     DirInfo *Parent = nullptr;
588   };
589   llvm::StringMap<DirInfo> Dirs;
590 
591   // A search path starts at a directory, and either includes ancestors or not.
592   using SearchPath = llvm::PointerIntPair<DirInfo *, 1>;
593 
594   // Add all ancestor directories of FilePath to the tracked set.
595   // Returns the immediate parent of the file.
596   DirInfo *addParents(llvm::StringRef FilePath) {
597     DirInfo *Leaf = nullptr;
598     DirInfo *Child = nullptr;
599     actOnAllParentDirectories(FilePath, [&](llvm::StringRef Dir) {
600       auto &Info = Dirs[Dir];
601       // If this is the first iteration, then this node is the overall result.
602       if (!Leaf)
603         Leaf = &Info;
604       // Fill in the parent link from the previous iteration to this parent.
605       if (Child)
606         Child->Parent = &Info;
607       // Keep walking, whether we inserted or not, if parent link is missing.
608       // (If it's present, parent links must be present up to the root, so stop)
609       Child = &Info;
610       return Info.Parent != nullptr;
611     });
612     return Leaf;
613   }
614 
615   // Populates DirInfo::Cache (and State, if it is TargetCDB).
616   void grabCaches() {
617     // Fast path out if there were no files, or CDB loading is off.
618     if (Dirs.empty())
619       return;
620 
621     std::vector<llvm::StringRef> DirKeys;
622     std::vector<DirInfo *> DirValues;
623     DirKeys.reserve(Dirs.size() + 1);
624     DirValues.reserve(Dirs.size());
625     for (auto &E : Dirs) {
626       DirKeys.push_back(E.first());
627       DirValues.push_back(&E.second);
628     }
629 
630     // Also look up the cache entry for the CDB we're broadcasting.
631     // Comparing DirectoryCache pointers is more robust than checking string
632     // equality, e.g. reuses the case-sensitivity handling.
633     DirKeys.push_back(ThisDir);
634     auto DirCaches = Parent.getDirectoryCaches(DirKeys);
635     const DirectoryCache *ThisCache = DirCaches.back();
636     DirCaches.pop_back();
637     DirKeys.pop_back();
638 
639     for (unsigned I = 0; I < DirKeys.size(); ++I) {
640       DirValues[I]->Cache = DirCaches[I];
641       if (DirCaches[I] == ThisCache)
642         DirValues[I]->State = DirInfo::TargetCDB;
643     }
644   }
645 
646   // Should we include a file from this search path?
647   bool shouldInclude(SearchPath P) {
648     DirInfo *Info = P.getPointer();
649     if (!Info)
650       return false;
651     if (Info->State == DirInfo::Unknown) {
652       assert(Info->Cache && "grabCaches() should have filled this");
653       // Given that we know that CDBs have been moved/generated, don't trust
654       // caches. (This should be rare, so it's OK to add a little latency).
655       constexpr auto IgnoreCache = std::chrono::steady_clock::time_point::max();
656       // Don't broadcast CDBs discovered while broadcasting!
657       bool ShouldBroadcast = false;
658       bool Exists =
659           nullptr != Info->Cache->get(Parent.Opts.TFS, ShouldBroadcast,
660                                       /*FreshTime=*/IgnoreCache,
661                                       /*FreshTimeMissing=*/IgnoreCache);
662       Info->State = Exists ? DirInfo::OtherCDB : DirInfo::Missing;
663     }
664     // If we have a CDB, include the file if it's the target CDB only.
665     if (Info->State != DirInfo::Missing)
666       return Info->State == DirInfo::TargetCDB;
667     // If we have no CDB and no relevant parent, don't include the file.
668     if (!P.getInt() || !Info->Parent)
669       return false;
670     // Walk up to the next parent.
671     return shouldInclude(SearchPath(Info->Parent, 1));
672   }
673 
674 public:
675   Filter(llvm::StringRef ThisDir,
676          DirectoryBasedGlobalCompilationDatabase &Parent)
677       : ThisDir(ThisDir), Parent(Parent) {}
678 
679   std::vector<std::string> filter(std::vector<std::string> AllFiles,
680                                   std::atomic<bool> &ShouldStop) {
681     std::vector<std::string> Filtered;
682     // Allow for clean early-exit of the slow parts.
683     auto ExitEarly = [&] {
684       if (ShouldStop.load(std::memory_order_acquire)) {
685         log("Giving up on broadcasting CDB, as we're shutting down");
686         Filtered.clear();
687         return true;
688       }
689       return false;
690     };
691     // Compute search path for each file.
692     std::vector<SearchPath> SearchPaths(AllFiles.size());
693     for (unsigned I = 0; I < AllFiles.size(); ++I) {
694       if (Parent.Opts.CompileCommandsDir) { // FIXME: unify with config
695         SearchPaths[I].setPointer(
696             &Dirs[Parent.Opts.CompileCommandsDir.getValue()]);
697         continue;
698       }
699       if (ExitEarly()) // loading config may be slow
700         return Filtered;
701       WithContext WithProvidedContent(Parent.Opts.ContextProvider(AllFiles[I]));
702       const Config::CDBSearchSpec &Spec =
703           Config::current().CompileFlags.CDBSearch;
704       switch (Spec.Policy) {
705       case Config::CDBSearchSpec::NoCDBSearch:
706         break;
707       case Config::CDBSearchSpec::Ancestors:
708         SearchPaths[I].setInt(/*Recursive=*/1);
709         SearchPaths[I].setPointer(addParents(AllFiles[I]));
710         break;
711       case Config::CDBSearchSpec::FixedDir:
712         SearchPaths[I].setPointer(&Dirs[Spec.FixedCDBPath.getValue()]);
713         break;
714       }
715     }
716     // Get the CDB cache for each dir on the search path, but don't load yet.
717     grabCaches();
718     // Now work out which files we want to keep, loading CDBs where needed.
719     for (unsigned I = 0; I < AllFiles.size(); ++I) {
720       if (ExitEarly()) // loading CDBs may be slow
721         return Filtered;
722       if (shouldInclude(SearchPaths[I]))
723         Filtered.push_back(std::move(AllFiles[I]));
724     }
725     return Filtered;
726   }
727 };
728 
729 void DirectoryBasedGlobalCompilationDatabase::BroadcastThread::process(
730     const CDBLookupResult &T) {
731   vlog("Broadcasting compilation database from {0}", T.PI.SourceRoot);
732   std::vector<std::string> GovernedFiles =
733       Filter(T.PI.SourceRoot, Parent).filter(T.CDB->getAllFiles(), ShouldStop);
734   if (!GovernedFiles.empty())
735     Parent.OnCommandChanged.broadcast(std::move(GovernedFiles));
736 }
737 
738 void DirectoryBasedGlobalCompilationDatabase::broadcastCDB(
739     CDBLookupResult Result) const {
740   assert(Result.CDB && "Trying to broadcast an invalid CDB!");
741   Broadcaster->enqueue(Result);
742 }
743 
744 bool DirectoryBasedGlobalCompilationDatabase::blockUntilIdle(
745     Deadline Timeout) const {
746   return Broadcaster->blockUntilIdle(Timeout);
747 }
748 
749 llvm::Optional<ProjectInfo>
750 DirectoryBasedGlobalCompilationDatabase::getProjectInfo(PathRef File) const {
751   CDBLookupRequest Req;
752   Req.FileName = File;
753   Req.ShouldBroadcast = false;
754   Req.FreshTime = Req.FreshTimeMissing =
755       std::chrono::steady_clock::time_point::min();
756   auto Res = lookupCDB(Req);
757   if (!Res)
758     return llvm::None;
759   return Res->PI;
760 }
761 
762 OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base,
763                        std::vector<std::string> FallbackFlags,
764                        tooling::ArgumentsAdjuster Adjuster)
765     : DelegatingCDB(Base), ArgsAdjuster(std::move(Adjuster)),
766       FallbackFlags(std::move(FallbackFlags)) {}
767 
768 llvm::Optional<tooling::CompileCommand>
769 OverlayCDB::getCompileCommand(PathRef File) const {
770   llvm::Optional<tooling::CompileCommand> Cmd;
771   {
772     std::lock_guard<std::mutex> Lock(Mutex);
773     auto It = Commands.find(removeDots(File));
774     if (It != Commands.end())
775       Cmd = It->second;
776   }
777   if (!Cmd)
778     Cmd = DelegatingCDB::getCompileCommand(File);
779   if (!Cmd)
780     return llvm::None;
781   if (ArgsAdjuster)
782     Cmd->CommandLine = ArgsAdjuster(Cmd->CommandLine, Cmd->Filename);
783   return Cmd;
784 }
785 
786 tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
787   auto Cmd = DelegatingCDB::getFallbackCommand(File);
788   std::lock_guard<std::mutex> Lock(Mutex);
789   Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
790                          FallbackFlags.end());
791   if (ArgsAdjuster)
792     Cmd.CommandLine = ArgsAdjuster(Cmd.CommandLine, Cmd.Filename);
793   return Cmd;
794 }
795 
796 void OverlayCDB::setCompileCommand(
797     PathRef File, llvm::Optional<tooling::CompileCommand> Cmd) {
798   // We store a canonical version internally to prevent mismatches between set
799   // and get compile commands. Also it assures clients listening to broadcasts
800   // doesn't receive different names for the same file.
801   std::string CanonPath = removeDots(File);
802   {
803     std::unique_lock<std::mutex> Lock(Mutex);
804     if (Cmd)
805       Commands[CanonPath] = std::move(*Cmd);
806     else
807       Commands.erase(CanonPath);
808   }
809   OnCommandChanged.broadcast({CanonPath});
810 }
811 
812 DelegatingCDB::DelegatingCDB(const GlobalCompilationDatabase *Base)
813     : Base(Base) {
814   if (Base)
815     BaseChanged = Base->watch([this](const std::vector<std::string> Changes) {
816       OnCommandChanged.broadcast(Changes);
817     });
818 }
819 
820 DelegatingCDB::DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base)
821     : DelegatingCDB(Base.get()) {
822   BaseOwner = std::move(Base);
823 }
824 
825 llvm::Optional<tooling::CompileCommand>
826 DelegatingCDB::getCompileCommand(PathRef File) const {
827   if (!Base)
828     return llvm::None;
829   return Base->getCompileCommand(File);
830 }
831 
832 llvm::Optional<ProjectInfo> DelegatingCDB::getProjectInfo(PathRef File) const {
833   if (!Base)
834     return llvm::None;
835   return Base->getProjectInfo(File);
836 }
837 
838 tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
839   if (!Base)
840     return GlobalCompilationDatabase::getFallbackCommand(File);
841   return Base->getFallbackCommand(File);
842 }
843 
844 bool DelegatingCDB::blockUntilIdle(Deadline D) const {
845   if (!Base)
846     return true;
847   return Base->blockUntilIdle(D);
848 }
849 
850 } // namespace clangd
851 } // namespace clang
852