kbobyrev created this revision.
kbobyrev added a reviewer: kadircet.
Herald added subscribers: cfe-commits, usaxena95, arphaman, jkorous.
Herald added a project: clang.
kbobyrev requested review of this revision.
Herald added subscribers: MaskRay, ilya-biryukov.

This patch adds a mechanism to load new versions of index into
clangd-index-server using SwapIndex and FileStatus information about last
modification time without downtime.


Repository:
  rG LLVM Github Monorepo

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
@@ -14,13 +14,18 @@
 #include "support/Logger.h"
 #include "support/Trace.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 <chrono>
 #include <grpc++/grpc++.h>
 #include <grpc++/health_check_service_interface.h>
+#include <memory>
+#include <thread>
 
 #include "Index.grpc.pb.h"
 
@@ -69,8 +74,7 @@
 
 class RemoteIndexServer final : public SymbolIndex::Service {
 public:
-  RemoteIndexServer(std::unique_ptr<clangd::SymbolIndex> Index,
-                    llvm::StringRef IndexRoot)
+  RemoteIndexServer(clangd::SwapIndex *Index, llvm::StringRef IndexRoot)
       : Index(std::move(Index)) {
     llvm::SmallString<256> NativePath = IndexRoot;
     llvm::sys::path::native(NativePath);
@@ -79,6 +83,8 @@
         /*LocalIndexRoot=*/""));
   }
 
+  clangd::SwapIndex *Index;
+
 private:
   grpc::Status Lookup(grpc::ServerContext *Context,
                       const LookupRequest *Request,
@@ -210,21 +216,52 @@
     return grpc::Status::OK;
   }
 
-  std::unique_ptr<clangd::SymbolIndex> Index;
   std::unique_ptr<Marshaller> ProtobufMarshaller;
 };
 
-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::sys::TimePoint<> LastModificationTime =
+      std::chrono::system_clock::now();
+  for (;; std::this_thread::sleep_for(std::chrono::seconds(90))) {
+    llvm::sys::fs::file_status Status;
+    const auto EC = llvm::sys::fs::status(IndexPath, Status, /*Follow=*/true);
+    if (EC)
+      continue;
+    const auto NewModificationTime = Status.getLastModificationTime();
+    // Current index is newer than the one before: no reload is needed.
+    if (NewModificationTime <= LastModificationTime)
+      continue;
+    vlog("Found new index version: existing index was modified at {0}, new "
+         "index was modified at {1}. Attempting to reload.",
+         LastModificationTime, NewModificationTime);
+    std::unique_ptr<clang::clangd::SymbolIndex> NewIndex = openIndex(IndexPath);
+    if (!NewIndex) {
+      vlog("Failed to load new index. Old index will be served.");
+      continue;
+    }
+    (*Index)->reset(std::move(NewIndex));
+    log("New index version loaded. Last modification time: {0}.",
+        NewModificationTime);
+    LastModificationTime = NewModificationTime;
+  }
+}
+
+void runServer(std::unique_ptr<clangd::SwapIndex> Index,
+               llvm::StringRef ServerAddress, llvm::StringRef IndexPath) {
+  RemoteIndexServer Service(Index.get(), 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 HotReloadThread(hotReload, &Service.Index, IndexPath);
+
   Server->Wait();
 }
 
@@ -273,12 +310,13 @@
   if (Tracer)
     TracingSession.emplace(*Tracer);
 
-  std::unique_ptr<clang::clangd::SymbolIndex> Index = openIndex(IndexPath);
+  std::unique_ptr<clang::clangd::SwapIndex> Index(
+      new clang::clangd::SwapIndex(openIndex(IndexPath)));
 
   if (!Index) {
     llvm::errs() << "Failed to open the index.\n";
     return -1;
   }
 
-  runServer(std::move(Index), ServerAddress);
+  runServer(std::move(Index), ServerAddress, IndexPath);
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to