From ed5e7e006b1a60ef01a0ee1db144e959436b53d7 Mon Sep 17 00:00:00 2001 From: yangg Date: Tue, 6 Jan 2015 10:16:15 -0800 Subject: [PATCH] Add deadline API on server side. Change on 2015/01/06 by yangg ------------- Created by MOE: http://code.google.com/p/moe-java MOE_MIGRATED_REVID=83351442 --- include/grpc++/server_context.h | 4 ++ src/cpp/server/server_context_impl.cc | 2 - src/cpp/server/server_context_impl.h | 14 +++- src/cpp/server/server_rpc_handler.cc | 2 +- src/cpp/util/time.cc | 3 + test/cpp/end2end/end2end_test.cc | 93 ++++++++++++++++++++++++++- test/cpp/util/echo.proto | 13 +++- test/cpp/util/time_test.cc | 6 ++ 8 files changed, 129 insertions(+), 8 deletions(-) diff --git a/include/grpc++/server_context.h b/include/grpc++/server_context.h index 9a14faa7fa6..47fd6cf1c85 100644 --- a/include/grpc++/server_context.h +++ b/include/grpc++/server_context.h @@ -34,12 +34,16 @@ #ifndef __GRPCPP_SERVER_CONTEXT_H_ #define __GRPCPP_SERVER_CONTEXT_H_ +#include + namespace grpc { // Interface of server side rpc context. class ServerContext { public: virtual ~ServerContext() {} + + virtual std::chrono::system_clock::time_point absolute_deadline() const = 0; }; } // namespace grpc diff --git a/src/cpp/server/server_context_impl.cc b/src/cpp/server/server_context_impl.cc index a229fcb6c99..13f2a3ae1ac 100644 --- a/src/cpp/server/server_context_impl.cc +++ b/src/cpp/server/server_context_impl.cc @@ -35,6 +35,4 @@ namespace grpc { -ServerContextImpl::ServerContextImpl() {} - } // namespace grpc diff --git a/src/cpp/server/server_context_impl.h b/src/cpp/server/server_context_impl.h index 58c4293b4f7..c6016b76357 100644 --- a/src/cpp/server/server_context_impl.h +++ b/src/cpp/server/server_context_impl.h @@ -36,12 +36,24 @@ #include +#include + +#include + namespace grpc { class ServerContextImpl : public ServerContext { public: - ServerContextImpl(); + explicit ServerContextImpl(std::chrono::system_clock::time_point deadline) + : absolute_deadline_(deadline) {} ~ServerContextImpl() {} + + std::chrono::system_clock::time_point absolute_deadline() const { + return absolute_deadline_; + } + + private: + std::chrono::system_clock::time_point absolute_deadline_; }; } // namespace grpc diff --git a/src/cpp/server/server_rpc_handler.cc b/src/cpp/server/server_rpc_handler.cc index c32722f81ad..3954f04f978 100644 --- a/src/cpp/server/server_rpc_handler.cc +++ b/src/cpp/server/server_rpc_handler.cc @@ -53,7 +53,7 @@ void ServerRpcHandler::StartRpc() { return; } - ServerContextImpl user_context; + ServerContextImpl user_context(async_server_context_->absolute_deadline()); if (method_->method_type() == RpcMethod::NORMAL_RPC) { // Start the rpc on this dedicated completion queue. diff --git a/src/cpp/util/time.cc b/src/cpp/util/time.cc index 6976fa1b321..e58dde82a3e 100644 --- a/src/cpp/util/time.cc +++ b/src/cpp/util/time.cc @@ -53,6 +53,9 @@ void Timepoint2Timespec(const system_clock::time_point& from, } system_clock::time_point Timespec2Timepoint(gpr_timespec t) { + if (gpr_time_cmp(t, gpr_inf_future) == 0) { + return system_clock::time_point::max(); + } system_clock::time_point tp; tp += duration_cast(seconds(t.tv_sec)); tp += diff --git a/test/cpp/end2end/end2end_test.cc b/test/cpp/end2end/end2end_test.cc index 4b5a9a8e6af..83037b5ab18 100644 --- a/test/cpp/end2end/end2end_test.cc +++ b/test/cpp/end2end/end2end_test.cc @@ -31,10 +31,12 @@ * */ +#include #include -#include "src/cpp/server/rpc_service_method.h" + #include "test/cpp/util/echo.pb.h" -#include "net/util/netutil.h" +#include "src/cpp/server/rpc_service_method.h" +#include "src/cpp/util/time.h" #include #include #include @@ -44,22 +46,43 @@ #include #include #include +#include "net/util/netutil.h" #include #include #include +#include using grpc::cpp::test::util::EchoRequest; using grpc::cpp::test::util::EchoResponse; using grpc::cpp::test::util::TestService; +using std::chrono::system_clock; namespace grpc { +namespace testing { + +namespace { + +// When echo_deadline is requested, deadline seen in the ServerContext is set in +// the response in seconds. +void MaybeEchoDeadline(ServerContext* context, const EchoRequest* request, + EchoResponse* response) { + if (request->has_param() && request->param().echo_deadline()) { + gpr_timespec deadline = gpr_inf_future; + if (context->absolute_deadline() != system_clock::time_point::max()) { + Timepoint2Timespec(context->absolute_deadline(), &deadline); + } + response->mutable_param()->set_request_deadline(deadline.tv_sec); + } +} +} // namespace class TestServiceImpl : public TestService::Service { public: Status Echo(ServerContext* context, const EchoRequest* request, EchoResponse* response) { response->set_message(request->message()); + MaybeEchoDeadline(context, request, response); return Status::OK; } @@ -179,6 +202,71 @@ TEST_F(End2endTest, RpcDeadlineExpires) { delete stub; } +// Set a long but finite deadline. +TEST_F(End2endTest, RpcLongDeadline) { + std::shared_ptr channel = + CreateChannel(server_address_.str(), ChannelArguments()); + TestService::Stub* stub = TestService::NewStub(channel); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + + ClientContext context; + std::chrono::system_clock::time_point deadline = + std::chrono::system_clock::now() + std::chrono::hours(1); + context.set_absolute_deadline(deadline); + Status s = stub->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.IsOk()); + + delete stub; +} + +// Ask server to echo back the deadline it sees. +TEST_F(End2endTest, EchoDeadline) { + std::shared_ptr channel = + CreateChannel(server_address_.str(), ChannelArguments()); + TestService::Stub* stub = TestService::NewStub(channel); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + request.mutable_param()->set_echo_deadline(true); + + ClientContext context; + std::chrono::system_clock::time_point deadline = + std::chrono::system_clock::now() + std::chrono::seconds(100); + context.set_absolute_deadline(deadline); + Status s = stub->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.IsOk()); + gpr_timespec sent_deadline; + Timepoint2Timespec(deadline, &sent_deadline); + // Allow 1 second error. + EXPECT_LE(response.param().request_deadline() - sent_deadline.tv_sec, 1); + EXPECT_GE(response.param().request_deadline() - sent_deadline.tv_sec, -1); + + delete stub; +} + +// Ask server to echo back the deadline it sees. The rpc has no deadline. +TEST_F(End2endTest, EchoDeadlineForNoDeadlineRpc) { + std::shared_ptr channel = + CreateChannel(server_address_.str(), ChannelArguments()); + TestService::Stub* stub = TestService::NewStub(channel); + EchoRequest request; + EchoResponse response; + request.set_message("Hello"); + request.mutable_param()->set_echo_deadline(true); + + ClientContext context; + Status s = stub->Echo(&context, request, &response); + EXPECT_EQ(response.message(), request.message()); + EXPECT_TRUE(s.IsOk()); + EXPECT_EQ(response.param().request_deadline(), gpr_inf_future.tv_sec); + + delete stub; +} + TEST_F(End2endTest, UnimplementedRpc) { std::shared_ptr channel = CreateChannel(server_address_.str(), ChannelArguments()); @@ -300,6 +388,7 @@ TEST_F(End2endTest, BidiStream) { delete stub; } +} // namespace testing } // namespace grpc int main(int argc, char** argv) { diff --git a/test/cpp/util/echo.proto b/test/cpp/util/echo.proto index abce7ad03a6..1240399bf88 100644 --- a/test/cpp/util/echo.proto +++ b/test/cpp/util/echo.proto @@ -2,12 +2,22 @@ syntax = "proto2"; package grpc.cpp.test.util; +message RequestParams { + optional bool echo_deadline = 1; +} + message EchoRequest { optional string message = 1; + optional RequestParams param = 2; +} + +message ResponseParams { + optional int64 request_deadline = 1; } message EchoResponse { optional string message = 1; + optional ResponseParams param = 2; } service TestService { @@ -15,6 +25,5 @@ service TestService { rpc RequestStream(stream EchoRequest) returns (EchoResponse); rpc ResponseStream(EchoRequest) returns (stream EchoResponse); rpc BidiStream(stream EchoRequest) returns (stream EchoResponse); - rpc Unimplemented(EchoRequest) returns (EchoResponse) { - } + rpc Unimplemented(EchoRequest) returns (EchoResponse); } diff --git a/test/cpp/util/time_test.cc b/test/cpp/util/time_test.cc index 97499fed28a..c5718086331 100644 --- a/test/cpp/util/time_test.cc +++ b/test/cpp/util/time_test.cc @@ -62,5 +62,11 @@ TEST_F(TimeTest, AbsolutePointTest) { EXPECT_TRUE(tp == tp_converted_2); } +// gpr_inf_future is treated specially and mapped to time_point::max() +TEST_F(TimeTest, InfFuture) { + EXPECT_EQ(system_clock::time_point::max(), + Timespec2Timepoint(gpr_inf_future)); +} + } // namespace } // namespace grpc