Server progress

pull/501/head
Craig Tiller 10 years ago
parent 061754a483
commit 1d2e21962e
  1. 11
      Makefile
  2. 5
      build.json
  3. 1
      include/grpc++/channel_interface.h
  4. 4
      include/grpc++/impl/rpc_method.h
  5. 25
      include/grpc++/impl/rpc_service_method.h
  6. 1
      include/grpc++/server.h
  7. 3
      include/grpc++/server_context.h
  8. 38
      include/grpc++/stream.h
  9. 40
      src/cpp/server/server.cc
  10. 10
      src/cpp/server/server_rpc_handler.h
  11. 2
      test/core/statistics/census_log_tests.c
  12. 154
      test/cpp/end2end/async_test_server.cc
  13. 75
      test/cpp/end2end/async_test_server.h

@ -2618,8 +2618,6 @@ LIBGRPC++_SRC = \
src/cpp/common/completion_queue.cc \
src/cpp/common/rpc_method.cc \
src/cpp/proto/proto_utils.cc \
src/cpp/server/async_server.cc \
src/cpp/server/async_server_context.cc \
src/cpp/server/server.cc \
src/cpp/server/server_builder.cc \
src/cpp/server/server_context_impl.cc \
@ -2631,8 +2629,6 @@ LIBGRPC++_SRC = \
src/cpp/util/time.cc \
PUBLIC_HEADERS_CXX += \
include/grpc++/async_server.h \
include/grpc++/async_server_context.h \
include/grpc++/channel_arguments.h \
include/grpc++/channel_interface.h \
include/grpc++/client_context.h \
@ -2678,8 +2674,6 @@ src/cpp/common/call.cc: $(OPENSSL_DEP)
src/cpp/common/completion_queue.cc: $(OPENSSL_DEP)
src/cpp/common/rpc_method.cc: $(OPENSSL_DEP)
src/cpp/proto/proto_utils.cc: $(OPENSSL_DEP)
src/cpp/server/async_server.cc: $(OPENSSL_DEP)
src/cpp/server/async_server_context.cc: $(OPENSSL_DEP)
src/cpp/server/server.cc: $(OPENSSL_DEP)
src/cpp/server/server_builder.cc: $(OPENSSL_DEP)
src/cpp/server/server_context_impl.cc: $(OPENSSL_DEP)
@ -2739,8 +2733,6 @@ objs/$(CONFIG)/src/cpp/common/call.o:
objs/$(CONFIG)/src/cpp/common/completion_queue.o:
objs/$(CONFIG)/src/cpp/common/rpc_method.o:
objs/$(CONFIG)/src/cpp/proto/proto_utils.o:
objs/$(CONFIG)/src/cpp/server/async_server.o:
objs/$(CONFIG)/src/cpp/server/async_server_context.o:
objs/$(CONFIG)/src/cpp/server/server.o:
objs/$(CONFIG)/src/cpp/server/server_builder.o:
objs/$(CONFIG)/src/cpp/server/server_context_impl.o:
@ -2756,7 +2748,6 @@ LIBGRPC++_TEST_UTIL_SRC = \
gens/test/cpp/util/messages.pb.cc \
gens/test/cpp/util/echo.pb.cc \
gens/test/cpp/util/echo_duplicate.pb.cc \
test/cpp/end2end/async_test_server.cc \
test/cpp/util/create_test_channel.cc \
@ -2775,7 +2766,6 @@ ifneq ($(OPENSSL_DEP),)
test/cpp/util/messages.proto: $(OPENSSL_DEP)
test/cpp/util/echo.proto: $(OPENSSL_DEP)
test/cpp/util/echo_duplicate.proto: $(OPENSSL_DEP)
test/cpp/end2end/async_test_server.cc: $(OPENSSL_DEP)
test/cpp/util/create_test_channel.cc: $(OPENSSL_DEP)
endif
@ -2803,7 +2793,6 @@ endif
objs/$(CONFIG)/test/cpp/end2end/async_test_server.o: gens/test/cpp/util/messages.pb.cc gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc
objs/$(CONFIG)/test/cpp/util/create_test_channel.o: gens/test/cpp/util/messages.pb.cc gens/test/cpp/util/echo.pb.cc gens/test/cpp/util/echo_duplicate.pb.cc

