pull/9205/head
yang-g 8 years ago
parent 50993b7a4c
commit 8e708b12cb
  1. 1
      include/grpc++/server.h
  2. 79
      src/cpp/server/server_cc.cc
  3. 126
      test/cpp/end2end/health_service_end2end_test.cc

@ -121,6 +121,7 @@ class Server final : public ServerInterface, private GrpcLibraryCodegen {
class HealthCheckAsyncRequestContext; class HealthCheckAsyncRequestContext;
class HealthCheckAsyncRequest; class HealthCheckAsyncRequest;
class HealthCheckAsyncResponse;
/// Server constructors. To be used by \a ServerBuilder only. /// Server constructors. To be used by \a ServerBuilder only.
/// ///

@ -119,11 +119,24 @@ class Server::UnimplementedAsyncResponse final
UnimplementedAsyncRequest* const request_; UnimplementedAsyncRequest* const request_;
}; };
class HealthCheckAsyncResponseWriter final
: public ServerAsyncStreamingInterface {
public:
HealthCheckAsyncResponseWriter() : call_(nullptr, nullptr, nullptr) {}
void SendInitialMetadata(void* tag) override {
abort(); // should not be called.
}
void BindCall(Call* call) override { call_ = *call; }
Call* call() { return &call_; }
private:
Call call_;
};
class Server::HealthCheckAsyncRequestContext { class Server::HealthCheckAsyncRequestContext {
protected: protected:
HealthCheckAsyncRequestContext() : rpc_(&server_context_) {}
ServerContext server_context_; ServerContext server_context_;
ServerAsyncResponseWriter<ByteBuffer> rpc_; HealthCheckAsyncResponseWriter rpc_;
}; };
class Server::HealthCheckAsyncRequest final class Server::HealthCheckAsyncRequest final
@ -137,26 +150,46 @@ class Server::HealthCheckAsyncRequest final
false), false),
service_(service), service_(service),
server_(server), server_(server),
cq_(cq), cq_(cq) {
had_request_(false) {
IssueRequest(service->method()->server_tag(), &payload_, cq); IssueRequest(service->method()->server_tag(), &payload_, cq);
} }
bool FinalizeResult(void** tag, bool* status) override; bool FinalizeResult(void** tag, bool* status) override;
Call* call() { return rpc_.call(); }
ByteBuffer* response() { return &response_; }
Status* status() { return &status_; }
ServerContext* server_context() { return &server_context_; }
private: private:
DefaultHealthCheckService::AsyncHealthCheckServiceImpl* service_; DefaultHealthCheckService::AsyncHealthCheckServiceImpl* service_;
Server* const server_; Server* const server_;
ServerCompletionQueue* const cq_; ServerCompletionQueue* const cq_;
grpc_byte_buffer* payload_; grpc_byte_buffer* payload_;
bool had_request_;
ByteBuffer request_; ByteBuffer request_;
ByteBuffer response_; ByteBuffer response_;
Status status_;
};
typedef SneakyCallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus>
HealthCheckAsyncResponseOp;
class Server::HealthCheckAsyncResponse final
: public HealthCheckAsyncResponseOp {
public:
HealthCheckAsyncResponse(HealthCheckAsyncRequest* request);
~HealthCheckAsyncResponse() { delete request_; }
bool FinalizeResult(void** tag, bool* status) override {
HealthCheckAsyncResponseOp::FinalizeResult(tag, status);
delete this;
return false;
}
private:
HealthCheckAsyncRequest* const request_;
}; };
bool Server::HealthCheckAsyncRequest::FinalizeResult(void** tag, bool* status) { bool Server::HealthCheckAsyncRequest::FinalizeResult(void** tag, bool* status) {
if (!had_request_) {
had_request_ = true;
bool serialization_status = bool serialization_status =
*status && payload_ && *status && payload_ &&
SerializationTraits<ByteBuffer>::Deserialize( SerializationTraits<ByteBuffer>::Deserialize(
@ -166,18 +199,35 @@ bool Server::HealthCheckAsyncRequest::FinalizeResult(void** tag, bool* status) {
*status = serialization_status && *status; *status = serialization_status && *status;
if (*status) { if (*status) {
new HealthCheckAsyncRequest(service_, server_, cq_); new HealthCheckAsyncRequest(service_, server_, cq_);
Status s = service_->Check(&server_context_, &request_, &response_); status_ = service_->Check(&server_context_, &request_, &response_);
rpc_.Finish(response_, s, this); new HealthCheckAsyncResponse(this);
return false; return false;
} else { } else {
// TODO what to do here
delete this; delete this;
return false; return false;
} }
}
Server::HealthCheckAsyncResponse::HealthCheckAsyncResponse(
HealthCheckAsyncRequest* request)
: request_(request) {
ServerContext* context = request_->server_context();
if (!context->sent_initial_metadata_) {
SendInitialMetadata(context->initial_metadata_,
context->initial_metadata_flags());
if (context->compression_level_set()) {
set_compression_level(context->compression_level());
}
context->sent_initial_metadata_ = true;
}
Status* status = request_->status();
if (status->ok()) {
ServerSendStatus(context->trailing_metadata_,
SendMessage(*request_->response()));
} else { } else {
delete this; ServerSendStatus(context->trailing_metadata_, *status);
return false;
} }
request_->call()->PerformOps(this);
} }
class ShutdownTag : public CompletionQueueTag { class ShutdownTag : public CompletionQueueTag {
@ -567,9 +617,10 @@ bool Server::Start(ServerCompletionQueue** cqs, size_t num_cqs) {
auto* default_hc_service = new DefaultHealthCheckService; auto* default_hc_service = new DefaultHealthCheckService;
health_check_service_.reset(default_hc_service); health_check_service_.reset(default_hc_service);
if (!sync_server_cqs_->empty()) { // Has sync methods. if (!sync_server_cqs_->empty()) { // Has sync methods.
gpr_log(GPR_ERROR, "register sync"); // XXX
RegisterService(nullptr, default_hc_service->GetSyncHealthCheckService()); RegisterService(nullptr, default_hc_service->GetSyncHealthCheckService());
} } else {
if (sync_server_cqs_->empty()) { // No sync methods. gpr_log(GPR_ERROR, "register async"); // XXX
async_health_service = default_hc_service->GetAsyncHealthCheckService(); async_health_service = default_hc_service->GetAsyncHealthCheckService();
RegisterService(nullptr, async_health_service); RegisterService(nullptr, async_health_service);
} }

@ -242,69 +242,69 @@ TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceDisabled) {
SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, "")); SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, ""));
} }
TEST_F(HealthServiceEnd2endTest, DefaultHealthService) { // TEST_F(HealthServiceEnd2endTest, DefaultHealthService) {
EnableDefaultHealthCheckService(true); // EnableDefaultHealthCheckService(true);
EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); // EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
SetUpServer(true, false, nullptr); // SetUpServer(true, false, nullptr);
VerifyHealthCheckService(); // VerifyHealthCheckService();
//
// The default service has a size limit of the service name. // // The default service has a size limit of the service name.
const grpc::string kTooLongServiceName(201, 'x'); // const grpc::string kTooLongServiceName(201, 'x');
SendHealthCheckRpc(kTooLongServiceName, // SendHealthCheckRpc(kTooLongServiceName,
Status(StatusCode::INVALID_ARGUMENT, "")); // Status(StatusCode::INVALID_ARGUMENT, ""));
} // }
//
void LoopCompletionQueue(ServerCompletionQueue* cq) { // void LoopCompletionQueue(ServerCompletionQueue* cq) {
void* tag; // void* tag;
bool ok; // bool ok;
while (cq->Next(&tag, &ok)) { // while (cq->Next(&tag, &ok)) {
gpr_log(GPR_ERROR, "next %p %d", tag, ok); // abort(); // Nothing should come out of the cq.
} // }
gpr_log(GPR_ERROR, "returning from thread"); // gpr_log(GPR_ERROR, "returning from thread");
} // }
//
TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceAsync) { // TEST_F(HealthServiceEnd2endTest, DefaultHealthServiceAsync) {
EnableDefaultHealthCheckService(true); // EnableDefaultHealthCheckService(true);
EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); // EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
SetUpServer(false, false, nullptr); // SetUpServer(false, false, nullptr);
cq_thread_ = std::thread(LoopCompletionQueue, cq_.get()); // cq_thread_ = std::thread(LoopCompletionQueue, cq_.get());
VerifyHealthCheckService(); // VerifyHealthCheckService();
//
// The default service has a size limit of the service name. // // The default service has a size limit of the service name.
const grpc::string kTooLongServiceName(201, 'x'); // const grpc::string kTooLongServiceName(201, 'x');
SendHealthCheckRpc(kTooLongServiceName, // SendHealthCheckRpc(kTooLongServiceName,
Status(StatusCode::INVALID_ARGUMENT, "")); // Status(StatusCode::INVALID_ARGUMENT, ""));
} // }
//
// Provide an empty service to disable the default service. // // Provide an empty service to disable the default service.
TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) { // TEST_F(HealthServiceEnd2endTest, ExplicitlyDisableViaOverride) {
EnableDefaultHealthCheckService(true); // EnableDefaultHealthCheckService(true);
EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); // EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
std::unique_ptr<HealthCheckServiceInterface> empty_service; // std::unique_ptr<HealthCheckServiceInterface> empty_service;
SetUpServer(true, true, std::move(empty_service)); // SetUpServer(true, true, std::move(empty_service));
HealthCheckServiceInterface* service = server_->GetHealthCheckService(); // HealthCheckServiceInterface* service = server_->GetHealthCheckService();
EXPECT_TRUE(service == nullptr); // EXPECT_TRUE(service == nullptr);
//
ResetStubs(); // ResetStubs();
//
SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, "")); // SendHealthCheckRpc("", Status(StatusCode::UNIMPLEMENTED, ""));
} // }
//
// Provide an explicit override of health checking service interface. // // Provide an explicit override of health checking service interface.
TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) { // TEST_F(HealthServiceEnd2endTest, ExplicitlyOverride) {
EnableDefaultHealthCheckService(true); // EnableDefaultHealthCheckService(true);
EXPECT_TRUE(DefaultHealthCheckServiceEnabled()); // EXPECT_TRUE(DefaultHealthCheckServiceEnabled());
std::unique_ptr<HealthCheckServiceInterface> override_service( // std::unique_ptr<HealthCheckServiceInterface> override_service(
new CustomHealthCheckService(&health_check_service_impl_)); // new CustomHealthCheckService(&health_check_service_impl_));
HealthCheckServiceInterface* underlying_service = override_service.get(); // HealthCheckServiceInterface* underlying_service = override_service.get();
SetUpServer(false, true, std::move(override_service)); // SetUpServer(false, true, std::move(override_service));
HealthCheckServiceInterface* service = server_->GetHealthCheckService(); // HealthCheckServiceInterface* service = server_->GetHealthCheckService();
EXPECT_TRUE(service == underlying_service); // EXPECT_TRUE(service == underlying_service);
//
ResetStubs(); // ResetStubs();
//
VerifyHealthCheckService(); // VerifyHealthCheckService();
} // }
} // namespace } // namespace
} // namespace testing } // namespace testing

Loading…
Cancel
Save