diff --git a/clang-tools-extra/clangd/index/Index.h b/clang-tools-extra/clangd/index/Index.h --- a/clang-tools-extra/clangd/index/Index.h +++ b/clang-tools-extra/clangd/index/Index.h @@ -123,6 +123,13 @@ /// Returns estimated size of index (in bytes). virtual size_t estimateMemoryUsage() const = 0; + + enum class Kind : uint8_t { + Unknown = 0, + Remote, + }; + + Kind Kind = Kind::Unknown; }; // Delegating implementation of SymbolIndex whose delegate can be swapped out. diff --git a/clang-tools-extra/clangd/index/remote/Client.h b/clang-tools-extra/clangd/index/remote/Client.h --- a/clang-tools-extra/clangd/index/remote/Client.h +++ b/clang-tools-extra/clangd/index/remote/Client.h @@ -29,6 +29,12 @@ std::unique_ptr getClient(llvm::StringRef Address, llvm::StringRef IndexRoot); +/// Sends data to the server and compares it against response. +/// +/// \returns true if Index is an instance of IndexClient and response matches +/// sent data. +bool handshake(const clangd::SymbolIndex *Index); + } // namespace remote } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/index/remote/Client.cpp b/clang-tools-extra/clangd/index/remote/Client.cpp --- a/clang-tools-extra/clangd/index/remote/Client.cpp +++ b/clang-tools-extra/clangd/index/remote/Client.cpp @@ -14,11 +14,14 @@ #include "marshalling/Marshalling.h" #include "support/Logger.h" #include "support/Trace.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/Version.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include +#include +#include namespace clang { namespace clangd { @@ -80,6 +83,36 @@ /*LocalIndexRoot=*/ProjectRoot)), DeadlineWaitingTime(DeadlineTime) { assert(!ProjectRoot.empty()); + this->Kind = Kind::Remote; + } + + // Returns true if received checksum matches given one. + bool handshake(uint32_t Checksum) const { + trace::Span Tracer(HandshakeRequest::descriptor()->name()); + HandshakeRequest RPCRequest; + RPCRequest.set_checksum(Checksum); + SPAN_ATTACH(Tracer, "Request", RPCRequest.DebugString()); + grpc::ClientContext Context; + Context.AddMetadata("version", clang::getClangToolFullVersion("clangd")); + const std::chrono::system_clock::time_point StartTime = + std::chrono::system_clock::now(); + const auto Deadline = StartTime + DeadlineWaitingTime; + Context.set_deadline(Deadline); + vlog("Sending RPC Request {0}: {1}", HandshakeRequest::descriptor()->name(), + RPCRequest.DebugString()); + HandshakeReply Reply; + const grpc::Status Status = + Stub.get()->Handshake(&Context, RPCRequest, &Reply); + assert(Checksum == Reply.checksum() && "Received checksum should match."); + const auto Millis = std::chrono::duration_cast( + std::chrono::system_clock::now() - StartTime) + .count(); + const std::string ChecksumMatches = + Checksum == Reply.checksum() ? "OK" : "CHECKSUM MISMATCH"; + vlog("RPC {0} => {1}: {2}ms", HandshakeRequest::descriptor()->name(), + ChecksumMatches, Reply.checksum(), Millis); + SPAN_ATTACH(Tracer, "Status", Status.ok()); + return Checksum == Reply.checksum(); } void lookup(const clangd::LookupRequest &Request, @@ -134,6 +167,25 @@ new IndexClient(Channel, ProjectRoot)); } +bool handshake(const clangd::SymbolIndex *Index) { + const auto *Client = dyn_cast_or_null(Index); + if (!Client) + return false; + const uint32_t Checksum = 42; + return Client->handshake(Checksum); +} + } // namespace remote } // namespace clangd } // namespace clang + +namespace llvm { +template <> +struct llvm::isa_impl { + static inline bool doit(const clang::clangd::SymbolIndex &Idx) { + return Idx.Kind == clang::clangd::SymbolIndex::Kind::Remote; + } +}; + +} // namespace llvm diff --git a/clang-tools-extra/clangd/index/remote/Index.proto b/clang-tools-extra/clangd/index/remote/Index.proto --- a/clang-tools-extra/clangd/index/remote/Index.proto +++ b/clang-tools-extra/clangd/index/remote/Index.proto @@ -10,6 +10,14 @@ package clang.clangd.remote; +message HandshakeRequest { + required uint32 checksum = 1; +} + +message HandshakeReply { + required uint32 checksum = 1; +} + // Common final result for streaming requests. message FinalResult { optional bool has_more = 1; } diff --git a/clang-tools-extra/clangd/index/remote/Service.proto b/clang-tools-extra/clangd/index/remote/Service.proto --- a/clang-tools-extra/clangd/index/remote/Service.proto +++ b/clang-tools-extra/clangd/index/remote/Service.proto @@ -15,6 +15,8 @@ // Semantics of SymbolIndex match clangd::SymbolIndex with all required // structures corresponding to their clangd::* counterparts. service SymbolIndex { + rpc Handshake(HandshakeRequest) returns (HandshakeReply) {} + rpc Lookup(LookupRequest) returns (stream LookupReply) {} rpc FuzzyFind(FuzzyFindRequest) returns (stream FuzzyFindReply) {} diff --git a/clang-tools-extra/clangd/index/remote/server/Server.cpp b/clang-tools-extra/clangd/index/remote/server/Server.cpp --- a/clang-tools-extra/clangd/index/remote/server/Server.cpp +++ b/clang-tools-extra/clangd/index/remote/server/Server.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -96,6 +97,18 @@ private: using stopwatch = std::chrono::steady_clock; + grpc::Status Handshake(grpc::ServerContext *Context, + const remote::HandshakeRequest *Request, + HandshakeReply *Reply) override { + WithContextValue WithRequestContext(CurrentRequest, Context); + logRequest(*Request); + trace::Span Tracer("LookupRequest"); + Reply->set_checksum(Request->checksum()); + logResponse(*Reply); + SPAN_ATTACH(Tracer, "Checksum", Reply->checksum()); + return grpc::Status::OK; + } + grpc::Status Lookup(grpc::ServerContext *Context, const LookupRequest *Request, grpc::ServerWriter *Reply) override { diff --git a/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp b/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp --- a/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp +++ b/clang-tools-extra/clangd/index/remote/unimplemented/UnimplementedClient.cpp @@ -20,6 +20,11 @@ return nullptr; } +bool handshake(const clangd::SymbolIndex *Index) { + elog("Can't perform a handshake without Remote Index support."); + return false; +} + } // namespace remote } // namespace clangd } // namespace clang diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp --- a/clang-tools-extra/clangd/tool/ClangdMain.cpp +++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp @@ -815,6 +815,10 @@ Opts.CodeComplete.RankingModel = RankingModel; Opts.CodeComplete.DecisionForestBase = DecisionForestBase; +#if CLANGD_ENABLE_REMOTE + // clang::clangd::remote::handshake(Opts.StaticIndex); +#endif + RealThreadsafeFS TFS; std::vector> ProviderStack; std::unique_ptr Config;