Merge branch 'master' into ruby_call_credentials_log_error

pull/5490/head
murgatroid99 9 years ago
commit 2c247433b8
  1. 181
      BUILD
  2. 19
      CONTRIBUTING.md
  3. 217
      INSTALL
  4. 57
      INSTALL.md
  5. 651
      Makefile
  6. 2
      README.md
  7. 1
      binding.gyp
  8. 113
      build.yaml
  9. 11
      composer.json
  10. 1
      config.m4
  11. 5
      doc/interop-test-descriptions.md
  12. 447
      examples/README.md
  13. 17
      examples/cpp/README.md
  14. 2
      examples/cpp/cpptutorial.md
  15. 2
      examples/cpp/helloworld/README.md
  16. 2
      examples/node/README.md
  17. 10
      examples/php/README.md
  18. 11
      examples/php/composer.json
  19. 6
      examples/php/greeter_client.php
  20. 6
      examples/php/route_guide/route_guide_client.php
  21. 4
      examples/python/route_guide/route_guide_server.py
  22. 13
      gRPC.podspec
  23. 1
      grpc.def
  24. 12
      grpc.gemspec
  25. 2
      include/grpc++/alarm.h
  26. 2
      include/grpc++/channel.h
  27. 29
      include/grpc++/impl/codegen/async_stream.h
  28. 9
      include/grpc++/impl/codegen/async_unary_call.h
  29. 82
      include/grpc++/impl/codegen/call.h
  30. 3
      include/grpc++/impl/codegen/client_context.h
  31. 3
      include/grpc++/impl/codegen/client_unary_call.h
  32. 44
      include/grpc++/impl/codegen/completion_queue.h
  33. 97
      include/grpc++/impl/codegen/core_codegen_interface.h
  34. 24
      include/grpc++/impl/codegen/grpc_library.h
  35. 463
      include/grpc++/impl/codegen/impl/async_stream.h
  36. 152
      include/grpc++/impl/codegen/impl/status_code_enum.h
  37. 45
      include/grpc++/impl/codegen/impl/sync.h
  38. 5
      include/grpc++/impl/codegen/method_handler_impl.h
  39. 23
      include/grpc++/impl/codegen/proto_utils.h
  40. 3
      include/grpc++/impl/codegen/server_context.h
  41. 7
      include/grpc++/impl/codegen/server_interface.h
  42. 20
      include/grpc++/impl/codegen/service_type.h
  43. 72
      include/grpc++/impl/codegen/string_ref.h
  44. 21
      include/grpc++/impl/codegen/sync_stream.h
  45. 10
      include/grpc++/impl/grpc_library.h
  46. 4
      include/grpc++/security/credentials.h
  47. 2
      include/grpc++/server.h
  48. 82
      include/grpc/census.h
  49. 35
      include/grpc/impl/codegen/port_platform.h
  50. 4
      include/grpc/impl/codegen/sync.h
  51. 12
      package.json
  52. 37
      package.xml
  53. 9
      setup.py
  54. 149
      src/core/census/context.c
  55. 31
      src/core/channel/client_channel.c
  56. 2
      src/core/channel/client_uchannel.c
  57. 6
      src/core/channel/subchannel_call_holder.c
  58. 6
      src/core/client_config/client_config.c
  59. 2
      src/core/client_config/lb_policies/pick_first.c
  60. 57
      src/core/client_config/resolvers/dns_resolver.c
  61. 110
      src/core/client_config/subchannel.c
  62. 75
      src/core/iomgr/exec_ctx.c
  63. 23
      src/core/iomgr/exec_ctx.h
  64. 14
      src/core/iomgr/iocp_windows.c
  65. 11
      src/core/iomgr/iocp_windows.h
  66. 19
      src/core/iomgr/iomgr.c
  67. 6
      src/core/iomgr/iomgr_internal.h
  68. 12
      src/core/iomgr/pollset.h
  69. 7
      src/core/iomgr/pollset_multipoller_with_poll_posix.c
  70. 6
      src/core/iomgr/resolve_address.h
  71. 19
      src/core/iomgr/resolve_address_posix.c
  72. 19
      src/core/iomgr/resolve_address_windows.c
  73. 3
      src/core/iomgr/tcp_server_windows.c
  74. 16
      src/core/iomgr/timer.c
  75. 1
      src/core/iomgr/timer.h
  76. 22
      src/core/iomgr/timer_heap.c
  77. 4
      src/core/iomgr/workqueue_posix.c
  78. 4
      src/core/support/alloc.c
  79. 71
      src/core/support/backoff.c
  80. 65
      src/core/support/backoff.h
  81. 7
      src/core/support/sync.c
  82. 2
      src/core/surface/completion_queue.c
  83. 14
      src/core/surface/server.c
  84. 21
      src/core/transport/chttp2/internal.h
  85. 6
      src/core/transport/chttp2/parsing.c
  86. 38
      src/core/transport/chttp2/stream_lists.c
  87. 37
      src/core/transport/chttp2/writing.c
  88. 99
      src/core/transport/chttp2_transport.c
  89. 8
      src/core/transport/metadata.c
  90. 2
      src/core/transport/transport.c
  91. 12
      src/core/transport/transport.h
  92. 76
      src/core/tsi/ssl_transport_security.c
  93. 5
      src/core/tsi/ssl_transport_security.h
  94. 74
      src/cpp/README.md
  95. 16
      src/cpp/client/secure_credentials.cc
  96. 45
      src/cpp/codegen/codegen_init.cc
  97. 92
      src/cpp/common/call.cc
  98. 33
      src/cpp/common/completion_queue.cc
  99. 106
      src/cpp/common/core_codegen.cc
  100. 71
      src/cpp/common/core_codegen.h
  101. Some files were not shown because too many files have changed in this diff Show More

181
BUILD

