Mercurial > hg > CbC > CbC_llvm
view 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 |
line wrap: on
line source
//== BackgroundIndexStorage.cpp - Provide caching support to BackgroundIndex ==/ // // 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 "GlobalCompilationDatabase.h" #include "index/Background.h" #include "support/Logger.h" #include "support/Path.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/ScopeExit.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/FileUtilities.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include <functional> namespace clang { namespace clangd { namespace { std::string getShardPathFromFilePath(llvm::StringRef ShardRoot, llvm::StringRef FilePath) { llvm::SmallString<128> ShardRootSS(ShardRoot); llvm::sys::path::append(ShardRootSS, llvm::sys::path::filename(FilePath) + "." + llvm::toHex(digest(FilePath)) + ".idx"); return std::string(ShardRootSS.str()); } // Uses disk as a storage for index shards. class DiskBackedIndexStorage : public BackgroundIndexStorage { std::string DiskShardRoot; public: // Creates `DiskShardRoot` and any parents during construction. DiskBackedIndexStorage(llvm::StringRef Directory) : DiskShardRoot(Directory) { std::error_code OK; std::error_code EC = llvm::sys::fs::create_directories(DiskShardRoot); if (EC != OK) { elog("Failed to create directory {0} for index storage: {1}", DiskShardRoot, EC.message()); } } std::unique_ptr<IndexFileIn> loadShard(llvm::StringRef ShardIdentifier) const override { const std::string ShardPath = getShardPathFromFilePath(DiskShardRoot, ShardIdentifier); auto Buffer = llvm::MemoryBuffer::getFile(ShardPath); if (!Buffer) return nullptr; if (auto I = readIndexFile(Buffer->get()->getBuffer())) return std::make_unique<IndexFileIn>(std::move(*I)); else elog("Error while reading shard {0}: {1}", ShardIdentifier, I.takeError()); return nullptr; } llvm::Error storeShard(llvm::StringRef ShardIdentifier, IndexFileOut Shard) const override { auto ShardPath = getShardPathFromFilePath(DiskShardRoot, ShardIdentifier); return llvm::writeFileAtomically(ShardPath + ".tmp.%%%%%%%%", ShardPath, [&Shard](llvm::raw_ostream &OS) { OS << Shard; return llvm::Error::success(); }); } }; // Doesn't persist index shards anywhere (used when the CDB dir is unknown). // We could consider indexing into ~/.clangd/ or so instead. class NullStorage : public BackgroundIndexStorage { public: std::unique_ptr<IndexFileIn> loadShard(llvm::StringRef ShardIdentifier) const override { return nullptr; } llvm::Error storeShard(llvm::StringRef ShardIdentifier, IndexFileOut Shard) const override { vlog("Couldn't find project for {0}, indexing in-memory only", ShardIdentifier); return llvm::Error::success(); } }; // Creates and owns IndexStorages for multiple CDBs. // When a CDB root is found, shards are stored in $ROOT/.cache/clangd/index/. // When no root is found, the fallback path is ~/.cache/clangd/index/. class DiskBackedIndexStorageManager { public: DiskBackedIndexStorageManager( std::function<llvm::Optional<ProjectInfo>(PathRef)> GetProjectInfo) : IndexStorageMapMu(std::make_unique<std::mutex>()), GetProjectInfo(std::move(GetProjectInfo)) { llvm::SmallString<128> FallbackDir; if (llvm::sys::path::cache_directory(FallbackDir)) llvm::sys::path::append(FallbackDir, "clangd", "index"); this->FallbackDir = FallbackDir.str().str(); } // Creates or fetches to storage from cache for the specified project. BackgroundIndexStorage *operator()(PathRef File) { std::lock_guard<std::mutex> Lock(*IndexStorageMapMu); llvm::SmallString<128> StorageDir(FallbackDir); if (auto PI = GetProjectInfo(File)) { StorageDir = PI->SourceRoot; llvm::sys::path::append(StorageDir, ".cache", "clangd", "index"); } auto &IndexStorage = IndexStorageMap[StorageDir]; if (!IndexStorage) IndexStorage = create(StorageDir); return IndexStorage.get(); } private: std::unique_ptr<BackgroundIndexStorage> create(PathRef CDBDirectory) { if (CDBDirectory.empty()) { elog("Tried to create storage for empty directory!"); return std::make_unique<NullStorage>(); } return std::make_unique<DiskBackedIndexStorage>(CDBDirectory); } Path FallbackDir; llvm::StringMap<std::unique_ptr<BackgroundIndexStorage>> IndexStorageMap; std::unique_ptr<std::mutex> IndexStorageMapMu; std::function<llvm::Optional<ProjectInfo>(PathRef)> GetProjectInfo; }; } // namespace BackgroundIndexStorage::Factory BackgroundIndexStorage::createDiskBackedStorageFactory( std::function<llvm::Optional<ProjectInfo>(PathRef)> GetProjectInfo) { return DiskBackedIndexStorageManager(std::move(GetProjectInfo)); } } // namespace clangd } // namespace clang