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"
31 llvm::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);
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);
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,
153 streamRPC(Request, &remote::v1::SymbolIndex::Stub::Relations,
155 [&](std::pair<SymbolID, clangd::Symbol> SubjectAndObject) {
156 Callback(SubjectAndObject.first, SubjectAndObject.second);
161 indexedFiles()
const override {
171 size_t estimateMemoryUsage()
const override {
return 0; }
174 std::unique_ptr<remote::v1::SymbolIndex::Stub> Stub;
175 std::shared_ptr<grpc::Channel> Channel;
176 llvm::SmallString<256> ServerAddress;
177 mutable std::atomic<grpc_connectivity_state> ConnectionStatus;
178 std::unique_ptr<Marshaller> ProtobufMarshaller;
180 std::chrono::milliseconds DeadlineWaitingTime;
185 std::unique_ptr<clangd::SymbolIndex>
getClient(llvm::StringRef Address,
186 llvm::StringRef ProjectRoot) {
188 grpc::CreateChannel(Address.str(), grpc::InsecureChannelCredentials());
189 return std::unique_ptr<clangd::SymbolIndex>(
190 new IndexClient(Channel, Address, ProjectRoot));