9#include <grpc++/grpc++.h>
13#include "Service.grpc.pb.h"
18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/Support/Error.h"
31llvm::StringRef
toString(
const grpc_connectivity_state &State) {
33 case GRPC_CHANNEL_IDLE:
35 case GRPC_CHANNEL_CONNECTING:
37 case GRPC_CHANNEL_READY:
39 case GRPC_CHANNEL_TRANSIENT_FAILURE:
40 return "transient failure";
41 case GRPC_CHANNEL_SHUTDOWN:
44 llvm_unreachable(
"Not a valid grpc_connectivity_state.");
48 void updateConnectionStatus()
const {
49 auto NewStatus = Channel->GetState(
false);
50 auto OldStatus = ConnectionStatus.exchange(NewStatus);
51 if (OldStatus != NewStatus)
52 vlog(
"Remote index connection [{0}]: {1} => {2}", ServerAddress,
56 template <
typename RequestT,
typename ReplyT>
57 using StreamingCall = std::unique_ptr<grpc::ClientReader<ReplyT>> (
58 remote::v1::SymbolIndex::Stub::*)(grpc::ClientContext *,
61 template <
typename RequestT,
typename ReplyT,
typename ClangdRequestT,
63 bool streamRPC(ClangdRequestT Request,
64 StreamingCall<RequestT, ReplyT> RPCCall,
66 updateConnectionStatus();
72 const auto RPCRequest = ProtobufMarshaller->toProtobuf(Request);
73 SPAN_ATTACH(Tracer,
"Request", RPCRequest.DebugString());
78 std::chrono::system_clock::time_point StartTime =
79 std::chrono::system_clock::now();
80 auto Deadline = StartTime + DeadlineWaitingTime;
82 auto Reader = (Stub.get()->*RPCCall)(&
Context, RPCRequest);
83 dlog(
"Sending {0}: {1}", RequestT::descriptor()->name(),
84 RPCRequest.DebugString());
86 unsigned Successful = 0;
87 unsigned FailedToParse = 0;
88 while (Reader->Read(&Reply)) {
89 if (!Reply.has_stream_result()) {
90 HasMore = Reply.final_result().has_more();
93 auto Response = ProtobufMarshaller->fromProtobuf(Reply.stream_result());
95 elog(
"Received invalid {0}: {1}. Reason: {2}",
96 ReplyT::descriptor()->name(), Reply.stream_result().DebugString(),
97 Response.takeError());
104 auto Millis = std::chrono::duration_cast<std::chrono::milliseconds>(
105 std::chrono::system_clock::now() - StartTime)
107 vlog(
"Remote index [{0}]: {1} => {2} results in {3}ms.", ServerAddress,
108 RequestT::descriptor()->name(), Successful, Millis);
109 SPAN_ATTACH(Tracer,
"Status", Reader->Finish().ok());
111 SPAN_ATTACH(Tracer,
"Failed to parse", FailedToParse);
112 updateConnectionStatus();
118 std::shared_ptr<grpc::Channel> Channel, llvm::StringRef Address,
119 llvm::StringRef ProjectRoot,
120 std::chrono::milliseconds DeadlineTime = std::chrono::milliseconds(1000))
121 : Stub(remote::v1::SymbolIndex::NewStub(Channel)), Channel(Channel),
122 ServerAddress(Address),
123 ConnectionStatus(Channel->GetState(
true)),
126 DeadlineWaitingTime(DeadlineTime) {
127 assert(!ProjectRoot.empty());
133 streamRPC(Request, &remote::v1::SymbolIndex::Stub::Lookup,
Callback);
139 return streamRPC(Request, &remote::v1::SymbolIndex::Stub::FuzzyFind,
146 return streamRPC(Request, &remote::v1::SymbolIndex::Stub::Refs,
Callback);
152 return streamRPC(Request, &remote::v1::SymbolIndex::Stub::ContainedRefs,
160 streamRPC(Request, &remote::v1::SymbolIndex::Stub::Relations,
162 [&](std::pair<SymbolID, clangd::Symbol> SubjectAndObject) {
163 Callback(SubjectAndObject.first, SubjectAndObject.second);
168 indexedFiles()
const override {
178 size_t estimateMemoryUsage()
const override {
return 0; }
181 std::unique_ptr<remote::v1::SymbolIndex::Stub> Stub;
182 std::shared_ptr<grpc::Channel> Channel;
183 llvm::SmallString<256> ServerAddress;
184 mutable std::atomic<grpc_connectivity_state> ConnectionStatus;
185 std::unique_ptr<Marshaller> ProtobufMarshaller;
187 std::chrono::milliseconds DeadlineWaitingTime;
192std::unique_ptr<clangd::SymbolIndex>
getClient(llvm::StringRef Address,
193 llvm::StringRef ProjectRoot) {
195 grpc::CreateChannel(Address.str(), grpc::InsecureChannelCredentials());
196 return std::unique_ptr<clangd::SymbolIndex>(
197 new IndexClient(Channel, Address, ProjectRoot));
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
A context is an immutable container for per-request data that must be propagated through layers that ...
A point in time we can wait for.
Interface for symbol indexes that can be used for searching or matching symbols among a set of symbol...
A notable exception is URI translation.
Records an event whose duration is the lifetime of the Span object.
std::unique_ptr< clangd::SymbolIndex > getClient(llvm::StringRef Address, llvm::StringRef ProjectRoot)
Returns an SymbolIndex client that passes requests to remote index located at Address.
IndexContents
Describes what data is covered by an index.
void vlog(const char *Fmt, Ts &&... Vals)
static const char * toString(OffsetEncoding OE)
std::string platformString()
std::string featureString()
llvm::unique_function< void(llvm::Expected< T >)> Callback
A Callback<T> is a void function that accepts Expected<T>.
std::vector< std::string > lookup(const SymbolIndex &I, llvm::ArrayRef< SymbolID > IDs)
void elog(const char *Fmt, Ts &&... Vals)
std::string versionString()
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Represents a symbol occurrence in the source file.
The class presents a C++ symbol, e.g.