kbobyrev updated this revision to Diff 291861.
kbobyrev marked 5 inline comments as done.
kbobyrev added a comment.

Address a round of comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D87450/new/

https://reviews.llvm.org/D87450

Files:
  clang-tools-extra/clangd/index/remote/server/Server.cpp

Index: clang-tools-extra/clangd/index/remote/server/Server.cpp
===================================================================
--- clang-tools-extra/clangd/index/remote/server/Server.cpp
+++ clang-tools-extra/clangd/index/remote/server/Server.cpp
@@ -12,15 +12,25 @@
 #include "index/Symbol.h"
 #include "index/remote/marshalling/Marshalling.h"
 #include "support/Logger.h"
+#include "support/Shutdown.h"
+#include "support/ThreadsafeFS.h"
 #include "support/Trace.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/ADT/None.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Chrono.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Error.h"
+#include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Signals.h"
+#include "llvm/Support/VirtualFileSystem.h"
 
+#include <chrono>
 #include <grpc++/grpc++.h>
 #include <grpc++/health_check_service_interface.h>
+#include <memory>
+#include <thread>
 
 #include "Index.grpc.pb.h"
 
@@ -63,15 +73,10 @@
     "server-address", llvm::cl::init("0.0.0.0:50051"),
     llvm::cl::desc("Address of the invoked server. Defaults to 0.0.0.0:50051"));
 
