Merge github.com:grpc/grpc into copyright

pull/654/head
Craig Tiller 10 years ago
commit d5bb9a3c93
  1. 43
      INSTALL
  2. 344
      Makefile
  3. 33
      README.md
  4. 99
      build.json
  5. 13
      examples/pubsub/main.cc
  6. 2
      examples/pubsub/publisher.cc
  7. 2
      examples/pubsub/publisher.h
  8. 6
      examples/pubsub/publisher_test.cc
  9. 2
      examples/pubsub/subscriber.cc
  10. 2
      examples/pubsub/subscriber.h
  11. 4
      examples/pubsub/subscriber_test.cc
  12. 95
      include/grpc++/async_server_context.h
  13. 140
      include/grpc++/async_unary_call.h
  14. 2
      include/grpc++/channel_arguments.h
  15. 28
      include/grpc++/channel_interface.h
  16. 72
      include/grpc++/client_context.h
  17. 97
      include/grpc++/completion_queue.h
  18. 5
      include/grpc++/config.h
  19. 2
      include/grpc++/create_channel.h
  20. 2
      include/grpc++/credentials.h
  21. 145
      include/grpc++/impl/call.h
  22. 49
      include/grpc++/impl/client_unary_call.h
  23. 2
      include/grpc++/impl/internal_stub.h
  24. 6
      include/grpc++/impl/rpc_method.h
  25. 30
      include/grpc++/impl/rpc_service_method.h
  26. 127
      include/grpc++/impl/service_type.h
  27. 42
      include/grpc++/server.h
  28. 16
      include/grpc++/server_builder.h
  29. 81
      include/grpc++/server_context.h
  30. 2
      include/grpc++/server_credentials.h
  31. 2
      include/grpc++/status.h
  32. 2
      include/grpc++/status_code_enum.h
  33. 639
      include/grpc++/stream.h
  34. 2
      include/grpc++/thread_pool_interface.h
  35. 2
      include/grpc/byte_buffer.h
  36. 2
      include/grpc/byte_buffer_reader.h
  37. 92
      include/grpc/grpc.h
  38. 2
      include/grpc/grpc_http.h
  39. 2
      include/grpc/grpc_security.h
  40. 2
      include/grpc/status.h
  41. 2
      include/grpc/support/alloc.h
  42. 2
      include/grpc/support/atm.h
  43. 2
      include/grpc/support/atm_gcc_atomic.h
  44. 2
      include/grpc/support/atm_gcc_sync.h
  45. 2
      include/grpc/support/atm_win32.h
  46. 2
      include/grpc/support/cancellable_platform.h
  47. 2
      include/grpc/support/cmdline.h
  48. 10
      include/grpc/support/cpu.h
  49. 2
      include/grpc/support/histogram.h
  50. 2
      include/grpc/support/host_port.h
  51. 2
      include/grpc/support/log.h
  52. 2
      include/grpc/support/log_win32.h
  53. 2
      include/grpc/support/port_platform.h
  54. 2
      include/grpc/support/slice.h
  55. 2
      include/grpc/support/slice_buffer.h
  56. 2
      include/grpc/support/sync.h
  57. 2
      include/grpc/support/sync_generic.h
  58. 2
      include/grpc/support/sync_posix.h
  59. 2
      include/grpc/support/sync_win32.h
  60. 2
      include/grpc/support/thd.h
  61. 2
      include/grpc/support/time.h
  62. 2
      include/grpc/support/useful.h
  63. 302
      src/compiler/cpp_generator.cc
  64. 2
      src/compiler/cpp_generator.h
  65. 2
      src/compiler/cpp_generator_helpers.h
  66. 2
      src/compiler/cpp_plugin.cc
  67. 330
      src/compiler/python_generator.cc
  68. 37
      src/compiler/python_generator.h
  69. 87
      src/compiler/python_plugin.cc
  70. 2
      src/compiler/ruby_generator.cc
  71. 2
      src/compiler/ruby_generator.h
  72. 2
      src/compiler/ruby_generator_helpers-inl.h
  73. 2
      src/compiler/ruby_generator_map-inl.h
  74. 2
      src/compiler/ruby_generator_string-inl.h
  75. 2
      src/compiler/ruby_plugin.cc
  76. 9
      src/core/README.md
  77. 2
      src/core/channel/call_op_string.c
  78. 2
      src/core/channel/census_filter.c
  79. 2
      src/core/channel/census_filter.h
  80. 2
      src/core/channel/channel_args.c
  81. 2
      src/core/channel/channel_args.h
  82. 2
      src/core/channel/channel_stack.c
  83. 2
      src/core/channel/channel_stack.h
  84. 2
      src/core/channel/child_channel.c
  85. 2
      src/core/channel/child_channel.h
  86. 2
      src/core/channel/client_channel.c
  87. 2
      src/core/channel/client_channel.h
  88. 31
      src/core/channel/client_setup.c
  89. 8
      src/core/channel/client_setup.h
  90. 2
      src/core/channel/connected_channel.c
  91. 2
      src/core/channel/connected_channel.h
  92. 2
      src/core/channel/http_client_filter.c
  93. 2
      src/core/channel/http_client_filter.h
  94. 2
      src/core/channel/http_filter.c
  95. 2
      src/core/channel/http_filter.h
  96. 2
      src/core/channel/http_server_filter.c
  97. 2
      src/core/channel/http_server_filter.h
  98. 2
      src/core/channel/metadata_buffer.c
  99. 2
      src/core/channel/metadata_buffer.h
  100. 2
      src/core/channel/noop_filter.c
  101. Some files were not shown because too many files have changed in this diff Show More

@ -23,6 +23,11 @@ Building the python wrapper requires the following:
# apt-get install python-all-dev python-virtualenv
If you want to install in a different directory than the default /usr/lib, you can
override it on the command line:
# make install prefix=/opt
*******************************
* More detailled instructions *
@ -95,6 +100,44 @@ will need clang and its instrumented libc++:
# apt-get install clang libc++-dev
Mac-specific notes:
-------------------
For a Mac system, git is not available by default. You will first need to
install Xcode from the Mac AppStore and then run the following command from a
terminal:
$ sudo xcode-select --install
You should also install "port" following the instructions at
https://www.macports.org . This will reside in /opt/local/bin/port for
most Mac installations. Do the "git submodule" command listed above.
Then execute the following for all the needed build dependencies
$ sudo /opt/local/bin/port install autoconf automake libtool gflags cmake
$ mkdir ~/gtest
$ svn checkout http://googletest.googlecode.com/svn/trunk/ gtest-svn
$ mkdir mybuild
$ cd mybuild
$ cmake ../gtest-svn
$ make
$ make gtest.a gtest_main.a
$ sudo cp libgtest.a libgtest_main.a /opt/local/lib
$ sudo mkdir /opt/local/include/gtest
$ sudo cp -pr ../gtest-svn/include/gtest /opt/local/include/gtest
We will also need to make openssl and install it appropriately
$ cd <git directory>
$ cd third_party/openssl
$ sudo make install
$ cd ../../
If you are going to make changes and need to regenerate the projects file,
you will need to install certain modules for python.
$ sudo easy_install simplejson mako
A word on OpenSSL
-----------------

File diff suppressed because one or more lines are too long