@ -378,8 +378,6 @@
"build": "all",
"language": "c++",
"public_headers": [
"include/grpc++/async_server.h",
"include/grpc++/async_server_context.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
"include/grpc++/client_context.h",
@ -417,8 +415,6 @@
"src/cpp/common/completion_queue.cc",
"src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_server.cc",
"src/cpp/server/async_server_context.cc",
"src/cpp/server/server.cc",
"src/cpp/server/server_builder.cc",
"src/cpp/server/server_context_impl.cc",
@ -443,7 +439,6 @@
"test/cpp/util/messages.proto",
"test/cpp/util/echo.proto",
"test/cpp/util/echo_duplicate.proto",
"test/cpp/end2end/async_test_server.cc",
"test/cpp/util/create_test_channel.cc"
]
},

@ -50,7 +50,6 @@ class CallOpBuffer;
class ClientContext;
class CompletionQueue;
class RpcMethod;
class StreamContextInterface;
class CallInterface;
class ChannelInterface {

@ -37,8 +37,8 @@
namespace google {
namespace protobuf {
class Message;
}
}
} // namespace protobuf
} // namespace google
namespace grpc {

@ -55,25 +55,18 @@ class MethodHandler {
public:
virtual ~MethodHandler() {}
struct HandlerParameter {
HandlerParameter(ServerContext* context,
HandlerParameter(Call *c,
ServerContext* context,
const google::protobuf::Message* req,
google::protobuf::Message* resp)
: server_context(context),
: call(c),
server_context(context),
request(req),
response(resp),
stream_context(nullptr) {}
HandlerParameter(ServerContext* context,
const google::protobuf::Message* req,
google::protobuf::Message* resp,
StreamContextInterface* stream)
: server_context(context),
request(req),
response(resp),
stream_context(stream) {}
response(resp) {}
Call* call;
ServerContext* server_context;
const google::protobuf::Message* request;
google::protobuf::Message* response;
StreamContextInterface* stream_context;
};
virtual Status RunHandler(const HandlerParameter& param) = 0;
};
@ -114,7 +107,7 @@ class ClientStreamingHandler : public MethodHandler {
: func_(func), service_(service) {}
Status RunHandler(const HandlerParameter& param) final {
ServerReader<RequestType> reader(param.stream_context);
ServerReader<RequestType> reader(param.call);
return func_(service_, param.server_context, &reader,
dynamic_cast<ResponseType*>(param.response));
}
@ -136,7 +129,7 @@ class ServerStreamingHandler : public MethodHandler {
: func_(func), service_(service) {}
Status RunHandler(const HandlerParameter& param) final {
ServerWriter<ResponseType> writer(param.stream_context);
ServerWriter<ResponseType> writer(param.call);
return func_(service_, param.server_context,
dynamic_cast<const RequestType*>(param.request), &writer);
}
@ -159,7 +152,7 @@ class BidiStreamingHandler : public MethodHandler {
: func_(func), service_(service) {}
Status RunHandler(const HandlerParameter& param) final {
ServerReaderWriter<ResponseType, RequestType> stream(param.stream_context);
ServerReaderWriter<ResponseType, RequestType> stream(param.call);
return func_(service_, param.server_context, &stream);
}

@ -80,7 +80,6 @@ class Server {
// Start the server.
bool Start();
void AllowOneRpc();
void HandleQueueClosed();
void RunRpc();
void ScheduleCallback();

@ -44,6 +44,9 @@ class ServerContext {
virtual ~ServerContext() {}
virtual std::chrono::system_clock::time_point absolute_deadline() const = 0;
private:
std::vector<std::pair<grpc::string, grpc::string> > metadata_;
};
} // namespace grpc

@ -37,12 +37,43 @@
#include <grpc++/call.h>
#include <grpc++/channel_interface.h>
#include <grpc++/completion_queue.h>
#include <grpc++/stream_context_interface.h>
#include <grpc++/status.h>
#include <grpc/support/log.h>
namespace grpc {
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
// DELETE DELETE DELETE
class StreamContextInterface {
public:
template <class T> bool Write(T, bool);
template <class T> void Start(T);
template <class T> bool Read(T);
google::protobuf::Message *request();
};
// Common interface for all client side streaming.
class ClientStreamingInterface {
public:
@ -207,17 +238,16 @@ class ClientReaderWriter final : public ClientStreamingInterface,
template <class R>
class ServerReader final : public ReaderInterface<R> {
public:
ServerReader(CompletionQueue* cq, Call* call) : cq_(cq), call_(call) {}
explicit ServerReader(Call* call) : call_(call) {}
virtual bool Read(R* msg) override {
CallOpBuffer buf;
buf.AddRecvMessage(msg);
call_->PerformOps(&buf, (void *)2);
return cq_->Pluck((void *)2);
return call_->cq()->Pluck((void *)2);
}
private:
CompletionQueue* cq_;
Call* call_;
};

@ -114,12 +114,6 @@ bool Server::Start() {
return true;
}
void Server::AllowOneRpc() {
GPR_ASSERT(started_);
grpc_call_error err = grpc_server_request_call_old(server_, nullptr);
GPR_ASSERT(err == GRPC_CALL_OK);
}
void Server::Shutdown() {
{
std::unique_lock<std::mutex> lock(mu_);
@ -152,25 +146,31 @@ void Server::ScheduleCallback() {
void Server::RunRpc() {
// Wait for one more incoming rpc.
void *tag = nullptr;
AllowOneRpc();
GPR_ASSERT(started_);
grpc_call *c_call = NULL;
grpc_call_details details;
grpc_call_details_init(&details);
grpc_metadata_array initial_metadata;
grpc_metadata_array_init(&initial_metadata);
CompletionQueue cq;
grpc_call_error err = grpc_server_request_call(server_, &call, &details, &initial_metadata, cq.cq(), nullptr);
GPR_ASSERT(err == GRPC_CALL_OK);
bool ok = false;
GPR_ASSERT(cq_.Next(&tag, &ok));
if (ok) {
AsyncServerContext *server_context = static_cast<AsyncServerContext *>(tag);
// server_context could be nullptr during server shutdown.
if (server_context != nullptr) {
// Schedule a new callback to handle more rpcs.
ScheduleCallback();
RpcServiceMethod *method = nullptr;
auto iter = method_map_.find(server_context->method());
if (iter != method_map_.end()) {
method = iter->second;
}
ServerRpcHandler rpc_handler(server_context, method);
rpc_handler.StartRpc();
ServerContext context;
Call call(c_call, nullptr, &cq);
ScheduleCallback();
RpcServiceMethod *method = nullptr;
auto iter = method_map_.find(call_details.method);
if (iter != method_map_.end()) {
method = iter->second;
}
ServerRpcHandler rpc_handler(&call, context, method);
rpc_handler.StartRpc();
}
grpc_call_details_destroy(&details);
grpc_metadata_array_destroy(&initial_metadata);
{
std::unique_lock<std::mutex> lock(mu_);

@ -41,13 +41,14 @@
namespace grpc {
class AsyncServerContext;
class
class ServerContext;
class RpcServiceMethod;
class ServerRpcHandler {
public:
// Takes ownership of async_server_context.
ServerRpcHandler(AsyncServerContext *async_server_context,
ServerRpcHandler(Call *call,
ServerContext *server_context,
RpcServiceMethod *method);
void StartRpc();
@ -55,7 +56,8 @@ class ServerRpcHandler {
private:
void FinishRpc(const Status &status);
std::unique_ptr<AsyncServerContext> async_server_context_;
Call *call_;
ServerContext* server_context_;
RpcServiceMethod *method_;
CompletionQueue cq_;
};

@ -35,7 +35,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "src/core/support/cpu.h"
#include <grpc/support/cpu.h>
#include <grpc/support/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/sync.h>

@ -1,154 +0,0 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#include "test/cpp/end2end/async_test_server.h"
#include <chrono>
#include <grpc/support/log.h>
#include "src/cpp/proto/proto_utils.h"
#include "test/cpp/util/echo.pb.h"
#include <grpc++/async_server.h>
#include <grpc++/async_server_context.h>
#include <grpc++/completion_queue.h>
#include <grpc++/status.h>
#include <gtest/gtest.h>
using grpc::cpp::test::util::EchoRequest;
using grpc::cpp::test::util::EchoResponse;
using std::chrono::duration_cast;
using std::chrono::microseconds;
using std::chrono::seconds;
using std::chrono::system_clock;
namespace grpc {
namespace testing {
AsyncTestServer::AsyncTestServer() : server_(&cq_), cq_drained_(false) {}
AsyncTestServer::~AsyncTestServer() {}
void AsyncTestServer::AddPort(const grpc::string& addr) {
server_.AddPort(addr);
}
void AsyncTestServer::Start() { server_.Start(); }
// Return true if deadline actual is within 0.5s from expected.
bool DeadlineMatched(const system_clock::time_point& actual,
const system_clock::time_point& expected) {
microseconds diff_usecs = duration_cast<microseconds>(expected - actual);
gpr_log(GPR_INFO, "diff_usecs= %d", diff_usecs.count());
return diff_usecs.count() < 500000 && diff_usecs.count() > -500000;
}
void AsyncTestServer::RequestOneRpc() { server_.RequestOneRpc(); }
void AsyncTestServer::MainLoop() {
EchoRequest request;
EchoResponse response;
void* tag = nullptr;
RequestOneRpc();
while (true) {
CompletionQueue::CompletionType t = cq_.Next(&tag);
AsyncServerContext* server_context = static_cast<AsyncServerContext*>(tag);
switch (t) {
case CompletionQueue::SERVER_RPC_NEW:
gpr_log(GPR_INFO, "SERVER_RPC_NEW %p", server_context);
if (server_context) {
EXPECT_EQ(server_context->method(), "/foo");
// TODO(ctiller): verify deadline
server_context->Accept(cq_.cq());
// Handle only one rpc at a time.
RequestOneRpc();
server_context->StartRead(&request);
}
break;
case CompletionQueue::RPC_END:
gpr_log(GPR_INFO, "RPC_END %p", server_context);
delete server_context;
break;
case CompletionQueue::SERVER_READ_OK:
gpr_log(GPR_INFO, "SERVER_READ_OK %p", server_context);
response.set_message(request.message());
server_context->StartWrite(response, 0);
break;
case CompletionQueue::SERVER_READ_ERROR:
gpr_log(GPR_INFO, "SERVER_READ_ERROR %p", server_context);
server_context->StartWriteStatus(Status::OK);
break;
case CompletionQueue::HALFCLOSE_OK:
gpr_log(GPR_INFO, "HALFCLOSE_OK %p", server_context);
// Do nothing, just wait for RPC_END.
break;
case CompletionQueue::SERVER_WRITE_OK:
gpr_log(GPR_INFO, "SERVER_WRITE_OK %p", server_context);
server_context->StartRead(&request);
break;
case CompletionQueue::SERVER_WRITE_ERROR:
EXPECT_TRUE(0);
break;
case CompletionQueue::QUEUE_CLOSED: {
gpr_log(GPR_INFO, "QUEUE_CLOSED");
HandleQueueClosed();
return;
}
default:
EXPECT_TRUE(0);
break;
}
}
}
void AsyncTestServer::HandleQueueClosed() {
std::unique_lock<std::mutex> lock(cq_drained_mu_);
cq_drained_ = true;
cq_drained_cv_.notify_all();
}
void AsyncTestServer::Shutdown() {
// The server need to be shut down before cq_ as grpc_server flushes all
// pending requested calls to the completion queue at shutdown.
server_.Shutdown();
cq_.Shutdown();
std::unique_lock<std::mutex> lock(cq_drained_mu_);
while (!cq_drained_) {
cq_drained_cv_.wait(lock);
}
}
} // namespace testing
} // namespace grpc

@ -1,75 +0,0 @@
/*
*
* Copyright 2014, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef __GRPCPP_TEST_END2END_ASYNC_TEST_SERVER_H__
#define __GRPCPP_TEST_END2END_ASYNC_TEST_SERVER_H__
#include <condition_variable>
#include <mutex>
#include <string>
#include <grpc++/async_server.h>
#include <grpc++/completion_queue.h>
namespace grpc {
namespace testing {
class AsyncTestServer {
public:
AsyncTestServer();
virtual ~AsyncTestServer();
void AddPort(const grpc::string& addr);
void Start();
void RequestOneRpc();
virtual void MainLoop();
void Shutdown();
CompletionQueue* completion_queue() { return &cq_; }
protected:
void HandleQueueClosed();
private:
CompletionQueue cq_;
AsyncServer server_;
bool cq_drained_;
std::mutex cq_drained_mu_;
std::condition_variable cq_drained_cv_;
};
} // namespace testing
} // namespace grpc
#endif // __GRPCPP_TEST_END2END_ASYNC_TEST_SERVER_H__
Loading…
Cancel
Save