• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *
3  * Copyright 2015 gRPC authors.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 #include <atomic>
20 #include <thread>
21 
22 #include <grpc/grpc.h>
23 #include <grpc/support/alloc.h>
24 #include <grpcpp/security/server_credentials.h>
25 #include <grpcpp/server.h>
26 #include <grpcpp/server_context.h>
27 
28 #include "src/core/lib/gpr/host_port.h"
29 #include "src/proto/grpc/testing/benchmark_service.grpc.pb.h"
30 #include "test/cpp/qps/qps_server_builder.h"
31 #include "test/cpp/qps/server.h"
32 #include "test/cpp/qps/usage_timer.h"
33 
34 namespace grpc {
35 namespace testing {
36 
37 class BenchmarkServiceImpl final : public BenchmarkService::Service {
38  public:
UnaryCall(ServerContext * context,const SimpleRequest * request,SimpleResponse * response)39   Status UnaryCall(ServerContext* context, const SimpleRequest* request,
40                    SimpleResponse* response) override {
41     auto s = SetResponse(request, response);
42     if (!s.ok()) {
43       return s;
44     }
45     return Status::OK;
46   }
StreamingCall(ServerContext * context,ServerReaderWriter<SimpleResponse,SimpleRequest> * stream)47   Status StreamingCall(
48       ServerContext* context,
49       ServerReaderWriter<SimpleResponse, SimpleRequest>* stream) override {
50     SimpleRequest request;
51     while (stream->Read(&request)) {
52       SimpleResponse response;
53       auto s = SetResponse(&request, &response);
54       if (!s.ok()) {
55         return s;
56       }
57       if (!stream->Write(response)) {
58         return Status(StatusCode::INTERNAL, "Server couldn't respond");
59       }
60     }
61     return Status::OK;
62   }
StreamingFromClient(ServerContext * context,ServerReader<SimpleRequest> * stream,SimpleResponse * response)63   Status StreamingFromClient(ServerContext* context,
64                              ServerReader<SimpleRequest>* stream,
65                              SimpleResponse* response) override {
66     auto s = ClientPull(context, stream, response);
67     if (!s.ok()) {
68       return s;
69     }
70     return Status::OK;
71   }
StreamingFromServer(ServerContext * context,const SimpleRequest * request,ServerWriter<SimpleResponse> * stream)72   Status StreamingFromServer(ServerContext* context,
73                              const SimpleRequest* request,
74                              ServerWriter<SimpleResponse>* stream) override {
75     SimpleResponse response;
76     auto s = SetResponse(request, &response);
77     if (!s.ok()) {
78       return s;
79     }
80     return ServerPush(context, stream, response, nullptr);
81   }
StreamingBothWays(ServerContext * context,ServerReaderWriter<SimpleResponse,SimpleRequest> * stream)82   Status StreamingBothWays(
83       ServerContext* context,
84       ServerReaderWriter<SimpleResponse, SimpleRequest>* stream) override {
85     // Read the first client message to setup server response
86     SimpleRequest request;
87     if (!stream->Read(&request)) {
88       return Status::OK;
89     }
90     SimpleResponse response;
91     auto s = SetResponse(&request, &response);
92     if (!s.ok()) {
93       return s;
94     }
95     std::atomic_bool done;
96     Status sp;
97     std::thread t([context, stream, &response, &done, &sp]() {
98       sp = ServerPush(context, stream, response, [&done]() {
99         return done.load(std::memory_order_relaxed);
100       });
101     });
102     SimpleResponse dummy;
103     auto cp = ClientPull(context, stream, &dummy);
104     done.store(true, std::memory_order_relaxed);  // can be lazy
105     t.join();
106     if (!cp.ok()) {
107       return cp;
108     }
109     if (!sp.ok()) {
110       return sp;
111     }
112     return Status::OK;
113   }
114 
115  private:
116   template <class R>
ClientPull(ServerContext * context,R * stream,SimpleResponse * response)117   static Status ClientPull(ServerContext* context, R* stream,
118                            SimpleResponse* response) {
119     SimpleRequest request;
120     while (stream->Read(&request)) {
121     }
122     if (request.response_size() > 0) {
123       if (!Server::SetPayload(request.response_type(), request.response_size(),
124                               response->mutable_payload())) {
125         return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
126       }
127     }
128     return Status::OK;
129   }
130   template <class W>
ServerPush(ServerContext * context,W * stream,const SimpleResponse & response,const std::function<bool ()> & done)131   static Status ServerPush(ServerContext* context, W* stream,
132                            const SimpleResponse& response,
133                            const std::function<bool()>& done) {
134     while ((done == nullptr) || !done()) {
135       // TODO(vjpai): Add potential for rate-pacing on this
136       if (!stream->Write(response)) {
137         return Status(StatusCode::INTERNAL, "Server couldn't push");
138       }
139     }
140     return Status::OK;
141   }
SetResponse(const SimpleRequest * request,SimpleResponse * response)142   static Status SetResponse(const SimpleRequest* request,
143                             SimpleResponse* response) {
144     if (request->response_size() > 0) {
145       if (!Server::SetPayload(request->response_type(),
146                               request->response_size(),
147                               response->mutable_payload())) {
148         return Status(grpc::StatusCode::INTERNAL, "Error creating payload.");
149       }
150     }
151     return Status::OK;
152   }
153 };
154 
155 class SynchronousServer final : public grpc::testing::Server {
156  public:
SynchronousServer(const ServerConfig & config)157   explicit SynchronousServer(const ServerConfig& config) : Server(config) {
158     std::unique_ptr<ServerBuilder> builder = CreateQpsServerBuilder();
159 
160     auto port_num = port();
161     // Negative port number means inproc server, so no listen port needed
162     if (port_num >= 0) {
163       char* server_address = nullptr;
164       gpr_join_host_port(&server_address, "::", port_num);
165       builder->AddListeningPort(server_address,
166                                 Server::CreateServerCredentials(config));
167       gpr_free(server_address);
168     }
169 
170     ApplyConfigToBuilder(config, builder.get());
171 
172     builder->RegisterService(&service_);
173 
174     impl_ = builder->BuildAndStart();
175   }
176 
InProcessChannel(const ChannelArguments & args)177   std::shared_ptr<Channel> InProcessChannel(
178       const ChannelArguments& args) override {
179     return impl_->InProcessChannel(args);
180   }
181 
182  private:
183   BenchmarkServiceImpl service_;
184   std::unique_ptr<grpc::Server> impl_;
185 };
186 
CreateSynchronousServer(const ServerConfig & config)187 std::unique_ptr<grpc::testing::Server> CreateSynchronousServer(
188     const ServerConfig& config) {
189   return std::unique_ptr<Server>(new SynchronousServer(config));
190 }
191 
192 }  // namespace testing
193 }  // namespace grpc
194