@ -7,6 +7,39 @@ Copyright 2015 Google Inc.
See grpc/INSTALL for installation instructions for various platforms.
#Repository Structure
This repository contains source code for gRPC libraries for multiple lanugages written on top
of shared C core library [src/core] (src/core).
* C++ source code: [src/cpp] (src/cpp)
* Python source code: [src/python] (src/python)
* Ruby source code: [src/ruby] (src/ruby)
* NodeJS source code: [src/node] (src/node)
* PHP source code: [src/php] (src/php)
* C# source code: [src/csharp] (src/csharp)
* Objective-C source code: [src/objective-c] (src/objective-c)
Java source code is in [grpc-java] (http://github.com/grpc/grpc-java) repository.
Go source code is in [grpc-go] (http://github.com/grpc/grpc-go) repository.
#Documentation
You can find more detailed documentation and examples in the [grpc-common repository](http://github.com/grpc/grpc-common).
#Current Status of libraries
Libraries in different languages are in different state of development. We are seeking contributions for all of these libraries.
* shared C core library [src/core] (src/core) : Early adopter ready - Alpha.
* C++ Library: [src/cpp] (src/cpp) : Early adopter ready - Alpha.
* Python Library: [src/python] (src/python) : Early adopter ready - Alpha.
* Ruby Library: [src/ruby] (src/ruby) : Early adopter ready - Alpha.
* NodeJS Library: [src/node] (src/node) : Early adopter ready - Alpha.
* PHP Library: [src/php] (src/php) : Pre-Alpha.
* C# Library: [src/csharp] (src/csharp) : Pre-Alpha.
* Objective-C Library: [src/objective-c] (src/objective-c): Pre-Alpha.
#Overview

@ -239,7 +239,6 @@
"include/grpc/support/useful.h"
],
"headers": [
"src/core/support/cpu.h",
"src/core/support/env.h",
"src/core/support/file.h",
"src/core/support/murmur_hash.h",
@ -345,7 +344,7 @@
{
"name": "grpc_csharp_ext",
"build": "all",
"language": "c",
"language": "csharp",
"src": [
"src/csharp/ext/grpc_csharp_ext.c"
],
@ -398,8 +397,7 @@
"build": "all",
"language": "c++",
"public_headers": [
"include/grpc++/async_server.h",
"include/grpc++/async_server_context.h",
"include/grpc++/async_unary_call.h",
"include/grpc++/channel_arguments.h",
"include/grpc++/channel_interface.h",
"include/grpc++/client_context.h",
@ -407,44 +405,44 @@
"include/grpc++/config.h",
"include/grpc++/create_channel.h",
"include/grpc++/credentials.h",
"include/grpc++/impl/call.h",
"include/grpc++/impl/client_unary_call.h",
"include/grpc++/impl/internal_stub.h",
"include/grpc++/impl/rpc_method.h",
"include/grpc++/impl/rpc_service_method.h",
"include/grpc++/impl/service_type.h",
"include/grpc++/server.h",
"include/grpc++/server_builder.h",
"include/grpc++/server_context.h",
"include/grpc++/server_credentials.h",
"include/grpc++/status.h",
"include/grpc++/status_code_enum.h",
"include/grpc++/stream.h",
"include/grpc++/stream_context_interface.h"
"include/grpc++/thread_pool_interface.h"
],
"headers": [
"src/cpp/client/channel.h",
"src/cpp/proto/proto_utils.h",
"src/cpp/server/server_rpc_handler.h",
"src/cpp/server/thread_pool.h",
"src/cpp/stream/stream_context.h",
"src/cpp/util/time.h"
],
"src": [
"src/cpp/client/channel.cc",
"src/cpp/client/channel_arguments.cc",
"src/cpp/client/client_context.cc",
"src/cpp/client/client_unary_call.cc",
"src/cpp/client/create_channel.cc",
"src/cpp/client/credentials.cc",
"src/cpp/client/internal_stub.cc",
"src/cpp/common/call.cc",
"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",
"src/cpp/server/server_context.cc",
"src/cpp/server/server_credentials.cc",
"src/cpp/server/server_rpc_handler.cc",
"src/cpp/server/thread_pool.cc",
"src/cpp/stream/stream_context.cc",
"src/cpp/util/status.cc",
"src/cpp/util/time.cc"
],
@ -462,7 +460,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"
]
},
@ -1550,6 +1547,22 @@
"gpr"
]
},
{
"name": "async_end2end_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/end2end/async_end2end_test.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "channel_arguments_test",
"build": "test",
@ -1564,7 +1577,7 @@
]
},
{
"name": "cpp_plugin",
"name": "grpc_cpp_plugin",
"build": "protoc",
"language": "c++",
"headers": [
@ -1578,6 +1591,31 @@
"deps": [],
"secure": false
},
{
"name": "grpc_ruby_plugin",
"build": "protoc",
"language": "c++",
"src": [
"src/compiler/ruby_generator.cc",
"src/compiler/ruby_plugin.cc"
],
"deps": [],
"secure": false
},
{
"name": "grpc_python_plugin",
"build": "protoc",
"language": "c++",
"headers": [
"src/compiler/python_generator.h"
],
"src": [
"src/compiler/python_generator.cc",
"src/compiler/python_plugin.cc"
],
"deps": [],
"secure": false
},
{
"name": "credentials_test",
"build": "test",
@ -1735,23 +1773,6 @@
"gpr"
]
},
{
"name": "ruby_plugin",
"build": "protoc",
"language": "c++",
"headers": [
"src/compiler/cpp_generator.h",
"src/compiler/cpp_generator_helpers-inl.h",
"src/compiler/cpp_generator_map-inl.h",
"src/compiler/cpp_generator_string-inl.h"
],
"src": [
"src/compiler/ruby_generator.cc",
"src/compiler/ruby_plugin.cc"
],
"deps": [],
"secure": false
},
{
"name": "status_test",
"build": "test",
@ -1767,22 +1788,6 @@
"gpr"
]
},
{
"name": "sync_client_async_server_test",
"build": "test",
"language": "c++",
"src": [
"test/cpp/end2end/sync_client_async_server_test.cc"
],
"deps": [
"grpc++_test_util",
"grpc_test_util",
"grpc++",
"grpc",
"gpr_test_util",
"gpr"
]
},
{
"name": "thread_pool_test",
"build": "test",

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -40,7 +40,7 @@
#include <grpc/grpc.h>
#include <grpc/support/log.h>
#include <google/gflags.h>
#include <gflags/gflags.h>
#include <grpc++/channel_interface.h>
#include <grpc++/create_channel.h>
#include <grpc++/credentials.h>
@ -60,6 +60,13 @@ DEFINE_string(oauth_scope,
"https://www.googleapis.com/auth/cloud-platform",
"Scope for OAuth tokens.");
// In some distros, gflags is in the namespace google, and in some others,
// in gflags. This hack is enabling us to find both.
namespace google { }
namespace gflags { }
using namespace google;
using namespace gflags;
namespace {
const char kTopic[] = "testtopics";
@ -81,7 +88,7 @@ grpc::string GetServiceAccountJsonKey() {
int main(int argc, char** argv) {
grpc_init();
google::ParseCommandLineFlags(&argc, &argv, true);
ParseCommandLineFlags(&argc, &argv, true);
gpr_log(GPR_INFO, "Start PUBSUB client");
std::ostringstream ss;

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -107,7 +107,7 @@ class PublisherTest : public ::testing::Test {
server_address_ << "localhost:" << port;
ServerBuilder builder;
builder.AddPort(server_address_.str());
builder.RegisterService(service_.service());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
channel_ = CreateChannel(server_address_.str(), ChannelArguments());
@ -138,7 +138,7 @@ TEST_F(PublisherTest, TestPublisher) {
std::vector<grpc::string> topics;
EXPECT_TRUE(publisher_->ListTopics(kProjectId, &topics).IsOk());
EXPECT_EQ(topics.size(), 1);
EXPECT_EQ(topics.size(), static_cast<size_t>(1));
EXPECT_EQ(topics[0], kTopic);
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -106,7 +106,7 @@ class SubscriberTest : public ::testing::Test {
server_address_ << "localhost:" << port;
ServerBuilder builder;
builder.AddPort(server_address_.str());
builder.RegisterService(service_.service());
builder.RegisterService(&service_);
server_ = builder.BuildAndStart();
channel_ = CreateChannel(server_address_.str(), ChannelArguments());

@ -1,95 +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_ASYNC_SERVER_CONTEXT_H__
#define __GRPCPP_ASYNC_SERVER_CONTEXT_H__
#include <chrono>
#include <grpc++/config.h>
struct grpc_byte_buffer;
struct grpc_call;
struct grpc_completion_queue;
namespace google {
namespace protobuf {
class Message;
}
}
using std::chrono::system_clock;
namespace grpc {
class Status;
// TODO(rocking): wrap grpc c structures.
class AsyncServerContext {
public:
AsyncServerContext(grpc_call* call, const grpc::string& method,
const grpc::string& host,
system_clock::time_point absolute_deadline);
~AsyncServerContext();
// Accept this rpc, bind it to a completion queue.
void Accept(grpc_completion_queue* cq);
// Read and write calls, all async. Return true for success.
bool StartRead(google::protobuf::Message* request);
bool StartWrite(const google::protobuf::Message& response, int flags);
bool StartWriteStatus(const Status& status);
bool ParseRead(grpc_byte_buffer* read_buffer);
grpc::string method() const { return method_; }
grpc::string host() const { return host_; }
system_clock::time_point absolute_deadline() { return absolute_deadline_; }
grpc_call* call() { return call_; }
private:
AsyncServerContext(const AsyncServerContext&);
AsyncServerContext& operator=(const AsyncServerContext&);
// These properties may be moved to a ServerContext class.
const grpc::string method_;
const grpc::string host_;
system_clock::time_point absolute_deadline_;
google::protobuf::Message* request_; // not owned
grpc_call* call_; // owned
};
} // namespace grpc
#endif // __GRPCPP_ASYNC_SERVER_CONTEXT_H__

@ -0,0 +1,140 @@
/*
*
* Copyright 2015, 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_ASYNC_UNARY_CALL_H__
#define __GRPCPP_ASYNC_UNARY_CALL_H__
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/completion_queue.h>
#include <grpc++/server_context.h>
#include <grpc++/impl/call.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/status.h>
#include <grpc/support/log.h>
namespace grpc {
template <class R>
class ClientAsyncResponseReader final {
public:
ClientAsyncResponseReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const google::protobuf::Message& request, void* tag)
: context_(context),
call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
init_buf_.AddSendMessage(request);
init_buf_.AddClientSendClose();
call_.PerformOps(&init_buf_);
}
void ReadInitialMetadata(void* tag) {
GPR_ASSERT(!context_->initial_metadata_received_);
meta_buf_.Reset(tag);
meta_buf_.AddRecvInitialMetadata(context_);
call_.PerformOps(&meta_buf_);
}
void Finish(R* msg, Status* status, void* tag) {
finish_buf_.Reset(tag);
if (!context_->initial_metadata_received_) {
finish_buf_.AddRecvInitialMetadata(context_);
}
finish_buf_.AddRecvMessage(msg);
finish_buf_.AddClientRecvStatus(context_, status);
call_.PerformOps(&finish_buf_);
}
private:
ClientContext* context_ = nullptr;
Call call_;
CallOpBuffer init_buf_;
CallOpBuffer meta_buf_;
CallOpBuffer finish_buf_;
};
template <class W>
class ServerAsyncResponseWriter final : public ServerAsyncStreamingInterface {
public:
explicit ServerAsyncResponseWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
meta_buf_.Reset(tag);
meta_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_buf_);
}
void Finish(const W& msg, const Status& status, void* tag) {
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
if (status.IsOk()) {
finish_buf_.AddSendMessage(msg);
}
finish_buf_.AddServerSendStatus(&ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
void FinishWithError(const Status& status, void* tag) {
GPR_ASSERT(!status.IsOk());
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_buf_.AddServerSendStatus(&ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
private:
void BindCall(Call* call) override { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpBuffer meta_buf_;
CallOpBuffer finish_buf_;
};
} // namespace grpc
#endif // __GRPCPP_ASYNC_UNARY_CALL_H__

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -35,32 +35,30 @@
#define __GRPCPP_CHANNEL_INTERFACE_H__
#include <grpc++/status.h>
#include <grpc++/impl/call.h>
namespace google {
namespace protobuf {
class Message;
}
}
} // namespace protobuf
} // namespace google
namespace grpc {
struct grpc_call;
namespace grpc {
class Call;
class CallOpBuffer;
class ClientContext;
class CompletionQueue;
class RpcMethod;
class StreamContextInterface;
class CallInterface;
class ChannelInterface {
class ChannelInterface : public CallHook {
public:
virtual ~ChannelInterface() {}
virtual Status StartBlockingRpc(const RpcMethod& method,
ClientContext* context,
const google::protobuf::Message& request,
google::protobuf::Message* result) = 0;
virtual StreamContextInterface* CreateStream(
const RpcMethod& method, ClientContext* context,
const google::protobuf::Message* request,
google::protobuf::Message* result) = 0;
virtual Call CreateCall(const RpcMethod &method, ClientContext *context,
CompletionQueue *cq) = 0;
};
} // namespace grpc

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -35,8 +35,8 @@
#define __GRPCPP_CLIENT_CONTEXT_H__
#include <chrono>
#include <map>
#include <string>
#include <vector>
#include <grpc/support/log.h>
#include <grpc/support/time.h>
@ -47,8 +47,34 @@ using std::chrono::system_clock;
struct grpc_call;
struct grpc_completion_queue;
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
namespace grpc {
class CallOpBuffer;
class ChannelInterface;
class CompletionQueue;
class RpcMethod;
class Status;
template <class R>
class ClientReader;
template <class W>
class ClientWriter;
template <class R, class W>
class ClientReaderWriter;
template <class R>
class ClientAsyncReader;
template <class W>
class ClientAsyncWriter;
template <class R, class W>
class ClientAsyncReaderWriter;
template <class R>
class ClientAsyncResponseReader;
class ClientContext {
public:
ClientContext();
@ -57,18 +83,46 @@ class ClientContext {
void AddMetadata(const grpc::string &meta_key,
const grpc::string &meta_value);
const std::multimap<grpc::string, grpc::string>& GetServerInitialMetadata() {
GPR_ASSERT(initial_metadata_received_);
return recv_initial_metadata_;
}
const std::multimap<grpc::string, grpc::string>& GetServerTrailingMetadata() {
// TODO(yangg) check finished
return trailing_metadata_;
}
void set_absolute_deadline(const system_clock::time_point &deadline);
system_clock::time_point absolute_deadline();
void StartCancel();
void set_authority(const grpc::string& authority) {
authority_ = authority;
}
void TryCancel();
private:
// Disallow copy and assign.
ClientContext(const ClientContext &);
ClientContext &operator=(const ClientContext &);
friend class CallOpBuffer;
friend class Channel;
friend class StreamContext;
template <class R>
friend class ::grpc::ClientReader;
template <class W>
friend class ::grpc::ClientWriter;
template <class R, class W>
friend class ::grpc::ClientReaderWriter;
template <class R>
friend class ::grpc::ClientAsyncReader;
template <class W>
friend class ::grpc::ClientAsyncWriter;
template <class R, class W>
friend class ::grpc::ClientAsyncReaderWriter;
template <class R>
friend class ::grpc::ClientAsyncResponseReader;
grpc_call *call() { return call_; }
void set_call(grpc_call *call) {
@ -81,10 +135,18 @@ class ClientContext {
gpr_timespec RawDeadline() { return absolute_deadline_; }
grpc::string authority() {
return authority_;
}
bool initial_metadata_received_ = false;
grpc_call *call_;
grpc_completion_queue *cq_;
gpr_timespec absolute_deadline_;
std::vector<std::pair<grpc::string, grpc::string> > metadata_;
grpc::string authority_;
std::multimap<grpc::string, grpc::string> send_initial_metadata_;
std::multimap<grpc::string, grpc::string> recv_initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_;
};
} // namespace grpc

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,52 +34,89 @@
#ifndef __GRPCPP_COMPLETION_QUEUE_H__
#define __GRPCPP_COMPLETION_QUEUE_H__
#include <grpc++/impl/client_unary_call.h>
struct grpc_completion_queue;
namespace grpc {
template <class R>
class ClientReader;
template <class W>
class ClientWriter;
template <class R, class W>
class ClientReaderWriter;
template <class R>
class ServerReader;
template <class W>
class ServerWriter;
template <class R, class W>
class ServerReaderWriter;
class CompletionQueue;
class Server;
class ServerContext;
class CompletionQueueTag {
public:
virtual ~CompletionQueueTag() {}
// Called prior to returning from Next(), return value
// is the status of the operation (return status is the default thing
// to do)
// If this function returns false, the tag is dropped and not returned
// from the completion queue
virtual bool FinalizeResult(void **tag, bool *status) = 0;
};
// grpc_completion_queue wrapper class
class CompletionQueue {
public:
CompletionQueue();
explicit CompletionQueue(grpc_completion_queue *take);
~CompletionQueue();
enum CompletionType {
QUEUE_CLOSED = 0, // Shutting down.
RPC_END = 1, // An RPC finished. Either at client or server.
CLIENT_READ_OK = 2, // A client-side read has finished successfully.
CLIENT_READ_ERROR = 3, // A client-side read has finished with error.
CLIENT_WRITE_OK = 4,
CLIENT_WRITE_ERROR = 5,
SERVER_RPC_NEW = 6, // A new RPC just arrived at the server.
SERVER_READ_OK = 7, // A server-side read has finished successfully.
SERVER_READ_ERROR = 8, // A server-side read has finished with error.
SERVER_WRITE_OK = 9,
SERVER_WRITE_ERROR = 10,
// Client or server has sent half close successfully.
HALFCLOSE_OK = 11,
// New CompletionTypes may be added in the future, so user code should
// always
// handle the default case of a CompletionType that appears after such code
// was
// written.
DO_NOT_USE = 20,
};
// Blocking read from queue.
// For QUEUE_CLOSED, *tag is not changed.
// For SERVER_RPC_NEW, *tag will be a newly allocated AsyncServerContext.
// For others, *tag will be the AsyncServerContext of this rpc.
CompletionType Next(void** tag);
// Returns true if an event was received, false if the queue is ready
// for destruction.
bool Next(void **tag, bool *ok);
// Shutdown has to be called, and the CompletionQueue can only be
// destructed when the QUEUE_CLOSED message has been read with Next().
// destructed when false is returned from Next().
void Shutdown();
grpc_completion_queue* cq() { return cq_; }
grpc_completion_queue *cq() { return cq_; }
private:
grpc_completion_queue* cq_; // owned
// Friend synchronous wrappers so that they can access Pluck(), which is
// a semi-private API geared towards the synchronous implementation.
template <class R>
friend class ::grpc::ClientReader;
template <class W>
friend class ::grpc::ClientWriter;
template <class R, class W>
friend class ::grpc::ClientReaderWriter;
template <class R>
friend class ::grpc::ServerReader;
template <class W>
friend class ::grpc::ServerWriter;
template <class R, class W>
friend class ::grpc::ServerReaderWriter;
friend class ::grpc::Server;
friend class ::grpc::ServerContext;
friend Status BlockingUnaryCall(ChannelInterface *channel,
const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result);
// Wraps grpc_completion_queue_pluck.
// Cannot be mixed with calls to Next().
bool Pluck(CompletionQueueTag *tag);
// Does a single polling pluck on tag
void TryPluck(CompletionQueueTag *tag);
grpc_completion_queue *cq_; // owned
};
} // namespace grpc

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -39,6 +39,7 @@
namespace grpc {
typedef std::string string;
}
} // namespace grpc
#endif // __GRPCPP_CONFIG_H__

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -0,0 +1,145 @@
/*
*
* Copyright 2015, 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_CALL_H__
#define __GRPCPP_CALL_H__
#include <grpc/grpc.h>
#include <grpc++/status.h>
#include <grpc++/completion_queue.h>
#include <memory>
#include <map>
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
struct grpc_call;
struct grpc_op;
namespace grpc {
class Call;
class CallOpBuffer : public CompletionQueueTag {
public:
CallOpBuffer() : return_tag_(this) {}
~CallOpBuffer();
void Reset(void *next_return_tag);
// Does not take ownership.
void AddSendInitialMetadata(
std::multimap<grpc::string, grpc::string> *metadata);
void AddSendInitialMetadata(ClientContext *ctx);
void AddRecvInitialMetadata(ClientContext *ctx);
void AddSendMessage(const google::protobuf::Message &message);
void AddRecvMessage(google::protobuf::Message *message);
void AddClientSendClose();
void AddClientRecvStatus(ClientContext *ctx, Status *status);
void AddServerSendStatus(std::multimap<grpc::string, grpc::string> *metadata,
const Status &status);
void AddServerRecvClose(bool *cancelled);
// INTERNAL API:
// Convert to an array of grpc_op elements
void FillOps(grpc_op *ops, size_t *nops);
// Called by completion queue just prior to returning from Next() or Pluck()
bool FinalizeResult(void **tag, bool *status) override;
bool got_message = false;
private:
void *return_tag_ = nullptr;
// Send initial metadata
bool send_initial_metadata_ = false;
size_t initial_metadata_count_ = 0;
grpc_metadata *initial_metadata_ = nullptr;
// Recv initial metadta
std::multimap<grpc::string, grpc::string> *recv_initial_metadata_ = nullptr;
grpc_metadata_array recv_initial_metadata_arr_ = {0, 0, nullptr};
// Send message
const google::protobuf::Message *send_message_ = nullptr;
grpc_byte_buffer *send_message_buf_ = nullptr;
// Recv message
google::protobuf::Message *recv_message_ = nullptr;
grpc_byte_buffer *recv_message_buf_ = nullptr;
// Client send close
bool client_send_close_ = false;
// Client recv status
std::multimap<grpc::string, grpc::string> *recv_trailing_metadata_ = nullptr;
Status *recv_status_ = nullptr;
grpc_metadata_array recv_trailing_metadata_arr_ = {0, 0, nullptr};
grpc_status_code status_code_ = GRPC_STATUS_OK;
char *status_details_ = nullptr;
size_t status_details_capacity_ = 0;
// Server send status
const Status *send_status_ = nullptr;
size_t trailing_metadata_count_ = 0;
grpc_metadata *trailing_metadata_ = nullptr;
int cancelled_buf_;
bool *recv_closed_ = nullptr;
};
// Channel and Server implement this to allow them to hook performing ops
class CallHook {
public:
virtual ~CallHook() {}
virtual void PerformOpsOnCall(CallOpBuffer *ops, Call *call) = 0;
};
// Straightforward wrapping of the C call object
class Call final {
public:
/* call is owned by the caller */
Call(grpc_call *call, CallHook *call_hook_, CompletionQueue *cq);
void PerformOps(CallOpBuffer *buffer);
grpc_call *call() { return call_; }
CompletionQueue *cq() { return cq_; }
private:
CallHook *call_hook_;
CompletionQueue *cq_;
grpc_call *call_;
};
} // namespace grpc
#endif // __GRPCPP_CALL_INTERFACE_H__

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,40 +31,29 @@
*
*/
#ifndef __GRPCPP_ASYNC_SERVER_H__
#define __GRPCPP_ASYNC_SERVER_H__
#ifndef __GRPCPP_CLIENT_UNARY_CALL_H__
#define __GRPCPP_CLIENT_UNARY_CALL_H__
#include <mutex>
#include <grpc++/config.h>
struct grpc_server;
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
namespace grpc {
class CompletionQueue;
class AsyncServer {
public:
explicit AsyncServer(CompletionQueue* cc);
~AsyncServer();
void AddPort(const grpc::string& addr);
void Start();
// The user has to call this to get one new rpc on the completion
// queue.
void RequestOneRpc();
void Shutdown();
class ChannelInterface;
class ClientContext;
class CompletionQueue;
class RpcMethod;
class Status;
private:
bool started_;
std::mutex shutdown_mu_;
bool shutdown_;
grpc_server* server_;
};
// Wrapper that performs a blocking unary call
Status BlockingUnaryCall(ChannelInterface *channel, const RpcMethod &method,
ClientContext *context,
const google::protobuf::Message &request,
google::protobuf::Message *result);
} // namespace grpc
#endif // __GRPCPP_ASYNC_SERVER_H__
#endif

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -37,8 +37,8 @@
namespace google {
namespace protobuf {
class Message;
}
}
} // namespace protobuf
} // namespace google
namespace grpc {

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -55,25 +55,14 @@ 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),
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) {}
: call(c), server_context(context), request(req), 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 +103,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, param.server_context);
return func_(service_, param.server_context, &reader,
dynamic_cast<ResponseType*>(param.response));
}
@ -136,7 +125,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, param.server_context);
return func_(service_, param.server_context,
dynamic_cast<const RequestType*>(param.request), &writer);
}
@ -159,7 +148,8 @@ 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,
param.server_context);
return func_(service_, param.server_context, &stream);
}
@ -202,9 +192,7 @@ class RpcServiceMethod : public RpcMethod {
class RpcService {
public:
// Takes ownership.
void AddMethod(RpcServiceMethod* method) {
methods_.push_back(std::unique_ptr<RpcServiceMethod>(method));
}
void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); }
RpcServiceMethod* GetMethod(int i) { return methods_[i].get(); }
int GetMethodCount() const { return methods_.size(); }