-std::unique_ptr<clangd::SymbolIndex> openIndex(llvm::StringRef Index) {
-  return loadIndex(Index, /*UseIndex=*/true);
-}
-
 class RemoteIndexServer final : public SymbolIndex::Service {
 public:
-  RemoteIndexServer(std::unique_ptr<clangd::SymbolIndex> Index,
-                    llvm::StringRef IndexRoot)
-      : Index(std::move(Index)) {
+  RemoteIndexServer(clangd::SymbolIndex &Index, llvm::StringRef IndexRoot)
+      : Index(Index) {
     llvm::SmallString<256> NativePath = IndexRoot;
     llvm::sys::path::native(NativePath);
     ProtobufMarshaller = std::unique_ptr<Marshaller>(new Marshaller(
@@ -91,7 +96,7 @@
     }
     unsigned Sent = 0;
     unsigned FailedToSend = 0;
-    Index->lookup(*Req, [&](const clangd::Symbol &Item) {
+    Index.lookup(*Req, [&](const clangd::Symbol &Item) {
       auto SerializedItem = ProtobufMarshaller->toProtobuf(Item);
       if (!SerializedItem) {
         elog("Unable to convert Symbol to protobuf: {0}",
@@ -124,7 +129,7 @@
     }
     unsigned Sent = 0;
     unsigned FailedToSend = 0;
-    bool HasMore = Index->fuzzyFind(*Req, [&](const clangd::Symbol &Item) {
+    bool HasMore = Index.fuzzyFind(*Req, [&](const clangd::Symbol &Item) {
       auto SerializedItem = ProtobufMarshaller->toProtobuf(Item);
       if (!SerializedItem) {
         elog("Unable to convert Symbol to protobuf: {0}",
@@ -155,7 +160,7 @@
     }
     unsigned Sent = 0;
     unsigned FailedToSend = 0;
-    bool HasMore = Index->refs(*Req, [&](const clangd::Ref &Item) {
+    bool HasMore = Index.refs(*Req, [&](const clangd::Ref &Item) {
       auto SerializedItem = ProtobufMarshaller->toProtobuf(Item);
       if (!SerializedItem) {
         elog("Unable to convert Ref to protobuf: {0}",
@@ -188,7 +193,7 @@
     }
     unsigned Sent = 0;
     unsigned FailedToSend = 0;
-    Index->relations(
+    Index.relations(
         *Req, [&](const SymbolID &Subject, const clangd::Symbol &Object) {
           auto SerializedItem = ProtobufMarshaller->toProtobuf(Subject, Object);
           if (!SerializedItem) {
@@ -210,22 +215,54 @@
     return grpc::Status::OK;
   }
 
-  std::unique_ptr<clangd::SymbolIndex> Index;
   std::unique_ptr<Marshaller> ProtobufMarshaller;
+  clangd::SymbolIndex &Index;
 };
 
-void runServer(std::unique_ptr<clangd::SymbolIndex> Index,
-               const std::string &ServerAddress) {
-  RemoteIndexServer Service(std::move(Index), IndexRoot);
+// Detect changes in \p IndexPath file and load new versions of the index
+// whenever they become available.
+void hotReload(clangd::SwapIndex &Index, llvm::StringRef IndexPath,
+               llvm::vfs::Status &LastStatus,
+               llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> &FS) {
+  auto Status = FS->status(IndexPath);
+  if (!Status || Status->equivalent(LastStatus))
+    return;
+  // Current index is different from the one before: no reload is needed.
+  vlog("Found different index version: existing index was modified at {0}, new "
+       "index was modified at {1}. Attempting to reload.",
+       LastStatus.getLastModificationTime(), Status->getLastModificationTime());
+  std::unique_ptr<clang::clangd::SymbolIndex> NewIndex = loadIndex(IndexPath);
+  if (!NewIndex) {
+    vlog("Failed to load new index. Old index will be served.");
+    return;
+  }
+  Index.reset(std::move(NewIndex));
+  log("New index version loaded. Last modification time: {0}.",
+      Status->getLastModificationTime());
+  LastStatus = *Status;
+}
+
+void runServerAndWait(clangd::SymbolIndex &Index, llvm::StringRef ServerAddress,
+                      llvm::StringRef IndexPath) {
+  RemoteIndexServer Service(Index, IndexRoot);
 
   grpc::EnableDefaultHealthCheckService(true);
   grpc::ServerBuilder Builder;
-  Builder.AddListeningPort(ServerAddress, grpc::InsecureServerCredentials());
+  Builder.AddListeningPort(ServerAddress.str(),
+                           grpc::InsecureServerCredentials());
   Builder.RegisterService(&Service);
   std::unique_ptr<grpc::Server> Server(Builder.BuildAndStart());
   log("Server listening on {0}", ServerAddress);
 
+  std::thread ServerShutdownWatcher([&]() {
+    static constexpr auto WatcherFrequency = std::chrono::seconds(5);
+    while (!clang::clangd::shutdownRequested())
+      std::this_thread::sleep_for(WatcherFrequency);
+    Server->Shutdown();
+  });
+
   Server->Wait();
+  ServerShutdownWatcher.join();
 }
 
 } // namespace
@@ -239,6 +276,7 @@
   using namespace clang::clangd::remote;
   llvm::cl::ParseCommandLineOptions(argc, argv, Overview);
   llvm::sys::PrintStackTraceOnErrorSignal(argv[0]);
+  llvm::sys::SetInterruptFunction(&clang::clangd::requestShutdown);
 
   if (!llvm::sys::path::is_absolute(IndexRoot)) {
     llvm::errs() << "Index root should be an absolute path.\n";
@@ -273,12 +311,32 @@
   if (Tracer)
     TracingSession.emplace(*Tracer);
 
-  std::unique_ptr<clang::clangd::SymbolIndex> Index = openIndex(IndexPath);
+  clang::clangd::RealThreadsafeFS TFS;
+  auto FS = TFS.view(llvm::None);
+  auto Status = FS->status(IndexPath);
+  if (!Status) {
+    elog("File {0} does not exist.", IndexPath);
+    return Status.getError().value();
+  }
+
+  auto Index = std::make_unique<clang::clangd::SwapIndex>(
+      clang::clangd::loadIndex(IndexPath));
 
   if (!Index) {
     llvm::errs() << "Failed to open the index.\n";
     return -1;
   }
 
-  runServer(std::move(Index), ServerAddress);
+  std::thread HotReloadThread([&Index, &Status, &FS]() {
+    llvm::vfs::Status LastStatus = *Status;
+    static constexpr auto RefreshFrequency = std::chrono::seconds(90);
+    while (!clang::clangd::shutdownRequested()) {
+      std::this_thread::sleep_for(RefreshFrequency);
+      hotReload(*Index, llvm::StringRef(IndexPath), LastStatus, FS);
+    }
+  });
+
+  runServerAndWait(*Index, ServerAddress, IndexPath);
+
+  HotReloadThread.join();
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to