@ -45,6 +45,7 @@ cc_library(
name = "gpr",
srcs = [
"src/core/profiling/timers.h",
"src/core/support/backoff.h",
"src/core/support/block_annotate.h",
"src/core/support/env.h",
"src/core/support/load_file.h",
@ -59,6 +60,7 @@ cc_library(
"src/core/profiling/stap_timers.c",
"src/core/support/alloc.c",
"src/core/support/avl.c",
"src/core/support/backoff.c",
"src/core/support/cmdline.c",
"src/core/support/cpu_iphone.c",
"src/core/support/cpu_linux.c",
@ -454,17 +456,17 @@ cc_library(
],
hdrs = [
"include/grpc/grpc_security.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/census.h",
],
includes = [
@ -482,6 +484,42 @@ cc_library(
)
cc_library(
name = "grpc_codegen_lib",
srcs = [
],
hdrs = [
"include/grpc/impl/codegen/alloc.h",
"include/grpc/impl/codegen/atm.h",
"include/grpc/impl/codegen/atm_gcc_atomic.h",
"include/grpc/impl/codegen/atm_gcc_sync.h",
"include/grpc/impl/codegen/atm_win32.h",
"include/grpc/impl/codegen/log.h",
"include/grpc/impl/codegen/port_platform.h",
"include/grpc/impl/codegen/slice.h",
"include/grpc/impl/codegen/slice_buffer.h",
"include/grpc/impl/codegen/sync.h",
"include/grpc/impl/codegen/sync_generic.h",
"include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
],
includes = [
"include",
".",
],
deps = [
"//external:protobuf_compiler",
],
)
cc_library(
name = "grpc_unsecure",
srcs = [
@ -799,9 +837,11 @@ cc_library(
name = "grpc++",
srcs = [
"src/cpp/client/secure_credentials.h",
"src/cpp/common/core_codegen.h",
"src/cpp/common/secure_auth_context.h",
"src/cpp/server/secure_server_credentials.h",
"src/cpp/client/create_channel_internal.h",
"src/cpp/common/core_codegen.h",
"src/cpp/common/create_auth_context.h",
"src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h",
@ -818,11 +858,10 @@ cc_library(
"src/cpp/client/credentials.cc",
"src/cpp/client/generic_stub.cc",
"src/cpp/client/insecure_credentials.cc",
"src/cpp/common/call.cc",
"src/cpp/common/channel_arguments.cc",
"src/cpp/common/completion_queue.cc",
"src/cpp/common/core_codegen.cc",
"src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc",
"src/cpp/server/dynamic_thread_pool.cc",
@ -836,7 +875,7 @@ cc_library(
"src/cpp/util/status.cc",
"src/cpp/util/string_ref.cc",
"src/cpp/util/time.cc",
"src/cpp/codegen/grpc_library.cc",
"src/cpp/codegen/codegen_init.cc",
],
hdrs = [
"include/grpc++/alarm.h",
@ -894,6 +933,7 @@ cc_library(
"include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/config_protobuf.h",
"include/grpc++/impl/codegen/core_codegen_interface.h",
"include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/proto_utils.h",
@ -926,10 +966,79 @@ cc_library(
)
cc_library(
name = "grpc++_codegen_lib",
srcs = [
"src/cpp/codegen/codegen_init.cc",
],
hdrs = [
"include/grpc/impl/codegen/alloc.h",
"include/grpc/impl/codegen/atm.h",
"include/grpc/impl/codegen/atm_gcc_atomic.h",
"include/grpc/impl/codegen/atm_gcc_sync.h",
"include/grpc/impl/codegen/atm_win32.h",
"include/grpc/impl/codegen/log.h",
"include/grpc/impl/codegen/port_platform.h",
"include/grpc/impl/codegen/slice.h",
"include/grpc/impl/codegen/slice_buffer.h",
"include/grpc/impl/codegen/sync.h",
"include/grpc/impl/codegen/sync_generic.h",
"include/grpc/impl/codegen/sync_posix.h",
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc++/impl/codegen/async_stream.h",
"include/grpc++/impl/codegen/async_unary_call.h",
"include/grpc++/impl/codegen/call.h",
"include/grpc++/impl/codegen/call_hook.h",
"include/grpc++/impl/codegen/channel_interface.h",
"include/grpc++/impl/codegen/client_context.h",
"include/grpc++/impl/codegen/client_unary_call.h",
"include/grpc++/impl/codegen/completion_queue.h",
"include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/config_protobuf.h",
"include/grpc++/impl/codegen/core_codegen_interface.h",
"include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/proto_utils.h",
"include/grpc++/impl/codegen/rpc_method.h",
"include/grpc++/impl/codegen/rpc_service_method.h",
"include/grpc++/impl/codegen/security/auth_context.h",
"include/grpc++/impl/codegen/serialization_traits.h",
"include/grpc++/impl/codegen/server_context.h",
"include/grpc++/impl/codegen/server_interface.h",
"include/grpc++/impl/codegen/service_type.h",
"include/grpc++/impl/codegen/status.h",
"include/grpc++/impl/codegen/status_code_enum.h",
"include/grpc++/impl/codegen/string_ref.h",
"include/grpc++/impl/codegen/stub_options.h",
"include/grpc++/impl/codegen/sync.h",
"include/grpc++/impl/codegen/sync_cxx11.h",
"include/grpc++/impl/codegen/sync_no_cxx11.h",
"include/grpc++/impl/codegen/sync_stream.h",
"include/grpc++/impl/codegen/time.h",
],
includes = [
"include",
".",
],
deps = [
"//external:protobuf_compiler",
],
)
cc_library(
name = "grpc++_unsecure",
srcs = [
"src/cpp/client/create_channel_internal.h",
"src/cpp/common/core_codegen.h",
"src/cpp/common/create_auth_context.h",
"src/cpp/server/dynamic_thread_pool.h",
"src/cpp/server/thread_pool_interface.h",
@ -941,11 +1050,10 @@ cc_library(
"src/cpp/client/credentials.cc",
"src/cpp/client/generic_stub.cc",
"src/cpp/client/insecure_credentials.cc",
"src/cpp/common/call.cc",
"src/cpp/common/channel_arguments.cc",
"src/cpp/common/completion_queue.cc",
"src/cpp/common/core_codegen.cc",
"src/cpp/common/rpc_method.cc",
"src/cpp/proto/proto_utils.cc",
"src/cpp/server/async_generic_service.cc",
"src/cpp/server/create_default_thread_pool.cc",
"src/cpp/server/dynamic_thread_pool.cc",
@ -959,7 +1067,7 @@ cc_library(
"src/cpp/util/status.cc",
"src/cpp/util/string_ref.cc",
"src/cpp/util/time.cc",
"src/cpp/codegen/grpc_library.cc",
"src/cpp/codegen/codegen_init.cc",
],
hdrs = [
"include/grpc++/alarm.h",
@ -1017,6 +1125,7 @@ cc_library(
"include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/config_protobuf.h",
"include/grpc++/impl/codegen/core_codegen_interface.h",
"include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/proto_utils.h",
@ -1072,45 +1181,8 @@ cc_library(
"src/compiler/objective_c_generator.cc",
"src/compiler/python_generator.cc",
"src/compiler/ruby_generator.cc",
"src/cpp/codegen/grpc_library.cc",
],
hdrs = [
"include/grpc++/impl/codegen/async_stream.h",
"include/grpc++/impl/codegen/async_unary_call.h",
"include/grpc++/impl/codegen/call.h",
"include/grpc++/impl/codegen/call_hook.h",
"include/grpc++/impl/codegen/channel_interface.h",
"include/grpc++/impl/codegen/client_context.h",
"include/grpc++/impl/codegen/client_unary_call.h",
"include/grpc++/impl/codegen/completion_queue.h",
"include/grpc++/impl/codegen/completion_queue_tag.h",
"include/grpc++/impl/codegen/config.h",
"include/grpc++/impl/codegen/config_protobuf.h",
"include/grpc++/impl/codegen/grpc_library.h",
"include/grpc++/impl/codegen/method_handler_impl.h",
"include/grpc++/impl/codegen/proto_utils.h",
"include/grpc++/impl/codegen/rpc_method.h",
"include/grpc++/impl/codegen/rpc_service_method.h",
"include/grpc++/impl/codegen/security/auth_context.h",
"include/grpc++/impl/codegen/serialization_traits.h",
"include/grpc++/impl/codegen/server_context.h",
"include/grpc++/impl/codegen/server_interface.h",
"include/grpc++/impl/codegen/service_type.h",
"include/grpc++/impl/codegen/status.h",
"include/grpc++/impl/codegen/status_code_enum.h",
"include/grpc++/impl/codegen/string_ref.h",
"include/grpc++/impl/codegen/stub_options.h",
"include/grpc++/impl/codegen/sync.h",
"include/grpc++/impl/codegen/sync_cxx11.h",
"include/grpc++/impl/codegen/sync_no_cxx11.h",
"include/grpc++/impl/codegen/sync_stream.h",
"include/grpc++/impl/codegen/time.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc/impl/codegen/alloc.h",
"include/grpc/impl/codegen/atm.h",
"include/grpc/impl/codegen/atm_gcc_atomic.h",
@ -1132,6 +1204,7 @@ cc_library(
],
deps = [
"//external:protobuf_compiler",
":grpc++_codegen_lib",
],
)
@ -1162,6 +1235,7 @@ objc_library(
"src/core/profiling/stap_timers.c",
"src/core/support/alloc.c",
"src/core/support/avl.c",
"src/core/support/backoff.c",
"src/core/support/cmdline.c",
"src/core/support/cpu_iphone.c",
"src/core/support/cpu_linux.c",
@ -1246,6 +1320,7 @@ objc_library(
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"src/core/profiling/timers.h",
"src/core/support/backoff.h",
"src/core/support/block_annotate.h",
"src/core/support/env.h",
"src/core/support/load_file.h",
@ -1432,17 +1507,17 @@ objc_library(
],
hdrs = [
"include/grpc/grpc_security.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/census.h",
"src/core/census/grpc_filter.h",
"src/core/channel/channel_args.h",

@ -13,7 +13,7 @@ In order to protect both you and ourselves, you will need to sign the
### Technical requirements
You will need several tools to work with this repository. In addition to all of
the packages described in the [INSTALL](INSTALL) file, you will also need
the packages described in the [INSTALL](INSTALL.md) file, you will also need
python, and the mako template renderer. To install the latter, using pip, one
should simply be able to do `pip install mako`.
@ -21,6 +21,15 @@ In order to run all of the tests we provide, you will need valgrind and clang.
More specifically, under debian, you will need the package libc++-dev to
properly run all the tests.
Compiling and running grpc C++ tests depend on protobuf 3.0.0, gtest and gflags.
Although gflags is provided in third_party, you will need to manually install
that dependency on your system to run these tests. Under a Debian or Ubuntu
system, you can install the gtests and gflags packages using apt-get:
```sh
$ [sudo] apt-get install libgflags-dev libgtest-dev
```
If you are planning to work on any of the languages other than C and C++, you
will also need their appropriate development environments.
@ -36,9 +45,13 @@ In order to run most of the available tests, one would need to run:
`./tools/run_tests/run_tests.py`
If you want to run all the possible tests for any of the languages {c, c++, node, php, python}, do this:
If you want to run tests for any of the languages {c, c++, csharp, node, objc, php, python, ruby}, do this:
`./tools/run_tests/run_tests.py -l <lang>`
To know about the list of available commands, do this:
`./tools/run_tests/run_tests.py -l <lang> -c all`
`./tools/run_tests/run_tests.py -h`
## Adding or removing source code

@ -1,217 +0,0 @@
These instructions only cover building grpc C and C++ libraries under
typical unix systems. If you need more information, please try grpc's
wiki pages:
https://github.com/google/grpc/wiki
*************************
* If you are in a hurry *
*************************
On Linux (Debian):
Note: you will need to add the Debian 'jessie-backports' distribution to your sources
file first.
Add the following line to your `/etc/apt/sources.list` file:
deb http://http.debian.net/debian jessie-backports main
Install the gRPC library:
$ [sudo] apt-get install libgrpc-dev
OR
$ git clone https://github.com/grpc/grpc.git
$ cd grpc
$ git submodule update --init
$ make
$ [sudo] make install
You don't need anything else than GNU Make, gcc and autotools. Under a Debian
or Ubuntu system, this should boil down to the following packages:
$ [sudo] apt-get install build-essential autoconf libtool
Building the python wrapper requires the following:
$ [sudo] 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:
$ [sudo] make install prefix=/opt
*******************************
* More detailled instructions *
*******************************
Setting up dependencies
=======================
Dependencies to compile the libraries
-------------------------------------
grpc libraries have few external dependencies. If you need to compile and
install them, they are present in the third_party directory if you have
cloned the github repository recursively. If you didn't clone recursively,
you can still get them later by running the following command:
$ git submodule update --init
Note that the Makefile makes it much easier for you to compile from sources
if you were to clone recursively our git repository: it will automatically
compile zlib and OpenSSL, which are core requirements for grpc. Note this
creates grpc libraries that will have zlib and OpenSSL built-in inside of them,
which significantly increases the libraries' size.
In order to decrease that size, you can manually install zlib and OpenSSL on
your system, so that the Makefile can use them instead.
Under a Debian or Ubuntu system, one can acquire the development package
for zlib this way:
# apt-get install zlib1g-dev
To the best of our knowledge, no distribution has an OpenSSL package that
supports ALPN yet, so you would still have to depend on installing from source
for that particular dependency if you want to reduce the libraries' size.
The recommended version of OpenSSL that provides ALPN support is available
at this URL:
https://www.openssl.org/source/openssl-1.0.2.tar.gz
Dependencies to compile and run the tests
-----------------------------------------
Compiling and running grpc plain-C tests dont't require any more dependency.
Compiling and running grpc C++ tests depend on protobuf 3.0.0, gtest and
gflags. Although gflags is provided in third_party, you will need to manually
install that dependency on your system to run these tests.
Under a Debian or Ubuntu system, you can install the gtests and gflags packages
using apt-get:
# apt-get install libgflags-dev libgtest-dev
However, protobuf 3.0.0 isn't in a debian package yet, but the Makefile will
automatically try and compile the one present in third_party if you cloned the
repository recursively, and that it detects your system is lacking it.
Compiling and installing protobuf 3.0.0 requires a few more dependencies in
itself, notably the autoconf suite. If you have apt-get, you can install
these dependencies this way:
# apt-get install autoconf libtool
If you want to run the tests using one of the sanitized configurations, you
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
$ 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
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
Mingw-specific notes:
---------------------
While gRPC compiles properly under mingw, some more preparation work is needed.
The recommendation is to use msys2. The installation instructions are available
at that address: http://msys2.github.io/
Once this is installed, make sure you are using the following: MinGW-w64 Win64.
You'll be required to install a few more packages:
$ pacman -S make mingw-w64-x86_64-gcc mingw-w64-x86_64-zlib autoconf automake libtool
Please also install OpenSSL from that website:
http://slproweb.com/products/Win32OpenSSL.html
The package Win64 OpenSSL v1.0.2a should do. At that point you should be able
to compile gRPC with the following:
$ export LDFLAGS="-L/mingw64/lib -L/c/OpenSSL-Win64"
$ export CPPFLAGS="-I/mingw64/include -I/c/OpenSSL-Win64/include"
$ make
A word on OpenSSL
-----------------
Secure HTTP2 requires the TLS extension ALPN (see rfc 7301 and
http://http2.github.io/http2-spec/ section 3.3). Our HTTP2 implementation
relies on OpenSSL's implementation. OpenSSL 1.0.2 is the first released version
of OpenSSL that has ALPN support, and this explains our dependency on it.
Note that the Makefile supports compiling only the unsecure elements of grpc,
and if you do not have OpenSSL and do not want it, you can still proceed
with installing only the elements you require. However, we strongly recommend
the use of encryption for all network traffic, and discourage the use of grpc
without TLS.
Compiling
=========
If you have all the dependencies mentioned above, you should simply be able
to go ahead and run "make" to compile grpc's C and C++ libraries:
$ make
Testing
=======
To build and run the tests, you can run the command:
$ make test
If you want to be able to run them in parallel, and get better output, you can
also use the python tool we have written:
$ ./tools/run_tests/run_tests.py
Installing
==========
Once everything is compiled, you should be able to install grpc C and C++
libraries and headers:
# make install

@ -0,0 +1,57 @@
#If you are in a hurry
For language-specific installation instructions for gRPC runtime, please
refer to these documents
* [C++](examples/cpp): Currently to install gRPC for C++, you need to build from source as described below.
* [C#](src/csharp): NuGet package `Grpc`
* [Go](https://github.com/grpc/grpc-go): `go get google.golang.org/grpc`
* [Java](https://github.com/grpc/grpc-java)
* [Node](src/node): `npm install grpc`
* [Objective-C](src/objective-c)
* [PHP](src/php): `pecl install grpc-beta`
* [Python](src/python/grpcio): `pip install grpcio`
* [Ruby](src/ruby): `gem install grpc`
#Pre-requisites
##Linux
```sh
$ [sudo] apt-get install build-essential autoconf libtool
```
##Mac OSX
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:
```sh
$ [sudo] xcode-select --install
```
##Protoc
By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
you will need the `protoc` compiler to generate stub server and client code.
If you compile gRPC from source, as described below, the Makefile will
automatically try and compile the `protoc` in third_party if you cloned the
repository recursively and it detects that you don't already have it
installed.
#Build from Source
For developers who are interested to contribute, here is how to compile the
gRPC C Core library.
```sh
$ git clone https://github.com/grpc/grpc.git
$ cd grpc
$ git submodule update --init
$ make
$ [sudo] make install
```

File diff suppressed because it is too large Load Diff

@ -13,7 +13,7 @@ You can find more detailed documentation and examples in the [doc](doc) and [exa
#Installation
See [grpc/INSTALL](INSTALL) for installation instructions for various platforms.
See [INSTALL](INSTALL.md) for installation instructions for various platforms.
#Repository Structure & Status

@ -496,6 +496,7 @@
'src/core/profiling/stap_timers.c',
'src/core/support/alloc.c',
'src/core/support/avl.c',
'src/core/support/backoff.c',
'src/core/support/cmdline.c',
'src/core/support/cpu_iphone.c',
'src/core/support/cpu_linux.c',

@ -55,6 +55,7 @@ filegroups:
- include/grpc/support/useful.h
headers:
- src/core/profiling/timers.h
- src/core/support/backoff.h
- src/core/support/block_annotate.h
- src/core/support/env.h
- src/core/support/load_file.h
@ -70,6 +71,7 @@ filegroups:
- src/core/profiling/stap_timers.c
- src/core/support/alloc.c
- src/core/support/avl.c
- src/core/support/backoff.c
- src/core/support/cmdline.c
- src/core/support/cpu_iphone.c
- src/core/support/cpu_linux.c
@ -173,6 +175,7 @@ filegroups:
- include/grpc++/support/time.h
headers:
- src/cpp/client/create_channel_internal.h
- src/cpp/common/core_codegen.h
- src/cpp/common/create_auth_context.h
- src/cpp/server/dynamic_thread_pool.h
- src/cpp/server/thread_pool_interface.h
@ -184,11 +187,10 @@ filegroups:
- src/cpp/client/credentials.cc
- src/cpp/client/generic_stub.cc
- src/cpp/client/insecure_credentials.cc
- src/cpp/common/call.cc
- src/cpp/common/channel_arguments.cc
- src/cpp/common/completion_queue.cc
- src/cpp/common/core_codegen.cc
- src/cpp/common/rpc_method.cc
- src/cpp/proto/proto_utils.cc
- src/cpp/server/async_generic_service.cc
- src/cpp/server/create_default_thread_pool.cc
- src/cpp/server/dynamic_thread_pool.cc
@ -215,6 +217,7 @@ filegroups:
- include/grpc++/impl/codegen/completion_queue_tag.h
- include/grpc++/impl/codegen/config.h
- include/grpc++/impl/codegen/config_protobuf.h
- include/grpc++/impl/codegen/core_codegen_interface.h
- include/grpc++/impl/codegen/grpc_library.h
- include/grpc++/impl/codegen/method_handler_impl.h
- include/grpc++/impl/codegen/proto_utils.h
@ -235,7 +238,7 @@ filegroups:
- include/grpc++/impl/codegen/sync_stream.h
- include/grpc++/impl/codegen/time.h
src:
- src/cpp/codegen/grpc_library.cc
- src/cpp/codegen/codegen_init.cc
- name: grpc_base
public_headers:
- include/grpc/byte_buffer.h
@ -595,9 +598,9 @@ libs:
deps_linkage: static
dll: true
filegroups:
- grpc_codegen
- grpc_base
- grpc_secure
- grpc_codegen
- census
- nanopb
secure: true
@ -605,6 +608,16 @@ libs:
- grpc.dependencies.openssl
- grpc.dependencies.zlib
vs_project_guid: '{29D16885-7228-4C31-81ED-5F9187C7F2A9}'
- name: grpc_codegen_lib
build: protoc
language: c
headers: []
src: []
filegroups:
- gpr_codegen
- grpc_codegen
secure: false
vs_project_guid: '{A828FD72-44CE-4EA5-8966-6E4624458D58}'
- name: grpc_dll
build: private
language: c
@ -719,6 +732,7 @@ libs:
language: c++
headers:
- src/cpp/client/secure_credentials.h
- src/cpp/common/core_codegen.h
- src/cpp/common/secure_auth_context.h
- src/cpp/server/secure_server_credentials.h
src:
@ -737,6 +751,17 @@ libs:
- grpc++_codegen
secure: check
vs_project_guid: '{C187A093-A0FE-489D-A40A-6E33DE0F9FEB}'
- name: grpc++_codegen_lib
build: protoc
language: c++
headers: []
src: []
filegroups:
- gpr_codegen
- grpc_codegen
- grpc++_codegen
secure: false
vs_project_guid: '{AAC6AF12-94C8-4A3C-A1BF-DAA4738F4500}'
- name: grpc++_test_config
build: private
language: c++
@ -809,10 +834,9 @@ libs:
- src/compiler/objective_c_generator.cc
- src/compiler/python_generator.cc
- src/compiler/ruby_generator.cc
deps: []
deps:
- grpc++_codegen_lib
filegroups:
- grpc++_codegen
- grpc_codegen
- gpr_codegen
secure: false
vs_project_guid: '{B6E81D84-2ACB-41B8-8781-493A944C7817}'
@ -1057,6 +1081,27 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: concurrent_connectivity_test
build: test
language: c
src:
- test/core/surface/concurrent_connectivity_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: dns_resolver_connectivity_test
cpu_cost: 0.1
build: test
language: c
src:
- test/core/client_config/resolvers/dns_resolver_connectivity_test.c
deps:
- grpc_test_util
- grpc
- gpr_test_util
- gpr
- name: dns_resolver_test
build: test
language: c
@ -1194,6 +1239,14 @@ targets:
deps:
- gpr_test_util
- gpr
- name: gpr_backoff_test
build: test
language: c
src:
- test/core/support/backoff_test.c
deps:
- gpr_test_util
- gpr
- name: gpr_cmdline_test
build: test
language: c
@ -2079,6 +2132,20 @@ targets:
- grpc
- gpr_test_util
- gpr
- name: codegen_test
gtest: true
build: test
language: c++
src:
- src/proto/grpc/testing/control.proto
- src/proto/grpc/testing/messages.proto
- src/proto/grpc/testing/payloads.proto
- src/proto/grpc/testing/perf_db.proto
- src/proto/grpc/testing/services.proto
- src/proto/grpc/testing/stats.proto
- test/cpp/codegen/codegen_test.cc
deps:
- grpc++_codegen_lib
- name: credentials_test
gtest: true
build: test
@ -2379,7 +2446,7 @@ targets:
- linux
- posix
- name: qps_openloop_test
cpu_cost: 10
cpu_cost: 0.5
build: test
language: c++
src:
@ -2724,6 +2791,36 @@ configs:
dbg:
CPPFLAGS: -O0
DEFINES: _DEBUG DEBUG
easan:
CC: clang
CPPFLAGS: -O0 -fsanitize=address -fno-omit-frame-pointer -Wno-unused-command-line-argument
-DGPR_NO_DIRECT_SYSCALLS
CXX: clang++
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
LD: clang
LDFLAGS: -fsanitize=address
LDXX: clang++
compile_the_world: true
test_environ:
ASAN_OPTIONS: detect_leaks=1:color=always
LSAN_OPTIONS: suppressions=tools/lsan_suppressions.txt:report_objects=1
timeout_multiplier: 3
edbg:
CPPFLAGS: -O0
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
etsan:
CC: clang
CPPFLAGS: -O0 -fsanitize=thread -fno-omit-frame-pointer -Wno-unused-command-line-argument
-fPIE -pie -DGPR_NO_DIRECT_SYSCALLS
CXX: clang++
DEFINES: _DEBUG DEBUG GRPC_EXECUTION_CONTEXT_SANITIZER
LD: clang
LDFLAGS: -fsanitize=thread -fPIE -pie $(if $(JENKINS_BUILD),-Wl$(comma)-Ttext-segment=0x7e0000000000,)
LDXX: clang++
compile_the_world: true
test_environ:
TSAN_OPTIONS: suppressions=tools/tsan_suppressions.txt:halt_on_error=1:second_deadlock_stack=1
timeout_multiplier: 5
gcov:
CC: gcc
CPPFLAGS: -O0 -fprofile-arcs -ftest-coverage -Wno-return-type

@ -2,13 +2,20 @@
"name": "grpc/grpc",
"type": "library",
"description": "gRPC library for PHP",
"version": "0.6.0",
"version": "0.14.0",
"keywords": ["rpc"],
"homepage": "http://grpc.io",
"license": "BSD-3-Clause",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/stanley-cheung/Protobuf-PHP"
}
],
"require": {
"php": ">=5.5.0",
"google/auth": "dev-master"
"datto/protobuf-php": "dev-master",
"google/auth": "v0.7"
},
"autoload": {
"psr-4": {

@ -40,6 +40,7 @@ if test "$PHP_GRPC" != "no"; then
src/core/profiling/stap_timers.c \
src/core/support/alloc.c \
src/core/support/avl.c \
src/core/support/backoff.c \
src/core/support/cmdline.c \
src/core/support/cpu_iphone.c \
src/core/support/cpu_linux.c \

@ -2,9 +2,8 @@ Interoperability Test Case Descriptions
=======================================
Client and server use
[test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto)
and the [gRPC over HTTP/2 v2
protocol](https://github.com/grpc/grpc/blob/master/doc/PROTOCOL-HTTP2.md).
[test.proto](../src/proto/grpc/testing/test.proto)
and the [gRPC over HTTP/2 v2 protocol](./PROTOCOL-HTTP2.md).
Client
------

@ -1,450 +1,27 @@
# Examples
# Getting started
This directory contains code examples for all the C-based gRPC implementations: C++, Node.js, Python, Ruby, Objective-C, PHP, and C#. You can find examples and instructions specific to your
favourite language in the relevant subdirectory.
Examples for Go and Java gRPC live in their own repositories:
Welcome to the developer documentation for gRPC, a language-neutral,
platform-neutral remote procedure call (RPC) system developed at Google.
* [Java](https://github.com/grpc/grpc-java/tree/master/examples)
* [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android)
* [Go](https://github.com/grpc/grpc-go/tree/master/examples)
This document introduces you to gRPC with a quick overview and a simple
Hello World example. You'll find more tutorials and reference docs in this repository - more documentation is coming soon!
For more comprehensive documentation, including an [overview](http://www.grpc.io/docs/) and tutorials that use this example code, visit [grpc.io](http://www.grpc.io/docs/).
<a name="quickstart"></a>
## Quick start
You can find quick start guides for each language, including installation instructions, examples, and tutorials here:
Each example directory has quick start instructions for the appropriate language, including installation instructions and how to run our simplest Hello World example:
* [C++](cpp)
* [Java](https://github.com/grpc/grpc-java/tree/master/examples)
* [Go](https://github.com/grpc/grpc-go/tree/master/examples)
* [Ruby](ruby)
* [Node.js](node)
* [Android Java](https://github.com/grpc/grpc-java/tree/master/examples/android)
* [Python](python/helloworld)
* [C#](csharp)
* [Objective-C](objective-c/helloworld)
* [PHP](php)
## What's in this repository?
The `examples` directory contains documentation, resources, and examples
for all gRPC users. You can find examples and instructions specific to your
favourite language in the relevant subdirectory.
You can find out about the gRPC source code repositories in
[`grpc`](https://github.com/grpc/grpc). Each repository provides instructions
for building the appropriate libraries for your language.
## What is gRPC?
In gRPC a *client* application can directly call
methods on a *server* application on a different machine as if it was a
local object, making it easier for you to create distributed applications and
services. As in many RPC systems, gRPC is based around the idea of defining
a *service*, specifying the methods that can be called remotely with their
parameters and return types. On the server side, the server implements this
interface and runs a gRPC server to handle client calls. On the client side,
the client has a *stub* that provides exactly the same methods as the server.
<!--TODO: diagram-->
gRPC clients and servers can run and talk to each other in a variety of
environments - from servers inside Google to your own desktop - and can
be written in any of gRPC's [supported languages](#quickstart). So, for
example, you can easily create a gRPC server in Java with clients in Go,
Python, or Ruby. In addition, the latest Google APIs will have gRPC versions
of their interfaces, letting you easily build Google functionality into
your applications.
<a name="protocolbuffers"></a>
### Working with protocol buffers
By default gRPC uses *protocol buffers*, Google’s
mature open source mechanism for serializing structured data (although it
can be used with other data formats such as JSON). As you'll
see in our example below, you define gRPC services using *proto files*,
with method parameters and return types specified as protocol buffer message
types. You
can find out lots more about protocol buffers in the [Protocol Buffers
documentation](https://developers.google.com/protocol-buffers/docs/overview).
#### Protocol buffer versions
While protocol buffers have been available for open source users for some
time, our examples use a new flavour of protocol buffers called proto3,
which has a slightly simplified syntax, some useful new features, and supports
lots more languages. This is currently available as an alpha release in
Java, C++, Java_nano (Android Java), Python, and Ruby from [the protocol buffers Github
repo](https://github.com/google/protobuf/releases), as well as a Go language
generator from [the golang/protobuf Github repo](https://github.com/golang/protobuf), with more languages in development. You can find out more in the [proto3 language guide](https://developers.google.com/protocol-buffers/docs/proto3), and see
the major differences from the current default version in the [release notes](https://github.com/google/protobuf/releases). More proto3 documentation is coming soon.
In general, while you *can* use proto2 (the current default protocol buffers version), we recommend that you use proto3 with gRPC as it lets you use the full range of gRPC-supported languages, as well as avoiding compatibility
issues with proto2 clients talking to proto3 servers and vice versa.
<a name="hello"></a>
## Hello gRPC!
Now that you know a bit more about gRPC, the easiest way to see how it
works is to look at a simple example. Our Hello World walks you through the
construction of a simple gRPC client-server application, showing you how to:
- Create a protocol buffers schema that defines a simple RPC service with
a single
Hello World method.
- Create a Java server that implements this interface.
- Create a Java client that accesses the Java server.
- Create a Go client that accesses
the same Java server.
The complete code for the example is available in the `examples`
directory. We use the Git versioning system for source code management:
however, you don't need to know anything about Git to follow along other
than how to install and run a few git commands.
This is an introductory example rather than a comprehensive tutorial, so
don't worry if you're not a Go or
Java developer - the concepts are similar for all languages, and you can
find more implementations of our Hello World example in other languages (and full tutorials where available) in
the [language-specific folders](#quickstart) in this repository. Complete tutorials and
reference documentation for all gRPC languages are coming soon.
<a name="setup"></a>
### Setup
This section explains how to set up your local machine to work with
the example code. If you just want to read the example, you can go straight
to the [next step](#servicedef).
#### Install Git
You can download and install Git from http://git-scm.com/download. Once
installed you should have access to the git command line tool. The main
commands that you will need to use are:
- git clone ... : clone a remote repository onto your local machine
- git checkout ... : check out a particular branch or a tagged version of
the code to hack on
#### Install gRPC
To build and install gRPC plugins and related tools:
- For Java, see the [Java quick start](https://github.com/grpc/grpc-java).
- For Go, see the [Go quick start](https://github.com/grpc/grpc-go).
#### Get the source code
The example code for our Java example lives in the `grpc-java`
GitHub repository. Clone this repository to your local machine by running the
following command:
```
git clone https://github.com/grpc/grpc-java.git
```
Change your current directory to grpc-java/examples
```
cd grpc-java/examples
```
<a name="servicedef"></a>
### Defining a service
The first step in creating our example is to define a *service*: an RPC
service specifies the methods that can be called remotely with their parameters
and return types. As you saw in the
[overview](#protocolbuffers) above, gRPC does this using [protocol
buffers](https://developers.google.com/protocol-buffers/docs/overview). We
use the protocol buffers interface definition language (IDL) to define our
service methods, and define the parameters and return
types as protocol buffer message types. Both the client and the
server use interface code generated from the service definition.
Here's our example service definition, defined using protocol buffers IDL in
[helloworld.proto](https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto). The `Greeter`
service has one method, `SayHello`, that lets the server receive a single
`HelloRequest`
message from the remote client containing the user's name, then send back
a greeting in a single `HelloReply`. This is the simplest type of RPC you
can specify in gRPC - you can find out about other types in the tutorial for your chosen language.
```proto
syntax = "proto3";
option java_package = "io.grpc.examples";
package helloworld;
// The greeter service definition.
service Greeter {
// Sends a greeting
rpc SayHello (HelloRequest) returns (HelloReply) {}
}
// The request message containing the user's name.
message HelloRequest {
string name = 1;
}
// The response message containing the greetings
message HelloReply {
string message = 1;
}
```
<a name="generating"></a>
### Generating gRPC code
Once we've defined our service, we use the protocol buffer compiler
`protoc` to generate the special client and server code we need to create
our application - right now we're going to generate Java code, though you
can generate gRPC code in any gRPC-supported language (as you'll see later
in this example). The generated code contains both stub code for clients to
use and an abstract interface for servers to implement, both with the method
defined in our `Greeter` service.
(If you didn't install the gRPC plugins and protoc on your system and are just reading along with
the example, you can skip this step and move
onto the next one where we examine the generated code.)
For simplicity, we've provided a [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) with our Java examples that runs `protoc` for you with the appropriate plugin, input, and output:
```shell
../gradlew build
```
This generates the following classes from our .proto, which contain all the generated code
we need to create our example:
- `Helloworld.java`, which
has all the protocol buffer code to populate, serialize, and retrieve our
`HelloRequest` and `HelloReply` message types
- `GreeterGrpc.java`, which contains (along with some other useful code):
- an interface for `Greeter` servers to implement
```java
public static interface Greeter {
public void sayHello(io.grpc.examples.Helloworld.HelloRequest request,
io.grpc.stub.StreamObserver<io.grpc.examples.Helloworld.HelloReply> responseObserver);
}
```
- _stub_ classes that clients can use to talk to a `Greeter` server. As you can see, they also implement the `Greeter` interface.
```java
public static class GreeterStub extends
io.grpc.stub.AbstractStub<GreeterStub, GreeterServiceDescriptor>
implements Greeter {
...
}
```
<a name="server"></a>
### Writing a server
Now let's write some code! First we'll create a server application to implement
our service. Note that we're not going to go into a lot of detail about how
to create a server in this section. More detailed information will be in the
tutorial for your chosen language: check if there's one available yet in the relevant [quick start](#quickstart).
Our server application has two classes:
- a main server class that hosts the service implementation and allows access over the
network: [HelloWorldServer.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java).
- a simple service implementation class [GreeterImpl.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java#L51).
#### Service implementation
[GreeterImpl.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java#L51)
actually implements our `Greeter` service's required behaviour.
As you can see, the class `GreeterImpl` implements the interface
`GreeterGrpc.Greeter` that we [generated](#generating) from our proto
[IDL](https://github.com/grpc/grpc-java/tree/master/examples/src/main/proto) by implementing the method `sayHello`:
```java
@Override
public void sayHello(HelloRequest req, StreamObserver<HelloReply> responseObserver) {
HelloReply reply = HelloReply.newBuilder().setMessage("Hello " + req.getName()).build();
responseObserver.onValue(reply);
responseObserver.onCompleted();
}
```
- `sayHello` takes two parameters:
- `HelloRequest`: the request
- `StreamObserver<HelloReply>`: a response observer, which is
a special interface for the server to call with its response
To return our response to the client and complete the call:
1. We construct and populate a `HelloReply` response object with our exciting
message, as specified in our interface definition.
2. We return the `HelloReply` to the client and then specify that we've finished dealing with the RPC.
#### Server implementation
[HelloWorldServer.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldServer.java)
shows the other main feature required to provide a gRPC service; making the service
implementation available from the network.
```java
/* The port on which the server should run */
private int port = 50051;
private ServerImpl server;
private void start() throws Exception {
server = NettyServerBuilder.forPort(port)
.addService(GreeterGrpc.bindService(new GreeterImpl()))
.build().start();
logger.info("Server started, listening on " + port);
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Use stderr here since the logger may have been reset by its JVM shutdown hook.
System.err.println("*** shutting down gRPC server since JVM is shutting down");
HelloWorldServer.this.stop();
System.err.println("*** server shut down");
}
});
}
```
Here we create an appropriate gRPC server, binding the `Greeter` service
implementation that we created to a port. Then we start the server running: the server is now ready to receive
requests from `Greeter` service clients on our specified port. We'll cover
how all this works in a bit more detail in our language-specific documentation.
<a name="client"></a>
### Writing a client
Client-side gRPC is pretty simple. In this step, we'll use the generated code
to write a simple client that can access the `Greeter` server we created
in the [previous section](#server). You can see the complete client code in
[HelloWorldClient.java](https://github.com/grpc/grpc-java/blob/master/examples/src/main/java/io/grpc/examples/helloworld/HelloWorldClient.java).
Again, we're not going to go into much detail about how to implement a client;
we'll leave that for the tutorial.
#### Connecting to the service
First let's look at how we connect to the `Greeter` server. First we need
to create a gRPC channel, specifying the hostname and port of the server we
want to connect to. Then we use the channel to construct the stub instance.
```java
private final ChannelImpl channel;
private final GreeterGrpc.GreeterBlockingStub blockingStub;
public HelloWorldClient(String host, int port) {
channel =
NettyChannelBuilder.forAddress(host, port).negotiationType(NegotiationType.PLAINTEXT)
.build();
blockingStub = GreeterGrpc.newBlockingStub(channel);
}
```
In this case, we create a blocking stub. This means that the RPC call waits
for the server to respond, and will either return a response or raise an
exception. gRPC Java has other kinds of stubs that make non-blocking calls
to the server, where the response is returned asynchronously.
#### Calling an RPC
Now we can contact the service and obtain a greeting:
1. We construct and fill in a `HelloRequest` to send to the service.
2. We call the stub's `hello()` RPC with our request and get a `HelloReply`
back, from which we can get our greeting.
```java
HelloRequest req = HelloRequest.newBuilder().setName(name).build();
HelloReply reply = blockingStub.sayHello(req);
```
<a name="run"></a>
### Try it out!
Our [Gradle build file](https://github.com/grpc/grpc-java/blob/master/examples/build.gradle) simplifies building and running the examples.
You can build and run the server from the `grpc-java` root folder with:
```sh
$ ./gradlew :grpc-examples:helloWorldServer
```
and in another terminal window confirm that it receives a message.
```sh
$ ./gradlew :grpc-examples:helloWorldClient
```
### Adding another client
Finally, let's look at one of gRPC's most useful features - interoperability
between code in different languages. So far, we've just looked at Java code
generated from and implementing our `Greeter` service definition. However,
as you'll see if you look at the language-specific subdirectories
in this repository, we've also generated and implemented `Greeter`
in some of gRPC's other supported languages. Each service
and client uses interface code generated from the same proto
that we used for the Java example.
So, for example, if we visit the [`go` example
directory](https://github.com/grpc/grpc-go/tree/master/examples) and look at the
[`greeter_client`](https://github.com/grpc/grpc-go/blob/master/examples/greeter_client/main.go),
we can see that like the Java client, it connects to a `Greeter` service
at `localhost:50051` and uses a stub to call the `SayHello` method with a
`HelloRequest`:
```go
const (
address = "localhost:50051"
defaultName = "world"
)
func main() {
// Set up a connection to the server.
conn, err := grpc.Dial(address)
if err != nil {
log.Fatalf("did not connect: %v", err)
}
defer conn.Close()
c := pb.NewGreeterClient(conn)
// Contact the server and print out its response.
name := defaultName
if len(os.Args) > 1 {
name = os.Args[1]
}
r, err := c.SayHello(context.Background(), &pb.HelloRequest{Name:
name})
if err != nil {
log.Fatalf("could not greet: %v", err)
}
log.Printf("Greeting: %s", r.Message)
}
```
If we run the Java server from earlier in another terminal window, we can
run the Go client and connect to it just like the Java client, even though
it's written in a different language.
```
$ greeter_client
```
## Read more!
- You can find links to language-specific tutorials, examples, and other docs in each language's [quick start](#quickstart).
- [gRPC Authentication Support](doc/grpc-auth-support.md) introduces authentication support in gRPC with supported mechanisms and examples.

@ -2,7 +2,7 @@
## Installation
To install gRPC on your system, follow the instructions [here](../../INSTALL).
To install gRPC on your system, follow the instructions to build from source [here](../../INSTALL.md). This also installs the protocol buffer compiler `protoc` (if you don't have it already), and the C++ gRPC plugin for `protoc`.
## Hello C++ gRPC!
@ -23,21 +23,6 @@ Change your current directory to examples/cpp/helloworld
$ cd examples/cpp/helloworld/
```
### Generating gRPC code
To generate the client and server side interfaces:
```sh
$ make helloworld.grpc.pb.cc helloworld.pb.cc
```
Which internally invokes the proto-compiler as:
```sh
$ protoc -I ../../protos/ --grpc_out=. --plugin=protoc-gen-grpc=grpc_cpp_plugin ../../protos/helloworld.proto
$ protoc -I ../../protos/ --cpp_out=. ../../protos/helloworld.proto
```
### Client and server implementations
The client implementation is at [greeter_client.cc](helloworld/greeter_client.cc).

@ -91,7 +91,7 @@ message Point {
Next we need to generate the gRPC client and server interfaces from our .proto service definition. We do this using the protocol buffer compiler `protoc` with a special gRPC C++ plugin.
For simplicity, we've provided a [makefile](route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](../../INSTALL) first):
For simplicity, we've provided a [makefile](route_guide/Makefile) that runs `protoc` for you with the appropriate plugin, input, and output (if you want to run this yourself, make sure you've installed protoc and followed the gRPC code [installation instructions](../../INSTALL.md) first):
```shell
$ make route_guide.grpc.pb.cc route_guide.pb.cc

@ -2,7 +2,7 @@
### Install gRPC
Make sure you have installed gRPC on your system. Follow the instructions here:
[https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL).
[https://github.com/grpc/grpc/blob/master/INSTALL](../../../INSTALL.md).
### Get the tutorial source code

@ -20,7 +20,7 @@ TRY IT!
- Run the server
```sh
$ # from this directory (grpc_common/node).
$ # from this directory
$ node ./greeter_server.js &
```

@ -4,16 +4,15 @@ gRPC in 3 minutes (PHP)
PREREQUISITES
-------------
This requires PHP 5.5 or greater.
This requires `php` >=5.5, `phpize`, `pecl`, `phpunit`
INSTALL
-------
- On Mac OS X, install [homebrew][]. Run the following command to install gRPC.
- Install the gRPC PHP extension
```sh
$ curl -fsSL https://goo.gl/getgrpc | bash -s php
$ [sudo] pecl install grpc-beta
```
This will download and run the [gRPC install script][] and compile the gRPC PHP extension.
- Clone this repository
@ -37,6 +36,7 @@ TRY IT!
Please follow the instruction in [Node][] to run the server
```
$ cd examples/node
$ npm install
$ nodejs greeter_server.js
```
@ -58,7 +58,5 @@ TUTORIAL
You can find a more detailed tutorial in [gRPC Basics: PHP][]
[homebrew]:http://brew.sh
[gRPC install script]:https://raw.githubusercontent.com/grpc/homebrew-grpc/master/scripts/install
[Node]:https://github.com/grpc/grpc/tree/master/examples/node
[gRPC Basics: PHP]:http://www.grpc.io/docs/tutorials/basic/php.html

@ -1,17 +1,14 @@
{
"name": "grpc/grpc-demo",
"description": "gRPC example for PHP",
"minimum-stability": "dev",
"repositories": [
{
"type": "vcs",
"url": "https://github.com/stanley-cheung/Protobuf-PHP"
}
],
"name": "grpc/grpc-demo",
"description": "gRPC example for PHP",
"minimum-stability": "dev",
"require": {
"php": ">=5.5.0",
"datto/protobuf-php": "dev-master",
"google/auth": "dev-master",
"grpc/grpc": "dev-release-0_11"
"grpc/grpc": "dev-release-0_13"
}
}

@ -1,7 +1,7 @@
<?php
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -36,7 +36,9 @@ require dirname(__FILE__) . '/vendor/autoload.php';
require dirname(__FILE__) . '/helloworld.php';
function greet($name) {
$client = new helloworld\GreeterClient('localhost:50051', []);
$client = new helloworld\GreeterClient('localhost:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure()
]);
$request = new helloworld\HelloRequest();
$request->setName($name);
list($reply, $status) = $client->SayHello($request)->wait();

@ -1,7 +1,7 @@
<?php
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -37,7 +37,9 @@ require dirname(__FILE__) . '/route_guide.php';
define('COORD_FACTOR', 1e7);
$client = new routeguide\RouteGuideClient('localhost:50051', []);
$client = new routeguide\RouteGuideClient('localhost:50051', [
'credentials' => Grpc\ChannelCredentials::createInsecure()
]);
function printFeature($feature) {
$name = $feature->getName();

@ -1,4 +1,4 @@
# Copyright 2015, Google Inc.
# Copyright 2015-2016, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
@ -128,7 +128,7 @@ def serve():
while True:
time.sleep(_ONE_DAY_IN_SECONDS)
except KeyboardInterrupt:
server.stop()
server.stop(0)
if __name__ == '__main__':
serve()

@ -64,6 +64,7 @@ Pod::Spec.new do |s|
# Core cross-platform gRPC library, written in C.
s.subspec 'C-Core' do |ss|
ss.source_files = 'src/core/profiling/timers.h',
'src/core/support/backoff.h',
'src/core/support/block_annotate.h',
'src/core/support/env.h',
'src/core/support/load_file.h',
@ -120,6 +121,7 @@ Pod::Spec.new do |s|
'src/core/profiling/stap_timers.c',
'src/core/support/alloc.c',
'src/core/support/avl.c',
'src/core/support/backoff.c',
'src/core/support/cmdline.c',
'src/core/support/cpu_iphone.c',
'src/core/support/cpu_linux.c',
@ -296,17 +298,17 @@ Pod::Spec.new do |s|
'third_party/nanopb/pb_decode.h',
'third_party/nanopb/pb_encode.h',
'include/grpc/grpc_security.h',
'include/grpc/byte_buffer.h',
'include/grpc/byte_buffer_reader.h',
'include/grpc/compression.h',
'include/grpc/grpc.h',
'include/grpc/status.h',
'include/grpc/impl/codegen/byte_buffer.h',
'include/grpc/impl/codegen/compression_types.h',
'include/grpc/impl/codegen/connectivity_state.h',
'include/grpc/impl/codegen/grpc_types.h',
'include/grpc/impl/codegen/propagation_bits.h',
'include/grpc/impl/codegen/status.h',
'include/grpc/byte_buffer.h',
'include/grpc/byte_buffer_reader.h',
'include/grpc/compression.h',
'include/grpc/grpc.h',
'include/grpc/status.h',
'include/grpc/census.h',
'src/core/census/grpc_context.c',
'src/core/census/grpc_filter.c',
@ -470,6 +472,7 @@ Pod::Spec.new do |s|
'third_party/nanopb/pb_encode.c'
ss.private_header_files = 'src/core/profiling/timers.h',
'src/core/support/backoff.h',
'src/core/support/block_annotate.h',
'src/core/support/env.h',
'src/core/support/load_file.h',

@ -182,6 +182,7 @@ EXPORTS
gpr_event_wait
gpr_ref_init
gpr_ref
gpr_ref_non_zero
gpr_refn
gpr_unref
gpr_stats_init

@ -89,6 +89,7 @@ Gem::Specification.new do |s|
s.files += %w( include/grpc/impl/codegen/sync_win32.h )
s.files += %w( include/grpc/impl/codegen/time.h )
s.files += %w( src/core/profiling/timers.h )
s.files += %w( src/core/support/backoff.h )
s.files += %w( src/core/support/block_annotate.h )
s.files += %w( src/core/support/env.h )
s.files += %w( src/core/support/load_file.h )
@ -103,6 +104,7 @@ Gem::Specification.new do |s|
s.files += %w( src/core/profiling/stap_timers.c )
s.files += %w( src/core/support/alloc.c )
s.files += %w( src/core/support/avl.c )
s.files += %w( src/core/support/backoff.c )
s.files += %w( src/core/support/cmdline.c )
s.files += %w( src/core/support/cpu_iphone.c )
s.files += %w( src/core/support/cpu_linux.c )
@ -143,17 +145,17 @@ Gem::Specification.new do |s|
s.files += %w( src/core/support/tmpfile_win32.c )
s.files += %w( src/core/support/wrap_memcpy.c )
s.files += %w( include/grpc/grpc_security.h )
s.files += %w( include/grpc/byte_buffer.h )
s.files += %w( include/grpc/byte_buffer_reader.h )
s.files += %w( include/grpc/compression.h )
s.files += %w( include/grpc/grpc.h )
s.files += %w( include/grpc/status.h )
s.files += %w( include/grpc/impl/codegen/byte_buffer.h )
s.files += %w( include/grpc/impl/codegen/compression_types.h )
s.files += %w( include/grpc/impl/codegen/connectivity_state.h )
s.files += %w( include/grpc/impl/codegen/grpc_types.h )
s.files += %w( include/grpc/impl/codegen/propagation_bits.h )
s.files += %w( include/grpc/impl/codegen/status.h )
s.files += %w( include/grpc/byte_buffer.h )
s.files += %w( include/grpc/byte_buffer_reader.h )
s.files += %w( include/grpc/compression.h )
s.files += %w( include/grpc/grpc.h )
s.files += %w( include/grpc/status.h )
s.files += %w( include/grpc/census.h )
s.files += %w( src/core/census/grpc_filter.h )
s.files += %w( src/core/channel/channel_args.h )

@ -50,7 +50,7 @@ namespace grpc {
class CompletionQueue;
/// A thin wrapper around \a grpc_alarm (see / \a / src/core/surface/alarm.h).
class Alarm : private GrpcLibrary {
class Alarm : private GrpcLibraryCodegen {
public:
/// Create a completion queue alarm instance associated to \a cq.
///

@ -49,7 +49,7 @@ namespace grpc {
class Channel GRPC_FINAL : public ChannelInterface,
public CallHook,
public std::enable_shared_from_this<Channel>,
private GrpcLibrary {
private GrpcLibraryCodegen {
public:
~Channel();

@ -34,10 +34,11 @@
#ifndef GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H
#define GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/call.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/server_context.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h>
namespace grpc {
@ -109,13 +110,13 @@ class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert
GPR_ASSERT(init_ops_.SendMessage(request).ok());
GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
init_ops_.ClientSendClose();
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
@ -177,7 +178,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
@ -187,7 +188,7 @@ class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_ASSERT(write_ops_.SendMessage(msg).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
@ -243,7 +244,7 @@ class ClientAsyncReaderWriter GRPC_FINAL
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
@ -262,7 +263,7 @@ class ClientAsyncReaderWriter GRPC_FINAL
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_ASSERT(write_ops_.SendMessage(msg).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
@ -300,7 +301,7 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
@ -331,7 +332,7 @@ class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
}
void FinishWithError(const Status& status, void* tag) {
GPR_ASSERT(!status.ok());
GPR_CODEGEN_ASSERT(!status.ok());
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
@ -360,7 +361,7 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
@ -375,7 +376,7 @@ class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
GPR_ASSERT(write_ops_.SendMessage(msg).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
@ -409,7 +410,7 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
@ -430,7 +431,7 @@ class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
GPR_ASSERT(write_ops_.SendMessage(msg).ok());
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}

@ -45,6 +45,7 @@
namespace grpc {
class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface;
template <class R>
class ClientAsyncResponseReaderInterface {
@ -68,13 +69,13 @@ class ClientAsyncResponseReader GRPC_FINAL
collection_->init_buf_.SetCollection(collection_);
collection_->init_buf_.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert
GPR_ASSERT(collection_->init_buf_.SendMessage(request).ok());
GPR_CODEGEN_ASSERT(collection_->init_buf_.SendMessage(request).ok());
collection_->init_buf_.ClientSendClose();
call_.PerformOps(&collection_->init_buf_);
}
void ReadInitialMetadata(void* tag) {
GPR_ASSERT(!context_->initial_metadata_received_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
collection_->meta_buf_.SetCollection(collection_);
collection_->meta_buf_.set_output_tag(tag);
@ -116,7 +117,7 @@ class ServerAsyncResponseWriter GRPC_FINAL
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_buf_.set_output_tag(tag);
meta_buf_.SendInitialMetadata(ctx_->initial_metadata_);
@ -141,7 +142,7 @@ class ServerAsyncResponseWriter GRPC_FINAL
}
void FinishWithError(const Status& status, void* tag) {
GPR_ASSERT(!status.ok());
GPR_CODEGEN_ASSERT(!status.ok());
finish_buf_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_buf_.SendInitialMetadata(ctx_->initial_metadata_);

@ -34,19 +34,21 @@
#ifndef GRPCXX_IMPL_CODEGEN_CALL_H
#define GRPCXX_IMPL_CODEGEN_CALL_H
#include <cstring>
#include <functional>
#include <memory>
#include <map>
#include <cstring>
#include <memory>
#include <grpc/impl/codegen/alloc.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc++/impl/codegen/client_context.h>
#include <grpc++/impl/codegen/call_hook.h>
#include <grpc++/impl/codegen/client_context.h>
#include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/string_ref.h>
#include <grpc/impl/codegen/alloc.h>
#include <grpc/impl/codegen/grpc_types.h>
struct grpc_byte_buffer;
@ -56,12 +58,39 @@ class ByteBuffer;
class Call;
class CallHook;
class CompletionQueue;
extern CoreCodegenInterface* g_core_codegen_interface;
void FillMetadataMap(
inline void FillMetadataMap(
grpc_metadata_array* arr,
std::multimap<grpc::string_ref, grpc::string_ref>* metadata);
grpc_metadata* FillMetadataArray(
const std::multimap<grpc::string, grpc::string>& metadata);
std::multimap<grpc::string_ref, grpc::string_ref>* metadata) {
for (size_t i = 0; i < arr->count; i++) {
// TODO(yangg) handle duplicates?
metadata->insert(std::pair<grpc::string_ref, grpc::string_ref>(
arr->metadata[i].key, grpc::string_ref(arr->metadata[i].value,
arr->metadata[i].value_length)));
}
g_core_codegen_interface->grpc_metadata_array_destroy(arr);
g_core_codegen_interface->grpc_metadata_array_init(arr);
}
// TODO(yangg) if the map is changed before we send, the pointers will be a
// mess. Make sure it does not happen.
inline grpc_metadata* FillMetadataArray(
const std::multimap<grpc::string, grpc::string>& metadata) {
if (metadata.empty()) {
return nullptr;
}
grpc_metadata* metadata_array =
(grpc_metadata*)(g_core_codegen_interface->gpr_malloc(
metadata.size() * sizeof(grpc_metadata)));
size_t i = 0;
for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
metadata_array[i].key = iter->first.c_str();
metadata_array[i].value = iter->second.c_str();
metadata_array[i].value_length = iter->second.size();
}
return metadata_array;
}
/// Per-message write options.
class WriteOptions {
@ -170,7 +199,7 @@ class CallOpSendInitialMetadata {
}
void FinishOp(bool* status, int max_message_size) {
if (!send_) return;
gpr_free(initial_metadata_);
g_core_codegen_interface->gpr_free(initial_metadata_);
send_ = false;
}
@ -204,7 +233,7 @@ class CallOpSendMessage {
write_options_.Clear();
}
void FinishOp(bool* status, int max_message_size) {
if (own_buf_) grpc_byte_buffer_destroy(send_buf_);
if (own_buf_) g_core_codegen_interface->grpc_byte_buffer_destroy(send_buf_);
send_buf_ = nullptr;
}
@ -254,7 +283,7 @@ class CallOpRecvMessage {
max_message_size).ok();
} else {
got_message = false;
grpc_byte_buffer_destroy(recv_buf_);
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
}
} else {
got_message = false;
@ -321,7 +350,7 @@ class CallOpGenericRecvMessage {
*status = deserialize_->Deserialize(recv_buf_, max_message_size).ok();
} else {
got_message = false;
grpc_byte_buffer_destroy(recv_buf_);
g_core_codegen_interface->grpc_byte_buffer_destroy(recv_buf_);
}
} else {
got_message = false;
@ -386,7 +415,7 @@ class CallOpServerSendStatus {
void FinishOp(bool* status, int max_message_size) {
if (!send_status_available_) return;
gpr_free(trailing_metadata_);
g_core_codegen_interface->gpr_free(trailing_metadata_);
send_status_available_ = false;
}
@ -462,7 +491,7 @@ class CallOpClientRecvStatus {
*recv_status_ = Status(
static_cast<StatusCode>(status_code_),
status_details_ ? grpc::string(status_details_) : grpc::string());
gpr_free(status_details_);
g_core_codegen_interface->gpr_free(status_details_);
recv_status_ = nullptr;
}
@ -576,11 +605,22 @@ class SneakyCallOpSet : public CallOpSet<Op1, Op2, Op3, Op4, Op5, Op6> {
class Call GRPC_FINAL {
public:
/* call is owned by the caller */
Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq);
Call(grpc_call* call, CallHook* call_hook_, CompletionQueue* cq,
int max_message_size);
void PerformOps(CallOpSetInterface* ops);
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
: call_hook_(call_hook), cq_(cq), call_(call), max_message_size_(-1) {}
Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
int max_message_size)
: call_hook_(call_hook),
cq_(cq),
call_(call),
max_message_size_(max_message_size) {}
void PerformOps(CallOpSetInterface* ops) {
if (max_message_size_ > 0) {
ops->set_max_message_size(max_message_size_);
}
call_hook_->PerformOpsOnCall(ops, this);
}
grpc_call* call() { return call_; }
CompletionQueue* cq() { return cq_; }

@ -54,6 +54,7 @@
#include <string>
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/security/auth_context.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/string_ref.h>
@ -192,7 +193,7 @@ class ClientContext {
/// \return A multimap of initial metadata key-value pairs from the server.
const std::multimap<grpc::string_ref, grpc::string_ref>&
GetServerInitialMetadata() {
GPR_ASSERT(initial_metadata_received_);
GPR_CODEGEN_ASSERT(initial_metadata_received_);
return recv_initial_metadata_;
}

@ -37,6 +37,7 @@
#include <grpc++/impl/codegen/call.h>
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/status.h>
namespace grpc {
@ -66,7 +67,7 @@ Status BlockingUnaryCall(ChannelInterface* channel, const RpcMethod& method,
ops.ClientSendClose();
ops.ClientRecvStatus(context, &status);
call.PerformOps(&ops);
GPR_ASSERT((cq.Pluck(&ops) && ops.got_message) || !status.ok());
GPR_CODEGEN_ASSERT((cq.Pluck(&ops) && ops.got_message) || !status.ok());
return status;
}

@ -36,9 +36,12 @@
#ifndef GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H
#define GRPCXX_IMPL_CODEGEN_COMPLETION_QUEUE_H
#include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/grpc_library.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc++/impl/codegen/time.h>
#include <grpc/impl/codegen/time.h>
struct grpc_completion_queue;
@ -76,13 +79,17 @@ class Server;
class ServerBuilder;
class ServerContext;
extern CoreCodegenInterface* g_core_codegen_interface;
/// A thin wrapper around \a grpc_completion_queue (see / \a
/// src/core/surface/completion_queue.h).
class CompletionQueue : private GrpcLibrary {
class CompletionQueue : private GrpcLibraryCodegen {
public:
/// Default constructor. Implicitly creates a \a grpc_completion_queue
/// instance.
CompletionQueue();
CompletionQueue() {
cq_ = g_core_codegen_interface->grpc_completion_queue_create(nullptr);
}
/// Wrap \a take, taking ownership of the instance.
///
@ -90,7 +97,9 @@ class CompletionQueue : private GrpcLibrary {
explicit CompletionQueue(grpc_completion_queue* take);
/// Destructor. Destroys the owned wrapped completion queue / instance.
~CompletionQueue();
~CompletionQueue() {
g_core_codegen_interface->grpc_completion_queue_destroy(cq_);
}
/// Tri-state return for AsyncNext: SHUTDOWN, GOT_EVENT, TIMEOUT.
enum NextStatus {
@ -124,8 +133,8 @@ class CompletionQueue : private GrpcLibrary {
///
/// \return true if read a regular event, false if the queue is shutting down.
bool Next(void** tag, bool* ok) {
return (AsyncNextInternal(tag, ok, gpr_inf_future(GPR_CLOCK_REALTIME)) !=
SHUTDOWN);
return (AsyncNextInternal(tag, ok, g_core_codegen_interface->gpr_inf_future(
GPR_CLOCK_REALTIME)) != SHUTDOWN);
}
/// Request the shutdown of the queue.
@ -181,10 +190,31 @@ class CompletionQueue : private GrpcLibrary {
/// Wraps \a grpc_completion_queue_pluck.
/// \warning Must not be mixed with calls to \a Next.
bool Pluck(CompletionQueueTag* tag);
bool Pluck(CompletionQueueTag* tag) {
auto deadline =
g_core_codegen_interface->gpr_inf_future(GPR_CLOCK_REALTIME);
auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
cq_, tag, deadline, nullptr);
bool ok = ev.success != 0;
void* ignored = tag;
GPR_CODEGEN_ASSERT(tag->FinalizeResult(&ignored, &ok));
GPR_CODEGEN_ASSERT(ignored == tag);
// Ignore mutations by FinalizeResult: Pluck returns the C API status
return ev.success != 0;
}
/// Performs a single polling pluck on \a tag.
void TryPluck(CompletionQueueTag* tag);
/// \warning Must not be mixed with calls to \a Next.
void TryPluck(CompletionQueueTag* tag) {
auto deadline = gpr_time_0(GPR_CLOCK_REALTIME);
auto ev = g_core_codegen_interface->grpc_completion_queue_pluck(
cq_, tag, deadline, nullptr);
if (ev.type == GRPC_QUEUE_TIMEOUT) return;
bool ok = ev.success != 0;
void* ignored = tag;
// the tag must be swallowed if using TryPluck
GPR_CODEGEN_ASSERT(!tag->FinalizeResult(&ignored, &ok));
}
grpc_completion_queue* cq_; // owned
};

@ -0,0 +1,97 @@
/*
*
* Copyright 2015-2016, 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 GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
#define GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H
#include <grpc++/impl/codegen/config_protobuf.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc/impl/codegen/grpc_types.h>
namespace grpc {
/// Interface between the codegen library and the minimal subset of core
/// features required by the generated code.
///
/// All undocumented methods are simply forwarding the call to their namesakes.
/// Please refer to their corresponding documentation for details.
///
/// \warning This interface should be considered internal and private.
class CoreCodegenInterface {
public:
// Serialize the msg into a buffer created inside the function. The caller
// should destroy the returned buffer when done with it. If serialization
// fails,
// false is returned and buffer is left unchanged.
virtual Status SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** buffer) = 0;
// The caller keeps ownership of buffer and msg.
virtual Status DeserializeProto(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg,
int max_message_size) = 0;
/// Upon a failed assertion, log the error.
virtual void assert_fail(const char* failed_assertion) = 0;
virtual grpc_completion_queue* grpc_completion_queue_create(
void* reserved) = 0;
virtual void grpc_completion_queue_destroy(grpc_completion_queue* cq) = 0;
virtual grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq,
void* tag,
gpr_timespec deadline,
void* reserved) = 0;
virtual void* gpr_malloc(size_t size) = 0;
virtual void gpr_free(void* p) = 0;
virtual void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) = 0;
virtual void grpc_metadata_array_init(grpc_metadata_array* array) = 0;
virtual void grpc_metadata_array_destroy(grpc_metadata_array* array) = 0;
virtual gpr_timespec gpr_inf_future(gpr_clock_type type) = 0;
};
extern CoreCodegenInterface* g_core_codegen_interface;
/// Codegen specific version of \a GPR_ASSERT.
#define GPR_CODEGEN_ASSERT(x) \
do { \
if (!(x)) { \
grpc::g_core_codegen_interface->assert_fail(#x); \
} \
} while (0)
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_CORE_CODEGEN_INTERFACE_H

@ -34,6 +34,7 @@
#ifndef GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H
#define GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc/impl/codegen/log.h>
namespace grpc {
@ -44,24 +45,27 @@ class GrpcLibraryInterface {
virtual void shutdown() = 0;
};
/// Initialized by \a grpc::GrpcLibraryInitializer from
/// <grpc++/impl/grpc_library.h>
extern GrpcLibraryInterface* g_glip;
class GrpcLibrary {
/// Classes that require gRPC to be initialized should inherit from this class.
class GrpcLibraryCodegen {
public:
GrpcLibrary() {
GPR_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
GrpcLibraryCodegen() {
GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
g_glip->init();
}
virtual ~GrpcLibrary() {
GPR_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
virtual ~GrpcLibraryCodegen() {
GPR_CODEGEN_ASSERT(g_glip &&
"gRPC library not initialized. See "
"grpc::internal::GrpcLibraryInitializer.");
g_glip->shutdown();
}
};
} // namespace grpc
#endif // GRPCXX_IMPL_GRPC_LIBRARY_H
#endif // GRPCXX_IMPL_CODEGEN_GRPC_LIBRARY_H

@ -0,0 +1,463 @@
/*
*
* Copyright 2015-2016, 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 GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H
#define GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H
#include <grpc++/impl/codegen/call.h>
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/server_context.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h>
namespace grpc {
class CompletionQueue;
/// Common interface for all client side asynchronous streaming.
class ClientAsyncStreamingInterface {
public:
virtual ~ClientAsyncStreamingInterface() {}
/// Request notification of the reading of the initial metadata. Completion
/// will be notified by \a tag on the associated completion queue.
///
/// \param[in] tag Tag identifying this request.
virtual void ReadInitialMetadata(void* tag) = 0;
/// Request notification completion.
///
/// \param[out] status To be updated with the operation status.
/// \param[in] tag Tag identifying this request.
virtual void Finish(Status* status, void* tag) = 0;
};
/// An interface that yields a sequence of messages of type \a R.
template <class R>
class AsyncReaderInterface {
public:
virtual ~AsyncReaderInterface() {}
/// Read a message of type \a R into \a msg. Completion will be notified by \a
/// tag on the associated completion queue.
///
/// \param[out] msg Where to eventually store the read message.
/// \param[in] tag The tag identifying the operation.
virtual void Read(R* msg, void* tag) = 0;
};
/// An interface that can be fed a sequence of messages of type \a W.
template <class W>
class AsyncWriterInterface {
public:
virtual ~AsyncWriterInterface() {}
/// Request the writing of \a msg with identifying tag \a tag.
///
/// Only one write may be outstanding at any given time. This means that
/// after calling Write, one must wait to receive \a tag from the completion
/// queue BEFORE calling Write again.
///
/// \param[in] msg The message to be written.
/// \param[in] tag The tag identifying the operation.
virtual void Write(const W& msg, void* tag) = 0;
};
template <class R>
class ClientAsyncReaderInterface : public ClientAsyncStreamingInterface,
public AsyncReaderInterface<R> {};
template <class R>
class ClientAsyncReader GRPC_FINAL : public ClientAsyncReaderInterface<R> {
public:
/// Create a stream and write the first request out.
template <class W>
ClientAsyncReader(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
const W& request, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(init_ops_.SendMessage(request).ok());
init_ops_.ClientSendClose();
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_);
}
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage, CallOpClientSendClose>
init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
};
/// Common interface for client side asynchronous writing.
template <class W>
class ClientAsyncWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
/// Signal the client is done with the writes.
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0;
};
template <class W>
class ClientAsyncWriter GRPC_FINAL : public ClientAsyncWriterInterface<W> {
public:
template <class R>
ClientAsyncWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
R* response, void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
finish_ops_.RecvMessage(response);
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void WritesDone(void* tag) GRPC_OVERRIDE {
writes_done_ops_.set_output_tag(tag);
writes_done_ops_.ClientSendClose();
call_.PerformOps(&writes_done_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata> init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpSendMessage> write_ops_;
CallOpSet<CallOpClientSendClose> writes_done_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpGenericRecvMessage,
CallOpClientRecvStatus> finish_ops_;
};
/// Client-side interface for asynchronous bi-directional streaming.
template <class W, class R>
class ClientAsyncReaderWriterInterface : public ClientAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
/// Signal the client is done with the writes.
///
/// \param[in] tag The tag identifying the operation.
virtual void WritesDone(void* tag) = 0;
};
template <class W, class R>
class ClientAsyncReaderWriter GRPC_FINAL
: public ClientAsyncReaderWriterInterface<W, R> {
public:
ClientAsyncReaderWriter(ChannelInterface* channel, CompletionQueue* cq,
const RpcMethod& method, ClientContext* context,
void* tag)
: context_(context), call_(channel->CreateCall(method, context, cq)) {
init_ops_.set_output_tag(tag);
init_ops_.SendInitialMetadata(context->send_initial_metadata_);
call_.PerformOps(&init_ops_);
}
void ReadInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
meta_ops_.set_output_tag(tag);
meta_ops_.RecvInitialMetadata(context_);
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
read_ops_.RecvInitialMetadata(context_);
}
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void WritesDone(void* tag) GRPC_OVERRIDE {
writes_done_ops_.set_output_tag(tag);
writes_done_ops_.ClientSendClose();
call_.PerformOps(&writes_done_ops_);
}
void Finish(Status* status, void* tag) GRPC_OVERRIDE {
finish_ops_.set_output_tag(tag);
if (!context_->initial_metadata_received_) {
finish_ops_.RecvInitialMetadata(context_);
}
finish_ops_.ClientRecvStatus(context_, status);
call_.PerformOps(&finish_ops_);
}
private:
ClientContext* context_;
Call call_;
CallOpSet<CallOpSendInitialMetadata> init_ops_;
CallOpSet<CallOpRecvInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendMessage> write_ops_;
CallOpSet<CallOpClientSendClose> writes_done_ops_;
CallOpSet<CallOpRecvInitialMetadata, CallOpClientRecvStatus> finish_ops_;
};
template <class W, class R>
class ServerAsyncReader GRPC_FINAL : public ServerAsyncStreamingInterface,
public AsyncReaderInterface<R> {
public:
explicit ServerAsyncReader(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Finish(const W& msg, const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// The response is dropped if the status is not OK.
if (status.ok()) {
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_,
finish_ops_.SendMessage(msg));
} else {
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
}
call_.PerformOps(&finish_ops_);
}
void FinishWithError(const Status& status, void* tag) {
GPR_CODEGEN_ASSERT(!status.ok());
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus> finish_ops_;
};
template <class W>
class ServerAsyncWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W> {
public:
explicit ServerAsyncWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void Finish(const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
};
/// Server-side interface for asynchronous bi-directional streaming.
template <class W, class R>
class ServerAsyncReaderWriter GRPC_FINAL : public ServerAsyncStreamingInterface,
public AsyncWriterInterface<W>,
public AsyncReaderInterface<R> {
public:
explicit ServerAsyncReaderWriter(ServerContext* ctx)
: call_(nullptr, nullptr, nullptr), ctx_(ctx) {}
void SendInitialMetadata(void* tag) GRPC_OVERRIDE {
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
meta_ops_.set_output_tag(tag);
meta_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
call_.PerformOps(&meta_ops_);
}
void Read(R* msg, void* tag) GRPC_OVERRIDE {
read_ops_.set_output_tag(tag);
read_ops_.RecvMessage(msg);
call_.PerformOps(&read_ops_);
}
void Write(const W& msg, void* tag) GRPC_OVERRIDE {
write_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
write_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
// TODO(ctiller): don't assert
GPR_CODEGEN_ASSERT(write_ops_.SendMessage(msg).ok());
call_.PerformOps(&write_ops_);
}
void Finish(const Status& status, void* tag) {
finish_ops_.set_output_tag(tag);
if (!ctx_->sent_initial_metadata_) {
finish_ops_.SendInitialMetadata(ctx_->initial_metadata_);
ctx_->sent_initial_metadata_ = true;
}
finish_ops_.ServerSendStatus(ctx_->trailing_metadata_, status);
call_.PerformOps(&finish_ops_);
}
private:
friend class ::grpc::Server;
void BindCall(Call* call) GRPC_OVERRIDE { call_ = *call; }
Call call_;
ServerContext* ctx_;
CallOpSet<CallOpSendInitialMetadata> meta_ops_;
CallOpSet<CallOpRecvMessage<R>> read_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage> write_ops_;
CallOpSet<CallOpSendInitialMetadata, CallOpServerSendStatus> finish_ops_;
};
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_ASYNC_STREAM_H

@ -0,0 +1,152 @@
/*
*
* Copyright 2016, 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 GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H
#define GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H
namespace grpc {
enum StatusCode {
/// Not an error; returned on success.
OK = 0,
/// The operation was cancelled (typically by the caller).
CANCELLED = 1,
/// Unknown error. An example of where this error may be returned is if a
/// Status value received from another address space belongs to an error-space
/// that is not known in this address space. Also errors raised by APIs that
/// do not return enough error information may be converted to this error.
UNKNOWN = 2,
/// Client specified an invalid argument. Note that this differs from
/// FAILED_PRECONDITION. INVALID_ARGUMENT indicates arguments that are
/// problematic regardless of the state of the system (e.g., a malformed file
/// name).
INVALID_ARGUMENT = 3,
/// Deadline expired before operation could complete. For operations that
/// change the state of the system, this error may be returned even if the
/// operation has completed successfully. For example, a successful response
/// from a server could have been delayed long enough for the deadline to
/// expire.
DEADLINE_EXCEEDED = 4,
/// Some requested entity (e.g., file or directory) was not found.
NOT_FOUND = 5,
/// Some entity that we attempted to create (e.g., file or directory) already
/// exists.
ALREADY_EXISTS = 6,
/// The caller does not have permission to execute the specified operation.
/// PERMISSION_DENIED must not be used for rejections caused by exhausting
/// some resource (use RESOURCE_EXHAUSTED instead for those errors).
/// PERMISSION_DENIED must not be used if the caller can not be identified
/// (use UNAUTHENTICATED instead for those errors).
PERMISSION_DENIED = 7,
/// The request does not have valid authentication credentials for the
/// operation.
UNAUTHENTICATED = 16,
/// Some resource has been exhausted, perhaps a per-user quota, or perhaps the
/// entire file system is out of space.
RESOURCE_EXHAUSTED = 8,
/// Operation was rejected because the system is not in a state required for
/// the operation's execution. For example, directory to be deleted may be
/// non-empty, an rmdir operation is applied to a non-directory, etc.
///
/// A litmus test that may help a service implementor in deciding
/// between FAILED_PRECONDITION, ABORTED, and UNAVAILABLE:
/// (a) Use UNAVAILABLE if the client can retry just the failing call.
/// (b) Use ABORTED if the client should retry at a higher-level
/// (e.g., restarting a read-modify-write sequence).
/// (c) Use FAILED_PRECONDITION if the client should not retry until
/// the system state has been explicitly fixed. E.g., if an "rmdir"
/// fails because the directory is non-empty, FAILED_PRECONDITION
/// should be returned since the client should not retry unless
/// they have first fixed up the directory by deleting files from it.
/// (d) Use FAILED_PRECONDITION if the client performs conditional
/// REST Get/Update/Delete on a resource and the resource on the
/// server does not match the condition. E.g., conflicting
/// read-modify-write on the same resource.
FAILED_PRECONDITION = 9,
/// The operation was aborted, typically due to a concurrency issue like
/// sequencer check failures, transaction aborts, etc.
///
/// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
/// and UNAVAILABLE.
ABORTED = 10,
/// Operation was attempted past the valid range. E.g., seeking or reading
/// past end of file.
///
/// Unlike INVALID_ARGUMENT, this error indicates a problem that may be fixed
/// if the system state changes. For example, a 32-bit file system will
/// generate INVALID_ARGUMENT if asked to read at an offset that is not in the
/// range [0,2^32-1], but it will generate OUT_OF_RANGE if asked to read from
/// an offset past the current file size.
///
/// There is a fair bit of overlap between FAILED_PRECONDITION and
/// OUT_OF_RANGE. We recommend using OUT_OF_RANGE (the more specific error)
/// when it applies so that callers who are iterating through a space can
/// easily look for an OUT_OF_RANGE error to detect when they are done.
OUT_OF_RANGE = 11,
/// Operation is not implemented or not supported/enabled in this service.
UNIMPLEMENTED = 12,
/// Internal errors. Means some invariants expected by underlying System has
/// been broken. If you see one of these errors, Something is very broken.
INTERNAL = 13,
/// The service is currently unavailable. This is a most likely a transient
/// condition and may be corrected by retrying with a backoff.
///
/// See litmus test above for deciding between FAILED_PRECONDITION, ABORTED,
/// and UNAVAILABLE.
UNAVAILABLE = 14,
/// Unrecoverable data loss or corruption.
DATA_LOSS = 15,
/// Force users to include a default branch:
DO_NOT_USE = -1
};
} // namespace grpc
#endif // GRPCXX_IMPL_CODEGEN_STATUS_CODE_ENUM_H

@ -0,0 +1,45 @@
/*
*
* Copyright 2015-2016, 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 GRPCXX_IMPL_CODEGEN_SYNC_H
#define GRPCXX_IMPL_CODEGEN_SYNC_H
#include <grpc++/impl/codegen/config.h>
#ifdef GRPC_CXX0X_NO_THREAD
#include <grpc++/impl/codegen/sync_no_cxx11.h>
#else
#include <grpc++/impl/codegen/sync_cxx11.h>
#endif
#endif // GRPCXX_IMPL_CODEGEN_SYNC_H

@ -34,6 +34,7 @@
#ifndef GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
#define GRPCXX_IMPL_CODEGEN_METHOD_HANDLER_IMPL_H
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/rpc_service_method.h>
#include <grpc++/impl/codegen/sync_stream.h>
@ -58,7 +59,7 @@ class RpcMethodHandler : public MethodHandler {
status = func_(service_, param.server_context, &req, &rsp);
}
GPR_ASSERT(!param.server_context->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus> ops;
ops.SendInitialMetadata(param.server_context->initial_metadata_);
@ -93,7 +94,7 @@ class ClientStreamingHandler : public MethodHandler {
ResponseType rsp;
Status status = func_(service_, param.server_context, &reader, &rsp);
GPR_ASSERT(!param.server_context->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!param.server_context->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata, CallOpSendMessage,
CallOpServerSendStatus> ops;
ops.SendInitialMetadata(param.server_context->initial_metadata_);

@ -36,22 +36,16 @@
#include <type_traits>
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/config_protobuf.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/status.h>
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc/impl/codegen/log.h>
namespace grpc {
// Serialize the msg into a buffer created inside the function. The caller
// should destroy the returned buffer when done with it. If serialization fails,
// false is returned and buffer is left unchanged.
Status SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** buffer);
// The caller keeps ownership of buffer and msg.
Status DeserializeProto(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg,
int max_message_size);
extern CoreCodegenInterface* g_core_codegen_interface;
template <class T>
class SerializationTraits<T, typename std::enable_if<std::is_base_of<
@ -60,14 +54,13 @@ class SerializationTraits<T, typename std::enable_if<std::is_base_of<
static Status Serialize(const grpc::protobuf::Message& msg,
grpc_byte_buffer** buffer, bool* own_buffer) {
*own_buffer = true;
return SerializeProto(msg, buffer);
return g_core_codegen_interface->SerializeProto(msg, buffer);
}
static Status Deserialize(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg,
int max_message_size) {
auto status = DeserializeProto(buffer, msg, max_message_size);
grpc_byte_buffer_destroy(buffer);
return status;
return g_core_codegen_interface->DeserializeProto(buffer, msg,
max_message_size);
}
};

@ -103,6 +103,9 @@ class ServerContext {
void AddInitialMetadata(const grpc::string& key, const grpc::string& value);
void AddTrailingMetadata(const grpc::string& key, const grpc::string& value);
// IsCancelled is always safe to call when using sync API
// When using async API, it is only safe to call IsCancelled after
// the AsyncNotifyWhenDone tag has been delivered
bool IsCancelled() const;
// Cancel the Call from the server. This is a best-effort API and depending on

@ -34,10 +34,11 @@
#ifndef GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H
#define GRPCXX_IMPL_CODEGEN_SERVER_INTERFACE_H
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc++/impl/codegen/call_hook.h>
#include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/rpc_service_method.h>
#include <grpc/impl/codegen/grpc_types.h>
namespace grpc {
@ -223,7 +224,7 @@ class ServerInterface : public CallHook {
CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag,
Message* message) {
GPR_ASSERT(method);
GPR_CODEGEN_ASSERT(method);
new PayloadAsyncRequest<Message>(method->server_tag(), this, context,
stream, call_cq, notification_cq, tag,
message);
@ -233,7 +234,7 @@ class ServerInterface : public CallHook {
ServerAsyncStreamingInterface* stream,
CompletionQueue* call_cq,
ServerCompletionQueue* notification_cq, void* tag) {
GPR_ASSERT(method);
GPR_CODEGEN_ASSERT(method);
new NoPayloadAsyncRequest(method->server_tag(), this, context, stream,
call_cq, notification_cq, tag);
}

@ -35,6 +35,7 @@
#define GRPCXX_IMPL_CODEGEN_SERVICE_TYPE_H
#include <grpc++/impl/codegen/config.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/rpc_service_method.h>
#include <grpc++/impl/codegen/serialization_traits.h>
#include <grpc++/impl/codegen/server_interface.h>
@ -131,21 +132,18 @@ class Service {
void AddMethod(RpcServiceMethod* method) { methods_.emplace_back(method); }
void MarkMethodAsync(int index) {
if (methods_[index].get() == nullptr) {
gpr_log(GPR_ERROR,
"Cannot mark the method as 'async' because it has already been "
"marked as 'generic'.");
return;
}
GPR_CODEGEN_ASSERT(
methods_[index].get() != nullptr &&
"Cannot mark the method as 'async' because it has already been "
"marked as 'generic'.");
methods_[index]->ResetHandler();
}
void MarkMethodGeneric(int index) {
if (methods_[index]->handler() == nullptr) {
gpr_log(GPR_ERROR,
"Cannot mark the method as 'generic' because it has already been "
"marked as 'async'.");
}
GPR_CODEGEN_ASSERT(
methods_[index]->handler() != nullptr &&
"Cannot mark the method as 'generic' because it has already been "
"marked as 'async'.");
methods_[index].reset();
}

@ -34,8 +34,12 @@
#ifndef GRPCXX_IMPL_CODEGEN_STRING_REF_H
#define GRPCXX_IMPL_CODEGEN_STRING_REF_H
#include <iterator>
#include <string.h>
#include <algorithm>
#include <iosfwd>
#include <iostream>
#include <iterator>
#include <grpc++/impl/codegen/config.h>
@ -62,8 +66,13 @@ class string_ref {
string_ref() : data_(nullptr), length_(0) {}
string_ref(const string_ref& other)
: data_(other.data_), length_(other.length_) {}
string_ref& operator=(const string_ref& rhs);
string_ref(const char* s);
string_ref& operator=(const string_ref& rhs) {
data_ = rhs.data_;
length_ = rhs.length_;
return *this;
}
string_ref(const char* s) : data_(s), length_(strlen(s)) {}
string_ref(const char* s, size_t l) : data_(s), length_(l) {}
string_ref(const grpc::string& s) : data_(s.data()), length_(s.length()) {}
@ -95,13 +104,40 @@ class string_ref {
const char* data() const { return data_; }
// string operations
int compare(string_ref x) const;
bool starts_with(string_ref x) const;
bool ends_with(string_ref x) const;
size_t find(string_ref s) const;
size_t find(char c) const;
int compare(string_ref x) const {
size_t min_size = length_ < x.length_ ? length_ : x.length_;
int r = memcmp(data_, x.data_, min_size);
if (r < 0) return -1;
if (r > 0) return 1;
if (length_ < x.length_) return -1;
if (length_ > x.length_) return 1;
return 0;
}
bool starts_with(string_ref x) const {
return length_ >= x.length_ && (memcmp(data_, x.data_, x.length_) == 0);
}
string_ref substr(size_t pos, size_t n = npos) const;
bool ends_with(string_ref x) const {
return length_ >= x.length_ &&
(memcmp(data_ + (length_ - x.length_), x.data_, x.length_) == 0);
}
size_t find(string_ref s) const {
auto it = std::search(cbegin(), cend(), s.cbegin(), s.cend());
return it == cend() ? npos : std::distance(cbegin(), it);
}
size_t find(char c) const {
auto it = std::find(cbegin(), cend(), c);
return it == cend() ? npos : std::distance(cbegin(), it);
}
string_ref substr(size_t pos, size_t n = npos) const {
if (pos > length_) pos = length_;
if (n > (length_ - pos)) n = length_ - pos;
return string_ref(data_ + pos, n);
}
private:
const char* data_;
@ -109,14 +145,16 @@ class string_ref {
};
// Comparison operators
bool operator==(string_ref x, string_ref y);
bool operator!=(string_ref x, string_ref y);
bool operator<(string_ref x, string_ref y);
bool operator>(string_ref x, string_ref y);
bool operator<=(string_ref x, string_ref y);
bool operator>=(string_ref x, string_ref y);
std::ostream& operator<<(std::ostream& stream, const string_ref& string);
inline bool operator==(string_ref x, string_ref y) { return x.compare(y) == 0; }
inline bool operator!=(string_ref x, string_ref y) { return x.compare(y) != 0; }
inline bool operator<(string_ref x, string_ref y) { return x.compare(y) < 0; }
inline bool operator<=(string_ref x, string_ref y) { return x.compare(y) <= 0; }
inline bool operator>(string_ref x, string_ref y) { return x.compare(y) > 0; }
inline bool operator>=(string_ref x, string_ref y) { return x.compare(y) >= 0; }
inline std::ostream& operator<<(std::ostream& out, const string_ref& string) {
return out << grpc::string(string.begin(), string.end());
}
} // namespace grpc

@ -38,6 +38,7 @@
#include <grpc++/impl/codegen/channel_interface.h>
#include <grpc++/impl/codegen/client_context.h>
#include <grpc++/impl/codegen/completion_queue.h>
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/server_context.h>
#include <grpc++/impl/codegen/service_type.h>
#include <grpc++/impl/codegen/status.h>
@ -125,14 +126,14 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
CallOpClientSendClose> ops;
ops.SendInitialMetadata(context->send_initial_metadata_);
// TODO(ctiller): don't assert
GPR_ASSERT(ops.SendMessage(request).ok());
GPR_CODEGEN_ASSERT(ops.SendMessage(request).ok());
ops.ClientSendClose();
call_.PerformOps(&ops);
cq_.Pluck(&ops);
}
void WaitForInitialMetadata() GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
CallOpSet<CallOpRecvInitialMetadata> ops;
ops.RecvInitialMetadata(context_);
@ -155,7 +156,7 @@ class ClientReader GRPC_FINAL : public ClientReaderInterface<R> {
Status status;
ops.ClientRecvStatus(context_, &status);
call_.PerformOps(&ops);
GPR_ASSERT(cq_.Pluck(&ops));
GPR_CODEGEN_ASSERT(cq_.Pluck(&ops));
return status;
}
@ -194,7 +195,7 @@ class ClientWriter : public ClientWriterInterface<W> {
}
void WaitForInitialMetadata() {
GPR_ASSERT(!context_->initial_metadata_received_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
CallOpSet<CallOpRecvInitialMetadata> ops;
ops.RecvInitialMetadata(context_);
@ -227,7 +228,7 @@ class ClientWriter : public ClientWriterInterface<W> {
}
finish_ops_.ClientRecvStatus(context_, &status);
call_.PerformOps(&finish_ops_);
GPR_ASSERT(cq_.Pluck(&finish_ops_));
GPR_CODEGEN_ASSERT(cq_.Pluck(&finish_ops_));
return status;
}
@ -271,7 +272,7 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
}
void WaitForInitialMetadata() GRPC_OVERRIDE {
GPR_ASSERT(!context_->initial_metadata_received_);
GPR_CODEGEN_ASSERT(!context_->initial_metadata_received_);
CallOpSet<CallOpRecvInitialMetadata> ops;
ops.RecvInitialMetadata(context_);
@ -312,7 +313,7 @@ class ClientReaderWriter GRPC_FINAL : public ClientReaderWriterInterface<W, R> {
Status status;
ops.ClientRecvStatus(context_, &status);
call_.PerformOps(&ops);
GPR_ASSERT(cq_.Pluck(&ops));
GPR_CODEGEN_ASSERT(cq_.Pluck(&ops));
return status;
}
@ -328,7 +329,7 @@ class ServerReader GRPC_FINAL : public ReaderInterface<R> {
ServerReader(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_);
@ -355,7 +356,7 @@ class ServerWriter GRPC_FINAL : public WriterInterface<W> {
ServerWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_);
@ -391,7 +392,7 @@ class ServerReaderWriter GRPC_FINAL : public WriterInterface<W>,
ServerReaderWriter(Call* call, ServerContext* ctx) : call_(call), ctx_(ctx) {}
void SendInitialMetadata() {
GPR_ASSERT(!ctx_->sent_initial_metadata_);
GPR_CODEGEN_ASSERT(!ctx_->sent_initial_metadata_);
CallOpSet<CallOpSendInitialMetadata> ops;
ops.SendInitialMetadata(ctx_->initial_metadata_);

@ -40,21 +40,27 @@
#include <grpc++/impl/codegen/grpc_library.h>
#include <grpc/grpc.h>
#include "src/cpp/common/core_codegen.h"
namespace grpc {
namespace internal {
class GrpcLibrary GRPC_FINAL : public GrpcLibraryInterface {
public:
void init() GRPC_OVERRIDE { grpc_init(); }
void shutdown() GRPC_OVERRIDE { grpc_shutdown(); }
};
static GrpcLibrary g_gli;
static CoreCodegen g_core_codegen;
/// Instantiating this class ensures the proper initialization of gRPC.
class GrpcLibraryInitializer GRPC_FINAL {
public:
GrpcLibraryInitializer() { grpc::g_glip = &g_gli; }
GrpcLibraryInitializer() {
grpc::g_glip = &g_gli;
grpc::g_core_codegen_interface = &g_core_codegen;
}
/// A no-op method to force the linker to reference this class, which will
/// take care of initializing and shutting down the gRPC runtime.

@ -57,7 +57,7 @@ class SecureCallCredentials;
/// for all the calls on that channel.
///
/// \see http://www.grpc.io/docs/guides/auth.html
class ChannelCredentials : private GrpcLibrary {
class ChannelCredentials : private GrpcLibraryCodegen {
public:
ChannelCredentials();
~ChannelCredentials();
@ -83,7 +83,7 @@ class ChannelCredentials : private GrpcLibrary {
/// authenticate with a server for a given call on a channel.
///
/// \see http://www.grpc.io/docs/guides/auth.html
class CallCredentials : private GrpcLibrary {
class CallCredentials : private GrpcLibraryCodegen {
public:
CallCredentials();
~CallCredentials();

@ -62,7 +62,7 @@ class ThreadPoolInterface;
/// Models a gRPC server.
///
/// Servers are configured and started via \a grpc::ServerBuilder.
class Server GRPC_FINAL : public ServerInterface, private GrpcLibrary {
class Server GRPC_FINAL : public ServerInterface, private GrpcLibraryCodegen {
public:
~Server();

@ -80,18 +80,18 @@ CENSUSAPI int census_enabled(void);
metrics will be recorded. Keys are unique within a context. */
typedef struct census_context census_context;
/* A tag is a key:value pair. The key is a non-empty, printable (UTF-8
encoded), nil-terminated string. The value is a binary string, that may be
printable. There are limits on the sizes of both keys and values (see
CENSUS_MAX_TAG_KB_LEN definition below), and the number of tags that can be
propagated (CENSUS_MAX_PROPAGATED_TAGS). Users should also remember that
some systems may have limits on, e.g., the number of bytes that can be
transmitted as metadata, and that larger tags means more memory consumed
and time in processing. */
/* A tag is a key:value pair. Both keys and values are nil-terminated strings,
containing printable ASCII characters (decimal 32-126). Keys must be at
least one character in length. Both keys and values can have at most
CENSUS_MAX_TAG_KB_LEN characters (including the terminating nil). The
maximum number of tags that can be propagated is
CENSUS_MAX_PROPAGATED_TAGS. Users should also remember that some systems
may have limits on, e.g., the number of bytes that can be transmitted as
metadata, and that larger tags means more memory consumed and time in
processing. */
typedef struct {
const char *key;
const char *value;
size_t value_len;
uint8_t flags;
} census_tag;
@ -103,28 +103,25 @@ typedef struct {
/* Tag flags. */
#define CENSUS_TAG_PROPAGATE 1 /* Tag should be propagated over RPC */
#define CENSUS_TAG_STATS 2 /* Tag will be used for statistics aggregation */
#define CENSUS_TAG_BINARY 4 /* Tag value is not printable */
#define CENSUS_TAG_RESERVED 8 /* Reserved for internal use. */
/* Flag values 8,16,32,64,128 are reserved for future/internal use. Clients
#define CENSUS_TAG_RESERVED 4 /* Reserved for internal use. */
/* Flag values 4,8,16,32,64,128 are reserved for future/internal use. Clients
should not use or rely on their values. */
#define CENSUS_TAG_IS_PROPAGATED(flags) (flags & CENSUS_TAG_PROPAGATE)
#define CENSUS_TAG_IS_STATS(flags) (flags & CENSUS_TAG_STATS)
#define CENSUS_TAG_IS_BINARY(flags) (flags & CENSUS_TAG_BINARY)
/* An instance of this structure is kept by every context, and records the
basic information associated with the creation of that context. */
typedef struct {
int n_propagated_tags; /* number of propagated printable tags */
int n_propagated_binary_tags; /* number of propagated binary tags */
int n_local_tags; /* number of non-propagated (local) tags */
int n_deleted_tags; /* number of tags that were deleted */
int n_added_tags; /* number of tags that were added */
int n_modified_tags; /* number of tags that were modified */
int n_invalid_tags; /* number of tags with bad keys or values (e.g.
longer than CENSUS_MAX_TAG_KV_LEN) */
int n_ignored_tags; /* number of tags ignored because of
CENSUS_MAX_PROPAGATED_TAGS limit. */
int n_propagated_tags; /* number of propagated tags */
int n_local_tags; /* number of non-propagated (local) tags */
int n_deleted_tags; /* number of tags that were deleted */
int n_added_tags; /* number of tags that were added */
int n_modified_tags; /* number of tags that were modified */
int n_invalid_tags; /* number of tags with bad keys or values (e.g.
longer than CENSUS_MAX_TAG_KV_LEN) */
int n_ignored_tags; /* number of tags ignored because of
CENSUS_MAX_PROPAGATED_TAGS limit. */
} census_context_status;
/* Create a new context, adding and removing tags from an existing context.
@ -132,10 +129,10 @@ typedef struct {
to add as many tags in a single operation as is practical for the client.
@param base Base context to build upon. Can be NULL.
@param tags A set of tags to be added/changed/deleted. Tags with keys that
are in 'tags', but not 'base', are added to the tag set. Keys that are in
are in 'tags', but not 'base', are added to the context. Keys that are in
both 'tags' and 'base' will have their value/flags modified. Tags with keys
in both, but with NULL or zero-length values, will be deleted from the tag
set. Tags with invalid (too long or short) keys or values will be ignored.
in both, but with NULL values, will be deleted from the context. Tags with
invalid (too long or short) keys or values will be ignored.
If adding a tag will result in more than CENSUS_MAX_PROPAGATED_TAGS in either
binary or non-binary tags, they will be ignored, as will deletions of
tags that don't exist.
@ -185,32 +182,19 @@ CENSUSAPI int census_context_get_tag(const census_context *context,
for use by RPC systems only, for purposes of transmitting/receiving contexts.
*/
/* Encode a context into a buffer. The propagated tags are encoded into the
buffer in two regions: one for printable tags, and one for binary tags.
/* Encode a context into a buffer.
@param context context to be encoded
@param buffer pointer to buffer. This address will be used to encode the
printable tags.
@param buffer buffer into which the context will be encoded.
@param buf_size number of available bytes in buffer.
@param print_buf_size Will be set to the number of bytes consumed by
printable tags.
@param bin_buf_size Will be set to the number of bytes used to encode the
binary tags.
@return A pointer to the binary tag's encoded, or NULL if the buffer was
insufficiently large to hold the encoded tags. Thus, if successful,
printable tags are encoded into
[buffer, buffer + *print_buf_size) and binary tags into
[returned-ptr, returned-ptr + *bin_buf_size) (and the returned
pointer should be buffer + *print_buf_size) */
CENSUSAPI char *census_context_encode(const census_context *context,
char *buffer, size_t buf_size,
size_t *print_buf_size,
size_t *bin_buf_size);
/* Decode context buffers encoded with census_context_encode(). Returns NULL
@return The number of buffer bytes consumed for the encoded context, or
zero if the buffer was of insufficient size. */
CENSUSAPI size_t census_context_encode(const census_context *context,
char *buffer, size_t buf_size);
/* Decode context buffer encoded with census_context_encode(). Returns NULL
if there is an error in parsing either buffer. */
CENSUSAPI census_context *census_context_decode(const char *buffer, size_t size,
const char *bin_buffer,
size_t bin_size);
CENSUSAPI census_context *census_context_decode(const char *buffer,
size_t size);
/* Distributed traces can have a number of options. */
enum census_trace_mask_values {

@ -247,8 +247,41 @@
#else /* _LP64 */
#define GPR_ARCH_32 1
#endif /* _LP64 */
#elif defined(__native_client__)
#define GPR_PLATFORM_STRING "nacl"
#ifndef _BSD_SOURCE
#define _BSD_SOURCE
#endif
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#define GPR_CPU_POSIX 1
#define GPR_GCC_ATOMIC 1
#define GPR_GCC_TLS 1
#define GPR_POSIX_LOG 1
#define GPR_POSIX_MULTIPOLL_WITH_POLL 1
#define GPR_POSIX_WAKEUP_FD 1
#define GPR_POSIX_NO_SPECIAL_WAKEUP_FD 1
#define GPR_POSIX_SOCKET 1
#define GPR_POSIX_SOCKETADDR 1
#define GPR_POSIX_SOCKETUTILS 1
#define GPR_POSIX_ENV 1
#define GPR_POSIX_FILE 1
#define GPR_POSIX_STRING 1
#define GPR_POSIX_SUBPROCESS 1
#define GPR_POSIX_SYNC 1
#define GPR_POSIX_TIME 1
#define GPR_GETPID_IN_UNISTD_H 1
#ifdef _LP64
#define GPR_ARCH_64 1
#else /* _LP64 */
#define GPR_ARCH_32 1
#endif /* _LP64 */
#else
#error Could not auto-detect platform
#error "Could not auto-detect platform"
#endif
#endif /* GPR_NO_AUTODETECT_PLATFORM */

@ -182,6 +182,10 @@ GPRAPI void gpr_ref_init(gpr_refcount *r, int n);
/* Increment the reference count *r. Requires *r initialized. */
GPRAPI void gpr_ref(gpr_refcount *r);
/* Increment the reference count *r. Requires *r initialized.
Crashes if refcount is zero */
GPRAPI void gpr_ref_non_zero(gpr_refcount *r);
/* Increment the reference count *r by n. Requires *r initialized, n > 0. */
GPRAPI void gpr_refn(gpr_refcount *r, int n);

@ -87,17 +87,17 @@
"src/node/src/metadata.js",
"src/node/src/server.js",
"include/grpc/grpc_security.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/impl/codegen/byte_buffer.h",
"include/grpc/impl/codegen/compression_types.h",
"include/grpc/impl/codegen/connectivity_state.h",
"include/grpc/impl/codegen/grpc_types.h",
"include/grpc/impl/codegen/propagation_bits.h",
"include/grpc/impl/codegen/status.h",
"include/grpc/byte_buffer.h",
"include/grpc/byte_buffer_reader.h",
"include/grpc/compression.h",
"include/grpc/grpc.h",
"include/grpc/status.h",
"include/grpc/census.h",
"src/core/census/grpc_filter.h",
"src/core/channel/channel_args.h",
@ -865,6 +865,7 @@
"include/grpc/impl/codegen/sync_win32.h",
"include/grpc/impl/codegen/time.h",
"src/core/profiling/timers.h",
"src/core/support/backoff.h",
"src/core/support/block_annotate.h",
"src/core/support/env.h",
"src/core/support/load_file.h",
@ -879,6 +880,7 @@
"src/core/profiling/stap_timers.c",
"src/core/support/alloc.c",
"src/core/support/avl.c",
"src/core/support/backoff.c",
"src/core/support/cmdline.c",
"src/core/support/cpu_iphone.c",
"src/core/support/cpu_linux.c",

@ -10,11 +10,11 @@
<email>grpc-packages@google.com</email>
<active>yes</active>
</lead>
<date>2016-02-24</date>
<date>2016-03-01</date>
<time>16:06:07</time>
<version>
<release>0.8.0</release>
<api>0.8.0</api>
<release>0.14.0</release>
<api>0.14.0</api>
</version>
<stability>
<release>beta</release>
@ -22,14 +22,14 @@
</stability>
<license>BSD</license>
<notes>
- Simplify gRPC PHP installation #4517
- Increase unit test code coverage #5225
</notes>
<contents>
<dir baseinstalldir="/" name="/">
<file baseinstalldir="/" name="config.m4" role="src" />
<file baseinstalldir="/" name="src/php/README.md" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/CREDITS" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/LICENSE" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/README.md" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/byte_buffer.c" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/call.c" role="src" />
<file baseinstalldir="/" name="src/php/ext/grpc/call_credentials.c" role="src" />
@ -93,6 +93,7 @@
<file baseinstalldir="/" name="include/grpc/impl/codegen/sync_win32.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/time.h" role="src" />
<file baseinstalldir="/" name="src/core/profiling/timers.h" role="src" />
<file baseinstalldir="/" name="src/core/support/backoff.h" role="src" />
<file baseinstalldir="/" name="src/core/support/block_annotate.h" role="src" />
<file baseinstalldir="/" name="src/core/support/env.h" role="src" />
<file baseinstalldir="/" name="src/core/support/load_file.h" role="src" />
@ -107,6 +108,7 @@
<file baseinstalldir="/" name="src/core/profiling/stap_timers.c" role="src" />
<file baseinstalldir="/" name="src/core/support/alloc.c" role="src" />
<file baseinstalldir="/" name="src/core/support/avl.c" role="src" />
<file baseinstalldir="/" name="src/core/support/backoff.c" role="src" />
<file baseinstalldir="/" name="src/core/support/cmdline.c" role="src" />
<file baseinstalldir="/" name="src/core/support/cpu_iphone.c" role="src" />
<file baseinstalldir="/" name="src/core/support/cpu_linux.c" role="src" />
@ -147,17 +149,17 @@
<file baseinstalldir="/" name="src/core/support/tmpfile_win32.c" role="src" />
<file baseinstalldir="/" name="src/core/support/wrap_memcpy.c" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc_security.h" role="src" />
<file baseinstalldir="/" name="include/grpc/byte_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/byte_buffer_reader.h" role="src" />
<file baseinstalldir="/" name="include/grpc/compression.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
<file baseinstalldir="/" name="include/grpc/status.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/byte_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/compression_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/connectivity_state.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/grpc_types.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/propagation_bits.h" role="src" />
<file baseinstalldir="/" name="include/grpc/impl/codegen/status.h" role="src" />
<file baseinstalldir="/" name="include/grpc/byte_buffer.h" role="src" />
<file baseinstalldir="/" name="include/grpc/byte_buffer_reader.h" role="src" />
<file baseinstalldir="/" name="include/grpc/compression.h" role="src" />
<file baseinstalldir="/" name="include/grpc/grpc.h" role="src" />
<file baseinstalldir="/" name="include/grpc/status.h" role="src" />
<file baseinstalldir="/" name="include/grpc/census.h" role="src" />
<file baseinstalldir="/" name="src/core/census/grpc_filter.h" role="src" />
<file baseinstalldir="/" name="src/core/channel/channel_args.h" role="src" />
@ -969,5 +971,20 @@ Update to wrap gRPC C Core version 0.10.0
- Simplify gRPC PHP installation #4517
</notes>
</release>
<release>
<version>
<release>0.14.0</release>
<api>0.14.0</api>
</version>
<stability>
<release>beta</release>
<api>beta</api>
</stability>
<date>2016-03-01</date>
<license>BSD</license>
<notes>
- Increase unit test code coverage #5225
</notes>
</release>
</changelog>
</package>

@ -108,8 +108,13 @@ if "linux" in sys.platform or "darwin" in sys.platform:
def cython_extensions(package_names, module_names, extra_sources, include_dirs,
libraries, define_macros, build_with_cython=False):
# Set compiler directives linetrace argument only if we care about tracing;
# this is due to Cython having different behavior between linetrace being
# False and linetrace being unset. See issue #5689.
cython_compiler_directives = {}
if ENABLE_CYTHON_TRACING:
define_macros = define_macros + [('CYTHON_TRACE_NOGIL', 1)]
cython_compiler_directives['linetrace'] = True
file_extension = 'pyx' if build_with_cython else 'c'
module_files = [os.path.join(PYTHON_STEM,
name.replace('.', '/') + '.' + file_extension)
@ -129,7 +134,7 @@ def cython_extensions(package_names, module_names, extra_sources, include_dirs,
return Cython.Build.cythonize(
extensions,
include_path=include_dirs,
compiler_directives={'linetrace': bool(ENABLE_CYTHON_TRACING)})
compiler_directives=cython_compiler_directives)
else:
return extensions
@ -154,6 +159,7 @@ INSTALL_REQUIRES = (
SETUP_REQUIRES = (
'sphinx>=1.3',
'sphinx_rtd_theme>=0.1.8'
) + INSTALL_REQUIRES
COMMAND_CLASS = {
@ -165,6 +171,7 @@ COMMAND_CLASS = {
'build_tagged_ext': precompiled.BuildTaggedExt,
'gather': commands.Gather,
'run_interop': commands.RunInterop,
'test_lite': commands.TestLite
}
# Ensure that package data is copied over before any commands have been run:

@ -60,10 +60,10 @@
// limit of 255 for both CENSUS_MAX_TAG_KV_LEN and CENSUS_MAX_PROPAGATED_TAGS.
// * Keep all tag information (keys/values/flags) in a single memory buffer,
// that can be directly copied to the wire.
// * Binary tags share the same structure as, but are encoded separately from,
// non-binary tags. This is primarily because non-binary tags are far more
// likely to be repeated across multiple RPC calls, so are more efficiently
// cached and compressed in any metadata schemes.
// min and max valid chars in tag keys and values. All printable ASCII is OK.
#define MIN_VALID_TAG_CHAR 32 // ' '
#define MAX_VALID_TAG_CHAR 126 // '~'
// Structure representing a set of tags. Essentially a count of number of tags
// present, and pointer to a chunk of memory that contains the per-tag details.
@ -77,7 +77,7 @@ struct tag_set {
char *kvm; // key/value memory. Consists of repeated entries of:
// Offset Size Description
// 0 1 Key length, including trailing 0. (K)
// 1 1 Value length. (V)
// 1 1 Value length, including trailing 0 (V)
// 2 1 Flags
// 3 K Key bytes
// 3 + K V Value bytes
@ -108,19 +108,36 @@ struct raw_tag {
#define CENSUS_TAG_DELETED CENSUS_TAG_RESERVED
#define CENSUS_TAG_IS_DELETED(flags) (flags & CENSUS_TAG_DELETED)
// Primary (external) representation of a context. Composed of 3 underlying
// tag_set structs, one for each of the binary/printable propagated tags, and
// one for everything else. This is to efficiently support tag
// encoding/decoding.
// Primary representation of a context. Composed of 2 underlying tag_set
// structs, one each for propagated and local (non-propagated) tags. This is
// to efficiently support tag encoding/decoding.
// TODO(aveitch): need to add tracing id's/structure.
struct census_context {
struct tag_set tags[3];
struct tag_set tags[2];
census_context_status status;
};
// Indices into the tags member of census_context
#define PROPAGATED_TAGS 0
#define PROPAGATED_BINARY_TAGS 1
#define LOCAL_TAGS 2
#define LOCAL_TAGS 1
// Validate (check all characters are in range and size is less than limit) a
// key or value string. Returns 0 if the string is invalid, or the length
// (including terminator) if valid.
static size_t validate_tag(const char *kv) {
size_t len = 1;
char ch;
while ((ch = *kv++) != 0) {
if (ch < MIN_VALID_TAG_CHAR || ch > MAX_VALID_TAG_CHAR) {
return 0;
}
len++;
}
if (len > CENSUS_MAX_TAG_KV_LEN) {
return 0;
}
return len;
}
// Extract a raw tag given a pointer (raw) to the tag header. Allow for some
// extra bytes in the tag header (see encode/decode functions for usage: this
@ -166,9 +183,7 @@ static bool context_delete_tag(census_context *context, const census_tag *tag,
size_t key_len) {
return (
tag_set_delete_tag(&context->tags[LOCAL_TAGS], tag->key, key_len) ||
tag_set_delete_tag(&context->tags[PROPAGATED_TAGS], tag->key, key_len) ||
tag_set_delete_tag(&context->tags[PROPAGATED_BINARY_TAGS], tag->key,
key_len));
tag_set_delete_tag(&context->tags[PROPAGATED_TAGS], tag->key, key_len));
}
// Add a tag to a tag_set. Return true on success, false if the tag could
@ -176,11 +191,11 @@ static bool context_delete_tag(census_context *context, const census_tag *tag,
// not be called if the tag may already exist (in a non-deleted state) in
// the tag_set, as that would result in two tags with the same key.
static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
size_t key_len) {
size_t key_len, size_t value_len) {
if (tags->ntags == CENSUS_MAX_PROPAGATED_TAGS) {
return false;
}
const size_t tag_size = key_len + tag->value_len + TAG_HEADER_SIZE;
const size_t tag_size = key_len + value_len + TAG_HEADER_SIZE;
if (tags->kvm_used + tag_size > tags->kvm_size) {
// allocate new memory if needed
tags->kvm_size += 2 * CENSUS_MAX_TAG_KV_LEN + TAG_HEADER_SIZE;
@ -191,13 +206,12 @@ static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
}
char *kvp = tags->kvm + tags->kvm_used;
*kvp++ = (char)key_len;
*kvp++ = (char)tag->value_len;
*kvp++ = (char)value_len;
// ensure reserved flags are not used.
*kvp++ = (char)(tag->flags & (CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS |
CENSUS_TAG_BINARY));
*kvp++ = (char)(tag->flags & (CENSUS_TAG_PROPAGATE | CENSUS_TAG_STATS));
memcpy(kvp, tag->key, key_len);
kvp += key_len;
memcpy(kvp, tag->value, tag->value_len);
memcpy(kvp, tag->value, value_len);
tags->kvm_used += tag_size;
tags->ntags++;
tags->ntags_alloc++;
@ -207,30 +221,20 @@ static bool tag_set_add_tag(struct tag_set *tags, const census_tag *tag,
// Add/modify/delete a tag to/in a context. Caller must validate that tag key
// etc. are valid.
static void context_modify_tag(census_context *context, const census_tag *tag,
size_t key_len) {
size_t key_len, size_t value_len) {
// First delete the tag if it is already present.
bool deleted = context_delete_tag(context, tag, key_len);
// Determine if we need to add it back.
bool call_add = tag->value != NULL && tag->value_len != 0;
bool added = false;
if (call_add) {
if (CENSUS_TAG_IS_PROPAGATED(tag->flags)) {
if (CENSUS_TAG_IS_BINARY(tag->flags)) {
added = tag_set_add_tag(&context->tags[PROPAGATED_BINARY_TAGS], tag,
key_len);
} else {
added = tag_set_add_tag(&context->tags[PROPAGATED_TAGS], tag, key_len);
}
} else {
added = tag_set_add_tag(&context->tags[LOCAL_TAGS], tag, key_len);
}
if (CENSUS_TAG_IS_PROPAGATED(tag->flags)) {
added = tag_set_add_tag(&context->tags[PROPAGATED_TAGS], tag, key_len,
value_len);
} else {
added =
tag_set_add_tag(&context->tags[LOCAL_TAGS], tag, key_len, value_len);
}
if (deleted) {
if (call_add) {
context->status.n_modified_tags++;
} else {
context->status.n_deleted_tags++;
}
context->status.n_modified_tags++;
} else {
if (added) {
context->status.n_added_tags++;
@ -292,8 +296,6 @@ census_context *census_context_create(const census_context *base,
memset(context, 0, sizeof(census_context));
} else {
tag_set_copy(&context->tags[PROPAGATED_TAGS], &base->tags[PROPAGATED_TAGS]);
tag_set_copy(&context->tags[PROPAGATED_BINARY_TAGS],
&base->tags[PROPAGATED_BINARY_TAGS]);
tag_set_copy(&context->tags[LOCAL_TAGS], &base->tags[LOCAL_TAGS]);
memset(&context->status, 0, sizeof(context->status));
}
@ -301,22 +303,29 @@ census_context *census_context_create(const census_context *base,
// the context to add/replace/delete as required.
for (int i = 0; i < ntags; i++) {
const census_tag *tag = &tags[i];
size_t key_len = strlen(tag->key) + 1;
// ignore the tag if it is too long/short.
if (key_len != 1 && key_len <= CENSUS_MAX_TAG_KV_LEN &&
tag->value_len <= CENSUS_MAX_TAG_KV_LEN) {
context_modify_tag(context, tag, key_len);
} else {
size_t key_len = validate_tag(tag->key);
// ignore the tag if it is invalid or too short.
if (key_len <= 1) {
context->status.n_invalid_tags++;
} else {
if (tag->value != NULL) {
size_t value_len = validate_tag(tag->value);
if (value_len != 0) {
context_modify_tag(context, tag, key_len, value_len);
} else {
context->status.n_invalid_tags++;
}
} else {
if (context_delete_tag(context, tag, key_len)) {
context->status.n_deleted_tags++;
}
}
}
}
// Remove any deleted tags, update status if needed, and return.
tag_set_flatten(&context->tags[PROPAGATED_TAGS]);
tag_set_flatten(&context->tags[PROPAGATED_BINARY_TAGS]);
tag_set_flatten(&context->tags[LOCAL_TAGS]);
context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags;
context->status.n_propagated_binary_tags =
context->tags[PROPAGATED_BINARY_TAGS].ntags;
context->status.n_local_tags = context->tags[LOCAL_TAGS].ntags;
if (status) {
*status = &context->status;
@ -331,7 +340,6 @@ const census_context_status *census_context_get_status(
void census_context_destroy(census_context *context) {
gpr_free(context->tags[PROPAGATED_TAGS].kvm);
gpr_free(context->tags[PROPAGATED_BINARY_TAGS].kvm);
gpr_free(context->tags[LOCAL_TAGS].kvm);
gpr_free(context);
}
@ -343,9 +351,6 @@ void census_context_initialize_iterator(const census_context *context,
if (context->tags[PROPAGATED_TAGS].ntags != 0) {
iterator->base = PROPAGATED_TAGS;
iterator->kvm = context->tags[PROPAGATED_TAGS].kvm;
} else if (context->tags[PROPAGATED_BINARY_TAGS].ntags != 0) {
iterator->base = PROPAGATED_BINARY_TAGS;
iterator->kvm = context->tags[PROPAGATED_BINARY_TAGS].kvm;
} else if (context->tags[LOCAL_TAGS].ntags != 0) {
iterator->base = LOCAL_TAGS;
iterator->kvm = context->tags[LOCAL_TAGS].kvm;
@ -363,7 +368,6 @@ int census_context_next_tag(census_context_iterator *iterator,
iterator->kvm = decode_tag(&raw, iterator->kvm, 0);
tag->key = raw.key;
tag->value = raw.value;
tag->value_len = raw.value_len;
tag->flags = raw.flags;
if (++iterator->index == iterator->context->tags[iterator->base].ntags) {
do {
@ -388,7 +392,6 @@ static bool tag_set_get_tag(const struct tag_set *tags, const char *key,
if (key_len == raw.key_len && memcmp(raw.key, key, key_len) == 0) {
tag->key = raw.key;
tag->value = raw.value;
tag->value_len = raw.value_len;
tag->flags = raw.flags;
return true;
}
@ -403,8 +406,6 @@ int census_context_get_tag(const census_context *context, const char *key,
return 0;
}
if (tag_set_get_tag(&context->tags[PROPAGATED_TAGS], key, key_len, tag) ||
tag_set_get_tag(&context->tags[PROPAGATED_BINARY_TAGS], key, key_len,
tag) ||
tag_set_get_tag(&context->tags[LOCAL_TAGS], key, key_len, tag)) {
return 1;
}
@ -447,21 +448,9 @@ static size_t tag_set_encode(const struct tag_set *tags, char *buffer,
return ENCODED_HEADER_SIZE + tags->kvm_used;
}
char *census_context_encode(const census_context *context, char *buffer,
size_t buf_size, size_t *print_buf_size,
size_t *bin_buf_size) {
*print_buf_size =
tag_set_encode(&context->tags[PROPAGATED_TAGS], buffer, buf_size);
if (*print_buf_size == 0) {
return NULL;
}
char *b_buffer = buffer + *print_buf_size;
*bin_buf_size = tag_set_encode(&context->tags[PROPAGATED_BINARY_TAGS],
b_buffer, buf_size - *print_buf_size);
if (*bin_buf_size == 0) {
return NULL;
}
return b_buffer;
size_t census_context_encode(const census_context *context, char *buffer,
size_t buf_size) {
return tag_set_encode(&context->tags[PROPAGATED_TAGS], buffer, buf_size);
}
// Decode a tag set.
@ -506,8 +495,7 @@ static void tag_set_decode(struct tag_set *tags, const char *buffer,
}
}
census_context *census_context_decode(const char *buffer, size_t size,
const char *bin_buffer, size_t bin_size) {
census_context *census_context_decode(const char *buffer, size_t size) {
census_context *context = gpr_malloc(sizeof(census_context));
memset(&context->tags[LOCAL_TAGS], 0, sizeof(struct tag_set));
if (buffer == NULL) {
@ -515,16 +503,7 @@ census_context *census_context_decode(const char *buffer, size_t size,
} else {
tag_set_decode(&context->tags[PROPAGATED_TAGS], buffer, size);
}
if (bin_buffer == NULL) {
memset(&context->tags[PROPAGATED_BINARY_TAGS], 0, sizeof(struct tag_set));
} else {
tag_set_decode(&context->tags[PROPAGATED_BINARY_TAGS], bin_buffer,
bin_size);
}
memset(&context->status, 0, sizeof(context->status));
context->status.n_propagated_tags = context->tags[PROPAGATED_TAGS].ntags;
context->status.n_propagated_binary_tags =
context->tags[PROPAGATED_BINARY_TAGS].ntags;
// TODO(aveitch): check that BINARY flag is correct for each type.
return context;
}

@ -165,7 +165,6 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
channel_data *chand = arg;
grpc_lb_policy *lb_policy = NULL;
grpc_lb_policy *old_lb_policy;
grpc_resolver *old_resolver;
grpc_connectivity_state state = GRPC_CHANNEL_TRANSIENT_FAILURE;
int exit_idle = 0;
@ -201,28 +200,25 @@ static void cc_on_config_changed(grpc_exec_ctx *exec_ctx, void *arg,
}
if (iomgr_success && chand->resolver) {
grpc_resolver *resolver = chand->resolver;
GRPC_RESOLVER_REF(resolver, "channel-next");
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker, state,
"new_lb+resolver");
if (lb_policy != NULL) {
watch_lb_policy(exec_ctx, chand, lb_policy, state);
}
gpr_mu_unlock(&chand->mu_config);
GRPC_CHANNEL_STACK_REF(chand->owning_stack, "resolver");
grpc_resolver_next(exec_ctx, resolver, &chand->incoming_configuration,
grpc_resolver_next(exec_ctx, chand->resolver,
&chand->incoming_configuration,
&chand->on_config_changed);
GRPC_RESOLVER_UNREF(exec_ctx, resolver, "channel-next");
gpr_mu_unlock(&chand->mu_config);
} else {
old_resolver = chand->resolver;
chand->resolver = NULL;
if (chand->resolver != NULL) {
grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
}
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "resolver_gone");
gpr_mu_unlock(&chand->mu_config);
if (old_resolver != NULL) {
grpc_resolver_shutdown(exec_ctx, old_resolver);
GRPC_RESOLVER_UNREF(exec_ctx, old_resolver, "channel");
}
}
if (exit_idle) {
@ -247,11 +243,10 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_channel_element *elem,
grpc_transport_op *op) {
channel_data *chand = elem->channel_data;
grpc_resolver *destroy_resolver = NULL;
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
GPR_ASSERT(op->set_accept_stream == NULL);
GPR_ASSERT(op->set_accept_stream == false);
if (op->bind_pollset != NULL) {
grpc_pollset_set_add_pollset(exec_ctx, chand->interested_parties,
op->bind_pollset);
@ -279,7 +274,8 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
if (op->disconnect && chand->resolver != NULL) {
grpc_connectivity_state_set(exec_ctx, &chand->state_tracker,
GRPC_CHANNEL_FATAL_FAILURE, "disconnect");
destroy_resolver = chand->resolver;
grpc_resolver_shutdown(exec_ctx, chand->resolver);
GRPC_RESOLVER_UNREF(exec_ctx, chand->resolver, "channel");
chand->resolver = NULL;
if (chand->lb_policy != NULL) {
grpc_pollset_set_del_pollset_set(exec_ctx,
@ -290,11 +286,6 @@ static void cc_start_transport_op(grpc_exec_ctx *exec_ctx,
}
}
gpr_mu_unlock(&chand->mu_config);
if (destroy_resolver) {
grpc_resolver_shutdown(exec_ctx, destroy_resolver);
GRPC_RESOLVER_UNREF(exec_ctx, destroy_resolver, "channel");
}
}
typedef struct {

@ -107,7 +107,7 @@ static void cuc_start_transport_op(grpc_exec_ctx *exec_ctx,
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
GPR_ASSERT(op->set_accept_stream == NULL);
GPR_ASSERT(op->set_accept_stream == false);
GPR_ASSERT(op->bind_pollset == NULL);
if (op->on_connectivity_state_change != NULL) {

@ -168,15 +168,15 @@ retry:
static void subchannel_ready(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
grpc_subchannel_call_holder *holder = arg;
grpc_subchannel_call *call;
gpr_mu_lock(&holder->mu);
GPR_ASSERT(holder->creation_phase ==
GRPC_SUBCHANNEL_CALL_HOLDER_PICKING_SUBCHANNEL);
call = GET_CALL(holder);
GPR_ASSERT(call == NULL || call == CANCELLED_CALL);
holder->creation_phase = GRPC_SUBCHANNEL_CALL_HOLDER_NOT_CREATING;
if (holder->connected_subchannel == NULL) {
fail_locked(exec_ctx, holder);
} else if (1 == gpr_atm_acq_load(&holder->subchannel_call)) {
/* already cancelled before subchannel became ready */
fail_locked(exec_ctx, holder);
} else {
gpr_atm_rel_store(
&holder->subchannel_call,

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -53,7 +53,9 @@ void grpc_client_config_ref(grpc_client_config *c) { gpr_ref(&c->refs); }
void grpc_client_config_unref(grpc_exec_ctx *exec_ctx, grpc_client_config *c) {
if (gpr_unref(&c->refs)) {
GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config");
if (c->lb_policy != NULL) {
GRPC_LB_POLICY_UNREF(exec_ctx, c->lb_policy, "client_config");
}
gpr_free(c);
}
}

@ -387,8 +387,8 @@ static void pick_first_factory_unref(grpc_lb_policy_factory *factory) {}
static grpc_lb_policy *create_pick_first(grpc_lb_policy_factory *factory,
grpc_lb_policy_args *args) {
if (args->num_subchannels == 0) return NULL;
pick_first_lb_policy *p = gpr_malloc(sizeof(*p));
GPR_ASSERT(args->num_subchannels > 0);
memset(p, 0, sizeof(*p));
grpc_lb_policy_init(&p->base, &pick_first_lb_policy_vtable);
p->subchannels =

@ -41,6 +41,7 @@
#include "src/core/client_config/lb_policy_registry.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/timer.h"
#include "src/core/support/string.h"
typedef struct {
@ -71,6 +72,9 @@ typedef struct {
grpc_client_config **target_config;
/** current (fully resolved) config */
grpc_client_config *resolved_config;
/** retry timer */
bool have_retry_timer;
grpc_timer retry_timer;
} dns_resolver;
static void dns_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
@ -91,6 +95,9 @@ static const grpc_resolver_vtable dns_resolver_vtable = {
static void dns_shutdown(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver) {
dns_resolver *r = (dns_resolver *)resolver;
gpr_mu_lock(&r->mu);
if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer);
}
if (r->next_completion != NULL) {
*r->target_config = NULL;
grpc_exec_ctx_enqueue(exec_ctx, r->next_completion, true, NULL);
@ -125,6 +132,22 @@ static void dns_next(grpc_exec_ctx *exec_ctx, grpc_resolver *resolver,
gpr_mu_unlock(&r->mu);
}
static void dns_on_retry_timer(grpc_exec_ctx *exec_ctx, void *arg,
bool success) {
dns_resolver *r = arg;
gpr_mu_lock(&r->mu);
r->have_retry_timer = false;
if (success) {
if (!r->resolving) {
dns_start_resolving_locked(r);
}
}
gpr_mu_unlock(&r->mu);
GRPC_RESOLVER_UNREF(exec_ctx, &r->base, "retry-timer");
}
static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_resolved_addresses *addresses) {
dns_resolver *r = arg;
@ -133,29 +156,47 @@ static void dns_on_resolved(grpc_exec_ctx *exec_ctx, void *arg,
grpc_subchannel_args args;
grpc_lb_policy *lb_policy;
size_t i;
if (addresses) {
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = 0;
if (addresses != NULL) {
grpc_lb_policy_args lb_policy_args;
config = grpc_client_config_create();
subchannels = gpr_malloc(sizeof(grpc_subchannel *) * addresses->naddrs);
size_t naddrs = 0;
for (i = 0; i < addresses->naddrs; i++) {
memset(&args, 0, sizeof(args));
args.addr = (struct sockaddr *)(addresses->addrs[i].addr);
args.addr_len = (size_t)addresses->addrs[i].len;
subchannels[i] = grpc_subchannel_factory_create_subchannel(
grpc_subchannel *subchannel = grpc_subchannel_factory_create_subchannel(
exec_ctx, r->subchannel_factory, &args);
if (subchannel != NULL) {
subchannels[naddrs++] = subchannel;
}
}
memset(&lb_policy_args, 0, sizeof(lb_policy_args));
lb_policy_args.subchannels = subchannels;
lb_policy_args.num_subchannels = addresses->naddrs;
lb_policy_args.num_subchannels = naddrs;
lb_policy = grpc_lb_policy_create(r->lb_policy_name, &lb_policy_args);
grpc_client_config_set_lb_policy(config, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
if (lb_policy != NULL) {
grpc_client_config_set_lb_policy(config, lb_policy);
GRPC_LB_POLICY_UNREF(exec_ctx, lb_policy, "construction");
}
grpc_resolved_addresses_destroy(addresses);
gpr_free(subchannels);
} else {
int retry_seconds = 15;
gpr_log(GPR_DEBUG, "dns resolution failed: retrying in %d seconds",
retry_seconds);
GPR_ASSERT(!r->have_retry_timer);
r->have_retry_timer = true;
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
GRPC_RESOLVER_REF(&r->base, "retry-timer");
grpc_timer_init(
exec_ctx, &r->retry_timer,
gpr_time_add(now, gpr_time_from_seconds(retry_seconds, GPR_TIMESPAN)),
dns_on_retry_timer, r, now);
}
gpr_mu_lock(&r->mu);
GPR_ASSERT(r->resolving);
r->resolving = 0;
if (r->resolved_config) {
grpc_client_config_unref(exec_ctx, r->resolved_config);
}

@ -45,6 +45,7 @@
#include "src/core/client_config/subchannel_index.h"
#include "src/core/iomgr/timer.h"
#include "src/core/profiling/timers.h"
#include "src/core/support/backoff.h"
#include "src/core/surface/channel.h"
#include "src/core/transport/connectivity_state.h"
@ -127,8 +128,8 @@ struct grpc_subchannel {
/** next connect attempt time */
gpr_timespec next_attempt;
/** amount to backoff each failure */
gpr_timespec backoff_delta;
/** backoff state */
gpr_backoff backoff_state;
/** do we have an active alarm? */
int have_alarm;
/** our alarm */
@ -146,7 +147,6 @@ struct grpc_subchannel_call {
#define CALLSTACK_TO_SUBCHANNEL_CALL(callstack) \
(((grpc_subchannel_call *)(callstack)) - 1)
static gpr_timespec compute_connect_deadline(grpc_subchannel *c);
static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *subchannel,
bool iomgr_success);
@ -337,6 +337,22 @@ grpc_subchannel *grpc_subchannel_create(grpc_exec_ctx *exec_ctx,
grpc_closure_init(&c->connected, subchannel_connected, c);
grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
"subchannel");
gpr_backoff_init(&c->backoff_state,
GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER,
GRPC_SUBCHANNEL_RECONNECT_JITTER,
GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS * 1000,
GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000);
if (c->args) {
for (size_t i = 0; i < c->args->num_args; i++) {
if (0 == strcmp(c->args->args[i].key,
"grpc.testing.fixed_reconnect_backoff")) {
GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
gpr_backoff_init(&c->backoff_state, 1.0, 0.0,
c->args->args[i].value.integer,
c->args->args[i].value.integer);
}
}
}
gpr_mu_init(&c->mu);
return grpc_subchannel_index_register(exec_ctx, key, c);
@ -348,7 +364,7 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
args.interested_parties = c->pollset_set;
args.addr = c->addr;
args.addr_len = c->addr_len;
args.deadline = compute_connect_deadline(c);
args.deadline = c->next_attempt;
args.channel_args = c->args;
args.initial_connect_string = c->initial_connect_string;
@ -359,10 +375,8 @@ static void continue_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
}
static void start_connect(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
c->backoff_delta = gpr_time_from_seconds(
GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS, GPR_TIMESPAN);
c->next_attempt =
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), c->backoff_delta);
gpr_backoff_begin(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
}
@ -395,7 +409,6 @@ void grpc_subchannel_notify_on_state_change(
grpc_exec_ctx *exec_ctx, grpc_subchannel *c,
grpc_pollset_set *interested_parties, grpc_connectivity_state *state,
grpc_closure *notify) {
int do_connect = 0;
external_state_watcher *w;
if (state == NULL) {
@ -425,17 +438,13 @@ void grpc_subchannel_notify_on_state_change(
w->next->prev = w->prev->next = w;
if (grpc_connectivity_state_notify_on_state_change(
exec_ctx, &c->state_tracker, state, &w->closure)) {
do_connect = 1;
c->connecting = 1;
/* released by connection */
GRPC_SUBCHANNEL_WEAK_REF(c, "connecting");
start_connect(exec_ctx, c);
}
gpr_mu_unlock(&c->mu);
}
if (do_connect) {
start_connect(exec_ctx, c);
}
}
void grpc_connected_subchannel_process_transport_op(
@ -510,7 +519,8 @@ void grpc_connected_subchannel_ping(grpc_exec_ctx *exec_ctx,
elem->filter->start_transport_op(exec_ctx, elem, &op);
}
static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
static void publish_transport_locked(grpc_exec_ctx *exec_ctx,
grpc_subchannel *c) {
size_t channel_stack_size;
grpc_connected_subchannel *con;
grpc_channel_stack *stk;
@ -546,8 +556,6 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
grpc_closure_init(&sw_subchannel->closure, subchannel_on_child_state_changed,
sw_subchannel);
gpr_mu_lock(&c->mu);
if (c->disconnected) {
gpr_mu_unlock(&c->mu);
gpr_free(sw_subchannel);
@ -580,54 +588,9 @@ static void publish_transport(grpc_exec_ctx *exec_ctx, grpc_subchannel *c) {
grpc_connectivity_state_set(exec_ctx, &c->state_tracker, GRPC_CHANNEL_READY,
"connected");
gpr_mu_unlock(&c->mu);
gpr_free((void *)filters);
}
/* Generate a random number between 0 and 1. */
static double generate_uniform_random_number(grpc_subchannel *c) {
c->random = (1103515245 * c->random + 12345) % ((uint32_t)1 << 31);
return c->random / (double)((uint32_t)1 << 31);
}
/* Update backoff_delta and next_attempt in subchannel */
static void update_reconnect_parameters(grpc_subchannel *c) {
size_t i;
int32_t backoff_delta_millis, jitter;
int32_t max_backoff_millis =
GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000;
double jitter_range;
if (c->args) {
for (i = 0; i < c->args->num_args; i++) {
if (0 == strcmp(c->args->args[i].key,
"grpc.testing.fixed_reconnect_backoff")) {
GPR_ASSERT(c->args->args[i].type == GRPC_ARG_INTEGER);
c->next_attempt = gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_millis(c->args->args[i].value.integer, GPR_TIMESPAN));
return;
}
}
}
backoff_delta_millis =
(int32_t)(gpr_time_to_millis(c->backoff_delta) *
GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER);
if (backoff_delta_millis > max_backoff_millis) {
backoff_delta_millis = max_backoff_millis;
}
c->backoff_delta = gpr_time_from_millis(backoff_delta_millis, GPR_TIMESPAN);
c->next_attempt =
gpr_time_add(gpr_now(GPR_CLOCK_MONOTONIC), c->backoff_delta);
jitter_range = GRPC_SUBCHANNEL_RECONNECT_JITTER * backoff_delta_millis;
jitter =
(int32_t)((2 * generate_uniform_random_number(c) - 1) * jitter_range);
c->next_attempt =
gpr_time_add(c->next_attempt, gpr_time_from_millis(jitter, GPR_TIMESPAN));
}
static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
@ -635,11 +598,13 @@ static void on_alarm(grpc_exec_ctx *exec_ctx, void *arg, bool iomgr_success) {
if (c->disconnected) {
iomgr_success = 0;
}
gpr_mu_unlock(&c->mu);
if (iomgr_success) {
update_reconnect_parameters(c);
c->next_attempt =
gpr_backoff_step(&c->backoff_state, gpr_now(GPR_CLOCK_MONOTONIC));
continue_connect(exec_ctx, c);
gpr_mu_unlock(&c->mu);
} else {
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
}
@ -648,32 +613,23 @@ static void subchannel_connected(grpc_exec_ctx *exec_ctx, void *arg,
bool iomgr_success) {
grpc_subchannel *c = arg;
GRPC_SUBCHANNEL_WEAK_REF(c, "connected");
gpr_mu_lock(&c->mu);
if (c->connecting_result.transport != NULL) {
publish_transport(exec_ctx, c);
publish_transport_locked(exec_ctx, c);
} else if (c->disconnected) {
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
} else {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
gpr_mu_lock(&c->mu);
GPR_ASSERT(!c->have_alarm);
c->have_alarm = 1;
grpc_connectivity_state_set(exec_ctx, &c->state_tracker,
GRPC_CHANNEL_TRANSIENT_FAILURE,
"connect_failed");
grpc_timer_init(exec_ctx, &c->alarm, c->next_attempt, on_alarm, c, now);
gpr_mu_unlock(&c->mu);
}
}
static gpr_timespec compute_connect_deadline(grpc_subchannel *c) {
gpr_timespec current_deadline =
gpr_time_add(c->next_attempt, c->backoff_delta);
gpr_timespec min_deadline = gpr_time_add(
gpr_now(GPR_CLOCK_MONOTONIC),
gpr_time_from_seconds(GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS,
GPR_TIMESPAN));
return gpr_time_cmp(current_deadline, min_deadline) > 0 ? current_deadline
: min_deadline;
gpr_mu_unlock(&c->mu);
GRPC_SUBCHANNEL_WEAK_UNREF(exec_ctx, c, "connecting");
}
/*

@ -34,9 +34,12 @@
#include "src/core/iomgr/exec_ctx.h"
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include "src/core/profiling/timers.h"
#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) {
bool did_something = 0;
GPR_TIMER_BEGIN("grpc_exec_ctx_flush", 0);
@ -74,3 +77,75 @@ void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
GPR_ASSERT(offload_target_or_null == NULL);
grpc_closure_list_move(list, &exec_ctx->closure_list);
}
void grpc_exec_ctx_global_init(void) {}
void grpc_exec_ctx_global_shutdown(void) {}
#else
static gpr_mu g_mu;
static gpr_cv g_cv;
static int g_threads = 0;
static void run_closure(void *arg) {
grpc_closure *closure = arg;
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
closure->cb(&exec_ctx, closure->cb_arg, (closure->final_data & 1) != 0);
grpc_exec_ctx_finish(&exec_ctx);
gpr_mu_lock(&g_mu);
if (--g_threads == 0) {
gpr_cv_signal(&g_cv);
}
gpr_mu_unlock(&g_mu);
}
static void start_closure(grpc_closure *closure) {
gpr_thd_id id;
gpr_mu_lock(&g_mu);
g_threads++;
gpr_mu_unlock(&g_mu);
gpr_thd_new(&id, run_closure, closure, NULL);
}
bool grpc_exec_ctx_flush(grpc_exec_ctx *exec_ctx) { return false; }
void grpc_exec_ctx_finish(grpc_exec_ctx *exec_ctx) {}
void grpc_exec_ctx_enqueue(grpc_exec_ctx *exec_ctx, grpc_closure *closure,
bool success,
grpc_workqueue *offload_target_or_null) {
GPR_ASSERT(offload_target_or_null == NULL);
if (closure == NULL) return;
closure->final_data = success;
start_closure(closure);
}
void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
grpc_closure_list *list,
grpc_workqueue *offload_target_or_null) {
GPR_ASSERT(offload_target_or_null == NULL);
if (list == NULL) return;
grpc_closure *p = list->head;
while (p) {
grpc_closure *start = p;
p = grpc_closure_next(start);
start_closure(start);
}
grpc_closure_list r = GRPC_CLOSURE_LIST_INIT;
*list = r;
}
void grpc_exec_ctx_global_init(void) {
gpr_mu_init(&g_mu);
gpr_cv_init(&g_cv);
}
void grpc_exec_ctx_global_shutdown(void) {
gpr_mu_lock(&g_mu);
while (g_threads != 0) {
gpr_cv_wait(&g_cv, &g_mu, gpr_inf_future(GPR_CLOCK_REALTIME));
}
gpr_mu_unlock(&g_mu);
gpr_mu_destroy(&g_mu);
gpr_cv_destroy(&g_cv);
}
#endif

@ -36,6 +36,14 @@
#include "src/core/iomgr/closure.h"
/* #define GRPC_EXECUTION_CONTEXT_SANITIZER 1 */
/** A workqueue represents a list of work to be executed asynchronously.
Forward declared here to avoid a circular dependency with workqueue.h. */
struct grpc_workqueue;
typedef struct grpc_workqueue grpc_workqueue;
#ifndef GRPC_EXECUTION_CONTEXT_SANITIZER
/** Execution context.
* A bag of data that collects information along a callstack.
* Generally created at public API entry points, and passed down as
@ -57,13 +65,15 @@ struct grpc_exec_ctx {
grpc_closure_list closure_list;
};
/** A workqueue represents a list of work to be executed asynchronously.
Forward declared here to avoid a circular dependency with workqueue.h. */
struct grpc_workqueue;
typedef struct grpc_workqueue grpc_workqueue;
#define GRPC_EXEC_CTX_INIT \
{ GRPC_CLOSURE_LIST_INIT }
#else
struct grpc_exec_ctx {
int unused;
};
#define GRPC_EXEC_CTX_INIT \
{ 0 }
#endif
/** Flush any work that has been enqueued onto this grpc_exec_ctx.
* Caller must guarantee that no interfering locks are held.
@ -82,4 +92,7 @@ void grpc_exec_ctx_enqueue_list(grpc_exec_ctx *exec_ctx,
grpc_closure_list *list,
grpc_workqueue *offload_target_or_null);
void grpc_exec_ctx_global_init(void);
void grpc_exec_ctx_global_shutdown(void);
#endif

@ -71,7 +71,8 @@ static DWORD deadline_to_millis_timeout(gpr_timespec deadline,
timeout, gpr_time_from_nanos(GPR_NS_PER_MS - 1, GPR_TIMESPAN)));
}
void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
gpr_timespec deadline) {
BOOL success;
DWORD bytes = 0;
DWORD flags = 0;
@ -84,14 +85,14 @@ void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
g_iocp, &bytes, &completion_key, &overlapped,
deadline_to_millis_timeout(deadline, gpr_now(deadline.clock_type)));
if (success == 0 && overlapped == NULL) {
return;
return GRPC_IOCP_WORK_TIMEOUT;
}
GPR_ASSERT(completion_key && overlapped);
if (overlapped == &g_iocp_custom_overlap) {
gpr_atm_full_fetch_add(&g_custom_events, -1);
if (completion_key == (ULONG_PTR)&g_iocp_kick_token) {
/* We were awoken from a kick. */
return;
return GRPC_IOCP_WORK_KICK;
}
gpr_log(GPR_ERROR, "Unknown custom completion key.");
abort();
@ -121,6 +122,7 @@ void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline) {
}
gpr_mu_unlock(&socket->state_mu);
grpc_exec_ctx_enqueue(exec_ctx, closure, true, NULL);
return GRPC_IOCP_WORK_WORK;
}
void grpc_iocp_init(void) {
@ -140,10 +142,12 @@ void grpc_iocp_kick(void) {
void grpc_iocp_flush(void) {
grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
grpc_iocp_work_status work_status;
do {
grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
} while (grpc_exec_ctx_flush(&exec_ctx));
work_status = grpc_iocp_work(&exec_ctx, gpr_inf_past(GPR_CLOCK_MONOTONIC));
} while (work_status == GRPC_IOCP_WORK_KICK ||
grpc_exec_ctx_flush(&exec_ctx));
}
void grpc_iocp_shutdown(void) {

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -38,7 +38,14 @@
#include "src/core/iomgr/socket_windows.h"
void grpc_iocp_work(grpc_exec_ctx *exec_ctx, gpr_timespec deadline);
typedef enum {
GRPC_IOCP_WORK_WORK,
GRPC_IOCP_WORK_TIMEOUT,
GRPC_IOCP_WORK_KICK
} grpc_iocp_work_status;
grpc_iocp_work_status grpc_iocp_work(grpc_exec_ctx *exec_ctx,
gpr_timespec deadline);
void grpc_iocp_init(void);
void grpc_iocp_kick(void);
void grpc_iocp_flush(void);

@ -41,9 +41,12 @@
#include <grpc/support/string_util.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
#include <grpc/support/useful.h>
#include "src/core/iomgr/exec_ctx.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/timer.h"
#include "src/core/support/env.h"
#include "src/core/support/string.h"
static gpr_mu g_mu;
@ -55,6 +58,7 @@ void grpc_iomgr_init(void) {
g_shutdown = 0;
gpr_mu_init(&g_mu);
gpr_cv_init(&g_rcv);
grpc_exec_ctx_global_init();
grpc_timer_list_init(gpr_now(GPR_CLOCK_MONOTONIC));
g_root_object.next = g_root_object.prev = &g_root_object;
g_root_object.name = "root";
@ -116,6 +120,9 @@ void grpc_iomgr_shutdown(void) {
"memory leaks are likely",
count_objects());
dump_objects("LEAKED");
if (grpc_iomgr_abort_on_leaks()) {
abort();
}
}
break;
}
@ -133,6 +140,7 @@ void grpc_iomgr_shutdown(void) {
grpc_pollset_global_shutdown();
grpc_iomgr_platform_shutdown();
grpc_exec_ctx_global_shutdown();
gpr_mu_destroy(&g_mu);
gpr_cv_destroy(&g_rcv);
}
@ -154,3 +162,14 @@ void grpc_iomgr_unregister_object(grpc_iomgr_object *obj) {
gpr_mu_unlock(&g_mu);
gpr_free(obj->name);
}
bool grpc_iomgr_abort_on_leaks(void) {
char *env = gpr_getenv("GRPC_ABORT_ON_LEAKS");
if (env == NULL) return false;
static const char *truthy[] = {"yes", "Yes", "YES", "true",
"True", "TRUE", "1"};
for (size_t i = 0; i < GPR_ARRAY_SIZE(truthy); i++) {
if (0 == strcmp(env, truthy[i])) return true;
}
return false;
}

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -34,6 +34,8 @@
#ifndef GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H
#define GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H
#include <stdbool.h>
#include "src/core/iomgr/iomgr.h"
#include <grpc/support/sync.h>
@ -55,4 +57,6 @@ void grpc_iomgr_platform_flush(void);
/** tear down all platform specific global iomgr structures */
void grpc_iomgr_platform_shutdown(void);
bool grpc_iomgr_abort_on_leaks(void);
#endif /* GRPC_INTERNAL_CORE_IOMGR_IOMGR_INTERNAL_H */

@ -55,7 +55,7 @@ typedef struct grpc_pollset_worker grpc_pollset_worker;
size_t grpc_pollset_size(void);
void grpc_pollset_init(grpc_pollset *pollset, gpr_mu **mu);
/* Begin shutting down the pollset, and call closure when done.
* GRPC_POLLSET_MU(pollset) must be held */
* pollset's mutex must be held */
void grpc_pollset_shutdown(grpc_exec_ctx *exec_ctx, grpc_pollset *pollset,
grpc_closure *closure);
/** Reset the pollset to its initial state (perhaps with some cached objects);
@ -66,16 +66,16 @@ void grpc_pollset_destroy(grpc_pollset *pollset);
/* Do some work on a pollset.
May involve invoking asynchronous callbacks, or actually polling file
descriptors.
Requires GRPC_POLLSET_MU(pollset) locked.
May unlock GRPC_POLLSET_MU(pollset) during its execution.
Requires pollset's mutex locked.
May unlock its mutex during its execution.
worker is a (platform-specific) handle that can be used to wake up
from grpc_pollset_work before any events are received and before the timeout
has expired. It is both initialized and destroyed by grpc_pollset_work.
Initialization of worker is guaranteed to occur BEFORE the
GRPC_POLLSET_MU(pollset) is released for the first time by
grpc_pollset_work, and it is guaranteed that GRPC_POLLSET_MU(pollset) will
not be released by grpc_pollset_work AFTER worker has been destroyed.
pollset's mutex is released for the first time by grpc_pollset_work
and it is guaranteed that it will not be released by grpc_pollset_work
AFTER worker has been destroyed.
Tries not to block past deadline.
May call grpc_closure_list_run on grpc_closure_list, without holding the

@ -122,6 +122,7 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
} else {
h->fds[fd_count++] = h->fds[i];
watchers[pfd_count].fd = h->fds[i];
GRPC_FD_REF(watchers[pfd_count].fd, "multipoller_start");
pfds[pfd_count].fd = h->fds[i]->fd;
pfds[pfd_count].revents = 0;
pfd_count++;
@ -135,8 +136,10 @@ static void multipoll_with_poll_pollset_maybe_work_and_unlock(
gpr_mu_unlock(&pollset->mu);
for (i = 2; i < pfd_count; i++) {
pfds[i].events = (short)grpc_fd_begin_poll(watchers[i].fd, pollset, worker,
POLLIN, POLLOUT, &watchers[i]);
grpc_fd *fd = watchers[i].fd;
pfds[i].events = (short)grpc_fd_begin_poll(fd, pollset, worker, POLLIN,
POLLOUT, &watchers[i]);
GRPC_FD_UNREF(fd, "multipoller_start");
}
/* TODO(vpai): Consider first doing a 0 timeout poll here to avoid

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -66,7 +66,7 @@ void grpc_resolved_addresses_destroy(grpc_resolved_addresses *addresses);
/* Resolve addr in a blocking fashion. Returns NULL on failure. On success,
result must be freed with grpc_resolved_addresses_destroy. */
grpc_resolved_addresses *grpc_blocking_resolve_address(
const char *addr, const char *default_port);
extern grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port);
#endif /* GRPC_INTERNAL_CORE_IOMGR_RESOLVE_ADDRESS_H */

@ -34,18 +34,13 @@
#include <grpc/support/port_platform.h>
#ifdef GPR_POSIX_SOCKET
#include "src/core/iomgr/sockaddr.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/sockaddr.h"
#include <string.h>
#include <sys/types.h>
#include <sys/un.h>
#include <string.h>
#include "src/core/iomgr/executor.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/block_annotate.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
@ -53,6 +48,11 @@
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
#include "src/core/iomgr/executor.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/block_annotate.h"
#include "src/core/support/string.h"
typedef struct {
char *name;
@ -62,7 +62,7 @@ typedef struct {
void *arg;
} request;
grpc_resolved_addresses *grpc_blocking_resolve_address(
static grpc_resolved_addresses *blocking_resolve_address_impl(
const char *name, const char *default_port) {
struct addrinfo hints;
struct addrinfo *result = NULL, *resp;
@ -150,6 +150,9 @@ done:
return addrs;
}
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port) = blocking_resolve_address_impl;
/* Callback to be passed to grpc_executor to asynch-ify
* grpc_blocking_resolve_address */
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {

@ -34,17 +34,12 @@
#include <grpc/support/port_platform.h>
#ifdef GPR_WINSOCK_SOCKET
#include "src/core/iomgr/sockaddr.h"
#include "src/core/iomgr/resolve_address.h"
#include "src/core/iomgr/sockaddr.h"
#include <sys/types.h>
#include <string.h>
#include <sys/types.h>
#include "src/core/iomgr/executor.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/block_annotate.h"
#include "src/core/support/string.h"
#include <grpc/support/alloc.h>
#include <grpc/support/host_port.h>
#include <grpc/support/log.h>
@ -52,6 +47,11 @@
#include <grpc/support/string_util.h>
#include <grpc/support/thd.h>
#include <grpc/support/time.h>
#include "src/core/iomgr/executor.h"
#include "src/core/iomgr/iomgr_internal.h"
#include "src/core/iomgr/sockaddr_utils.h"
#include "src/core/support/block_annotate.h"
#include "src/core/support/string.h"
typedef struct {
char *name;
@ -61,7 +61,7 @@ typedef struct {
void *arg;
} request;
grpc_resolved_addresses *grpc_blocking_resolve_address(
static grpc_resolved_addresses *blocking_resolve_address_impl(
const char *name, const char *default_port) {
struct addrinfo hints;
struct addrinfo *result = NULL, *resp;
@ -133,6 +133,9 @@ done:
return addrs;
}
grpc_resolved_addresses *(*grpc_blocking_resolve_address)(
const char *name, const char *default_port) = blocking_resolve_address_impl;
/* Callback to be passed to grpc_executor to asynch-ify
* grpc_blocking_resolve_address */
static void do_request_thread(grpc_exec_ctx *exec_ctx, void *rp, bool success) {

@ -240,8 +240,7 @@ static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
sp->shutting_down = 0;
gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->active_ports > 0);
if (0 == --sp->server->active_ports &&
sp->server->shutdown_complete != NULL) {
if (0 == --sp->server->active_ports) {
notify = 1;
}
gpr_mu_unlock(&sp->server->mu);

@ -33,11 +33,11 @@
#include "src/core/iomgr/timer.h"
#include "src/core/iomgr/timer_heap.h"
#include "src/core/iomgr/time_averaged_stats.h"
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/useful.h>
#include "src/core/iomgr/time_averaged_stats.h"
#include "src/core/iomgr/timer_heap.h"
#define INVALID_HEAP_INDEX 0xffffffffu
@ -330,6 +330,18 @@ static int run_some_expired_timers(grpc_exec_ctx *exec_ctx, gpr_timespec now,
gpr_mu_unlock(&g_mu);
gpr_mu_unlock(&g_checker_mu);
} else if (next != NULL) {
/* TODO(ctiller): this forces calling code to do an short poll, and
then retry the timer check (because this time through the timer list was
contended).
We could reduce the cost here dramatically by keeping a count of how many
currently active pollers got through the uncontended case above
successfully, and waking up other pollers IFF that count drops to zero.
Once that count is in place, this entire else branch could disappear. */
*next = gpr_time_min(
*next, gpr_time_add(now, gpr_time_from_millis(1, GPR_TIMESPAN)));
}
return (int)n;

@ -96,7 +96,6 @@ void grpc_timer_cancel(grpc_exec_ctx *exec_ctx, grpc_timer *timer);
*next is never guaranteed to be updated on any given execution; however,
with high probability at least one thread in the system will see an update
at any time slice. */
bool grpc_timer_check(grpc_exec_ctx *exec_ctx, gpr_timespec now,
gpr_timespec *next);
void grpc_timer_list_init(gpr_timespec now);

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -46,7 +46,7 @@
static void adjust_upwards(grpc_timer **first, uint32_t i, grpc_timer *t) {
while (i > 0) {
uint32_t parent = (uint32_t)(((int)i - 1) / 2);
if (gpr_time_cmp(first[parent]->deadline, t->deadline) >= 0) break;
if (gpr_time_cmp(first[parent]->deadline, t->deadline) <= 0) break;
first[i] = first[parent];
first[i]->heap_index = i;
i = parent;
@ -62,16 +62,14 @@ static void adjust_downwards(grpc_timer **first, uint32_t i, uint32_t length,
grpc_timer *t) {
for (;;) {
uint32_t left_child = 1u + 2u * i;
uint32_t right_child;
uint32_t next_i;
if (left_child >= length) break;
right_child = left_child + 1;
next_i = right_child < length &&
gpr_time_cmp(first[left_child]->deadline,
first[right_child]->deadline) < 0
? right_child
: left_child;
if (gpr_time_cmp(t->deadline, first[next_i]->deadline) >= 0) break;
uint32_t right_child = left_child + 1;
uint32_t next_i = right_child < length &&
gpr_time_cmp(first[left_child]->deadline,
first[right_child]->deadline) > 0
? right_child
: left_child;
if (gpr_time_cmp(t->deadline, first[next_i]->deadline) <= 0) break;
first[i] = first[next_i];
first[i]->heap_index = i;
i = next_i;
@ -95,7 +93,7 @@ static void maybe_shrink(grpc_timer_heap *heap) {
static void note_changed_priority(grpc_timer_heap *heap, grpc_timer *timer) {
uint32_t i = timer->heap_index;
uint32_t parent = (uint32_t)(((int)i - 1) / 2);
if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) < 0) {
if (gpr_time_cmp(heap->timers[parent]->deadline, timer->deadline) > 0) {
adjust_upwards(heap->timers, i, timer);
} else {
adjust_downwards(heap->timers, i, heap->timer_count, timer);

@ -107,7 +107,7 @@ void grpc_workqueue_flush(grpc_exec_ctx *exec_ctx, grpc_workqueue *workqueue) {
if (grpc_closure_list_empty(workqueue->closure_list)) {
grpc_wakeup_fd_wakeup(&workqueue->wakeup_fd);
}
grpc_closure_list_move(&exec_ctx->closure_list, &workqueue->closure_list);
grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
gpr_mu_unlock(&workqueue->mu);
}
@ -123,7 +123,7 @@ static void on_readable(grpc_exec_ctx *exec_ctx, void *arg, bool success) {
gpr_free(workqueue);
} else {
gpr_mu_lock(&workqueue->mu);
grpc_closure_list_move(&workqueue->closure_list, &exec_ctx->closure_list);
grpc_exec_ctx_enqueue_list(exec_ctx, &workqueue->closure_list, NULL);
grpc_wakeup_fd_consume_wakeup(&workqueue->wakeup_fd);
gpr_mu_unlock(&workqueue->mu);
grpc_fd_notify_on_read(exec_ctx, workqueue->wakeup_read_fd,

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -87,4 +87,4 @@ void *gpr_malloc_aligned(size_t size, size_t alignment_log) {
return (void *)ret;
}
void gpr_free_aligned(void *ptr) { free(((void **)ptr)[-1]); }
void gpr_free_aligned(void *ptr) { gpr_free(((void **)ptr)[-1]); }

@ -0,0 +1,71 @@
/*
*
* Copyright 2016, 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 "src/core/support/backoff.h"
#include <grpc/support/useful.h>
void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter,
int64_t min_timeout_millis, int64_t max_timeout_millis) {
backoff->multiplier = multiplier;
backoff->jitter = jitter;
backoff->min_timeout_millis = min_timeout_millis;
backoff->max_timeout_millis = max_timeout_millis;
backoff->rng_state = (uint32_t)gpr_now(GPR_CLOCK_REALTIME).tv_nsec;
}
gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now) {
backoff->current_timeout_millis = backoff->min_timeout_millis;
return gpr_time_add(
now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN));
}
/* Generate a random number between 0 and 1. */
static double generate_uniform_random_number(uint32_t *rng_state) {
*rng_state = (1103515245 * *rng_state + 12345) % ((uint32_t)1 << 31);
return *rng_state / (double)((uint32_t)1 << 31);
}
gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now) {
double new_timeout_millis =
backoff->multiplier * (double)backoff->current_timeout_millis;
double jitter_range = backoff->jitter * new_timeout_millis;
double jitter =
(2 * generate_uniform_random_number(&backoff->rng_state) - 1) *
jitter_range;
backoff->current_timeout_millis =
GPR_CLAMP((int64_t)(new_timeout_millis + jitter),
backoff->min_timeout_millis, backoff->max_timeout_millis);
return gpr_time_add(
now, gpr_time_from_millis(backoff->current_timeout_millis, GPR_TIMESPAN));
}

@ -0,0 +1,65 @@
/*
*
* Copyright 2016, 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 GRPC_INTERNAL_CORE_SUPPORT_BACKOFF_H
#define GRPC_INTERNAL_CORE_SUPPORT_BACKOFF_H
#include <grpc/support/time.h>
typedef struct {
/// const: multiplier between retry attempts
double multiplier;
/// const: amount to randomize backoffs
double jitter;
/// const: minimum time between retries in milliseconds
int64_t min_timeout_millis;
/// const: maximum time between retries in milliseconds
int64_t max_timeout_millis;
/// random number generator
uint32_t rng_state;
/// current retry timeout in milliseconds
int64_t current_timeout_millis;
} gpr_backoff;
/// Initialize backoff machinery - does not need to be destroyed
void gpr_backoff_init(gpr_backoff *backoff, double multiplier, double jitter,
int64_t min_timeout_millis, int64_t max_timeout_millis);
/// Begin retry loop: returns a timespec for the NEXT retry
gpr_timespec gpr_backoff_begin(gpr_backoff *backoff, gpr_timespec now);
/// Step a retry loop: returns a timespec for the NEXT retry
gpr_timespec gpr_backoff_step(gpr_backoff *backoff, gpr_timespec now);
#endif // GRPC_INTERNAL_CORE_SUPPORT_BACKOFF_H

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -98,6 +98,11 @@ void gpr_ref_init(gpr_refcount *r, int n) { gpr_atm_rel_store(&r->count, n); }
void gpr_ref(gpr_refcount *r) { gpr_atm_no_barrier_fetch_add(&r->count, 1); }
void gpr_ref_non_zero(gpr_refcount *r) {
gpr_atm prior = gpr_atm_no_barrier_fetch_add(&r->count, 1);
GPR_ASSERT(prior > 0);
}
void gpr_refn(gpr_refcount *r, int n) {
gpr_atm_no_barrier_fetch_add(&r->count, n);
}

@ -86,7 +86,7 @@ struct grpc_completion_queue {
#define POLLSET_FROM_CQ(cq) ((grpc_pollset *)(cq + 1))
static gpr_mu g_freelist_mu;
grpc_completion_queue *g_freelist;
static grpc_completion_queue *g_freelist;
static void on_pollset_shutdown_done(grpc_exec_ctx *exec_ctx, void *cc,
bool success);

@ -407,8 +407,15 @@ static void destroy_channel(grpc_exec_ctx *exec_ctx, channel_data *chand) {
maybe_finish_shutdown(exec_ctx, chand->server);
chand->finish_destroy_channel_closure.cb = finish_destroy_channel;
chand->finish_destroy_channel_closure.cb_arg = chand;
grpc_exec_ctx_enqueue(exec_ctx, &chand->finish_destroy_channel_closure, true,
NULL);
grpc_transport_op op;
memset(&op, 0, sizeof(op));
op.set_accept_stream = true;
op.on_consumed = &chand->finish_destroy_channel_closure;
grpc_channel_next_op(exec_ctx,
grpc_channel_stack_element(
grpc_channel_get_channel_stack(chand->channel), 0),
&op);
}
static void finish_start_new_rpc(grpc_exec_ctx *exec_ctx, grpc_server *server,
@ -971,7 +978,8 @@ void grpc_server_setup_transport(grpc_exec_ctx *exec_ctx, grpc_server *s,
GRPC_CHANNEL_INTERNAL_REF(channel, "connectivity");
memset(&op, 0, sizeof(op));
op.set_accept_stream = accept_stream;
op.set_accept_stream = true;
op.set_accept_stream_fn = accept_stream;
op.set_accept_stream_user_data = chand;
op.on_connectivity_state_change = &chand->channel_connectivity_changed;
op.connectivity_state = &chand->connectivity_state;

@ -358,6 +358,9 @@ struct grpc_chttp2_transport {
/** connectivity tracking */
grpc_connectivity_state_tracker state_tracker;
} channel_callback;
/** Transport op to be applied post-parsing */
grpc_transport_op *post_parsing_op;
};
typedef struct {
@ -417,7 +420,7 @@ typedef struct {
/** HTTP2 stream id for this stream, or zero if one has not been assigned */
uint32_t id;
uint8_t fetching;
uint8_t sent_initial_metadata;
bool sent_initial_metadata;
uint8_t sent_message;
uint8_t sent_trailing_metadata;
uint8_t read_closed;
@ -509,7 +512,7 @@ void grpc_chttp2_publish_reads(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_global *global,
grpc_chttp2_transport_parsing *parsing);
void grpc_chttp2_list_add_writable_stream(
bool grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
/** Get a writable stream
@ -519,14 +522,13 @@ int grpc_chttp2_list_pop_writable_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_global **stream_global,
grpc_chttp2_stream_writing **stream_writing);
void grpc_chttp2_list_remove_writable_stream(
bool grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
grpc_chttp2_stream_global *stream_global) GRPC_MUST_USE_RESULT;
/* returns 1 if stream added, 0 if it was already present */
int grpc_chttp2_list_add_writing_stream(
void grpc_chttp2_list_add_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing) GRPC_MUST_USE_RESULT;
grpc_chttp2_stream_writing *stream_writing);
int grpc_chttp2_list_have_writing_streams(
grpc_chttp2_transport_writing *transport_writing);
int grpc_chttp2_list_pop_writing_stream(
@ -770,4 +772,9 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport_parsing *parsing,
const uint8_t *opaque_8bytes);
/** add a ref to the stream and add it to the writable list;
ref will be dropped in writing.c */
void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global);
#endif

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -149,7 +149,7 @@ void grpc_chttp2_publish_reads(
if (was_zero && !is_zero) {
while (grpc_chttp2_list_pop_stalled_by_transport(transport_global,
&stream_global)) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@ -178,7 +178,7 @@ void grpc_chttp2_publish_reads(
outgoing_window);
is_zero = stream_global->outgoing_window <= 0;
if (was_zero && !is_zero) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_become_writable(transport_global, stream_global);
}
stream_global->max_recv_bytes -= (uint32_t)GPR_MIN(

@ -100,11 +100,14 @@ static void stream_list_remove(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
}
}
static void stream_list_maybe_remove(grpc_chttp2_transport *t,
static bool stream_list_maybe_remove(grpc_chttp2_transport *t,
grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
if (s->included[id]) {
stream_list_remove(t, s, id);
return true;
} else {
return false;
}
}
@ -125,23 +128,24 @@ static void stream_list_add_tail(grpc_chttp2_transport *t,
s->included[id] = 1;
}
static int stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
static bool stream_list_add(grpc_chttp2_transport *t, grpc_chttp2_stream *s,
grpc_chttp2_stream_list_id id) {
if (s->included[id]) {
return 0;
return false;
}
stream_list_add_tail(t, s, id);
return 1;
return true;
}
/* wrappers for specializations */
void grpc_chttp2_list_add_writable_stream(
bool grpc_chttp2_list_add_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
GPR_ASSERT(stream_global->id != 0);
stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global), GRPC_CHTTP2_LIST_WRITABLE);
return stream_list_add(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE);
}
int grpc_chttp2_list_pop_writable_stream(
@ -159,20 +163,20 @@ int grpc_chttp2_list_pop_writable_stream(
return r;
}
void grpc_chttp2_list_remove_writable_stream(
bool grpc_chttp2_list_remove_writable_stream(
grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE);
return stream_list_maybe_remove(TRANSPORT_FROM_GLOBAL(transport_global),
STREAM_FROM_GLOBAL(stream_global),
GRPC_CHTTP2_LIST_WRITABLE);
}
int grpc_chttp2_list_add_writing_stream(
void grpc_chttp2_list_add_writing_stream(
grpc_chttp2_transport_writing *transport_writing,
grpc_chttp2_stream_writing *stream_writing) {
return stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
STREAM_FROM_WRITING(stream_writing),
GRPC_CHTTP2_LIST_WRITING);
GPR_ASSERT(stream_list_add(TRANSPORT_FROM_WRITING(transport_writing),
STREAM_FROM_WRITING(stream_writing),
GRPC_CHTTP2_LIST_WRITING));
}
int grpc_chttp2_list_have_writing_streams(
@ -332,7 +336,7 @@ void grpc_chttp2_list_flush_writing_stalled_by_transport(
while (stream_list_pop(transport, &stream,
GRPC_CHTTP2_LIST_WRITING_STALLED_BY_TRANSPORT)) {
if (is_window_available) {
grpc_chttp2_list_add_writable_stream(&transport->global, &stream->global);
grpc_chttp2_become_writable(&transport->global, &stream->global);
} else {
grpc_chttp2_list_add_stalled_by_transport(transport_writing,
&stream->writing);

@ -83,7 +83,8 @@ int grpc_chttp2_unlocking_check_writes(
(according to available window sizes) and add to the output buffer */
while (grpc_chttp2_list_pop_writable_stream(
transport_global, transport_writing, &stream_global, &stream_writing)) {
uint8_t sent_initial_metadata;
bool sent_initial_metadata = stream_writing->sent_initial_metadata;
bool become_writable = false;
stream_writing->id = stream_global->id;
stream_writing->read_closed = stream_global->read_closed;
@ -92,16 +93,12 @@ int grpc_chttp2_unlocking_check_writes(
outgoing_window, stream_global,
outgoing_window);
sent_initial_metadata = stream_writing->sent_initial_metadata;
if (!sent_initial_metadata && stream_global->send_initial_metadata) {
stream_writing->send_initial_metadata =
stream_global->send_initial_metadata;
stream_global->send_initial_metadata = NULL;
if (grpc_chttp2_list_add_writing_stream(transport_writing,
stream_writing)) {
GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
}
sent_initial_metadata = 1;
become_writable = true;
sent_initial_metadata = true;
}
if (sent_initial_metadata) {
if (stream_global->send_message != NULL) {
@ -128,10 +125,7 @@ int grpc_chttp2_unlocking_check_writes(
stream_writing->flow_controlled_buffer.length > 0) &&
stream_writing->outgoing_window > 0) {
if (transport_writing->outgoing_window > 0) {
if (grpc_chttp2_list_add_writing_stream(transport_writing,
stream_writing)) {
GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
}
become_writable = true;
} else {
grpc_chttp2_list_add_stalled_by_transport(transport_writing,
stream_writing);
@ -141,10 +135,7 @@ int grpc_chttp2_unlocking_check_writes(
stream_writing->send_trailing_metadata =
stream_global->send_trailing_metadata;
stream_global->send_trailing_metadata = NULL;
if (grpc_chttp2_list_add_writing_stream(transport_writing,
stream_writing)) {
GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
}
become_writable = true;
}
}
@ -153,10 +144,13 @@ int grpc_chttp2_unlocking_check_writes(
GRPC_CHTTP2_FLOW_MOVE_STREAM("write", transport_global, stream_writing,
announce_window, stream_global,
unannounced_incoming_window_for_writing);
if (grpc_chttp2_list_add_writing_stream(transport_writing,
stream_writing)) {
GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
}
become_writable = true;
}
if (become_writable) {
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
} else {
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
}
}
@ -310,10 +304,7 @@ static void finalize_outbuf(grpc_exec_ctx *exec_ctx,
(stream_writing->send_message && !stream_writing->fetching)) &&
stream_writing->outgoing_window > 0) {
if (transport_writing->outgoing_window > 0) {
if (grpc_chttp2_list_add_writing_stream(transport_writing,
stream_writing)) {
/* do nothing - already reffed */
}
grpc_chttp2_list_add_writing_stream(transport_writing, stream_writing);
} else {
grpc_chttp2_list_add_writing_stalled_by_transport(transport_writing,
stream_writing);

@ -142,7 +142,7 @@ static void incoming_byte_stream_update_flow_control(
static void fail_pending_writes(grpc_exec_ctx *exec_ctx,
grpc_chttp2_stream_global *stream_global);
/*
/*******************************************************************************
* CONSTRUCTION/DESTRUCTION/REFCOUNTING
*/
@ -432,6 +432,14 @@ static void close_transport_locked(grpc_exec_ctx *exec_ctx,
if (t->ep) {
allow_endpoint_shutdown_locked(exec_ctx, t);
}
/* flush writable stream list to avoid dangling references */
grpc_chttp2_stream_global *stream_global;
grpc_chttp2_stream_writing *stream_writing;
while (grpc_chttp2_list_pop_writable_stream(
&t->global, &t->writing, &stream_global, &stream_writing)) {
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, stream_global, "chttp2_writing");
}
}
}
@ -521,7 +529,6 @@ static void destroy_stream(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
s->global.id) == NULL);
}
grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
grpc_chttp2_list_remove_unannounced_incoming_window_available(&t->global,
&s->global);
grpc_chttp2_list_remove_stalled_by_transport(&t->global, &s->global);
@ -583,7 +590,7 @@ grpc_chttp2_stream_parsing *grpc_chttp2_parsing_accept_stream(
return &accepting->parsing;
}
/*
/*******************************************************************************
* LOCK MANAGEMENT
*/
@ -611,10 +618,18 @@ static void unlock(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t) {
GPR_TIMER_END("unlock", 0);
}
/*
/*******************************************************************************
* OUTPUT PROCESSING
*/
void grpc_chttp2_become_writable(grpc_chttp2_transport_global *transport_global,
grpc_chttp2_stream_global *stream_global) {
if (!TRANSPORT_FROM_GLOBAL(transport_global)->closed &&
grpc_chttp2_list_add_writable_stream(transport_global, stream_global)) {
GRPC_CHTTP2_STREAM_REF(stream_global, "chttp2_writing");
}
}
static void push_setting(grpc_chttp2_transport *t, grpc_chttp2_setting_id id,
uint32_t value) {
const grpc_chttp2_setting_parameters *sp =
@ -732,7 +747,7 @@ static void maybe_start_some_streams(
stream_global->id, STREAM_FROM_GLOBAL(stream_global));
stream_global->in_stream_map = 1;
transport_global->concurrent_stream_count++;
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_become_writable(transport_global, stream_global);
}
/* cancel out streams that will never be started */
while (transport_global->next_stream_id >= MAX_CLIENT_STREAM_ID &&
@ -821,7 +836,7 @@ static void perform_stream_op_locked(
maybe_start_some_streams(exec_ctx, transport_global);
} else {
GPR_ASSERT(stream_global->id != 0);
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_become_writable(transport_global, stream_global);
}
} else {
grpc_chttp2_complete_closure_step(
@ -836,9 +851,11 @@ static void perform_stream_op_locked(
if (stream_global->write_closed) {
grpc_chttp2_complete_closure_step(
exec_ctx, &stream_global->send_message_finished, 0);
} else if (stream_global->id != 0) {
} else {
stream_global->send_message = op->send_message;
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
if (stream_global->id != 0) {
grpc_chttp2_become_writable(transport_global, stream_global);
}
}
}
@ -858,7 +875,7 @@ static void perform_stream_op_locked(
} else if (stream_global->id != 0) {
/* TODO(ctiller): check if there's flow control for any outstanding
bytes before going writable */
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@ -944,12 +961,10 @@ void grpc_chttp2_ack_ping(grpc_exec_ctx *exec_ctx,
unlock(exec_ctx, t);
}
static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_transport_op *op) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
int close_transport = 0;
lock(t);
static void perform_transport_op_locked(grpc_exec_ctx *exec_ctx,
grpc_chttp2_transport *t,
grpc_transport_op *op) {
bool close_transport = false;
grpc_exec_ctx_enqueue(exec_ctx, op->on_consumed, true, NULL);
@ -968,8 +983,8 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
close_transport = !grpc_chttp2_has_streams(t);
}
if (op->set_accept_stream != NULL) {
t->channel_callback.accept_stream = op->set_accept_stream;
if (op->set_accept_stream) {
t->channel_callback.accept_stream = op->set_accept_stream_fn;
t->channel_callback.accept_stream_user_data =
op->set_accept_stream_user_data;
}
@ -990,16 +1005,31 @@ static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
close_transport_locked(exec_ctx, t);
}
unlock(exec_ctx, t);
if (close_transport) {
lock(t);
close_transport_locked(exec_ctx, t);
unlock(exec_ctx, t);
}
}
/*
static void perform_transport_op(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
grpc_transport_op *op) {
grpc_chttp2_transport *t = (grpc_chttp2_transport *)gt;
lock(t);
/* If there's a set_accept_stream ensure that we're not parsing
to avoid changing things out from underneath */
if (t->parsing_active && op->set_accept_stream) {
GPR_ASSERT(t->post_parsing_op == NULL);
t->post_parsing_op = gpr_malloc(sizeof(*op));
memcpy(t->post_parsing_op, op, sizeof(*op));
} else {
perform_transport_op_locked(exec_ctx, t, op);
}
unlock(exec_ctx, t);
}
/*******************************************************************************
* INPUT PROCESSING
*/
@ -1064,7 +1094,6 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (!s) {
s = grpc_chttp2_stream_map_delete(&t->new_stream_map, id);
}
grpc_chttp2_list_remove_writable_stream(&t->global, &s->global);
GPR_ASSERT(s);
s->global.in_stream_map = 0;
if (t->parsing.incoming_stream == &s->parsing) {
@ -1080,6 +1109,9 @@ static void remove_stream(grpc_exec_ctx *exec_ctx, grpc_chttp2_transport *t,
if (grpc_chttp2_unregister_stream(t, s) && t->global.sent_goaway) {
close_transport_locked(exec_ctx, t);
}
if (grpc_chttp2_list_remove_writable_stream(&t->global, &s->global)) {
GRPC_CHTTP2_STREAM_UNREF(exec_ctx, &s->global, "chttp2_writing");
}
new_stream_count = grpc_chttp2_stream_map_size(&t->parsing_stream_map) +
grpc_chttp2_stream_map_size(&t->new_stream_map);
@ -1331,7 +1363,7 @@ static void update_global_window(void *args, uint32_t id, void *stream) {
is_zero = stream_global->outgoing_window <= 0;
if (was_zero && !is_zero) {
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@ -1392,6 +1424,13 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
/* handle higher level things */
grpc_chttp2_publish_reads(exec_ctx, transport_global, transport_parsing);
t->parsing_active = 0;
/* handle delayed transport ops (if there is one) */
if (t->post_parsing_op) {
grpc_transport_op *op = t->post_parsing_op;
t->post_parsing_op = NULL;
perform_transport_op_locked(exec_ctx, t, op);
gpr_free(op);
}
/* if a stream is in the stream map, and gets cancelled, we need to ensure
* we are not parsing before continuing the cancellation to keep things in
* a sane state */
@ -1426,7 +1465,7 @@ static void recv_data(grpc_exec_ctx *exec_ctx, void *tp, bool success) {
GPR_TIMER_END("recv_data", 0);
}
/*
/*******************************************************************************
* CALLBACK LOOP
*/
@ -1440,7 +1479,7 @@ static void connectivity_state_set(
state, reason);
}
/*
/*******************************************************************************
* POLLSET STUFF
*/
@ -1468,7 +1507,7 @@ static void set_pollset(grpc_exec_ctx *exec_ctx, grpc_transport *gt,
unlock(exec_ctx, t);
}
/*
/*******************************************************************************
* BYTE STREAM
*/
@ -1508,7 +1547,7 @@ static void incoming_byte_stream_update_flow_control(
add_max_recv_bytes);
grpc_chttp2_list_add_unannounced_incoming_window_available(transport_global,
stream_global);
grpc_chttp2_list_add_writable_stream(transport_global, stream_global);
grpc_chttp2_become_writable(transport_global, stream_global);
}
}
@ -1623,7 +1662,7 @@ grpc_chttp2_incoming_byte_stream *grpc_chttp2_incoming_byte_stream_create(
return incoming_byte_stream;
}
/*
/*******************************************************************************
* TRACING
*/
@ -1709,7 +1748,7 @@ void grpc_chttp2_flowctl_trace(const char *file, int line, const char *phase,
gpr_free(prefix);
}
/*
/*******************************************************************************
* INTEGRATION GLUE
*/

@ -43,11 +43,13 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include "src/core/profiling/timers.h"
#include "src/core/support/murmur_hash.h"
#include "src/core/support/string.h"
#include "src/core/transport/chttp2/bin_encoder.h"
#include "src/core/transport/static_metadata.h"
#include "src/core/iomgr/iomgr_internal.h"
/* There are two kinds of mdelem and mdstr instances.
* Static instances are declared in static_metadata.{h,c} and
@ -227,6 +229,9 @@ void grpc_mdctx_global_shutdown(void) {
if (shard->count != 0) {
gpr_log(GPR_DEBUG, "WARNING: %d metadata elements were leaked",
shard->count);
if (grpc_iomgr_abort_on_leaks()) {
abort();
}
}
gpr_free(shard->elems);
}
@ -237,6 +242,9 @@ void grpc_mdctx_global_shutdown(void) {
if (shard->count != 0) {
gpr_log(GPR_DEBUG, "WARNING: %d metadata strings were leaked",
shard->count);
if (grpc_iomgr_abort_on_leaks()) {
abort();
}
}
gpr_free(shard->strs);
}

@ -45,7 +45,7 @@ void grpc_stream_ref(grpc_stream_refcount *refcount, const char *reason) {
#else
void grpc_stream_ref(grpc_stream_refcount *refcount) {
#endif
gpr_ref(&refcount->refs);
gpr_ref_non_zero(&refcount->refs);
}
#ifdef GRPC_STREAM_REFCOUNT_DEBUG

@ -123,7 +123,7 @@ typedef struct grpc_transport_stream_op {
/** Transport op: a set of operations to perform on a transport as a whole */
typedef struct grpc_transport_op {
/** called when processing of this op is done */
/** Called when processing of this op is done. */
grpc_closure *on_consumed;
/** connectivity monitoring - set connectivity_state to NULL to unsubscribe */
grpc_closure *on_connectivity_state_change;
@ -138,9 +138,13 @@ typedef struct grpc_transport_op {
grpc_status_code goaway_status;
gpr_slice *goaway_message;
/** set the callback for accepting new streams;
this is a permanent callback, unlike the other one-shot closures */
void (*set_accept_stream)(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_transport *transport, const void *server_data);
this is a permanent callback, unlike the other one-shot closures.
If true, the callback is set to set_accept_stream_fn, with its
user_data argument set to set_accept_stream_user_data */
bool set_accept_stream;
void (*set_accept_stream_fn)(grpc_exec_ctx *exec_ctx, void *user_data,
grpc_transport *transport,
const void *server_data);
void *set_accept_stream_user_data;
/** add this transport to a pollset */
grpc_pollset *bind_pollset;

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -33,9 +33,18 @@
#include "src/core/tsi/ssl_transport_security.h"
#include <grpc/support/port_platform.h>
#include <limits.h>
#include <string.h>
/* TODO(jboeuf): refactor inet_ntop into a portability header. */
#ifdef GPR_WINSOCK_SOCKET
#include <ws2tcpip.h>
#else
#include <arpa/inet.h>
#endif
#include <grpc/support/log.h>
#include <grpc/support/sync.h>
#include <grpc/support/thd.h>
@ -197,13 +206,16 @@ static void ssl_info_callback(const SSL *ssl, int where, int ret) {
}
/* Returns 1 if name looks like an IP address, 0 otherwise.
This is a very rough heuristic as it does not handle IPV6 or things like:
0300.0250.00.01, 0xC0.0Xa8.0x0.0x1, 000030052000001, 0xc0.052000001 */
This is a very rough heuristic, and only handles IPv6 in hexadecimal form. */
static int looks_like_ip_address(const char *name) {
size_t i;
size_t dot_count = 0;
size_t num_size = 0;
for (i = 0; i < strlen(name); i++) {
if (name[i] == ':') {
/* IPv6 Address in hexadecimal form, : is not allowed in DNS names. */
return 1;
}
if (name[i] >= '0' && name[i] <= '9') {
if (num_size > 3) return 0;
num_size++;
@ -296,21 +308,44 @@ static tsi_result add_subject_alt_names_properties_to_peer(
sk_GENERAL_NAME_value(subject_alt_names, TSI_SIZE_AS_SIZE(i));
/* Filter out the non-dns entries names. */
if (subject_alt_name->type == GEN_DNS) {
unsigned char *dns_name = NULL;
int dns_name_size =
ASN1_STRING_to_UTF8(&dns_name, subject_alt_name->d.dNSName);
if (dns_name_size < 0) {
unsigned char *name = NULL;
int name_size;
name_size = ASN1_STRING_to_UTF8(&name, subject_alt_name->d.dNSName);
if (name_size < 0) {
gpr_log(GPR_ERROR, "Could not get utf8 from asn1 string.");
result = TSI_INTERNAL_ERROR;
break;
}
result = tsi_construct_string_peer_property(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY,
(const char *)dns_name, (size_t)dns_name_size,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, (const char *)name,
(size_t)name_size, &peer->properties[peer->property_count++]);
OPENSSL_free(name);
} else if (subject_alt_name->type == GEN_IPADD) {
char ntop_buf[INET6_ADDRSTRLEN];
int af;
if (subject_alt_name->d.iPAddress->length == 4) {
af = AF_INET;
} else if (subject_alt_name->d.iPAddress->length == 16) {
af = AF_INET6;
} else {
gpr_log(GPR_ERROR, "SAN IP Address contained invalid IP");
result = TSI_INTERNAL_ERROR;
break;
}
const char *name = inet_ntop(af, subject_alt_name->d.iPAddress->data,
ntop_buf, INET6_ADDRSTRLEN);
if (name == NULL) {
gpr_log(GPR_ERROR, "Could not get IP string from asn1 octet.");
result = TSI_INTERNAL_ERROR;
break;
}
result = tsi_construct_string_peer_property_from_cstring(
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY, name,
&peer->properties[peer->property_count++]);
OPENSSL_free(dns_name);
if (result != TSI_OK) break;
}
if (result != TSI_OK) break;
}
return result;
}
@ -1436,9 +1471,7 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
size_t i = 0;
size_t san_count = 0;
const tsi_peer_property *cn_property = NULL;
/* For now reject what looks like an IP address. */
if (looks_like_ip_address(name)) return 0;
int like_ip = looks_like_ip_address(name);
/* Check the SAN first. */
for (i = 0; i < peer->property_count; i++) {
@ -1447,8 +1480,15 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
if (strcmp(property->name,
TSI_X509_SUBJECT_ALTERNATIVE_NAME_PEER_PROPERTY) == 0) {
san_count++;
if (does_entry_match_name(property->value.data, property->value.length,
name)) {
if (!like_ip && does_entry_match_name(property->value.data,
property->value.length, name)) {
return 1;
} else if (like_ip &&
strncmp(name, property->value.data, property->value.length) ==
0 &&
strlen(name) == property->value.length) {
/* IP Addresses are exact matches only. */
return 1;
}
} else if (strcmp(property->name,
@ -1457,8 +1497,8 @@ int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name) {
}
}
/* If there's no SAN, try the CN. */
if (san_count == 0 && cn_property != NULL) {
/* If there's no SAN, try the CN, but only if its not like an IP Address */
if (san_count == 0 && cn_property != NULL && !like_ip) {
if (does_entry_match_name(cn_property->value.data,
cn_property->value.length, name)) {
return 1;

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2015-2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -162,8 +162,7 @@ void tsi_ssl_handshaker_factory_destroy(tsi_ssl_handshaker_factory *self);
Still TODO(jboeuf):
- handle mixed case.
- handle %encoded chars.
- handle public suffix wildchar more strictly (e.g. *.co.uk)
- handle IP addresses in SAN. */
- handle public suffix wildchar more strictly (e.g. *.co.uk) */
int tsi_ssl_peer_matches_name(const tsi_peer *peer, const char *name);
#ifdef __cplusplus

@ -6,3 +6,77 @@ This directory contains source code for C++ implementation of gRPC.
#Status
Beta
#Pre-requisites
##Linux
```sh
$ [sudo] apt-get install build-essential autoconf libtool
```
##Mac OSX
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:
```sh
$ [sudo] xcode-select --install
```
##Protoc
By default gRPC uses [protocol buffers](https://github.com/google/protobuf),
you will need the `protoc` compiler to generate stub server and client code.
If you compile gRPC from source, as described below, this also installs the
`protoc` compiler.
If it hasn't been installed, you can run the following commands to install it.
```sh
$ cd grpc/third_party/protobuf
$ sudo make install # 'make' should have been run by core grpc
```
Alternatively, you can download `protoc` binaries from
[the protocol buffers Github repository](https://github.com/google/protobuf/releases).
#Installation
Currently to install gRPC for C++, you need to build from source as described
below.
#Build from Source
```sh
$ git clone https://github.com/grpc/grpc.git
$ cd grpc
$ git submodule update --init
$ make
$ [sudo] make install
```
#Documentation
You can find out how to build and run our simplest gRPC C++ example in our
[C++ quick start](https://github.com/grpc/grpc/tree/{{ site.data.config.grpc_release_branch }}/examples/cpp).
For more detailed documentation on using gRPC in C++ , see our main
documentation site at [grpc.io](http://grpc.io), specifically:
* [Overview](http://www.grpc.io/docs/): An introduction to gRPC with a simple
Hello World example in all our supported languages, including C++.
* [gRPC Basics - C++](http://www.grpc.io/docs/tutorials/basic/c.html):
A tutorial that steps you through creating a simple gRPC C++ example
application.
* [Asynchronous Basics - C++](http://www.grpc.io/docs/tutorials/async/helloasync-cpp.html):
A tutorial that shows you how to use gRPC C++'s asynchronous/non-blocking
APIs.
# Examples
Code examples for gRPC C++ live in this repository's
[examples/cpp](https://github.com/grpc/grpc/tree/{{ site.data.config.grpc_release_branch }}/examples/cpp) directory.

@ -83,14 +83,14 @@ std::shared_ptr<CallCredentials> WrapCallCredentials(
} // namespace
std::shared_ptr<ChannelCredentials> GoogleDefaultCredentials() {
GrpcLibrary init; // To call grpc_init().
GrpcLibraryCodegen init; // To call grpc_init().
return WrapChannelCredentials(grpc_google_default_credentials_create());
}
// Builds SSL Credentials given SSL specific options
std::shared_ptr<ChannelCredentials> SslCredentials(
const SslCredentialsOptions& options) {
GrpcLibrary init; // To call grpc_init().
GrpcLibraryCodegen init; // To call grpc_init().
grpc_ssl_pem_key_cert_pair pem_key_cert_pair = {
options.pem_private_key.c_str(), options.pem_cert_chain.c_str()};
@ -102,7 +102,7 @@ std::shared_ptr<ChannelCredentials> SslCredentials(
// Builds credentials for use when running in GCE
std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
GrpcLibrary init; // To call grpc_init().
GrpcLibraryCodegen init; // To call grpc_init().
return WrapCallCredentials(
grpc_google_compute_engine_credentials_create(nullptr));
}
@ -110,7 +110,7 @@ std::shared_ptr<CallCredentials> GoogleComputeEngineCredentials() {
// Builds JWT credentials.
std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
const grpc::string& json_key, long token_lifetime_seconds) {
GrpcLibrary init; // To call grpc_init().
GrpcLibraryCodegen init; // To call grpc_init().
if (token_lifetime_seconds <= 0) {
gpr_log(GPR_ERROR,
"Trying to create JWTCredentials with non-positive lifetime");
@ -125,7 +125,7 @@ std::shared_ptr<CallCredentials> ServiceAccountJWTAccessCredentials(
// Builds refresh token credentials.
std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
const grpc::string& json_refresh_token) {
GrpcLibrary init; // To call grpc_init().
GrpcLibraryCodegen init; // To call grpc_init().
return WrapCallCredentials(grpc_google_refresh_token_credentials_create(
json_refresh_token.c_str(), nullptr));
}
@ -133,7 +133,7 @@ std::shared_ptr<CallCredentials> GoogleRefreshTokenCredentials(
// Builds access token credentials.
std::shared_ptr<CallCredentials> AccessTokenCredentials(
const grpc::string& access_token) {
GrpcLibrary init; // To call grpc_init().
GrpcLibraryCodegen init; // To call grpc_init().
return WrapCallCredentials(
grpc_access_token_credentials_create(access_token.c_str(), nullptr));
}
@ -142,7 +142,7 @@ std::shared_ptr<CallCredentials> AccessTokenCredentials(
std::shared_ptr<CallCredentials> GoogleIAMCredentials(
const grpc::string& authorization_token,
const grpc::string& authority_selector) {
GrpcLibrary init; // To call grpc_init().
GrpcLibraryCodegen init; // To call grpc_init().
return WrapCallCredentials(grpc_google_iam_credentials_create(
authorization_token.c_str(), authority_selector.c_str(), nullptr));
}
@ -224,7 +224,7 @@ MetadataCredentialsPluginWrapper::MetadataCredentialsPluginWrapper(
std::shared_ptr<CallCredentials> MetadataCredentialsFromPlugin(
std::unique_ptr<MetadataCredentialsPlugin> plugin) {
GrpcLibrary init; // To call grpc_init().
GrpcLibraryCodegen init; // To call grpc_init().
const char* type = plugin->GetType();
MetadataCredentialsPluginWrapper* wrapper =
new MetadataCredentialsPluginWrapper(std::move(plugin));

@ -0,0 +1,45 @@
/*
*
* Copyright 2016, 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 <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc++/impl/codegen/grpc_library.h>
/// Initializes the global gRPC variables for the codegen library. These will
/// stay null in the absence of of grpc++ library. In this case, no gRPC
/// features such as the ability to perform calls will be available. Trying to
/// perform them would result in a segmentation fault when trying to deference
/// the following nulled globals. These should be associated with actual
/// as part of the instantiation of a \a grpc::GrpcLibraryInitializer variable.
grpc::CoreCodegenInterface* grpc::g_core_codegen_interface = nullptr;
grpc::GrpcLibraryInterface* grpc::g_glip = nullptr;

@ -1,92 +0,0 @@
/*
*
* 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 <grpc++/impl/call.h>
#include <grpc/support/alloc.h>
#include <grpc++/channel.h>
#include <grpc++/client_context.h>
#include <grpc++/support/byte_buffer.h>
#include "src/core/profiling/timers.h"
namespace grpc {
void FillMetadataMap(
grpc_metadata_array* arr,
std::multimap<grpc::string_ref, grpc::string_ref>* metadata) {
for (size_t i = 0; i < arr->count; i++) {
// TODO(yangg) handle duplicates?
metadata->insert(std::pair<grpc::string_ref, grpc::string_ref>(
arr->metadata[i].key, grpc::string_ref(arr->metadata[i].value,
arr->metadata[i].value_length)));
}
grpc_metadata_array_destroy(arr);
grpc_metadata_array_init(arr);
}
// TODO(yangg) if the map is changed before we send, the pointers will be a
// mess. Make sure it does not happen.
grpc_metadata* FillMetadataArray(
const std::multimap<grpc::string, grpc::string>& metadata) {
if (metadata.empty()) {
return nullptr;
}
grpc_metadata* metadata_array =
(grpc_metadata*)gpr_malloc(metadata.size() * sizeof(grpc_metadata));
size_t i = 0;
for (auto iter = metadata.cbegin(); iter != metadata.cend(); ++iter, ++i) {
metadata_array[i].key = iter->first.c_str();
metadata_array[i].value = iter->second.c_str();
metadata_array[i].value_length = iter->second.size();
}
return metadata_array;
}
Call::Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq)
: call_hook_(call_hook), cq_(cq), call_(call), max_message_size_(-1) {}
Call::Call(grpc_call* call, CallHook* call_hook, CompletionQueue* cq,
int max_message_size)
: call_hook_(call_hook),
cq_(cq),
call_(call),
max_message_size_(max_message_size) {}
void Call::PerformOps(CallOpSetInterface* ops) {
if (max_message_size_ > 0) {
ops->set_max_message_size(max_message_size_);
}
call_hook_->PerformOpsOnCall(ops, this);
}
} // namespace grpc

@ -34,7 +34,6 @@
#include <memory>
#include <grpc++/impl/codegen/completion_queue_tag.h>
#include <grpc++/impl/grpc_library.h>
#include <grpc++/support/time.h>
#include <grpc/grpc.h>
@ -43,16 +42,13 @@
namespace grpc {
static internal::GrpcLibraryInitializer g_gli_initializer;
CompletionQueue::CompletionQueue() {
g_gli_initializer.summon();
cq_ = grpc_completion_queue_create(nullptr);
}
CompletionQueue::CompletionQueue(grpc_completion_queue* take) : cq_(take) {}
CompletionQueue::~CompletionQueue() { grpc_completion_queue_destroy(cq_); }
void CompletionQueue::Shutdown() { grpc_completion_queue_shutdown(cq_); }
void CompletionQueue::Shutdown() {
g_gli_initializer.summon();
grpc_completion_queue_shutdown(cq_);
}
CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal(
void** tag, bool* ok, gpr_timespec deadline) {
@ -75,25 +71,4 @@ CompletionQueue::NextStatus CompletionQueue::AsyncNextInternal(
}
}
bool CompletionQueue::Pluck(CompletionQueueTag* tag) {
auto deadline = gpr_inf_future(GPR_CLOCK_REALTIME);
auto ev = grpc_completion_queue_pluck(cq_, tag, deadline, nullptr);
bool ok = ev.success != 0;
void* ignored = tag;
GPR_ASSERT(tag->FinalizeResult(&ignored, &ok));
GPR_ASSERT(ignored == tag);
// Ignore mutations by FinalizeResult: Pluck returns the C API status
return ev.success != 0;
}
void CompletionQueue::TryPluck(CompletionQueueTag* tag) {
auto deadline = gpr_time_0(GPR_CLOCK_REALTIME);
auto ev = grpc_completion_queue_pluck(cq_, tag, deadline, nullptr);
if (ev.type == GRPC_QUEUE_TIMEOUT) return;
bool ok = ev.success != 0;
void* ignored = tag;
// the tag must be swallowed if using TryPluck
GPR_ASSERT(!tag->FinalizeResult(&ignored, &ok));
}
} // namespace grpc

@ -1,6 +1,6 @@
/*
*
* Copyright 2015, Google Inc.
* Copyright 2016, Google Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -31,28 +31,31 @@
*
*/
#include <grpc++/impl/proto_utils.h>
#include "src/cpp/common/core_codegen.h"
#include <climits>
#include <stdlib.h>
#include <grpc/grpc.h>
#include <grpc++/support/config.h>
#include <grpc/byte_buffer.h>
#include <grpc/byte_buffer_reader.h>
#include <grpc/support/log.h>
#include <grpc/grpc.h>
#include <grpc/impl/codegen/alloc.h>
#include <grpc/impl/codegen/byte_buffer.h>
#include <grpc/impl/codegen/log.h>
#include <grpc/support/port_platform.h>
#include <grpc/support/slice.h>
#include <grpc/support/slice_buffer.h>
#include <grpc/support/port_platform.h>
#include <grpc++/support/config.h>
#include "src/core/profiling/timers.h"
const int kMaxBufferLength = 8192;
namespace {
const int kGrpcBufferWriterMaxBufferLength = 8192;
class GrpcBufferWriter GRPC_FINAL
: public ::grpc::protobuf::io::ZeroCopyOutputStream {
public:
explicit GrpcBufferWriter(grpc_byte_buffer** bp,
int block_size = kMaxBufferLength)
explicit GrpcBufferWriter(grpc_byte_buffer** bp, int block_size)
: block_size_(block_size), byte_count_(0), have_backup_(false) {
*bp = grpc_raw_byte_buffer_create(NULL, 0);
slice_buffer_ = &(*bp)->data.raw.slice_buffer;
@ -161,14 +164,56 @@ class GrpcBufferReader GRPC_FINAL
grpc_byte_buffer_reader reader_;
gpr_slice slice_;
};
} // namespace
namespace grpc {
Status SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** bp) {
grpc_completion_queue* CoreCodegen::grpc_completion_queue_create(
void* reserved) {
return ::grpc_completion_queue_create(reserved);
}
void CoreCodegen::grpc_completion_queue_destroy(grpc_completion_queue* cq) {
::grpc_completion_queue_destroy(cq);
}
grpc_event CoreCodegen::grpc_completion_queue_pluck(grpc_completion_queue* cq,
void* tag,
gpr_timespec deadline,
void* reserved) {
return ::grpc_completion_queue_pluck(cq, tag, deadline, reserved);
}
void* CoreCodegen::gpr_malloc(size_t size) { return ::gpr_malloc(size); }
void CoreCodegen::gpr_free(void* p) { return ::gpr_free(p); }
void CoreCodegen::grpc_byte_buffer_destroy(grpc_byte_buffer* bb) {
::grpc_byte_buffer_destroy(bb);
}
void CoreCodegen::grpc_metadata_array_init(grpc_metadata_array* array) {
::grpc_metadata_array_init(array);
}
void CoreCodegen::grpc_metadata_array_destroy(grpc_metadata_array* array) {
::grpc_metadata_array_destroy(array);
}
gpr_timespec CoreCodegen::gpr_inf_future(gpr_clock_type type) {
return ::gpr_inf_future(type);
}
void CoreCodegen::assert_fail(const char* failed_assertion) {
gpr_log(GPR_ERROR, "assertion failed: %s", failed_assertion);
abort();
}
Status CoreCodegen::SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** bp) {
GPR_TIMER_SCOPE("SerializeProto", 0);
int byte_size = msg.ByteSize();
if (byte_size <= kMaxBufferLength) {
if (byte_size <= kGrpcBufferWriterMaxBufferLength) {
gpr_slice slice = gpr_slice_malloc(byte_size);
GPR_ASSERT(GPR_SLICE_END_PTR(slice) ==
msg.SerializeWithCachedSizesToArray(GPR_SLICE_START_PTR(slice)));
@ -176,31 +221,36 @@ Status SerializeProto(const grpc::protobuf::Message& msg,
gpr_slice_unref(slice);
return Status::OK;
} else {
GrpcBufferWriter writer(bp);
GrpcBufferWriter writer(bp, kGrpcBufferWriterMaxBufferLength);
return msg.SerializeToZeroCopyStream(&writer)
? Status::OK
: Status(StatusCode::INTERNAL, "Failed to serialize message");
}
}
Status DeserializeProto(grpc_byte_buffer* buffer, grpc::protobuf::Message* msg,
int max_message_size) {
Status CoreCodegen::DeserializeProto(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg,
int max_message_size) {
GPR_TIMER_SCOPE("DeserializeProto", 0);
if (!buffer) {
if (buffer == nullptr) {
return Status(StatusCode::INTERNAL, "No payload");
}
GrpcBufferReader reader(buffer);
::grpc::protobuf::io::CodedInputStream decoder(&reader);
if (max_message_size > 0) {
decoder.SetTotalBytesLimit(max_message_size, max_message_size);
}
if (!msg->ParseFromCodedStream(&decoder)) {
return Status(StatusCode::INTERNAL, msg->InitializationErrorString());
}
if (!decoder.ConsumedEntireMessage()) {
return Status(StatusCode::INTERNAL, "Did not read entire message");
Status result = Status::OK;
{
GrpcBufferReader reader(buffer);
::grpc::protobuf::io::CodedInputStream decoder(&reader);
if (max_message_size > 0) {
decoder.SetTotalBytesLimit(max_message_size, max_message_size);
}
if (!msg->ParseFromCodedStream(&decoder)) {
result = Status(StatusCode::INTERNAL, msg->InitializationErrorString());
}
if (!decoder.ConsumedEntireMessage()) {
result = Status(StatusCode::INTERNAL, "Did not read entire message");
}
}
return Status::OK;
grpc_byte_buffer_destroy(buffer);
return result;
}
} // namespace grpc

@ -0,0 +1,71 @@
/*
*
* Copyright 2016, 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.
*
*/
// This file should be compiled as part of grpc++.
#include <grpc++/impl/codegen/core_codegen_interface.h>
#include <grpc/impl/codegen/grpc_types.h>
#include <grpc/byte_buffer.h>
namespace grpc {
/// Implementation of the core codegen interface.
class CoreCodegen : public CoreCodegenInterface {
private:
Status SerializeProto(const grpc::protobuf::Message& msg,
grpc_byte_buffer** bp) override;
Status DeserializeProto(grpc_byte_buffer* buffer,
grpc::protobuf::Message* msg,
int max_message_size) override;
grpc_completion_queue* grpc_completion_queue_create(void* reserved) override;
void grpc_completion_queue_destroy(grpc_completion_queue* cq) override;
grpc_event grpc_completion_queue_pluck(grpc_completion_queue* cq, void* tag,
gpr_timespec deadline,
void* reserved) override;
void* gpr_malloc(size_t size) override;
void gpr_free(void* p) override;
void grpc_byte_buffer_destroy(grpc_byte_buffer* bb) override;
void grpc_metadata_array_init(grpc_metadata_array* array) override;
void grpc_metadata_array_destroy(grpc_metadata_array* array) override;
gpr_timespec gpr_inf_future(gpr_clock_type type) override;
void assert_fail(const char* failed_assertion) override;
};
} // namespace grpc

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

Loading…
Cancel
Save