@ -0,0 +1,127 @@
/*
*
* Copyright 2015, 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_IMPL_SERVICE_TYPE_H__
#define __GRPCPP_IMPL_SERVICE_TYPE_H__
namespace google {
namespace protobuf {
class Message;
} // namespace protobuf
} // namespace google
namespace grpc {
class Call;
class RpcService;
class Server;
class ServerContext;
class Status;
class SynchronousService {
public:
virtual ~SynchronousService() {}
virtual RpcService* service() = 0;
};
class ServerAsyncStreamingInterface {
public:
virtual ~ServerAsyncStreamingInterface() {}
virtual void SendInitialMetadata(void* tag) = 0;
private:
friend class Server;
virtual void BindCall(Call* call) = 0;
};
class AsynchronousService {
public:
// this is Server, but in disguise to avoid a link dependency
class DispatchImpl {
public:
virtual void RequestAsyncCall(void* registered_method,
ServerContext* context,
::google::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) = 0;
};
AsynchronousService(CompletionQueue* cq, const char** method_names,
size_t method_count)
: cq_(cq), method_names_(method_names), method_count_(method_count) {}
~AsynchronousService() { delete[] request_args_; }
CompletionQueue* completion_queue() const { return cq_; }
protected:
void RequestAsyncUnary(int index, ServerContext* context,
::google::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) {
dispatch_impl_->RequestAsyncCall(request_args_[index], context, request,
stream, cq, tag);
}
void RequestClientStreaming(int index, ServerContext* context,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) {
dispatch_impl_->RequestAsyncCall(request_args_[index], context, nullptr,
stream, cq, tag);
}
void RequestServerStreaming(int index, ServerContext* context,
::google::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) {
dispatch_impl_->RequestAsyncCall(request_args_[index], context, request,
stream, cq, tag);
}
void RequestBidiStreaming(int index, ServerContext* context,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag) {
dispatch_impl_->RequestAsyncCall(request_args_[index], context, nullptr,
stream, cq, tag);
}
private:
friend class Server;
CompletionQueue* const cq_;
DispatchImpl* dispatch_impl_ = nullptr;
const char** const method_names_;
size_t method_count_;
void** request_args_ = nullptr;
};
} // namespace grpc
#endif // __GRPCPP_IMPL_SERVICE_TYPE_H__

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -35,12 +35,14 @@
#define __GRPCPP_SERVER_H__
#include <condition_variable>
#include <map>
#include <list>
#include <memory>
#include <mutex>
#include <grpc++/completion_queue.h>
#include <grpc++/config.h>
#include <grpc++/impl/call.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/status.h>
struct grpc_server;
@ -48,18 +50,19 @@ struct grpc_server;
namespace google {
namespace protobuf {
class Message;
}
}
} // namespace protobuf
} // namespace google
namespace grpc {
class AsyncServerContext;
class AsynchronousService;
class RpcService;
class RpcServiceMethod;
class ServerCredentials;
class ThreadPoolInterface;
// Currently it only supports handling rpcs in a single thread.
class Server {
class Server final : private CallHook,
private AsynchronousService::DispatchImpl {
public:
~Server();
@ -69,22 +72,34 @@ class Server {
private:
friend class ServerBuilder;
class SyncRequest;
class AsyncRequest;
// ServerBuilder use only
Server(ThreadPoolInterface* thread_pool, ServerCredentials* creds);
Server(ThreadPoolInterface* thread_pool, bool thread_pool_owned,
ServerCredentials* creds);
Server();
// Register a service. This call does not take ownership of the service.
// The service must exist for the lifetime of the Server instance.
void RegisterService(RpcService* service);
bool RegisterService(RpcService* service);
bool RegisterAsyncService(AsynchronousService* service);
// Add a listening port. Can be called multiple times.
void AddPort(const grpc::string& addr);
int AddPort(const grpc::string& addr);
// Start the server.
void Start();
bool Start();
void AllowOneRpc();
void HandleQueueClosed();
void RunRpc();
void ScheduleCallback();
void PerformOpsOnCall(CallOpBuffer* ops, Call* call) override;
// DispatchImpl
void RequestAsyncCall(void* registered_method, ServerContext* context,
::google::protobuf::Message* request,
ServerAsyncStreamingInterface* stream,
CompletionQueue* cq, void* tag);
// Completion queue.
CompletionQueue cq_;
@ -96,12 +111,11 @@ class Server {
int num_running_cb_;
std::condition_variable callback_cv_;
std::list<SyncRequest> sync_methods_;
// Pointer to the c grpc server.
grpc_server* server_;
// A map for all method information.
std::map<grpc::string, RpcServiceMethod*> method_map_;
ThreadPoolInterface* thread_pool_;
// Whether the thread pool is created and owned by the server.
bool thread_pool_owned_;

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -41,9 +41,12 @@
namespace grpc {
class AsynchronousService;
class CompletionQueue;
class RpcService;
class Server;
class ServerCredentials;
class SynchronousService;
class ThreadPoolInterface;
class ServerBuilder {
@ -53,7 +56,13 @@ class ServerBuilder {
// Register a service. This call does not take ownership of the service.
// The service must exist for the lifetime of the Server instance returned by
// BuildAndStart().
void RegisterService(RpcService* service);
void RegisterService(SynchronousService* service);
// Register an asynchronous service. New calls will be delevered to cq.
// This call does not take ownership of the service or completion queue.
// The service and completion queuemust exist for the lifetime of the Server
// instance returned by BuildAndStart().
void RegisterAsyncService(AsynchronousService* service);
// Add a listening port. Can be called multiple times.
void AddPort(const grpc::string& addr);
@ -71,9 +80,10 @@ class ServerBuilder {
private:
std::vector<RpcService*> services_;
std::vector<AsynchronousService*> async_services_;
std::vector<grpc::string> ports_;
std::shared_ptr<ServerCredentials> creds_;
ThreadPoolInterface* thread_pool_;
ThreadPoolInterface* thread_pool_ = nullptr;
};
} // namespace grpc

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -35,15 +35,88 @@
#define __GRPCPP_SERVER_CONTEXT_H_
#include <chrono>
#include <map>
#include "config.h"
struct gpr_timespec;
struct grpc_metadata;
struct grpc_call;
namespace grpc {
template <class W, class R>
class ServerAsyncReader;
template <class W>
class ServerAsyncWriter;
template <class W>
class ServerAsyncResponseWriter;
template <class R, class W>
class ServerAsyncReaderWriter;
template <class R>
class ServerReader;
template <class W>
class ServerWriter;
template <class R, class W>
class ServerReaderWriter;
class Call;
class CallOpBuffer;
class CompletionQueue;
class Server;
// Interface of server side rpc context.
class ServerContext {
class ServerContext final {
public:
virtual ~ServerContext() {}
ServerContext(); // for async calls
~ServerContext();
std::chrono::system_clock::time_point absolute_deadline() {
return deadline_;
}
void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
bool IsCancelled();
const std::multimap<grpc::string, grpc::string>& client_metadata() {
return client_metadata_;
}
private:
friend class ::grpc::Server;
template <class W, class R>
friend class ::grpc::ServerAsyncReader;
template <class W>
friend class ::grpc::ServerAsyncWriter;
template <class W>
friend class ::grpc::ServerAsyncResponseWriter;
template <class R, class W>
friend class ::grpc::ServerAsyncReaderWriter;
template <class R>
friend class ::grpc::ServerReader;
template <class W>
friend class ::grpc::ServerWriter;
template <class R, class W>
friend class ::grpc::ServerReaderWriter;
class CompletionOp;
void BeginCompletionOp(Call* call);
ServerContext(gpr_timespec deadline, grpc_metadata* metadata,
size_t metadata_count);
CompletionOp* completion_op_ = nullptr;
virtual std::chrono::system_clock::time_point absolute_deadline() const = 0;
std::chrono::system_clock::time_point deadline_;
grpc_call* call_ = nullptr;
CompletionQueue* cq_ = nullptr;
bool sent_initial_metadata_ = false;
std::multimap<grpc::string, grpc::string> client_metadata_;
std::multimap<grpc::string, grpc::string> initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_;
};
} // namespace grpc

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,7 +34,12 @@
#ifndef __GRPCPP_STREAM_H__
#define __GRPCPP_STREAM_H__
#include <grpc++/stream_context_interface.h>
#include <grpc++/channel_interface.h>
#include <grpc++/client_context.h>
#include <grpc++/completion_queue.h>
#include <grpc++/server_context.h>
#include <grpc++/impl/call.h>
#include <grpc++/impl/service_type.h>
#include <grpc++/status.h>
#include <grpc/support/log.h>
@ -45,16 +50,12 @@ class ClientStreamingInterface {
public:
virtual ~ClientStreamingInterface() {}
// Try to cancel the stream. Wait() still needs to be called to get the final
// status. Cancelling after the stream has finished has no effects.
virtual void Cancel() = 0;
// Wait until the stream finishes, and return the final status. When the
// client side declares it has no more message to send, either implicitly or
// by calling WritesDone, it needs to make sure there is no more message to
// be received from the server, either implicitly or by getting a false from
// a Read(). Otherwise, this implicitly cancels the stream.
virtual const Status& Wait() = 0;
virtual Status Finish() = 0;
};
// An interface that yields a sequence of R messages.
@ -82,147 +83,629 @@ class WriterInterface {
};
template <class R>
class ClientReader : public ClientStreamingInterface,
class ClientReader final : public ClientStreamingInterface,
public ReaderInterface<R> {
public:
// Blocking create a stream and write the first request out.
explicit ClientReader(StreamContextInterface* context) : context_(context) {
GPR_ASSERT(context_);
context_->Start(true);
context_->Write(context_->request(), true);
ClientReader(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, const google::protobuf::Message& request)
: context_(context), call_(channel->CreateCall(method, context, &cq_)) {
CallOpBuffer buf;
buf.AddSendInitialMetadata(&context->send_initial_metadata_);
buf.AddSendMessage(request);
buf.AddClientSendClose();
call_.PerformOps(&buf);
cq_.Pluck(&buf);
}
~ClientReader() { delete context_; }
virtual bool Read(R* msg) { return context_->Read(msg); }
// Blocking wait for initial metadata from server. The received metadata
// can only be accessed after this call returns. Should only be called before
// the first read. Calling this method is optional, and if it is not called
// the metadata will be available in ClientContext after the first read.
void WaitForInitialMetadata() {
GPR_ASSERT(!context_->initial_metadata_received_);
CallOpBuffer buf;
buf.AddRecvInitialMetadata(context_);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
}
virtual void Cancel() { context_->Cancel(); }
virtual bool Read(R* msg) override {
CallOpBuffer buf;
if (!context_->initial_metadata_received_) {
buf.AddRecvInitialMetadata(context_);
}
buf.AddRecvMessage(msg);
call_.PerformOps(&buf);
return cq_.Pluck(&buf) && buf.got_message;
}
virtual const Status& Wait() { return context_->Wait(); }
virtual Status Finish() override {
CallOpBuffer buf;
Status status;
buf.AddClientRecvStatus(context_, &status);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
return status;
}
private:
StreamContextInterface* const context_;
ClientContext* context_;
CompletionQueue cq_;
Call call_;
};
template <class W>
class ClientWriter : public ClientStreamingInterface,
class ClientWriter final : public ClientStreamingInterface,
public WriterInterface<W> {
public:
// Blocking create a stream.
explicit ClientWriter(StreamContextInterface* context) : context_(context) {
GPR_ASSERT(context_);
context_->Start(false);
ClientWriter(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context, google::protobuf::Message* response)
: context_(context),
response_(response),
call_(channel->CreateCall(method, context, &cq_)) {
CallOpBuffer buf;
buf.AddSendInitialMetadata(&context->send_initial_metadata_);
call_.PerformOps(&buf);
cq_.Pluck(&buf);
}
~ClientWriter() { delete context_; }
virtual bool Write(const W& msg) {
return context_->Write(const_cast<W*>(&msg), false);
virtual bool Write(const W& msg) override {
CallOpBuffer buf;
buf.AddSendMessage(msg);
call_.PerformOps(&buf);
return cq_.Pluck(&buf);
}
virtual void WritesDone() { context_->Write(nullptr, true); }
virtual void Cancel() { context_->Cancel(); }
virtual bool WritesDone() {
CallOpBuffer buf;
buf.AddClientSendClose();
call_.PerformOps(&buf);
return cq_.Pluck(&buf);
}
// Read the final response and wait for the final status.
virtual const Status& Wait() {
bool success = context_->Read(context_->response());
if (!success) {
Cancel();
} else {
success = context_->Read(nullptr);
if (success) {
Cancel();
}
}
return context_->Wait();
virtual Status Finish() override {
CallOpBuffer buf;
Status status;
buf.AddRecvMessage(response_);
buf.AddClientRecvStatus(context_, &status);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf) && buf.got_message);
return status;
}
private:
StreamContextInterface* const context_;
ClientContext* context_;
google::protobuf::Message* const response_;
CompletionQueue cq_;
Call call_;
};
// Client-side interface for bi-directional streaming.
template <class W, class R>
class ClientReaderWriter : public ClientStreamingInterface,
class ClientReaderWriter final : public ClientStreamingInterface,
public WriterInterface<W>,
public ReaderInterface<R> {
public:
// Blocking create a stream.
explicit ClientReaderWriter(StreamContextInterface* context)
: context_(context) {
GPR_ASSERT(context_);
context_->Start(false);
ClientReaderWriter(ChannelInterface* channel, const RpcMethod& method,
ClientContext* context)
: context_(context), call_(channel->CreateCall(method, context, &cq_)) {
CallOpBuffer buf;
buf.AddSendInitialMetadata(&context->send_initial_metadata_);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
}
~ClientReaderWriter() { delete context_; }
virtual bool Read(R* msg) { return context_->Read(msg); }
// Blocking wait for initial metadata from server. The received metadata
// can only be accessed after this call returns. Should only be called before
// the first read. Calling this method is optional, and if it is not called
// the metadata will be available in ClientContext after the first read.
void WaitForInitialMetadata() {
GPR_ASSERT(!context_->initial_metadata_received_);
CallOpBuffer buf;
buf.AddRecvInitialMetadata(context_);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
}
virtual bool Write(const W& msg) {
return context_->Write(const_cast<W*>(&msg), false);
virtual bool Read(R* msg) override {
CallOpBuffer buf;
if (!context_->initial_metadata_received_) {
buf.AddRecvInitialMetadata(context_);
}
buf.AddRecvMessage(msg);
call_.PerformOps(&buf);
return cq_.Pluck(&buf) && buf.got_message;
}
virtual void WritesDone() { context_->Write(nullptr, true); }
virtual bool Write(const W& msg) override {
CallOpBuffer buf;
buf.AddSendMessage(msg);
call_.PerformOps(&buf);
return cq_.Pluck(&buf);
}
virtual void Cancel() { context_->Cancel(); }
virtual bool WritesDone() {
CallOpBuffer buf;
buf.AddClientSendClose();
call_.PerformOps(&buf);
return cq_.Pluck(&buf);
}
virtual const Status& Wait() { return context_->Wait(); }
virtual Status Finish() override {
CallOpBuffer buf;
Status status;
buf.AddClientRecvStatus(context_, &status);
call_.PerformOps(&buf);
GPR_ASSERT(cq_.Pluck(&buf));
return status;
}
private:
StreamContextInterface* const context_;
ClientContext* context_;
CompletionQueue cq_;
Call call_;
};
template <class R>
class ServerReader : public ReaderInterface<R> {
class ServerReader final : public ReaderInterface<R> {
public:
explicit ServerReader(StreamContextInterface* context) : context_(context) {
GPR_ASSERT(context_);
context_->Start(true);
ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
CallOpBuffer buf;
buf.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&buf);
call_->cq()->Pluck(&buf);
}
virtual bool Read(R* msg) { return context_->Read(msg); }
virtual bool Read(R* msg) override {
CallOpBuffer buf;
buf.AddRecvMessage(msg);
call_->PerformOps(&buf);
return call_->cq()->Pluck(&buf) && buf.got_message;
}
private:
StreamContextInterface* const context_; // not owned
Call* const call_;
ServerContext* const ctx_;
};
template <class W>
class ServerWriter : public WriterInterface<W> {
class ServerWriter final : public WriterInterface<W> {
public:
explicit ServerWriter(StreamContextInterface* context) : context_(context) {
GPR_ASSERT(context_);
context_->Start(true);
context_->Read(context_->request());
ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
CallOpBuffer buf;
buf.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&buf);
call_->cq()->Pluck(&buf);
}
virtual bool Write(const W& msg) {
return context_->Write(const_cast<W*>(&msg), false);
virtual bool Write(const W& msg) override {
CallOpBuffer buf;
if (!ctx_->sent_initial_metadata_) {
buf.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
buf.AddSendMessage(msg);
call_->PerformOps(&buf);
return call_->cq()->Pluck(&buf);
}
private:
StreamContextInterface* const context_; // not owned
Call* const call_;
ServerContext* const ctx_;
};
// Server-side interface for bi-directional streaming.
template <class W, class R>
class ServerReaderWriter : public WriterInterface<W>,
class ServerReaderWriter final : public WriterInterface<W>,
public ReaderInterface<R> {
public:
explicit ServerReaderWriter(StreamContextInterface* context)
: context_(context) {
GPR_ASSERT(context_);
context_->Start(true);
ServerReaderWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
CallOpBuffer buf;
buf.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_->PerformOps(&buf);
call_->cq()->Pluck(&buf);
}
virtual bool Read(R* msg) override {
CallOpBuffer buf;
buf.AddRecvMessage(msg);
call_->PerformOps(&buf);
return call_->cq()->Pluck(&buf) && buf.got_message;
}
virtual bool Write(const W& msg) override {
CallOpBuffer buf;
if (!ctx_->sent_initial_metadata_) {
buf.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
buf.AddSendMessage(msg);
call_->PerformOps(&buf);
return call_->cq()->Pluck(&buf);
}
private:
Call* const call_;
ServerContext* const ctx_;
};
// Async interfaces
// Common interface for all client side streaming.
class ClientAsyncStreamingInterface {
public:
virtual ~ClientAsyncStreamingInterface() {}
virtual void ReadInitialMetadata(void* tag) = 0;
virtual void Finish(Status* status, void* tag) = 0;
};
// An interface that yields a sequence of R messages.
template <class R>
class AsyncReaderInterface {
public:
virtual ~AsyncReaderInterface() {}
virtual void Read(R* msg, void* tag) = 0;
};
// An interface that can be fed a sequence of W messages.
template <class W>
class AsyncWriterInterface {
public:
virtual ~AsyncWriterInterface() {}
virtual void Write(const W& msg, void* tag) = 0;
};
template <class R>
class ClientAsyncReader final : public ClientAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public:
// Create a stream and write the first request out.
ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const google::protobuf::Message& request, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
init_buf_.AddSendMessage(request);
init_buf_.AddClientSendClose();
call_.PerformOps(&init_buf_);
}
void ReadInitialMetadata(void* tag) override {
GPR_ASSERT(!context_->initial_metadata_received_);
meta_buf_.Reset(tag);
meta_buf_.AddRecvInitialMetadata(context_);
call_.PerformOps(&meta_buf_);
}
void Read(R* msg, void* tag) override {
read_buf_.Reset(tag);
if (!context_->initial_metadata_received_) {
read_buf_.AddRecvInitialMetadata(context_);
}
read_buf_.AddRecvMessage(msg);
call_.PerformOps(&read_buf_);
}
void Finish(Status* status, void* tag) override {
finish_buf_.Reset(tag);
if (!context_->initial_metadata_received_) {
finish_buf_.AddRecvInitialMetadata(context_);
}
finish_buf_.AddClientRecvStatus(context_, status);
call_.PerformOps(&finish_buf_);
}
private:
ClientContext* context_ = nullptr;
Call call_;
CallOpBuffer init_buf_;
CallOpBuffer meta_buf_;
CallOpBuffer read_buf_;
CallOpBuffer finish_buf_;
};
template <class W>
class ClientAsyncWriter final : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
google::protobuf::Message* response, void* tag)
: context_(context),
response_(response),
call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
call_.PerformOps(&init_buf_);
}
void ReadInitialMetadata(void* tag) override {
GPR_ASSERT(!context_->initial_metadata_received_);
meta_buf_.Reset(tag);
meta_buf_.AddRecvInitialMetadata(context_);
call_.PerformOps(&meta_buf_);
}
void Write(const W& msg, void* tag) override {
write_buf_.Reset(tag);
write_buf_.AddSendMessage(msg);
call_.PerformOps(&write_buf_);
}
void WritesDone(void* tag) {
writes_done_buf_.Reset(tag);
writes_done_buf_.AddClientSendClose();
call_.PerformOps(&writes_done_buf_);
}
void Finish(Status* status, void* tag) override {
finish_buf_.Reset(tag);
if (!context_->initial_metadata_received_) {
finish_buf_.AddRecvInitialMetadata(context_);
}
finish_buf_.AddRecvMessage(response_);
finish_buf_.AddClientRecvStatus(context_, status);
call_.PerformOps(&finish_buf_);
}
private:
ClientContext* context_ = nullptr;
google::protobuf::Message* const response_;
Call call_;
CallOpBuffer init_buf_;
CallOpBuffer meta_buf_;
CallOpBuffer write_buf_;
CallOpBuffer writes_done_buf_;
CallOpBuffer finish_buf_;
};
// Client-side interface for bi-directional streaming.
template <class W, class R>
class ClientAsyncReaderWriter final : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
ClientAsyncReaderWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_buf_.Reset(tag);
init_buf_.AddSendInitialMetadata(&context->send_initial_metadata_);
call_.PerformOps(&init_buf_);
}
void ReadInitialMetadata(void* tag) override {
GPR_ASSERT(!context_->initial_metadata_received_);
meta_buf_.Reset(tag);
meta_buf_.AddRecvInitialMetadata(context_);
call_.PerformOps(&meta_buf_);
}
void Read(R* msg, void* tag) override {
read_buf_.Reset(tag);
if (!context_->initial_metadata_received_) {
read_buf_.AddRecvInitialMetadata(context_);
}
read_buf_.AddRecvMessage(msg);
call_.PerformOps(&read_buf_);
}
void Write(const W& msg, void* tag) override {
write_buf_.Reset(tag);
write_buf_.AddSendMessage(msg);
call_.PerformOps(&write_buf_);
}
void WritesDone(void* tag) {
writes_done_buf_.Reset(tag);
writes_done_buf_.AddClientSendClose();
call_.PerformOps(&writes_done_buf_);
}
void Finish(Status* status, void* tag) override {
finish_buf_.Reset(tag);
if (!context_->initial_metadata_received_) {
finish_buf_.AddRecvInitialMetadata(context_);
}
finish_buf_.AddClientRecvStatus(context_, status);
call_.PerformOps(&finish_buf_);
}
private:
ClientContext* context_ = nullptr;
Call call_;
CallOpBuffer init_buf_;
CallOpBuffer meta_buf_;
CallOpBuffer read_buf_;
CallOpBuffer write_buf_;
CallOpBuffer writes_done_buf_;
CallOpBuffer finish_buf_;
};
template <class W, class R>
class ServerAsyncReader : public ServerAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public:
explicit ServerAsyncReader(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) override {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
meta_buf_.Reset(tag);
meta_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_buf_);
}
void Read(R* msg, void* tag) override {
read_buf_.Reset(tag);
read_buf_.AddRecvMessage(msg);
call_.PerformOps(&read_buf_);
}
void Finish(const W& msg, const Status& status, void* tag) {
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
if (status.IsOk()) {
finish_buf_.AddSendMessage(msg);
}
finish_buf_.AddServerSendStatus(&ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
void FinishWithError(const Status& status, void* tag) {
GPR_ASSERT(!status.IsOk());
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_buf_.AddServerSendStatus(&ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
private:
void BindCall(Call* call) override { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpBuffer meta_buf_;
CallOpBuffer read_buf_;
CallOpBuffer finish_buf_;
};
template <class W>
class ServerAsyncWriter : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
explicit ServerAsyncWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) override {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
meta_buf_.Reset(tag);
meta_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_buf_);
}
void Write(const W& msg, void* tag) override {
write_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
write_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
write_buf_.AddSendMessage(msg);
call_.PerformOps(&write_buf_);
}
void Finish(const Status& status, void* tag) {
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_buf_.AddServerSendStatus(&ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
private:
void BindCall(Call* call) override { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpBuffer meta_buf_;
CallOpBuffer write_buf_;
CallOpBuffer finish_buf_;
};
// Server-side interface for bi-directional streaming.
template <class W, class R>
class ServerAsyncReaderWriter : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
explicit ServerAsyncReaderWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) override {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
meta_buf_.Reset(tag);
meta_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_buf_);
}
virtual bool Read(R* msg) { return context_->Read(msg); }
virtual void Read(R* msg, void* tag) override {
read_buf_.Reset(tag);
read_buf_.AddRecvMessage(msg);
call_.PerformOps(&read_buf_);
}
virtual bool Write(const W& msg) {
return context_->Write(const_cast<W*>(&msg), false);
virtual void Write(const W& msg, void* tag) override {
write_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
write_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
write_buf_.AddSendMessage(msg);
call_.PerformOps(&write_buf_);
}
void Finish(const Status& status, void* tag) {
finish_buf_.Reset(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.AddSendInitialMetadata(&ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_buf_.AddServerSendStatus(&ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_buf_);
}
private:
StreamContextInterface* const context_; // not owned
void BindCall(Call* call) override { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpBuffer meta_buf_;
CallOpBuffer read_buf_;
CallOpBuffer write_buf_;
CallOpBuffer finish_buf_;
};
} // namespace grpc

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -92,7 +92,12 @@ typedef struct {
} value;
} grpc_arg;
/* An array of arguments that can be passed around */
/* An array of arguments that can be passed around.
Used to set optional channel-level configuration.
These configuration options are modelled as key-value pairs as defined
by grpc_arg; keys are strings to allow easy backwards-compatible extension
by arbitrary parties.
All evaluation is performed at channel creation time. */
typedef struct {
size_t num_args;
grpc_arg *args;
@ -255,15 +260,18 @@ void grpc_call_details_init(grpc_call_details *details);
void grpc_call_details_destroy(grpc_call_details *details);
typedef enum {
/* Send initial metadata: one and only one instance MUST be sent for each call,
/* Send initial metadata: one and only one instance MUST be sent for each
call,
unless the call was cancelled - in which case this can be skipped */
GRPC_OP_SEND_INITIAL_METADATA = 0,
/* Send a message: 0 or more of these operations can occur for each call */
GRPC_OP_SEND_MESSAGE,
/* Send a close from the server: one and only one instance MUST be sent from the client,
/* Send a close from the server: one and only one instance MUST be sent from
the client,
unless the call was cancelled - in which case this can be skipped */
GRPC_OP_SEND_CLOSE_FROM_CLIENT,
/* Send status from the server: one and only one instance MUST be sent from the server
/* Send status from the server: one and only one instance MUST be sent from
the server
unless the call was cancelled - in which case this can be skipped */
GRPC_OP_SEND_STATUS_FROM_SERVER,
/* Receive initial metadata: one and only one MUST be made on the client, must
@ -271,13 +279,16 @@ typedef enum {
GRPC_OP_RECV_INITIAL_METADATA,
/* Receive a message: 0 or more of these operations can occur for each call */
GRPC_OP_RECV_MESSAGE,
/* Receive status on the client: one and only one must be made on the client */
/* Receive status on the client: one and only one must be made on the client
*/
GRPC_OP_RECV_STATUS_ON_CLIENT,
/* Receive status on the server: one and only one must be made on the server */
/* Receive status on the server: one and only one must be made on the server
*/
GRPC_OP_RECV_CLOSE_ON_SERVER
} grpc_op_type;
/* Operation data: one field for each op type (except SEND_CLOSE_FROM_CLIENT which has
/* Operation data: one field for each op type (except SEND_CLOSE_FROM_CLIENT
which has
no arguments) */
typedef struct grpc_op {
grpc_op_type op;
@ -301,16 +312,20 @@ typedef struct grpc_op {
grpc_metadata_array *recv_initial_metadata;
grpc_byte_buffer **recv_message;
struct {
/* ownership of the array is with the caller, but ownership of the elements
/* ownership of the array is with the caller, but ownership of the
elements
stays with the call object (ie key, value members are owned by the call
object, trailing_metadata->array is owned by the caller).
After the operation completes, call grpc_metadata_array_destroy on this
value, or reuse it in a future op. */
grpc_metadata_array *trailing_metadata;
grpc_status_code *status;
/* status_details is a buffer owned by the application before the op completes
and after the op has completed. During the operation status_details may be
reallocated to a size larger than *status_details_capacity, in which case
/* status_details is a buffer owned by the application before the op
completes
and after the op has completed. During the operation status_details may
be
reallocated to a size larger than *status_details_capacity, in which
case
*status_details_capacity will be updated with the new array capacity.
Pre-allocating space:
@ -331,17 +346,26 @@ typedef struct grpc_op {
size_t *status_details_capacity;
} recv_status_on_client;
struct {
/* out argument, set to 1 if the call failed in any way (seen as a cancellation
/* out argument, set to 1 if the call failed in any way (seen as a
cancellation
on the server), or 0 if the call succeeded */
int *cancelled;
} recv_close_on_server;
} data;
} grpc_op;
/* Initialize the grpc library */
/* Initialize the grpc library.
It is not safe to call any other grpc functions before calling this.
(To avoid overhead, little checking is done, and some things may work. We
do not warrant that they will continue to do so in future revisions of this
library). */
void grpc_init(void);
/* Shut down the grpc library */
/* Shut down the grpc library.
No memory is used by grpc after this call returns, nor are any instructions
executing within the grpc library.
Prior to calling, all application owned grpc objects must have been
destroyed. */
void grpc_shutdown(void);
grpc_completion_queue *grpc_completion_queue_create(void);
@ -370,7 +394,12 @@ grpc_event *grpc_completion_queue_pluck(grpc_completion_queue *cq, void *tag,
void grpc_event_finish(grpc_event *event);
/* Begin destruction of a completion queue. Once all possible events are
drained it's safe to call grpc_completion_queue_destroy. */
drained then grpc_completion_queue_next will start to produce
GRPC_QUEUE_SHUTDOWN events only. At that point it's safe to call
grpc_completion_queue_destroy.
After calling this function applications should ensure that no
NEW work is added to be published on this completion queue. */
void grpc_completion_queue_shutdown(grpc_completion_queue *cq);
/* Destroy a completion queue. The caller must ensure that the queue is
@ -400,7 +429,10 @@ grpc_call *grpc_channel_create_call(grpc_channel *channel,
grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
size_t nops, void *tag);
/* Create a client channel */
/* Create a client channel to 'target'. Additional channel level configuration
MAY be provided by grpc_channel_args, though the expectation is that most
clients will want to simply pass NULL. See grpc_channel_args definition
for more on this. */
grpc_channel *grpc_channel_create(const char *target,
const grpc_channel_args *args);
@ -540,12 +572,34 @@ void grpc_call_destroy(grpc_call *call);
grpc_call_error grpc_server_request_call_old(grpc_server *server,
void *tag_new);
/* Request notification of a new call */
grpc_call_error grpc_server_request_call(
grpc_server *server, grpc_call **call, grpc_call_details *details,
grpc_metadata_array *request_metadata,
grpc_completion_queue *completion_queue, void *tag_new);
grpc_completion_queue *cq_bound_to_call,
void *tag_new);
/* Create a server */
/* Registers a method in the server.
Methods to this (host, method) pair will not be reported by
grpc_server_request_call, but instead be reported by
grpc_server_request_registered_call when passed the appropriate
registered_method (as returned by this function).
Must be called before grpc_server_start.
Returns NULL on failure. */
void *grpc_server_register_method(grpc_server *server, const char *method,
const char *host,
grpc_completion_queue *new_call_cq);
/* Request notification of a new pre-registered call */
grpc_call_error grpc_server_request_registered_call(
grpc_server *server, void *registered_method, grpc_call **call,
gpr_timespec *deadline, grpc_metadata_array *request_metadata,
grpc_byte_buffer **optional_payload,
grpc_completion_queue *cq_bound_to_call, void *tag_new);
/* Create a server. Additional configuration for each incoming channel can
be specified with args. If no additional configuration is needed, args can
be NULL. See grpc_channel_args for more. */
grpc_server *grpc_server_create(grpc_completion_queue *cq,
const grpc_channel_args *args);

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,6 +34,10 @@
#ifndef __GRPC_INTERNAL_SUPPORT_CPU_H__
#define __GRPC_INTERNAL_SUPPORT_CPU_H__
#ifdef __cplusplus
extern "C" {
#endif
/* Interface providing CPU information for currently running system */
/* Return the number of CPU cores on the current system. Will return 0 if
@ -46,4 +50,8 @@ unsigned gpr_cpu_num_cores(void);
[0, gpr_cpu_num_cores() - 1] */
unsigned gpr_cpu_current_cpu(void);
#ifdef __cplusplus
} // extern "C"
#endif
#endif /* __GRPC_INTERNAL_SUPPORT_CPU_H__ */

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -41,10 +41,18 @@
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <sstream>
namespace grpc_cpp_generator {
namespace {
template <class T>
std::string as_string(T x) {
std::ostringstream out;
out << x;
return out.str();
}
bool NoStreaming(const google::protobuf::MethodDescriptor *method) {
return !method->client_streaming() && !method->server_streaming();
}
@ -61,6 +69,17 @@ bool BidiStreaming(const google::protobuf::MethodDescriptor *method) {
return method->client_streaming() && method->server_streaming();
}
bool HasUnaryCalls(const google::protobuf::FileDescriptor *file) {
for (int i = 0; i < file->service_count(); i++) {
for (int j = 0; j < file->service(i)->method_count(); j++) {
if (NoStreaming(file->service(i)->method(j))) {
return true;
}
}
}
return false;
}
bool HasClientOnlyStreaming(const google::protobuf::FileDescriptor *file) {
for (int i = 0; i < file->service_count(); i++) {
for (int j = 0; j < file->service(i)->method_count(); j++) {
@ -97,20 +116,32 @@ bool HasBidiStreaming(const google::protobuf::FileDescriptor *file) {
std::string GetHeaderIncludes(const google::protobuf::FileDescriptor *file) {
std::string temp =
"#include \"grpc++/impl/internal_stub.h\"\n"
"#include \"grpc++/status.h\"\n"
"#include <grpc++/impl/internal_stub.h>\n"
"#include <grpc++/impl/service_type.h>\n"
"#include <grpc++/status.h>\n"
"\n"
"namespace grpc {\n"
"class CompletionQueue;\n"
"class ChannelInterface;\n"
"class RpcService;\n"
"class ServerContext;\n";
if (HasUnaryCalls(file)) {
temp.append(
"template <class OutMessage> class ClientAsyncResponseReader;\n");
temp.append(
"template <class OutMessage> class ServerAsyncResponseWriter;\n");
}
if (HasClientOnlyStreaming(file)) {
temp.append("template <class OutMessage> class ClientWriter;\n");
temp.append("template <class InMessage> class ServerReader;\n");
temp.append("template <class OutMessage> class ClientAsyncWriter;\n");
temp.append("template <class OutMessage, class InMessage> class ServerAsyncReader;\n");
}
if (HasServerOnlyStreaming(file)) {
temp.append("template <class InMessage> class ClientReader;\n");
temp.append("template <class OutMessage> class ServerWriter;\n");
temp.append("template <class OutMessage> class ClientAsyncReader;\n");
temp.append("template <class InMessage> class ServerAsyncWriter;\n");
}
if (HasBidiStreaming(file)) {
temp.append(
@ -119,16 +150,25 @@ std::string GetHeaderIncludes(const google::protobuf::FileDescriptor *file) {
temp.append(
"template <class OutMessage, class InMessage>\n"
"class ServerReaderWriter;\n");
temp.append(
"template <class OutMessage, class InMessage>\n"
"class ClientAsyncReaderWriter;\n");
temp.append(
"template <class OutMessage, class InMessage>\n"
"class ServerAsyncReaderWriter;\n");
}
temp.append("} // namespace grpc\n");
return temp;
}
std::string GetSourceIncludes() {
return "#include \"grpc++/channel_interface.h\"\n"
"#include \"grpc++/impl/rpc_method.h\"\n"
"#include \"grpc++/impl/rpc_service_method.h\"\n"
"#include \"grpc++/stream.h\"\n";
return "#include <grpc++/async_unary_call.h>\n"
"#include <grpc++/channel_interface.h>\n"
"#include <grpc++/impl/client_unary_call.h>\n"
"#include <grpc++/impl/rpc_method.h>\n"
"#include <grpc++/impl/rpc_service_method.h>\n"
"#include <grpc++/impl/service_type.h>\n"
"#include <grpc++/stream.h>\n";
}
void PrintHeaderClientMethod(google::protobuf::io::Printer *printer,
@ -142,25 +182,42 @@ void PrintHeaderClientMethod(google::protobuf::io::Printer *printer,
if (NoStreaming(method)) {
printer->Print(*vars,
"::grpc::Status $Method$(::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response);\n\n");
"const $Request$& request, $Response$* response);\n");
printer->Print(*vars,
"::grpc::ClientAsyncResponseReader< $Response$>* "
"$Method$(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag);\n");
} else if (ClientOnlyStreaming(method)) {
printer->Print(
*vars,
printer->Print(*vars,
"::grpc::ClientWriter< $Request$>* $Method$("
"::grpc::ClientContext* context, $Response$* response);\n\n");
"::grpc::ClientContext* context, $Response$* response);\n");
printer->Print(*vars,
"::grpc::ClientAsyncWriter< $Request$>* $Method$("
"::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq, void* tag);\n");
} else if (ServerOnlyStreaming(method)) {
printer->Print(
*vars,
"::grpc::ClientReader< $Response$>* $Method$("
"::grpc::ClientContext* context, const $Request$* request);\n\n");
"::grpc::ClientContext* context, const $Request$& request);\n");
printer->Print(*vars,
"::grpc::ClientAsyncReader< $Response$>* $Method$("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag);\n");
} else if (BidiStreaming(method)) {
printer->Print(*vars,
"::grpc::ClientReaderWriter< $Request$, $Response$>* "
"$Method$(::grpc::ClientContext* context);\n\n");
"$Method$(::grpc::ClientContext* context);\n");
printer->Print(*vars,
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
"$Method$(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq, void* tag);\n");
}
}
void PrintHeaderServerMethod(google::protobuf::io::Printer *printer,
void PrintHeaderServerMethodSync(
google::protobuf::io::Printer *printer,
const google::protobuf::MethodDescriptor *method,
std::map<std::string, std::string> *vars) {
(*vars)["Method"] = method->name();
@ -194,19 +251,56 @@ void PrintHeaderServerMethod(google::protobuf::io::Printer *printer,
}
}
void PrintHeaderServerMethodAsync(
google::protobuf::io::Printer *printer,
const google::protobuf::MethodDescriptor *method,
std::map<std::string, std::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] =
grpc_cpp_generator::ClassName(method->input_type(), true);
(*vars)["Response"] =
grpc_cpp_generator::ClassName(method->output_type(), true);
if (NoStreaming(method)) {
printer->Print(*vars,
"void Request$Method$("
"::grpc::ServerContext* context, $Request$* request, "
"::grpc::ServerAsyncResponseWriter< $Response$>* response, "
"::grpc::CompletionQueue* cq, void *tag);\n");
} else if (ClientOnlyStreaming(method)) {
printer->Print(*vars,
"void Request$Method$("
"::grpc::ServerContext* context, "
"::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
"::grpc::CompletionQueue* cq, void *tag);\n");
} else if (ServerOnlyStreaming(method)) {
printer->Print(*vars,
"void Request$Method$("
"::grpc::ServerContext* context, $Request$* request, "
"::grpc::ServerAsyncWriter< $Response$>* writer, "
"::grpc::CompletionQueue* cq, void *tag);\n");
} else if (BidiStreaming(method)) {
printer->Print(
*vars,
"void Request$Method$("
"::grpc::ServerContext* context, "
"::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
"::grpc::CompletionQueue* cq, void *tag);\n");
}
}
void PrintHeaderService(google::protobuf::io::Printer *printer,
const google::protobuf::ServiceDescriptor *service,
std::map<std::string, std::string> *vars) {
(*vars)["Service"] = service->name();
printer->Print(*vars,
"class $Service$ {\n"
"class $Service$ final {\n"
" public:\n");
printer->Indent();
// Client side
printer->Print(
"class Stub : public ::grpc::InternalStub {\n"
"class Stub final : public ::grpc::InternalStub {\n"
" public:\n");
printer->Indent();
for (int i = 0; i < service->method_count(); ++i) {
@ -220,23 +314,37 @@ void PrintHeaderService(google::protobuf::io::Printer *printer,
printer->Print("\n");
// Server side
// Server side - Synchronous
printer->Print(
"class Service {\n"
"class Service : public ::grpc::SynchronousService {\n"
" public:\n");
printer->Indent();
printer->Print("Service() : service_(nullptr) {}\n");
printer->Print("virtual ~Service();\n");
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderServerMethod(printer, service->method(i), vars);
PrintHeaderServerMethodSync(printer, service->method(i), vars);
}
printer->Print("::grpc::RpcService* service();\n");
printer->Print("::grpc::RpcService* service() override final;\n");
printer->Outdent();
printer->Print(
" private:\n"
" ::grpc::RpcService* service_;\n");
printer->Print("};\n");
// Server side - Asynchronous
printer->Print(
"class AsyncService final : public ::grpc::AsynchronousService {\n"
" public:\n");
printer->Indent();
(*vars)["MethodCount"] = as_string(service->method_count());
printer->Print("explicit AsyncService(::grpc::CompletionQueue* cq);\n");
printer->Print("~AsyncService() {};\n");
for (int i = 0; i < service->method_count(); ++i) {
PrintHeaderServerMethodAsync(printer, service->method(i), vars);
}
printer->Outdent();
printer->Print("};\n");
printer->Outdent();
printer->Print("};\n");
}
@ -268,10 +376,21 @@ void PrintSourceClientMethod(google::protobuf::io::Printer *printer,
"::grpc::ClientContext* context, "
"const $Request$& request, $Response$* response) {\n");
printer->Print(*vars,
" return channel()->StartBlockingRpc("
"::grpc::RpcMethod(\"/$Package$$Service$/$Method$\"), "
" return ::grpc::BlockingUnaryCall(channel(),"
"::grpc::RpcMethod($Service$_method_names[$Idx$]), "
"context, request, response);\n"
"}\n\n");
printer->Print(*vars,
"::grpc::ClientAsyncResponseReader< $Response$>* "
"$Service$::Stub::$Method$(::grpc::ClientContext* context, "
"const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(*vars,
" return new ::grpc::ClientAsyncResponseReader< $Response$>("
"channel(), cq, "
"::grpc::RpcMethod($Service$_method_names[$Idx$]), "
"context, request, tag);\n"
"}\n\n");
} else if (ClientOnlyStreaming(method)) {
printer->Print(
*vars,
@ -279,22 +398,46 @@ void PrintSourceClientMethod(google::protobuf::io::Printer *printer,
"::grpc::ClientContext* context, $Response$* response) {\n");
printer->Print(*vars,
" return new ::grpc::ClientWriter< $Request$>("
"channel()->CreateStream("
"::grpc::RpcMethod(\"/$Package$$Service$/$Method$\", "
"channel(),"
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
"::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
"context, nullptr, response));\n"
"context, response);\n"
"}\n\n");
printer->Print(
*vars,
"::grpc::ClientAsyncWriter< $Request$>* $Service$::Stub::$Method$("
"::grpc::ClientContext* context, $Response$* response, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(*vars,
" return new ::grpc::ClientAsyncWriter< $Request$>("
"channel(), cq, "
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
"::grpc::RpcMethod::RpcType::CLIENT_STREAMING), "
"context, response, tag);\n"
"}\n\n");
} else if (ServerOnlyStreaming(method)) {
printer->Print(
*vars,
"::grpc::ClientReader< $Response$>* $Service$::Stub::$Method$("
"::grpc::ClientContext* context, const $Request$* request) {\n");
"::grpc::ClientContext* context, const $Request$& request) {\n");
printer->Print(*vars,
" return new ::grpc::ClientReader< $Response$>("
"channel()->CreateStream("
"::grpc::RpcMethod(\"/$Package$$Service$/$Method$\", "
"channel(),"
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
"::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
"context, request, nullptr));\n"
"context, request);\n"
"}\n\n");
printer->Print(
*vars,
"::grpc::ClientAsyncReader< $Response$>* $Service$::Stub::$Method$("
"::grpc::ClientContext* context, const $Request$& request, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(*vars,
" return new ::grpc::ClientAsyncReader< $Response$>("
"channel(), cq, "
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
"::grpc::RpcMethod::RpcType::SERVER_STREAMING), "
"context, request, tag);\n"
"}\n\n");
} else if (BidiStreaming(method)) {
printer->Print(
@ -304,10 +447,23 @@ void PrintSourceClientMethod(google::protobuf::io::Printer *printer,
printer->Print(
*vars,
" return new ::grpc::ClientReaderWriter< $Request$, $Response$>("
"channel()->CreateStream("
"::grpc::RpcMethod(\"/$Package$$Service$/$Method$\", "
"channel(),"
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
"::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
"context);\n"
"}\n\n");
printer->Print(
*vars,
"::grpc::ClientAsyncReaderWriter< $Request$, $Response$>* "
"$Service$::Stub::$Method$(::grpc::ClientContext* context, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(
*vars,
" return new ::grpc::ClientAsyncReaderWriter< $Request$, $Response$>("
"channel(), cq, "
"::grpc::RpcMethod($Service$_method_names[$Idx$], "
"::grpc::RpcMethod::RpcType::BIDI_STREAMING), "
"context, nullptr, nullptr));\n"
"context, tag);\n"
"}\n\n");
}
}
@ -362,10 +518,73 @@ void PrintSourceServerMethod(google::protobuf::io::Printer *printer,
}
}
void PrintSourceServerAsyncMethod(
google::protobuf::io::Printer *printer,
const google::protobuf::MethodDescriptor *method,
std::map<std::string, std::string> *vars) {
(*vars)["Method"] = method->name();
(*vars)["Request"] =
grpc_cpp_generator::ClassName(method->input_type(), true);
(*vars)["Response"] =
grpc_cpp_generator::ClassName(method->output_type(), true);
if (NoStreaming(method)) {
printer->Print(*vars,
"void $Service$::AsyncService::Request$Method$("
"::grpc::ServerContext* context, "
"$Request$* request, "
"::grpc::ServerAsyncResponseWriter< $Response$>* response, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(
*vars,
" AsynchronousService::RequestAsyncUnary($Idx$, context, request, response, cq, tag);\n");
printer->Print("}\n\n");
} else if (ClientOnlyStreaming(method)) {
printer->Print(*vars,
"void $Service$::AsyncService::Request$Method$("
"::grpc::ServerContext* context, "
"::grpc::ServerAsyncReader< $Response$, $Request$>* reader, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(
*vars,
" AsynchronousService::RequestClientStreaming($Idx$, context, reader, cq, tag);\n");
printer->Print("}\n\n");
} else if (ServerOnlyStreaming(method)) {
printer->Print(*vars,
"void $Service$::AsyncService::Request$Method$("
"::grpc::ServerContext* context, "
"$Request$* request, "
"::grpc::ServerAsyncWriter< $Response$>* writer, "
"::grpc::CompletionQueue* cq, void* tag) {\n");
printer->Print(
*vars,
" AsynchronousService::RequestServerStreaming($Idx$, context, request, writer, cq, tag);\n");
printer->Print("}\n\n");
} else if (BidiStreaming(method)) {
printer->Print(
*vars,
"void $Service$::AsyncService::Request$Method$("
"::grpc::ServerContext* context, "
"::grpc::ServerAsyncReaderWriter< $Response$, $Request$>* stream, "
"::grpc::CompletionQueue* cq, void *tag) {\n");
printer->Print(
*vars,
" AsynchronousService::RequestBidiStreaming($Idx$, context, stream, cq, tag);\n");
printer->Print("}\n\n");
}
}
void PrintSourceService(google::protobuf::io::Printer *printer,
const google::protobuf::ServiceDescriptor *service,
std::map<std::string, std::string> *vars) {
(*vars)["Service"] = service->name();
printer->Print(*vars, "static const char* $Service$_method_names[] = {\n");
for (int i = 0; i < service->method_count(); ++i) {
(*vars)["Method"] = service->method(i)->name();
printer->Print(*vars, " \"/$Package$$Service$/$Method$\",\n");
}
printer->Print(*vars, "};\n\n");
printer->Print(
*vars,
"$Service$::Stub* $Service$::NewStub("
@ -375,15 +594,25 @@ void PrintSourceService(google::protobuf::io::Printer *printer,
" return stub;\n"
"};\n\n");
for (int i = 0; i < service->method_count(); ++i) {
(*vars)["Idx"] = as_string(i);
PrintSourceClientMethod(printer, service->method(i), vars);
}
(*vars)["MethodCount"] = as_string(service->method_count());
printer->Print(
*vars,
"$Service$::AsyncService::AsyncService(::grpc::CompletionQueue* cq) : "
"::grpc::AsynchronousService(cq, $Service$_method_names, $MethodCount$) "
"{}\n\n");
printer->Print(*vars,
"$Service$::Service::~Service() {\n"
" delete service_;\n"
"}\n\n");
for (int i = 0; i < service->method_count(); ++i) {
(*vars)["Idx"] = as_string(i);
PrintSourceServerMethod(printer, service->method(i), vars);
PrintSourceServerAsyncMethod(printer, service->method(i), vars);
}
printer->Print(*vars,
"::grpc::RpcService* $Service$::Service::service() {\n");
@ -395,6 +624,7 @@ void PrintSourceService(google::protobuf::io::Printer *printer,
printer->Print("service_ = new ::grpc::RpcService();\n");
for (int i = 0; i < service->method_count(); ++i) {
const google::protobuf::MethodDescriptor *method = service->method(i);
(*vars)["Idx"] = as_string(i);
(*vars)["Method"] = method->name();
(*vars)["Request"] =
grpc_cpp_generator::ClassName(method->input_type(), true);
@ -404,7 +634,7 @@ void PrintSourceService(google::protobuf::io::Printer *printer,
printer->Print(
*vars,
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
" \"/$Package$$Service$/$Method$\",\n"
" $Service$_method_names[$Idx$],\n"
" ::grpc::RpcMethod::NORMAL_RPC,\n"
" new ::grpc::RpcMethodHandler< $Service$::Service, $Request$, "
"$Response$>(\n"
@ -416,7 +646,7 @@ void PrintSourceService(google::protobuf::io::Printer *printer,
printer->Print(
*vars,
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
" \"/$Package$$Service$/$Method$\",\n"
" $Service$_method_names[$Idx$],\n"
" ::grpc::RpcMethod::CLIENT_STREAMING,\n"
" new ::grpc::ClientStreamingHandler< "
"$Service$::Service, $Request$, $Response$>(\n"
@ -429,7 +659,7 @@ void PrintSourceService(google::protobuf::io::Printer *printer,
printer->Print(
*vars,
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
" \"/$Package$$Service$/$Method$\",\n"
" $Service$_method_names[$Idx$],\n"
" ::grpc::RpcMethod::SERVER_STREAMING,\n"
" new ::grpc::ServerStreamingHandler< "
"$Service$::Service, $Request$, $Response$>(\n"
@ -442,7 +672,7 @@ void PrintSourceService(google::protobuf::io::Printer *printer,
printer->Print(
*vars,
"service_->AddMethod(new ::grpc::RpcServiceMethod(\n"
" \"/$Package$$Service$/$Method$\",\n"
" $Service$_method_names[$Idx$],\n"
" ::grpc::RpcMethod::BIDI_STREAMING,\n"
" new ::grpc::BidiStreamingHandler< "
"$Service$::Service, $Request$, $Response$>(\n"

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -0,0 +1,330 @@
/*
*
* Copyright 2015, 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 <cassert>
#include <cctype>
#include <map>
#include <ostream>
#include <sstream>
#include "src/compiler/python_generator.h"
#include <google/protobuf/io/printer.h>
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
#include <google/protobuf/descriptor.pb.h>
#include <google/protobuf/descriptor.h>
using google::protobuf::FileDescriptor;
using google::protobuf::ServiceDescriptor;
using google::protobuf::MethodDescriptor;
using google::protobuf::io::Printer;
using google::protobuf::io::StringOutputStream;
using std::initializer_list;
using std::map;
using std::string;
namespace grpc_python_generator {
namespace {
//////////////////////////////////
// BEGIN FORMATTING BOILERPLATE //
//////////////////////////////////
// Converts an initializer list of the form { key0, value0, key1, value1, ... }
// into a map of key* to value*. Is merely a readability helper for later code.
map<string, string> ListToDict(const initializer_list<string>& values) {
assert(values.size() % 2 == 0);
map<string, string> value_map;
auto value_iter = values.begin();
for (unsigned i = 0; i < values.size()/2; ++i) {
string key = *value_iter;
++value_iter;
string value = *value_iter;
value_map[key] = value;
++value_iter;
}
return value_map;
}
// Provides RAII indentation handling. Use as:
// {
// IndentScope raii_my_indent_var_name_here(my_py_printer);
// // constructor indented my_py_printer
// ...
// // destructor called at end of scope, un-indenting my_py_printer
// }
class IndentScope {
public:
explicit IndentScope(Printer* printer) : printer_(printer) {
printer_->Indent();
}
~IndentScope() {
printer_->Outdent();
}
private:
Printer* printer_;
};
////////////////////////////////
// END FORMATTING BOILERPLATE //
////////////////////////////////
void PrintService(const ServiceDescriptor* service,
Printer* out) {
string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
out->Print(dict, "class $Service$Service(object):\n");
{
IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
out->Print("def __init__(self):\n");
{
IndentScope raii_method_indent(out);
out->Print("pass\n");
}
}
}
void PrintServicer(const ServiceDescriptor* service,
Printer* out) {
string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
out->Print(dict, "class $Service$Servicer(object):\n");
{
IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
for (int i = 0; i < service->method_count(); ++i) {
auto meth = service->method(i);
out->Print("def $Method$(self, arg):\n", "Method", meth->name());
{
IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n");
}
}
}
}
void PrintStub(const ServiceDescriptor* service,
Printer* out) {
string doc = "<fill me in later!>";
map<string, string> dict = ListToDict({
"Service", service->name(),
"Documentation", doc,
});
out->Print(dict, "class $Service$Stub(object):\n");
{
IndentScope raii_class_indent(out);
out->Print(dict, "\"\"\"$Documentation$\"\"\"\n");
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i);
auto methdict = ListToDict({"Method", meth->name()});
out->Print(methdict, "def $Method$(self, arg):\n");
{
IndentScope raii_method_indent(out);
out->Print("raise NotImplementedError()\n");
}
out->Print(methdict, "$Method$.async = None\n");
}
}
}
void PrintStubImpl(const ServiceDescriptor* service,
Printer* out) {
map<string, string> dict = ListToDict({
"Service", service->name(),
});
out->Print(dict, "class _$Service$Stub($Service$Stub):\n");
{
IndentScope raii_class_indent(out);
out->Print("def __init__(self, face_stub, default_timeout):\n");
{
IndentScope raii_method_indent(out);
out->Print("self._face_stub = face_stub\n"
"self._default_timeout = default_timeout\n"
"stub_self = self\n");
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i);
bool server_streaming = meth->server_streaming();
bool client_streaming = meth->client_streaming();
std::string blocking_call, future_call;
if (server_streaming) {
if (client_streaming) {
blocking_call = "stub_self._face_stub.inline_stream_in_stream_out";
future_call = blocking_call;
} else {
blocking_call = "stub_self._face_stub.inline_value_in_stream_out";
future_call = blocking_call;
}
} else {
if (client_streaming) {
blocking_call = "stub_self._face_stub.blocking_stream_in_value_out";
future_call = "stub_self._face_stub.future_stream_in_value_out";
} else {
blocking_call = "stub_self._face_stub.blocking_value_in_value_out";
future_call = "stub_self._face_stub.future_value_in_value_out";
}
}
// TODO(atash): use the solution described at
// http://stackoverflow.com/a/2982 to bind 'async' attribute
// functions to def'd functions instead of using callable attributes.
auto methdict = ListToDict({
"Method", meth->name(),
"BlockingCall", blocking_call,
"FutureCall", future_call
});
out->Print(methdict, "class $Method$(object):\n");
{
IndentScope raii_callable_indent(out);
out->Print("def __call__(self, arg):\n");
{
IndentScope raii_callable_call_indent(out);
out->Print(methdict,
"return $BlockingCall$(\"$Method$\", arg, "
"stub_self._default_timeout)\n");
}
out->Print("def async(self, arg):\n");
{
IndentScope raii_callable_async_indent(out);
out->Print(methdict,
"return $FutureCall$(\"$Method$\", arg, "
"stub_self._default_timeout)\n");
}
}
out->Print(methdict, "self.$Method$ = $Method$()\n");
}
}
}
}
void PrintStubGenerators(const ServiceDescriptor* service, Printer* out) {
map<string, string> dict = ListToDict({
"Service", service->name(),
});
// Write out a generator of linked pairs of Server/Stub
out->Print(dict, "def mock_$Service$(servicer, default_timeout):\n");
{
IndentScope raii_mock_indent(out);
out->Print("value_in_value_out = {}\n"
"value_in_stream_out = {}\n"
"stream_in_value_out = {}\n"
"stream_in_stream_out = {}\n");
for (int i = 0; i < service->method_count(); ++i) {
const MethodDescriptor* meth = service->method(i);
std::string super_interface, meth_dict;
bool server_streaming = meth->server_streaming();
bool client_streaming = meth->client_streaming();
if (server_streaming) {
if (client_streaming) {
super_interface = "InlineStreamInStreamOutMethod";
meth_dict = "stream_in_stream_out";
} else {
super_interface = "InlineValueInStreamOutMethod";
meth_dict = "value_in_stream_out";
}
} else {
if (client_streaming) {
super_interface = "InlineStreamInValueOutMethod";
meth_dict = "stream_in_value_out";
} else {
super_interface = "InlineValueInValueOutMethod";
meth_dict = "value_in_value_out";
}
}
map<string, string> methdict = ListToDict({
"Method", meth->name(),
"SuperInterface", super_interface,
"MethodDict", meth_dict
});
out->Print(
methdict, "class $Method$(_face_interfaces.$SuperInterface$):\n");
{
IndentScope raii_inline_class_indent(out);
out->Print("def service(self, request, context):\n");
{
IndentScope raii_inline_class_fn_indent(out);
out->Print(methdict, "return servicer.$Method$(request)\n");
}
}
out->Print(methdict, "$MethodDict$['$Method$'] = $Method$()\n");
}
out->Print(
"face_linked_pair = _face_testing.server_and_stub(default_timeout,"
"inline_value_in_value_out_methods=value_in_value_out,"
"inline_value_in_stream_out_methods=value_in_stream_out,"
"inline_stream_in_value_out_methods=stream_in_value_out,"
"inline_stream_in_stream_out_methods=stream_in_stream_out)\n");
out->Print("class LinkedPair(object):\n");
{
IndentScope raii_linked_pair(out);
out->Print("def __init__(self, server, stub):\n");
{
IndentScope raii_linked_pair_init(out);
out->Print("self.server = server\n"
"self.stub = stub\n");
}
}
out->Print(
dict,
"stub = _$Service$Stub(face_linked_pair.stub, default_timeout)\n");
out->Print("return LinkedPair(None, stub)\n");
}
}
} // namespace
string GetServices(const FileDescriptor* file) {
string output;
StringOutputStream output_stream(&output);
Printer out(&output_stream, '$');
out.Print("from grpc.framework.face import demonstration as _face_testing\n");
out.Print("from grpc.framework.face import interfaces as _face_interfaces\n");
for (int i = 0; i < file->service_count(); ++i) {
auto service = file->service(i);
PrintService(service, &out);
PrintServicer(service, &out);
PrintStub(service, &out);
PrintStubImpl(service, &out);
PrintStubGenerators(service, &out);
}
return output;
}
} // namespace grpc_python_generator

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,34 +31,21 @@
*
*/
#ifndef __GRPCPP_STREAM_CONTEXT_INTERFACE_H__
#define __GRPCPP_STREAM_CONTEXT_INTERFACE_H__
#ifndef __GRPC_COMPILER_PYTHON_GENERATOR_H__
#define __GRPC_COMPILER_PYTHON_GENERATOR_H__
#include <string>
namespace google {
namespace protobuf {
class Message;
}
}
namespace grpc {
class Status;
// An interface to avoid dependency on internal implementation.
class StreamContextInterface {
public:
virtual ~StreamContextInterface() {}
virtual void Start(bool buffered) = 0;
class FileDescriptor;
} // namespace protobuf
} // namespace google
virtual bool Read(google::protobuf::Message* msg) = 0;
virtual bool Write(const google::protobuf::Message* msg, bool is_last) = 0;
virtual const Status& Wait() = 0;
virtual void Cancel() = 0;
namespace grpc_python_generator {
virtual google::protobuf::Message* request() = 0;
virtual google::protobuf::Message* response() = 0;
};
std::string GetServices(const google::protobuf::FileDescriptor* file);
} // namespace grpc
} // namespace grpc_python_generator
#endif // __GRPCPP_STREAM_CONTEXT_INTERFACE_H__
#endif // __GRPC_COMPILER_PYTHON_GENERATOR_H__

@ -0,0 +1,87 @@
/*
*
* Copyright 2015, 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.
*
*/
// Generates a Python gRPC service interface out of Protobuf IDL.
#include <memory>
#include <string>
#include "src/compiler/python_generator.h"
#include <google/protobuf/compiler/code_generator.h>
#include <google/protobuf/compiler/plugin.h>
#include <google/protobuf/io/coded_stream.h>
#include <google/protobuf/io/zero_copy_stream.h>
#include <google/protobuf/descriptor.h>
using google::protobuf::FileDescriptor;
using google::protobuf::compiler::CodeGenerator;
using google::protobuf::compiler::GeneratorContext;
using google::protobuf::compiler::PluginMain;
using google::protobuf::io::CodedOutputStream;
using google::protobuf::io::ZeroCopyOutputStream;
using std::string;
class PythonGrpcGenerator : public CodeGenerator {
public:
PythonGrpcGenerator() {}
~PythonGrpcGenerator() override {}
bool Generate(const FileDescriptor* file,
const string& parameter,
GeneratorContext* context,
string* error) const override {
// Get output file name.
string file_name;
static const int proto_suffix_length = 6; // length of ".proto"
if (file->name().size() > proto_suffix_length &&
file->name().find_last_of(".proto") == file->name().size() - 1) {
file_name = file->name().substr(
0, file->name().size() - proto_suffix_length) + "_pb2.py";
} else {
*error = "Invalid proto file name. Proto file must end with .proto";
return false;
}
std::unique_ptr<ZeroCopyOutputStream> output(
context->OpenForInsert(file_name, "module_scope"));
CodedOutputStream coded_out(output.get());
string code = grpc_python_generator::GetServices(file);
coded_out.WriteRaw(code.data(), code.size());
return true;
}
};
int main(int argc, char* argv[]) {
PythonGrpcGenerator generator;
return PluginMain(argc, argv, &generator);
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -0,0 +1,9 @@
#Overview
This directory contains source code for shared C library. Libraries in other languages in this repository (C++, Ruby,
Python, PHP, NodeJS, Objective-C) are layered on top of this library.
#Status
Alpha : Ready for early adopters

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -49,8 +49,11 @@ struct grpc_client_setup {
grpc_alarm backoff_alarm;
gpr_timespec current_backoff_interval;
int in_alarm;
int in_cb;
int cancelled;
gpr_mu mu;
gpr_cv cv;
grpc_client_setup_request *active_request;
int refs;
};
@ -67,6 +70,7 @@ gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r) {
static void destroy_setup(grpc_client_setup *s) {
gpr_mu_destroy(&s->mu);
gpr_cv_destroy(&s->cv);
s->done(s->user_data);
grpc_channel_args_destroy(s->args);
gpr_free(s);
@ -111,6 +115,10 @@ static void setup_cancel(grpc_transport_setup *sp) {
int cancel_alarm = 0;
gpr_mu_lock(&s->mu);
s->cancelled = 1;
while (s->in_cb) {
gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
}
GPR_ASSERT(s->refs > 0);
/* effectively cancels the current request (if any) */
@ -129,6 +137,24 @@ static void setup_cancel(grpc_transport_setup *sp) {
}
}
int grpc_client_setup_cb_begin(grpc_client_setup_request *r) {
gpr_mu_lock(&r->setup->mu);
if (r->setup->cancelled) {
gpr_mu_unlock(&r->setup->mu);
return 0;
}
r->setup->in_cb++;
gpr_mu_unlock(&r->setup->mu);
return 1;
}
void grpc_client_setup_cb_end(grpc_client_setup_request *r) {
gpr_mu_lock(&r->setup->mu);
r->setup->in_cb--;
if (r->setup->cancelled) gpr_cv_signal(&r->setup->cv);
gpr_mu_unlock(&r->setup->mu);
}
/* vtable for transport setup */
static const grpc_transport_setup_vtable setup_vtable = {setup_initiate,
setup_cancel};
@ -142,6 +168,7 @@ void grpc_client_setup_create_and_attach(
s->base.vtable = &setup_vtable;
gpr_mu_init(&s->mu);
gpr_cv_init(&s->cv);
s->refs = 1;
s->mdctx = mdctx;
s->initiate = initiate;
@ -151,6 +178,8 @@ void grpc_client_setup_create_and_attach(
s->args = grpc_channel_args_copy(args);
s->current_backoff_interval = gpr_time_from_micros(1000000);
s->in_alarm = 0;
s->in_cb = 0;
s->cancelled = 0;
grpc_client_channel_set_transport_setup(newly_minted_channel, &s->base);
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -58,6 +58,12 @@ void grpc_client_setup_request_finish(grpc_client_setup_request *r,
const grpc_channel_args *grpc_client_setup_get_channel_args(
grpc_client_setup_request *r);
/* Call before calling back into the setup listener, and call only if
this function returns 1. If it returns 1, also promise to call
grpc_client_setup_cb_end */
int grpc_client_setup_cb_begin(grpc_client_setup_request *r);
void grpc_client_setup_cb_end(grpc_client_setup_request *r);
/* Get the deadline for a request passed in to initiate. Implementations should
make a best effort to honor this deadline. */
gpr_timespec grpc_client_setup_request_deadline(grpc_client_setup_request *r);

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,5 +1,5 @@
/*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

@ -1,6 +1,6 @@
/*
*
* Copyright 2014, Google Inc.
* Copyright 2015, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save