Merge branch 'master' of https://github.com/grpc/grpc into zookeeper

pull/2882/head
Hongwei Wang 9 years ago
commit 1284552713
  1. 3
      BUILD
  2. 6
      build.json
  3. 77
      doc/connection-backoff-interop-test-description.md
  4. 57
      doc/interop-test-descriptions.md
  5. 2
      gRPC.podspec
  6. 8
      include/grpc++/client_context.h
  7. 1
      include/grpc++/dynamic_thread_pool.h
  8. 2
      include/grpc++/impl/sync_no_cxx11.h
  9. 7
      include/grpc++/server_context.h
  10. 32
      include/grpc/census.h
  11. 48
      include/grpc/grpc.h
  12. 2
      include/grpc/support/atm_gcc_atomic.h
  13. 5
      include/grpc/support/atm_gcc_sync.h
  14. 5
      include/grpc/support/atm_win32.h
  15. 5
      src/core/census/grpc_context.c
  16. 57
      src/core/census/grpc_context.h
  17. 19
      src/core/census/initialize.c
  18. 65
      src/core/client_config/subchannel.c
  19. 6
      src/core/iomgr/fd_posix.c
  20. 1
      src/core/iomgr/fd_posix.h
  21. 2
      src/core/iomgr/tcp_server_posix.c
  22. 22
      src/core/iomgr/tcp_server_windows.c
  23. 14
      src/core/iomgr/tcp_windows.c
  24. 12
      src/core/support/stack_lockfree.c
  25. 17
      src/core/surface/call.c
  26. 7
      src/core/surface/init.c
  27. 5
      src/core/surface/server.c
  28. 3
      src/cpp/client/channel.cc
  29. 4
      src/cpp/server/server_context.cc
  30. 2
      src/csharp/buildall.bat
  31. 3
      src/node/examples/perf_test.js
  32. 3
      src/node/examples/qps_test.js
  33. 3
      src/node/examples/route_guide_client.js
  34. 3
      src/node/examples/stock_client.js
  35. 52
      src/node/ext/channel.cc
  36. 47
      src/node/ext/credentials.cc
  37. 1
      src/node/ext/credentials.h
  38. 8
      src/node/interop/interop_client.js
  39. 6
      src/node/src/client.js
  40. 6
      src/node/test/call_test.js
  41. 33
      src/node/test/channel_test.js
  42. 4
      src/node/test/end_to_end_test.js
  43. 3
      src/node/test/health_test.js
  44. 3
      src/node/test/math_client_test.js
  45. 14
      src/node/test/surface_test.js
  46. 6
      src/objective-c/generated_libraries/RemoteTestClient/RemoteTest.podspec
  47. 6
      src/objective-c/generated_libraries/RouteGuideClient/RouteGuide.podspec
  48. 3
      src/objective-c/tests/GRPCClientTests.m
  49. 4
      src/objective-c/tests/InteropTests.m
  50. 6
      src/objective-c/tests/Tests.xcodeproj/xcshareddata/xcschemes/AllTests.xcscheme
  51. 39
      src/objective-c/tests/build_tests.sh
  52. 7
      src/objective-c/tests/run_tests.sh
  53. 4
      src/python/grpcio/.gitignore
  54. 2
      src/python/grpcio/MANIFEST.in
  55. 0
      src/python/grpcio/README.rst
  56. 76
      src/python/grpcio/commands.py
  57. 0
      src/python/grpcio/grpc/__init__.py
  58. 0
      src/python/grpcio/grpc/_adapter/.gitignore
  59. 0
      src/python/grpcio/grpc/_adapter/__init__.py
  60. 0
      src/python/grpcio/grpc/_adapter/_c/module.c
  61. 0
      src/python/grpcio/grpc/_adapter/_c/types.c
  62. 0
      src/python/grpcio/grpc/_adapter/_c/types.h
  63. 0
      src/python/grpcio/grpc/_adapter/_c/types/call.c
  64. 0
      src/python/grpcio/grpc/_adapter/_c/types/channel.c
  65. 0
      src/python/grpcio/grpc/_adapter/_c/types/client_credentials.c
  66. 0
      src/python/grpcio/grpc/_adapter/_c/types/completion_queue.c
  67. 0
      src/python/grpcio/grpc/_adapter/_c/types/server.c
  68. 0
      src/python/grpcio/grpc/_adapter/_c/types/server_credentials.c
  69. 0
      src/python/grpcio/grpc/_adapter/_c/utility.c
  70. 0
      src/python/grpcio/grpc/_adapter/_common.py
  71. 0
      src/python/grpcio/grpc/_adapter/_intermediary_low.py
  72. 0
      src/python/grpcio/grpc/_adapter/_low.py
  73. 0
      src/python/grpcio/grpc/_adapter/_types.py
  74. 0
      src/python/grpcio/grpc/_adapter/fore.py
  75. 0
      src/python/grpcio/grpc/_adapter/rear.py
  76. 0
      src/python/grpcio/grpc/_cython/.gitignore
  77. 0
      src/python/grpcio/grpc/_cython/README.rst
  78. 0
      src/python/grpcio/grpc/_cython/__init__.py
  79. 0
      src/python/grpcio/grpc/_cython/_cygrpc/__init__.py
  80. 0
      src/python/grpcio/grpc/_cython/_cygrpc/call.pxd
  81. 0
      src/python/grpcio/grpc/_cython/_cygrpc/call.pyx
  82. 0
      src/python/grpcio/grpc/_cython/_cygrpc/channel.pxd
  83. 0
      src/python/grpcio/grpc/_cython/_cygrpc/channel.pyx
  84. 0
      src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pxd
  85. 0
      src/python/grpcio/grpc/_cython/_cygrpc/completion_queue.pyx
  86. 0
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pxd
  87. 0
      src/python/grpcio/grpc/_cython/_cygrpc/credentials.pyx
  88. 0
      src/python/grpcio/grpc/_cython/_cygrpc/grpc.pxd
  89. 0
      src/python/grpcio/grpc/_cython/_cygrpc/records.pxd
  90. 0
      src/python/grpcio/grpc/_cython/_cygrpc/records.pyx
  91. 0
      src/python/grpcio/grpc/_cython/_cygrpc/server.pxd
  92. 0
      src/python/grpcio/grpc/_cython/_cygrpc/server.pyx
  93. 0
      src/python/grpcio/grpc/_cython/adapter_low.py
  94. 0
      src/python/grpcio/grpc/_cython/cygrpc.pyx
  95. 0
      src/python/grpcio/grpc/_links/__init__.py
  96. 0
      src/python/grpcio/grpc/_links/invocation.py
  97. 0
      src/python/grpcio/grpc/_links/service.py
  98. 0
      src/python/grpcio/grpc/early_adopter/__init__.py
  99. 0
      src/python/grpcio/grpc/early_adopter/implementations.py
  100. 0
      src/python/grpcio/grpc/framework/__init__.py
  101. Some files were not shown because too many files have changed in this diff Show More

@ -149,7 +149,6 @@ cc_library(
"src/core/tsi/ssl_transport_security.h",
"src/core/tsi/transport_security.h",
"src/core/tsi/transport_security_interface.h",
"src/core/census/grpc_context.h",
"src/core/channel/census_filter.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",
@ -408,7 +407,6 @@ cc_library(
cc_library(
name = "grpc_unsecure",
srcs = [
"src/core/census/grpc_context.h",
"src/core/channel/census_filter.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",
@ -1150,7 +1148,6 @@ objc_library(
"src/core/tsi/ssl_transport_security.h",
"src/core/tsi/transport_security.h",
"src/core/tsi/transport_security_interface.h",
"src/core/census/grpc_context.h",
"src/core/channel/census_filter.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",

@ -114,7 +114,6 @@
"include/grpc/status.h"
],
"headers": [
"src/core/census/grpc_context.h",
"src/core/channel/census_filter.h",
"src/core/channel/channel_args.h",
"src/core/channel/channel_stack.h",
@ -506,6 +505,7 @@
"gpr"
],
"baselib": true,
"dll": "yes",
"filegroups": [
"grpc_base",
"census"
@ -561,6 +561,7 @@
"gpr"
],
"baselib": true,
"dll": "yes",
"filegroups": [
"grpc_base",
"census"
@ -613,6 +614,7 @@
"grpc"
],
"baselib": true,
"dll": "yes",
"filegroups": [
"grpc++_base"
],
@ -664,6 +666,7 @@
"grpc_unsecure"
],
"baselib": true,
"dll": "yes",
"filegroups": [
"grpc++_base"
],
@ -852,6 +855,7 @@
"gpr",
"grpc"
],
"dll": "only",
"vs_project_guid": "{D64C6D63-4458-4A88-AB38-35678384A7E4}"
}
],

@ -0,0 +1,77 @@
Connection Backoff Interop Test Descriptions
===============================================
This test is to verify the client is reconnecting the server with correct
backoffs as specified in
[the spec](http://github.com/grpc/grpc/blob/master/doc/connection-backoff.md).
The test server has a port (control_port) running a rpc service for controlling
the server and another port (retry_port) to close any incoming tcp connections.
The test has the following flow:
1. The server starts listening on control_port.
2. The client calls Start rpc on server control_port.
3. The server starts listening on retry_port.
4. The client connects to server retry_port and retries with backoff for 540s,
which translates to about 13 retries.
5. The client calls Stop rpc on server control port.
6. The client checks the response to see whether the server thinks the backoffs
are conforming the spec or do its own check on the backoffs in the response.
Client and server use
[test.proto](https://github.com/grpc/grpc/blob/master/test/proto/test.proto).
Each language should implement its own client. The C++ server is shared among
languages.
Client
------
Clients should accept these arguments:
* --server_control_port=PORT
* The server port to connect to for rpc. For example, "8080"
* --server_retry_port=PORT
* The server port to connect to for testing backoffs. For example, "8081"
The client must connect to the control port without TLS. The client should
either assert on the server returned backoff status or check the returned
backoffs on its own.
Procedure of client:
1. Calls Start on server control port with a large deadline or no deadline,
waits for its finish and checks it succeeded.
2. Initiates a channel connection to server retry port, which should perform
reconnections with proper backoffs. A convienent way to achieve this is to
call Start with a deadline of 540s. The rpc should fail with deadline exceeded.
3. Calls Stop on server control port and checks it succeeded.
4. Checks the response to see whether the server thinks the backoffs passed the
test.
5. Optionally, the client can do its own check on the returned backoffs.
Server
------
A C++ server can be used for the test. Other languages do NOT need to implement
a server. To minimize the network delay, the server binary should run on the
same machine or on a nearby machine (in terms of network distance) with the
client binary.
A server implements the ReconnectService to its state. It also opens a
tcp server on the retry_port, which just shuts down all incoming tcp
connections to simulate connection failures. The server will keep a record of
all the reconnection timestamps and return the connection backoffs in the
response in milliseconds. The server also checks the backoffs to see whether
they conform the spec and returns whether the client passes the test.
If the server receives a Start call when another client is being tested, it
finishes the call when the other client is done. If some other host connects
to the server retry_port when a client is being tested, the server will log an
error but likely would think the client fails the test.
The server accepts these arguments:
* --control_port=PORT
* The port to listen on for control rpcs. For example, "8080"
* --retry_port=PORT
* The tcp server port. For example, "8081"

@ -483,18 +483,17 @@ library to obtain the authorization token
* received SimpleResponse.oauth_scope is in `--oauth_scope`
### Metadata (TODO: fix name)
Status: Not yet implementable
### custom_metadata
This test verifies that custom metadata in either binary or ascii format can be
sent in header and trailer.
sent as initial-metadata by the client and as both initial- and trailing-metadata
by the server.
Server features:
* [UnaryCall][]
* [FullDuplexCall][]
* [Compressable Payload][]
* Ability to receive custom metadata from client in header and send custom data
back to client in both header and trailer. (TODO: this is not defined)
* [Echo Metadata][]
Procedure:
1. While sending custom metadata (ascii + binary) in the header, client calls
@ -509,21 +508,29 @@ Procedure:
}
}
```
The client attaches custom metadata with the following keys and values:
```
key: "x-grpc-test-echo-initial", value: "test_initial_metadata_value"
key: "x-grpc-test-echo-trailing-bin", value: 0xababab
```
2. Client repeats step 1. with FullDuplexCall instead of UnaryCall.
Asserts:
* call was successful
* custom metadata is echoed back in the response header.
* custom metadata is echoed back in the response trailer.
* metadata with key `"x-grpc-test-echo-initial"` and value `"test_initial_metadata_value"`is received in the initial metadata.
* metadata with key `"x-grpc-test-echo-trailing-bin"` and value `0xababab` is received in the trailing metadata.
### status_code_and_message
Status: Not yet implementable
### status_code_and_message
This test verifies unary calls succeed in sending messages, and propagates back
status code and message sent along with the messages.
Server features:
* [UnaryCall][]
* [FullDuplexCall][]
* [Echo Status][]
Procedure:
1. Client calls UnaryCall with:
@ -536,6 +543,8 @@ Procedure:
}
}
```
2. Client repeats step 1. with FullDuplexCall instead of UnaryCall.
Asserts:
* received status code is the same with sent code
@ -543,21 +552,15 @@ Asserts:
### unimplemented_method
Status: Not yet implementable
Status: Ready for implementation. Blocking beta.
This test verifies calling unimplemented RPC method returns unimplemented
status.
This test verifies calling unimplemented RPC method returns the UNIMPLEMENTED status code.
Procedure:
* Client calls UnimplementedCall with:
* Client calls `grpc.testing.UnimplementedService/UnimplementedCall` with an empty request (defined as `grpc.testing.Empty`):
```
{
response_type: COMPRESSABLE
response_size: 314159
payload:{
body: 271828 bytes of zeros
}
}
```
@ -767,6 +770,22 @@ When the client requests COMPRESSABLE payload, the response includes a payload
of the size requested containing all zeros and the payload type is
COMPRESSABLE.
### Echo Status
[Echo Status]: #echo-status
When the client sends a response_status in the request payload, the server closes
the stream with the status code and messsage contained within said response_status.
The server will not process any further messages on the stream sent by the client.
This can be used by clients to verify correct handling of different status codes and
associated status messages end-to-end.
### Echo Metadata
[Echo Metadata]: #echo-metadata
When the client sends metadata with the key `"x-grpc-test-echo-initial"` with its
request, the server sends back exactly this key and the corresponding value back to
the client as part of initial metadata. When the client sends metadata with the key
`"x-grpc-test-echo-trailing-bin"` with its request, the server sends back exactly this
key and the corresponding value back to the client as trailing metadata.
### Observe ResponseParameters.interval_us
[Observe ResponseParameters.interval_us]: #observe-responseparametersinterval_us

@ -151,7 +151,6 @@ Pod::Spec.new do |s|
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/transport_security.h',
'src/core/tsi/transport_security_interface.h',
'src/core/census/grpc_context.h',
'src/core/channel/census_filter.h',
'src/core/channel/channel_args.h',
'src/core/channel/channel_stack.h',
@ -418,7 +417,6 @@ Pod::Spec.new do |s|
'src/core/tsi/ssl_transport_security.h',
'src/core/tsi/transport_security.h',
'src/core/tsi/transport_security_interface.h',
'src/core/census/grpc_context.h',
'src/core/channel/census_filter.h',
'src/core/channel/channel_args.h',
'src/core/channel/channel_stack.h',

@ -110,7 +110,7 @@ class ClientContext {
creds_ = creds;
}
grpc_compression_algorithm get_compression_algorithm() const {
grpc_compression_algorithm compression_algorithm() const {
return compression_algorithm_;
}
@ -119,8 +119,8 @@ class ClientContext {
std::shared_ptr<const AuthContext> auth_context() const;
// Get and set census context
void set_census_context(census_context* ccp) { census_context_ = ccp; }
census_context* get_census_context() const { return census_context_; }
void set_census_context(struct census_context* ccp) { census_context_ = ccp; }
struct census_context* census_context() const { return census_context_; }
void TryCancel();
@ -170,7 +170,7 @@ class ClientContext {
grpc::string authority_;
std::shared_ptr<Credentials> creds_;
mutable std::shared_ptr<const AuthContext> auth_context_;
census_context* census_context_;
struct census_context* census_context_;
std::multimap<grpc::string, grpc::string> send_initial_metadata_;
std::multimap<grpc::string, grpc::string> recv_initial_metadata_;
std::multimap<grpc::string, grpc::string> trailing_metadata_;

@ -41,6 +41,7 @@
#include <grpc++/thread_pool_interface.h>
#include <list>
#include <memory>
#include <queue>
namespace grpc {

@ -87,7 +87,7 @@ class condition_variable {
~condition_variable() { gpr_cv_destroy(&cv_); }
void wait(lock_guard<mutex> &mu) {
mu.locked = false;
gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future(GPR_CLOCK_REALTIME);
gpr_cv_wait(&cv_, &mu.mu_.mu_, gpr_inf_future(GPR_CLOCK_REALTIME));
mu.locked = true;
}
void notify_one() { gpr_cv_signal(&cv_); }

@ -46,6 +46,7 @@
struct gpr_timespec;
struct grpc_metadata;
struct grpc_call;
struct census_context;
namespace grpc {
@ -104,18 +105,20 @@ class ServerContext {
return client_metadata_;
}
grpc_compression_level get_compression_level() const {
grpc_compression_level compression_level() const {
return compression_level_;
}
void set_compression_level(grpc_compression_level level);
grpc_compression_algorithm get_compression_algorithm() const {
grpc_compression_algorithm compression_algorithm() const {
return compression_algorithm_;
}
void set_compression_algorithm(grpc_compression_algorithm algorithm);
std::shared_ptr<const AuthContext> auth_context() const;
const struct census_context* census_context() const;
private:
friend class ::grpc::testing::InteropContextInspector;
friend class ::grpc::Server;

@ -44,26 +44,30 @@
extern "C" {
#endif
/* Identify census functionality that can be enabled via census_initialize(). */
enum census_functions {
CENSUS_NONE = 0, /* Do not enable census. */
CENSUS_TRACING = 1, /* Enable census tracing. */
CENSUS_STATS = 2, /* Enable Census stats collection. */
CENSUS_CPU = 4, /* Enable Census CPU usage collection. */
CENSUS_ALL = CENSUS_TRACING | CENSUS_STATS | CENSUS_CPU
/* Identify census features that can be enabled via census_initialize(). */
enum census_features {
CENSUS_FEATURE_NONE = 0, /* Do not enable census. */
CENSUS_FEATURE_TRACING = 1, /* Enable census tracing. */
CENSUS_FEATURE_STATS = 2, /* Enable Census stats collection. */
CENSUS_FEATURE_CPU = 4, /* Enable Census CPU usage collection. */
CENSUS_FEATURE_ALL =
CENSUS_FEATURE_TRACING | CENSUS_FEATURE_STATS | CENSUS_FEATURE_CPU
};
/* Shutdown and startup census subsystem. The 'functions' argument should be
* the OR (|) of census_functions values. If census fails to initialize, then
/** Shutdown and startup census subsystem. The 'features' argument should be
* the OR (|) of census_features values. If census fails to initialize, then
* census_initialize() will return a non-zero value. It is an error to call
* census_initialize() more than once (without an intervening
* census_shutdown()). */
int census_initialize(int functions);
void census_shutdown();
int census_initialize(int features);
void census_shutdown(void);
/* If any census feature has been initialized, this funtion will return a
* non-zero value. */
int census_available();
/** Return the features supported by the current census implementation (not all
* features will be available on all platforms). */
int census_supported(void);
/** Return the census features currently enabled. */
int census_enabled(void);
/* Internally, Census relies on a context, which should be propagated across
* RPC's. From the RPC subsystems viewpoint, this is an opaque data structure.

@ -50,7 +50,7 @@ extern "C" {
* \section intro_sec The GRPC Core library is a low-level library designed
* to be wrapped by higher level libraries.
*
* The top-level API is provided in grpc.h.
* The top-level API is provided in grpc.h.
* Security related functionality lives in grpc_security.h.
*/
@ -175,7 +175,7 @@ typedef enum grpc_call_error {
GRPC_CALL_ERROR_INVALID_FLAGS,
/** invalid metadata was passed to this call */
GRPC_CALL_ERROR_INVALID_METADATA,
/** completion queue for notification has not been registered with the
/** completion queue for notification has not been registered with the
server */
GRPC_CALL_ERROR_NOT_SERVER_COMPLETION_QUEUE
} grpc_call_error;
@ -198,7 +198,8 @@ typedef struct grpc_metadata {
size_t value_length;
/** The following fields are reserved for grpc internal use.
There is no need to initialize them, and they will be set to garbage during
There is no need to initialize them, and they will be set to garbage
during
calls to grpc. */
struct {
void *obfuscated[3];
@ -256,24 +257,25 @@ typedef enum {
/** Send a message: 0 or more of these operations can occur for each call */
GRPC_OP_SEND_MESSAGE,
/** Send a close from the client: one and only one instance MUST be sent from
the client, unless the call was cancelled - in which case this can be
the client, unless the call was cancelled - in which case this can be
skipped */
GRPC_OP_SEND_CLOSE_FROM_CLIENT,
/** Send status from the server: one and only one instance MUST be sent from
the server unless the call was cancelled - in which case this can be
the server unless the call was cancelled - in which case this can be
skipped */
GRPC_OP_SEND_STATUS_FROM_SERVER,
/** Receive initial metadata: one and only one MUST be made on the client,
/** Receive initial metadata: one and only one MUST be made on the client,
must not be made on the server */
GRPC_OP_RECV_INITIAL_METADATA,
/** Receive a message: 0 or more of these operations can occur for each call */
/** Receive a message: 0 or more of these operations can occur for each call
*/
GRPC_OP_RECV_MESSAGE,
/** Receive status on the client: one and only one must be made on the client.
This operation always succeeds, meaning ops paired with this operation
will also appear to succeed, even though they may not have. In that case
the status will indicate some failure. */
GRPC_OP_RECV_STATUS_ON_CLIENT,
/** Receive close on the server: one and only one must be made on the
/** Receive close on the server: one and only one must be made on the
server */
GRPC_OP_RECV_CLOSE_ON_SERVER
} grpc_op_type;
@ -284,7 +286,7 @@ typedef struct grpc_op {
/** Operation type, as defined by grpc_op_type */
grpc_op_type op;
/** Write flags bitset for grpc_begin_messages */
gpr_uint32 flags;
gpr_uint32 flags;
union {
struct {
size_t count;
@ -303,21 +305,23 @@ typedef struct grpc_op {
After the operation completes, call grpc_metadata_array_destroy on this
value, or reuse it in a future op. */
grpc_metadata_array *recv_initial_metadata;
/** ownership of the byte buffer is moved to the caller; the caller must call
/** ownership of the byte buffer is moved to the caller; the caller must
call
grpc_byte_buffer_destroy on this value, or reuse it in a future op. */
grpc_byte_buffer **recv_message;
struct {
/** ownership of the array is with the caller, but ownership of the
elements stays with the call object (ie key, value members are owned
elements stays with the call object (ie key, value members are owned
by the call object, trailing_metadata->array is owned by the caller).
After the operation completes, call grpc_metadata_array_destroy on this
After the operation completes, call grpc_metadata_array_destroy on
this
value, or reuse it in a future op. */
grpc_metadata_array *trailing_metadata;
grpc_status_code *status;
/** status_details is a buffer owned by the application before the op
completes and after the op has completed. During the operation
status_details may be reallocated to a size larger than
*status_details_capacity, in which case *status_details_capacity will
status_details may be reallocated to a size larger than
*status_details_capacity, in which case *status_details_capacity will
be updated with the new array capacity.
Pre-allocating space:
@ -466,6 +470,16 @@ grpc_call_error grpc_call_start_batch(grpc_call *call, const grpc_op *ops,
functionality. Instead, use grpc_auth_context. */
char *grpc_call_get_peer(grpc_call *call);
struct census_context;
/* Set census context for a call; Must be called before first call to
grpc_call_start_batch(). */
void grpc_census_call_set_context(grpc_call *call,
struct census_context *context);
/* Retrieve the calls current census context. */
struct census_context *grpc_census_call_get_context(grpc_call *call);
/** Return a newly allocated string representing the target a channel was
created for. */
char *grpc_channel_get_target(grpc_channel *channel);
@ -512,7 +526,7 @@ grpc_call_error grpc_call_cancel_with_status(grpc_call *call,
void grpc_call_destroy(grpc_call *call);
/** Request notification of a new call. 'cq_for_notification' must
have been registered to the server via
have been registered to the server via
grpc_server_register_completion_queue. */
grpc_call_error grpc_server_request_call(
grpc_server *server, grpc_call **call, grpc_call_details *details,
@ -530,8 +544,8 @@ grpc_call_error grpc_server_request_call(
void *grpc_server_register_method(grpc_server *server, const char *method,
const char *host);
/** Request notification of a new pre-registered call. 'cq_for_notification'
must have been registered to the server via
/** Request notification of a new pre-registered call. 'cq_for_notification'
must have been registered to the server via
grpc_server_register_completion_queue. */
grpc_call_error grpc_server_request_registered_call(
grpc_server *server, void *registered_method, grpc_call **call,

@ -46,6 +46,8 @@ typedef gpr_intptr gpr_atm;
#define gpr_atm_no_barrier_load(p) (__atomic_load_n((p), __ATOMIC_RELAXED))
#define gpr_atm_rel_store(p, value) \
(__atomic_store_n((p), (gpr_intptr)(value), __ATOMIC_RELEASE))
#define gpr_atm_no_barrier_store(p, value) \
(__atomic_store_n((p), (gpr_intptr)(value), __ATOMIC_RELAXED))
#define gpr_atm_no_barrier_fetch_add(p, delta) \
(__atomic_fetch_add((p), (gpr_intptr)(delta), __ATOMIC_RELAXED))

@ -68,6 +68,11 @@ static __inline void gpr_atm_rel_store(gpr_atm *p, gpr_atm value) {
*p = value;
}
static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) {
GPR_ATM_COMPILE_BARRIER_();
*p = value;
}
#undef GPR_ATM_LS_BARRIER_
#undef GPR_ATM_COMPILE_BARRIER_

@ -57,6 +57,11 @@ static __inline void gpr_atm_rel_store(gpr_atm *p, gpr_atm value) {
*p = value;
}
static __inline void gpr_atm_no_barrier_store(gpr_atm *p, gpr_atm value) {
/* TODO(ctiller): Can we implement something better here? */
gpr_atm_rel_store(p, value);
}
static __inline int gpr_atm_no_barrier_cas(gpr_atm *p, gpr_atm o, gpr_atm n) {
/* InterlockedCompareExchangePointerNoFence() not available on vista or
windows7 */

@ -32,14 +32,15 @@
*/
#include <grpc/census.h>
#include "src/core/census/grpc_context.h"
#include <grpc/grpc.h>
#include "src/core/surface/call.h"
static void grpc_census_context_destroy(void *context) {
census_context_destroy((census_context *)context);
}
void grpc_census_call_set_context(grpc_call *call, census_context *context) {
if (!census_available()) {
if (census_enabled() == CENSUS_FEATURE_NONE) {
return;
}
if (context == NULL) {

@ -1,57 +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.
*
*/
/* GRPC <--> CENSUS context interface */
#ifndef CENSUS_GRPC_CONTEXT_H
#define CENSUS_GRPC_CONTEXT_H
#include <grpc/census.h>
#include "src/core/surface/call.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Set census context for the call; Must be called before first call to
grpc_call_start_batch(). */
void grpc_census_call_set_context(grpc_call *call, census_context *context);
/* Retrieve the calls current census context. */
census_context *grpc_census_call_get_context(grpc_call *call);
#ifdef __cplusplus
}
#endif
#endif /* CENSUS_GRPC_CONTEXT_H */

@ -33,20 +33,25 @@
#include <grpc/census.h>
static int census_fns_enabled = CENSUS_NONE;
static int features_enabled = CENSUS_FEATURE_NONE;
int census_initialize(int functions) {
if (census_fns_enabled != CENSUS_NONE) {
int census_initialize(int features) {
if (features_enabled != CENSUS_FEATURE_NONE) {
return 1;
}
if (functions != CENSUS_NONE) {
if (features != CENSUS_FEATURE_NONE) {
return 1;
} else {
census_fns_enabled = functions;
features_enabled = features;
return 0;
}
}
void census_shutdown() { census_fns_enabled = CENSUS_NONE; }
void census_shutdown(void) { features_enabled = CENSUS_FEATURE_NONE; }
int census_available() { return (census_fns_enabled != CENSUS_NONE); }
int census_supported(void) {
/* TODO(aveitch): improve this as we implement features... */
return CENSUS_FEATURE_NONE;
}
int census_enabled(void) { return features_enabled; }

@ -44,6 +44,12 @@
#include "src/core/transport/connectivity_state.h"
#include "src/core/surface/channel.h"
#define GRPC_SUBCHANNEL_MIN_CONNECT_TIMEOUT_SECONDS 20
#define GRPC_SUBCHANNEL_INITIAL_CONNECT_BACKOFF_SECONDS 1
#define GRPC_SUBCHANNEL_RECONNECT_BACKOFF_MULTIPLIER 1.6
#define GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS 120
#define GRPC_SUBCHANNEL_RECONNECT_JITTER 0.2
typedef struct {
/* all fields protected by subchannel->mu */
/** refcount */
@ -125,6 +131,8 @@ struct grpc_subchannel {
int have_alarm;
/** our alarm */
grpc_alarm alarm;
/** current random value */
gpr_uint32 random;
};
struct grpc_subchannel_call {
@ -264,6 +272,10 @@ void grpc_subchannel_del_interested_party(grpc_subchannel *c,
grpc_pollset_set_del_pollset(c->pollset_set, pollset);
}
static gpr_uint32 random_seed() {
return (gpr_uint32)(gpr_time_to_millis(gpr_now(GPR_CLOCK_MONOTONIC)));
}
grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
grpc_subchannel_args *args) {
grpc_subchannel *c = gpr_malloc(sizeof(*c));
@ -284,6 +296,7 @@ grpc_subchannel *grpc_subchannel_create(grpc_connector *connector,
c->mdctx = args->mdctx;
c->master = args->master;
c->pollset_set = grpc_client_channel_get_connecting_pollset_set(parent_elem);
c->random = random_seed();
grpc_mdctx_ref(c->mdctx);
grpc_iomgr_closure_init(&c->connected, subchannel_connected, c);
grpc_connectivity_state_init(&c->state_tracker, GRPC_CHANNEL_IDLE,
@ -307,10 +320,10 @@ static void continue_connect(grpc_subchannel *c) {
}
static void start_connect(grpc_subchannel *c) {
gpr_timespec now = gpr_now(GPR_CLOCK_MONOTONIC);
c->next_attempt = now;
c->backoff_delta = gpr_time_from_seconds(1, GPR_TIMESPAN);
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);
continue_connect(c);
}
@ -576,6 +589,35 @@ static void publish_transport(grpc_subchannel *c) {
}
}
/* Generate a random number between 0 and 1. */
static double generate_uniform_random_number(grpc_subchannel *c) {
c->random = (1103515245 * c->random + 12345) % ((gpr_uint32)1 << 31);
return c->random / (double)((gpr_uint32)1 << 31);
}
/* Update backoff_delta and next_attempt in subchannel */
static void update_reconnect_parameters(grpc_subchannel *c) {
gpr_int32 backoff_delta_millis, jitter;
gpr_int32 max_backoff_millis =
GRPC_SUBCHANNEL_RECONNECT_MAX_BACKOFF_SECONDS * 1000;
double jitter_range;
backoff_delta_millis =
(gpr_int32)(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 =
(gpr_int32)((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(void *arg, int iomgr_success) {
grpc_subchannel *c = arg;
gpr_mu_lock(&c->mu);
@ -586,6 +628,7 @@ static void on_alarm(void *arg, int iomgr_success) {
connectivity_state_changed_locked(c, "alarm");
gpr_mu_unlock(&c->mu);
if (iomgr_success) {
update_reconnect_parameters(c);
continue_connect(c);
} else {
GRPC_CHANNEL_INTERNAL_UNREF(c->master, "connecting");
@ -603,18 +646,20 @@ static void subchannel_connected(void *arg, int iomgr_success) {
GPR_ASSERT(!c->have_alarm);
c->have_alarm = 1;
connectivity_state_changed_locked(c, "connect_failed");
c->next_attempt = gpr_time_add(c->next_attempt, c->backoff_delta);
if (gpr_time_cmp(c->backoff_delta,
gpr_time_from_seconds(60, GPR_TIMESPAN)) < 0) {
c->backoff_delta = gpr_time_add(c->backoff_delta, c->backoff_delta);
}
grpc_alarm_init(&c->alarm, c->next_attempt, on_alarm, c, now);
gpr_mu_unlock(&c->mu);
}
}
static gpr_timespec compute_connect_deadline(grpc_subchannel *c) {
return gpr_time_add(c->next_attempt, c->backoff_delta);
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;
}
static grpc_connectivity_state compute_connectivity_locked(grpc_subchannel *c) {

@ -102,6 +102,7 @@ static grpc_fd *alloc_fd(int fd) {
r->freelist_next = NULL;
r->read_watcher = r->write_watcher = NULL;
r->on_done_closure = NULL;
r->closed = 0;
return r;
}
@ -209,6 +210,8 @@ void grpc_fd_orphan(grpc_fd *fd, grpc_iomgr_closure *on_done,
REF_BY(fd, 1, reason); /* remove active status, but keep referenced */
gpr_mu_lock(&fd->watcher_mu);
if (!has_watchers(fd)) {
GPR_ASSERT(!fd->closed);
fd->closed = 1;
close(fd->fd);
if (fd->on_done_closure) {
grpc_iomgr_add_callback(fd->on_done_closure);
@ -426,7 +429,8 @@ void grpc_fd_end_poll(grpc_fd_watcher *watcher, int got_read, int got_write) {
if (kick) {
maybe_wake_one_watcher_locked(fd);
}
if (grpc_fd_is_orphaned(fd) && !has_watchers(fd)) {
if (grpc_fd_is_orphaned(fd) && !has_watchers(fd) && !fd->closed) {
fd->closed = 1;
close(fd->fd);
if (fd->on_done_closure != NULL) {
grpc_iomgr_add_callback(fd->on_done_closure);

@ -60,6 +60,7 @@ struct grpc_fd {
gpr_mu set_state_mu;
gpr_atm shutdown;
int closed;
/* The watcher list.

@ -142,6 +142,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
static void finish_shutdown(grpc_tcp_server *s) {
s->shutdown_complete(s->shutdown_complete_arg);
s->shutdown_complete = NULL;
gpr_mu_destroy(&s->mu);
@ -157,6 +158,7 @@ static void destroyed_port(void *server, int success) {
gpr_mu_unlock(&s->mu);
finish_shutdown(s);
} else {
GPR_ASSERT(s->destroyed_ports < s->nports);
gpr_mu_unlock(&s->mu);
}
}

@ -79,6 +79,8 @@ struct grpc_tcp_server {
/* active port count: how many ports are actually still listening */
int active_ports;
/* number of iomgr callbacks that have been explicitly scheduled during shutdown */
int iomgr_callbacks_pending;
/* all listening ports */
server_port *ports;
@ -93,6 +95,7 @@ grpc_tcp_server *grpc_tcp_server_create(void) {
gpr_mu_init(&s->mu);
gpr_cv_init(&s->cv);
s->active_ports = 0;
s->iomgr_callbacks_pending = 0;
s->cb = NULL;
s->cb_arg = NULL;
s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
@ -112,10 +115,10 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s,
for (i = 0; i < s->nports; i++) {
server_port *sp = &s->ports[i];
sp->shutting_down = 1;
grpc_winsocket_shutdown(sp->socket);
s->iomgr_callbacks_pending += grpc_winsocket_shutdown(sp->socket);
}
/* This happens asynchronously. Wait while that happens. */
while (s->active_ports) {
while (s->active_ports || s->iomgr_callbacks_pending) {
gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future(GPR_CLOCK_REALTIME));
}
gpr_mu_unlock(&s->mu);
@ -254,8 +257,16 @@ static void on_accept(void *arg, int from_iocp) {
/* The general mechanism for shutting down is to queue abortion calls. While
this is necessary in the read/write case, it's useless for the accept
case. Let's do nothing. */
if (!from_iocp) return;
case. We only need to adjust the pending callback count */
if (!from_iocp) {
gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->iomgr_callbacks_pending > 0);
if (0 == --sp->server->iomgr_callbacks_pending) {
gpr_cv_broadcast(&sp->server->cv);
}
gpr_mu_unlock(&sp->server->mu);
return;
}
/* The IOCP notified us of a completed operation. Let's grab the results,
and act accordingly. */
@ -264,11 +275,12 @@ static void on_accept(void *arg, int from_iocp) {
&transfered_bytes, FALSE, &flags);
if (!wsa_success) {
if (sp->shutting_down) {
/* During the shutdown case, we ARE expecting an error. So that's swell,
/* During the shutdown case, we ARE expecting an error. So that's well,
and we can wake up the shutdown thread. */
sp->shutting_down = 0;
sp->socket->read_info.outstanding = 0;
gpr_mu_lock(&sp->server->mu);
GPR_ASSERT(sp->server->active_ports > 0);
if (0 == --sp->server->active_ports) {
gpr_cv_broadcast(&sp->server->cv);
}

@ -368,7 +368,14 @@ static grpc_endpoint_write_status win_write(grpc_endpoint *ep,
return GRPC_ENDPOINT_WRITE_PENDING;
}
static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *pollset) {
static void win_add_to_pollset(grpc_endpoint *ep, grpc_pollset *ps) {
(void) ps;
grpc_tcp *tcp = (grpc_tcp *) ep;
grpc_iocp_add_socket(tcp->socket);
}
static void win_add_to_pollset_set(grpc_endpoint *ep, grpc_pollset_set *pss) {
(void) pss;
grpc_tcp *tcp = (grpc_tcp *) ep;
grpc_iocp_add_socket(tcp->socket);
}
@ -402,8 +409,9 @@ static char *win_get_peer(grpc_endpoint *ep) {
}
static grpc_endpoint_vtable vtable = {win_notify_on_read, win_write,
win_add_to_pollset, win_shutdown,
win_destroy, win_get_peer};
win_add_to_pollset, win_add_to_pollset_set,
win_shutdown, win_destroy,
win_get_peer};
grpc_endpoint *grpc_tcp_create(grpc_winsocket *socket, char *peer_string) {
grpc_tcp *tcp = (grpc_tcp *) gpr_malloc(sizeof(grpc_tcp));

@ -95,6 +95,8 @@ gpr_stack_lockfree *gpr_stack_lockfree_create(int entries) {
memset(&stack->pushed, 0, sizeof(stack->pushed));
#endif
GPR_ASSERT(sizeof(stack->entries->atm) == sizeof(stack->entries->contents));
/* Point the head at reserved dummy entry */
stack->head.contents.index = INVALID_ENTRY_INDEX;
return stack;
@ -108,11 +110,15 @@ void gpr_stack_lockfree_destroy(gpr_stack_lockfree *stack) {
int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
lockfree_node head;
lockfree_node newhead;
lockfree_node curent;
lockfree_node newent;
/* First fill in the entry's index and aba ctr for new head */
newhead.contents.index = (gpr_uint16)entry;
/* Also post-increment the aba_ctr */
newhead.contents.aba_ctr = stack->entries[entry].contents.aba_ctr++;
curent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
newhead.contents.aba_ctr = ++curent.contents.aba_ctr;
gpr_atm_no_barrier_store(&stack->entries[entry].atm, curent.atm);
#ifndef NDEBUG
/* Check for double push */
@ -131,7 +137,9 @@ int gpr_stack_lockfree_push(gpr_stack_lockfree *stack, int entry) {
/* Atomically get the existing head value for use */
head.atm = gpr_atm_no_barrier_load(&(stack->head.atm));
/* Point to it */
stack->entries[entry].contents.index = head.contents.index;
newent.atm = gpr_atm_no_barrier_load(&stack->entries[entry].atm);
newent.contents.index = head.contents.index;
gpr_atm_no_barrier_store(&stack->entries[entry].atm, newent.atm);
} while (!gpr_atm_rel_cas(&(stack->head.atm), head.atm, newhead.atm));
/* Use rel_cas above to make sure that entry index is set properly */
return head.contents.index == INVALID_ENTRY_INDEX;

@ -40,7 +40,6 @@
#include <grpc/support/log.h>
#include <grpc/support/string_util.h>
#include "src/core/census/grpc_context.h"
#include "src/core/channel/channel_stack.h"
#include "src/core/iomgr/alarm.h"
#include "src/core/profiling/timers.h"
@ -348,7 +347,8 @@ grpc_call *grpc_call_create(grpc_channel *channel, grpc_completion_queue *cq,
}
grpc_call_stack_init(channel_stack, server_transport_data, initial_op_ptr,
CALL_STACK_FROM_CALL(call));
if (gpr_time_cmp(send_deadline, gpr_inf_future(send_deadline.clock_type)) != 0) {
if (gpr_time_cmp(send_deadline, gpr_inf_future(send_deadline.clock_type)) !=
0) {
set_deadline_alarm(call, send_deadline);
}
return call;
@ -1283,8 +1283,9 @@ static void set_deadline_alarm(grpc_call *call, gpr_timespec deadline) {
}
GRPC_CALL_INTERNAL_REF(call, "alarm");
call->have_alarm = 1;
grpc_alarm_init(&call->alarm, gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), call_alarm, call,
gpr_now(GPR_CLOCK_MONOTONIC));
grpc_alarm_init(&call->alarm,
gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC),
call_alarm, call, gpr_now(GPR_CLOCK_MONOTONIC));
}
/* we offset status by a small amount when storing it into transport metadata
@ -1319,15 +1320,17 @@ static gpr_uint32 decode_compression(grpc_mdelem *md) {
grpc_compression_algorithm algorithm;
void *user_data = grpc_mdelem_get_user_data(md, destroy_compression);
if (user_data) {
algorithm = ((grpc_compression_level)(gpr_intptr)user_data) - COMPRESS_OFFSET;
algorithm =
((grpc_compression_level)(gpr_intptr)user_data) - COMPRESS_OFFSET;
} else {
const char *md_c_str = grpc_mdstr_as_c_string(md->value);
if (!grpc_compression_algorithm_parse(md_c_str, &algorithm)) {
gpr_log(GPR_ERROR, "Invalid compression algorithm: '%s'", md_c_str);
assert(0);
}
grpc_mdelem_set_user_data(md, destroy_compression,
(void *)(gpr_intptr)(algorithm + COMPRESS_OFFSET));
grpc_mdelem_set_user_data(
md, destroy_compression,
(void *)(gpr_intptr)(algorithm + COMPRESS_OFFSET));
}
return algorithm;
}

@ -107,8 +107,11 @@ void grpc_init(void) {
grpc_security_pre_init();
grpc_iomgr_init();
grpc_tracer_init("GRPC_TRACE");
if (census_initialize(CENSUS_NONE)) {
gpr_log(GPR_ERROR, "Could not initialize census.");
/* Only initialize census if noone else has. */
if (census_enabled() == CENSUS_FEATURE_NONE) {
if (census_initialize(census_supported())) { /* enable all features. */
gpr_log(GPR_ERROR, "Could not initialize census.");
}
}
grpc_timers_global_init();
for (plugin = g_plugins_head; plugin != NULL; plugin = plugin->next) {

@ -1271,6 +1271,8 @@ static void done_request_event(void *req, grpc_cq_completion *c) {
} else {
gpr_free(req);
}
server_unref(server);
}
static void fail_call(grpc_server *server, requested_call *rc) {
@ -1283,6 +1285,7 @@ static void fail_call(grpc_server *server, requested_call *rc) {
rc->data.registered.initial_metadata->count = 0;
break;
}
server_ref(server);
grpc_cq_end_op(rc->cq_for_notification, rc->tag, 0, done_request_event, rc,
&rc->completion);
}
@ -1293,6 +1296,8 @@ static void publish_registered_or_batch(grpc_call *call, int success,
grpc_call_stack_element(grpc_call_get_call_stack(call), 0);
requested_call *rc = prc;
call_data *calld = elem->call_data;
channel_data *chand = elem->channel_data;
server_ref(chand->server);
grpc_cq_end_op(calld->cq_new, rc->tag, success, done_request_event, rc,
&rc->completion);
GRPC_CALL_INTERNAL_UNREF(call, "server", 0);

@ -39,7 +39,6 @@
#include <grpc/support/log.h>
#include <grpc/support/slice.h>
#include "src/core/census/grpc_context.h"
#include "src/core/profiling/timers.h"
#include <grpc++/channel_arguments.h>
#include <grpc++/client_context.h>
@ -69,7 +68,7 @@ Call Channel::CreateCall(const RpcMethod& method, ClientContext* context,
? target_.c_str()
: context->authority().c_str(),
context->raw_deadline());
grpc_census_call_set_context(c_call, context->get_census_context());
grpc_census_call_set_context(c_call, context->census_context());
GRPC_TIMER_MARK(GRPC_PTAG_CPP_CALL_CREATED, c_call);
context->set_call(c_call, shared_from_this());
return Call(c_call, this, cq);

@ -179,4 +179,8 @@ std::shared_ptr<const AuthContext> ServerContext::auth_context() const {
return auth_context_;
}
const struct census_context* ServerContext::census_context() const {
return grpc_census_call_get_context(call_);
}
} // namespace grpc

@ -9,7 +9,7 @@ cd /d %~dp0
@call "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" x86
@rem Build the C# native extension
msbuild ..\..\vsprojects\grpc.sln /t:grpc_csharp_ext /p:PlatformToolset=v120 || goto :error
msbuild ..\..\vsprojects\grpc_csharp_ext.sln /p:PlatformToolset=v120 || goto :error
msbuild Grpc.sln /p:Configuration=Debug || goto :error
msbuild Grpc.sln /p:Configuration=Release || goto :error

@ -41,7 +41,8 @@ var interop_server = require('../interop/interop_server.js');
function runTest(iterations, callback) {
var testServer = interop_server.getServer(0, false);
testServer.server.listen();
var client = new testProto.TestService('localhost:' + testServer.port);
var client = new testProto.TestService('localhost:' + testServer.port,
grpc.Credentials.createInsecure());
function runIterations(finish) {
var start = process.hrtime();

@ -61,7 +61,8 @@ var interop_server = require('../interop/interop_server.js');
function runTest(concurrent_calls, seconds, callback) {
var testServer = interop_server.getServer(0, false);
testServer.server.listen();
var client = new testProto.TestService('localhost:' + testServer.port);
var client = new testProto.TestService('localhost:' + testServer.port,
grpc.Credentials.createInsecure());
var warmup_num = 100;

@ -40,7 +40,8 @@ var path = require('path');
var _ = require('lodash');
var grpc = require('..');
var examples = grpc.load(__dirname + '/route_guide.proto').examples;
var client = new examples.RouteGuide('localhost:50051');
var client = new examples.RouteGuide('localhost:50051',
grpc.Credentials.createInsecure());
var COORD_FACTOR = 1e7;

@ -38,7 +38,8 @@ var examples = grpc.load(__dirname + '/stock.proto').examples;
* This exports a client constructor for the Stock service. The usage looks like
*
* var StockClient = require('stock_client.js');
* var stockClient = new StockClient(server_address);
* var stockClient = new StockClient(server_address,
* grpc.Credentials.createInsecure());
* stockClient.getLastTradePrice({symbol: 'GOOG'}, function(error, response) {
* console.log(error || response);
* });

@ -98,31 +98,30 @@ NAN_METHOD(Channel::New) {
if (args.IsConstructCall()) {
if (!args[0]->IsString()) {
return NanThrowTypeError("Channel expects a string and an object");
return NanThrowTypeError(
"Channel expects a string, a credential and an object");
}
grpc_channel *wrapped_channel;
// Owned by the Channel object
NanUtf8String *host = new NanUtf8String(args[0]);
NanUtf8String *host_override = NULL;
if (args[1]->IsUndefined()) {
grpc_credentials *creds;
if (!Credentials::HasInstance(args[1])) {
return NanThrowTypeError(
"Channel's second argument must be a credential");
}
Credentials *creds_object = ObjectWrap::Unwrap<Credentials>(
args[1]->ToObject());
creds = creds_object->GetWrappedCredentials();
grpc_channel_args *channel_args_ptr;
if (args[2]->IsUndefined()) {
channel_args_ptr = NULL;
wrapped_channel = grpc_insecure_channel_create(**host, NULL);
} else if (args[1]->IsObject()) {
grpc_credentials *creds = NULL;
Handle<Object> args_hash(args[1]->ToObject()->Clone());
} else if (args[2]->IsObject()) {
Handle<Object> args_hash(args[2]->ToObject()->Clone());
if (args_hash->HasOwnProperty(NanNew(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG))) {
host_override = new NanUtf8String(args_hash->Get(NanNew(GRPC_SSL_TARGET_NAME_OVERRIDE_ARG)));
}
if (args_hash->HasOwnProperty(NanNew("credentials"))) {
Handle<Value> creds_value = args_hash->Get(NanNew("credentials"));
if (!Credentials::HasInstance(creds_value)) {
return NanThrowTypeError(
"credentials arg must be a Credentials object");
}
Credentials *creds_object =
ObjectWrap::Unwrap<Credentials>(creds_value->ToObject());
creds = creds_object->GetWrappedCredentials();
args_hash->Delete(NanNew("credentials"));
}
Handle<Array> keys(args_hash->GetOwnPropertyNames());
grpc_channel_args channel_args;
channel_args.num_args = keys->Length();
@ -149,16 +148,19 @@ NAN_METHOD(Channel::New) {
return NanThrowTypeError("Arg values must be strings");
}
}
if (creds == NULL) {
wrapped_channel = grpc_insecure_channel_create(**host, &channel_args);
} else {
wrapped_channel =
grpc_secure_channel_create(creds, **host, &channel_args);
}
free(channel_args.args);
channel_args_ptr = &channel_args;
} else {
return NanThrowTypeError("Channel expects a string and an object");
}
if (creds == NULL) {
wrapped_channel = grpc_insecure_channel_create(**host, channel_args_ptr);
} else {
wrapped_channel =
grpc_secure_channel_create(creds, **host, channel_args_ptr);
}
if (channel_args_ptr != NULL) {
free(channel_args_ptr->args);
}
Channel *channel;
if (host_override == NULL) {
channel = new Channel(wrapped_channel, host);
@ -168,8 +170,8 @@ NAN_METHOD(Channel::New) {
channel->Wrap(args.This());
NanReturnValue(args.This());
} else {
const int argc = 2;
Local<Value> argv[argc] = {args[0], args[1]};
const int argc = 3;
Local<Value> argv[argc] = {args[0], args[1], args[2]};
NanReturnValue(constructor->GetFunction()->NewInstance(argc, argv));
}
}

@ -81,6 +81,8 @@ void Credentials::Init(Handle<Object> exports) {
NanNew<FunctionTemplate>(CreateGce)->GetFunction());
ctr->Set(NanNew("createIam"),
NanNew<FunctionTemplate>(CreateIam)->GetFunction());
ctr->Set(NanNew("createInsecure"),
NanNew<FunctionTemplate>(CreateInsecure)->GetFunction());
constructor = new NanCallback(ctr);
exports->Set(NanNew("Credentials"), ctr);
}
@ -92,9 +94,6 @@ bool Credentials::HasInstance(Handle<Value> val) {
Handle<Value> Credentials::WrapStruct(grpc_credentials *credentials) {
NanEscapableScope();
if (credentials == NULL) {
return NanEscapeScope(NanNull());
}
const int argc = 1;
Handle<Value> argv[argc] = {
NanNew<External>(reinterpret_cast<void *>(credentials))};
@ -128,7 +127,11 @@ NAN_METHOD(Credentials::New) {
NAN_METHOD(Credentials::CreateDefault) {
NanScope();
NanReturnValue(WrapStruct(grpc_google_default_credentials_create()));
grpc_credentials *creds = grpc_google_default_credentials_create();
if (creds == NULL) {
NanReturnNull();
}
NanReturnValue(WrapStruct(creds));
}
NAN_METHOD(Credentials::CreateSsl) {
@ -152,9 +155,12 @@ NAN_METHOD(Credentials::CreateSsl) {
return NanThrowTypeError(
"createSSl's third argument must be a Buffer if provided");
}
NanReturnValue(WrapStruct(grpc_ssl_credentials_create(
root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair)));
grpc_credentials *creds = grpc_ssl_credentials_create(
root_certs, key_cert_pair.private_key == NULL ? NULL : &key_cert_pair);
if (creds == NULL) {
NanReturnNull();
}
NanReturnValue(WrapStruct(creds));
}
NAN_METHOD(Credentials::CreateComposite) {
@ -169,13 +175,21 @@ NAN_METHOD(Credentials::CreateComposite) {
}
Credentials *creds1 = ObjectWrap::Unwrap<Credentials>(args[0]->ToObject());
Credentials *creds2 = ObjectWrap::Unwrap<Credentials>(args[1]->ToObject());
NanReturnValue(WrapStruct(grpc_composite_credentials_create(
creds1->wrapped_credentials, creds2->wrapped_credentials)));
grpc_credentials *creds = grpc_composite_credentials_create(
creds1->wrapped_credentials, creds2->wrapped_credentials);
if (creds == NULL) {
NanReturnNull();
}
NanReturnValue(WrapStruct(creds));
}
NAN_METHOD(Credentials::CreateGce) {
NanScope();
NanReturnValue(WrapStruct(grpc_compute_engine_credentials_create()));
grpc_credentials *creds = grpc_compute_engine_credentials_create();
if (creds == NULL) {
NanReturnNull();
}
NanReturnValue(WrapStruct(creds));
}
NAN_METHOD(Credentials::CreateIam) {
@ -188,8 +202,17 @@ NAN_METHOD(Credentials::CreateIam) {
}
NanUtf8String auth_token(args[0]);
NanUtf8String auth_selector(args[1]);
NanReturnValue(
WrapStruct(grpc_iam_credentials_create(*auth_token, *auth_selector)));
grpc_credentials *creds = grpc_iam_credentials_create(*auth_token,
*auth_selector);
if (creds == NULL) {
NanReturnNull();
}
NanReturnValue(WrapStruct(creds));
}
NAN_METHOD(Credentials::CreateInsecure) {
NanScope();
NanReturnValue(WrapStruct(NULL));
}
} // namespace node

@ -68,6 +68,7 @@ class Credentials : public ::node::ObjectWrap {
static NAN_METHOD(CreateGce);
static NAN_METHOD(CreateFake);
static NAN_METHOD(CreateIam);
static NAN_METHOD(CreateInsecure);
static NanCallback *constructor;
// Used for typechecking instances of this javascript class
static v8::Persistent<v8::FunctionTemplate> fun_tpl;

@ -397,6 +397,7 @@ var test_cases = {
function runTest(address, host_override, test_case, tls, test_ca, done) {
// TODO(mlumish): enable TLS functionality
var options = {};
var creds;
if (tls) {
var ca_path;
if (test_ca) {
@ -405,13 +406,14 @@ function runTest(address, host_override, test_case, tls, test_ca, done) {
ca_path = process.env.SSL_CERT_FILE;
}
var ca_data = fs.readFileSync(ca_path);
var creds = grpc.Credentials.createSsl(ca_data);
options.credentials = creds;
creds = grpc.Credentials.createSsl(ca_data);
if (host_override) {
options['grpc.ssl_target_name_override'] = host_override;
}
} else {
creds = grpc.Credentials.createInsecure();
}
var client = new testProto.TestService(address, options);
var client = new testProto.TestService(address, creds, options);
test_cases[test_case](client, done);
}

@ -531,11 +531,13 @@ exports.makeClientConstructor = function(methods, serviceName) {
* Create a client with the given methods
* @constructor
* @param {string} address The address of the server to connect to
* @param {grpc.Credentials} credentials Credentials to use to connect
* to the server
* @param {Object} options Options to pass to the underlying channel
* @param {function(string, Object, function)=} updateMetadata function to
* update the metadata for each request
*/
function Client(address, options, updateMetadata) {
function Client(address, credentials, options, updateMetadata) {
if (!updateMetadata) {
updateMetadata = function(uri, metadata, callback) {
callback(null, metadata);
@ -545,7 +547,7 @@ exports.makeClientConstructor = function(methods, serviceName) {
options = {};
}
options['grpc.primary_user_agent'] = 'grpc-node/' + version;
this.channel = new grpc.Channel(address, options);
this.channel = new grpc.Channel(address, credentials, options);
this.server_address = address.replace(/\/$/, '');
this.auth_uri = this.server_address + '/' + serviceName;
this.updateMetadata = updateMetadata;

@ -48,6 +48,8 @@ function getDeadline(timeout_secs) {
return deadline;
}
var insecureCreds = grpc.Credentials.createInsecure();
describe('call', function() {
var channel;
var server;
@ -55,7 +57,7 @@ describe('call', function() {
server = new grpc.Server();
var port = server.addHttp2Port('localhost:0');
server.start();
channel = new grpc.Channel('localhost:' + port);
channel = new grpc.Channel('localhost:' + port, insecureCreds);
});
after(function() {
server.shutdown();
@ -82,7 +84,7 @@ describe('call', function() {
});
});
it('should fail with a closed channel', function() {
var local_channel = new grpc.Channel('hostname');
var local_channel = new grpc.Channel('hostname', insecureCreds);
local_channel.close();
assert.throws(function() {
new grpc.Call(channel, 'method');

@ -36,11 +36,13 @@
var assert = require('assert');
var grpc = require('bindings')('grpc.node');
var insecureCreds = grpc.Credentials.createInsecure();
describe('channel', function() {
describe('constructor', function() {
it('should require a string for the first argument', function() {
assert.doesNotThrow(function() {
new grpc.Channel('hostname');
new grpc.Channel('hostname', insecureCreds);
});
assert.throws(function() {
new grpc.Channel();
@ -49,38 +51,49 @@ describe('channel', function() {
new grpc.Channel(5);
});
});
it('should accept an object for the second parameter', function() {
it('should require a credential for the second argument', function() {
assert.doesNotThrow(function() {
new grpc.Channel('hostname', {});
new grpc.Channel('hostname', insecureCreds);
});
assert.throws(function() {
new grpc.Channel('hostname', 5);
});
assert.throws(function() {
new grpc.Channel('hostname');
});
});
it('should accept an object for the third argument', function() {
assert.doesNotThrow(function() {
new grpc.Channel('hostname', insecureCreds, {});
});
assert.throws(function() {
new grpc.Channel('hostname', insecureCreds, 'abc');
});
});
it('should only accept objects with string or int values', function() {
assert.doesNotThrow(function() {
new grpc.Channel('hostname', {'key' : 'value'});
new grpc.Channel('hostname', insecureCreds,{'key' : 'value'});
});
assert.doesNotThrow(function() {
new grpc.Channel('hostname', {'key' : 5});
new grpc.Channel('hostname', insecureCreds, {'key' : 5});
});
assert.throws(function() {
new grpc.Channel('hostname', {'key' : null});
new grpc.Channel('hostname', insecureCreds, {'key' : null});
});
assert.throws(function() {
new grpc.Channel('hostname', {'key' : new Date()});
new grpc.Channel('hostname', insecureCreds, {'key' : new Date()});
});
});
});
describe('close', function() {
it('should succeed silently', function() {
var channel = new grpc.Channel('hostname', {});
var channel = new grpc.Channel('hostname', insecureCreds, {});
assert.doesNotThrow(function() {
channel.close();
});
});
it('should be idempotent', function() {
var channel = new grpc.Channel('hostname', {});
var channel = new grpc.Channel('hostname', insecureCreds, {});
assert.doesNotThrow(function() {
channel.close();
channel.close();
@ -89,7 +102,7 @@ describe('channel', function() {
});
describe('getTarget', function() {
it('should return a string', function() {
var channel = new grpc.Channel('localhost', {});
var channel = new grpc.Channel('localhost', insecureCreds, {});
assert.strictEqual(typeof channel.getTarget(), 'string');
});
});

@ -57,6 +57,8 @@ function multiDone(done, count) {
};
}
var insecureCreds = grpc.Credentials.createInsecure();
describe('end-to-end', function() {
var server;
var channel;
@ -64,7 +66,7 @@ describe('end-to-end', function() {
server = new grpc.Server();
var port_num = server.addHttp2Port('0.0.0.0:0');
server.start();
channel = new grpc.Channel('localhost:' + port_num);
channel = new grpc.Channel('localhost:' + port_num, insecureCreds);
});
after(function() {
server.shutdown();

@ -56,7 +56,8 @@ describe('Health Checking', function() {
before(function() {
var port_num = healthServer.bind('0.0.0.0:0');
healthServer.start();
healthClient = new health.Client('localhost:' + port_num);
healthClient = new health.Client('localhost:' + port_num,
grpc.Credentials.createInsecure());
});
after(function() {
healthServer.shutdown();

@ -53,7 +53,8 @@ describe('Math client', function() {
before(function(done) {
var port_num = server.bind('0.0.0.0:0');
server.start();
math_client = new math.Math('localhost:' + port_num);
math_client = new math.Math('localhost:' + port_num,
grpc.Credentials.createInsecure());
done();
});
after(function() {

@ -124,7 +124,7 @@ describe('Echo service', function() {
});
var port = server.bind('localhost:0');
var Client = surface_client.makeProtobufClientConstructor(echo_service);
client = new Client('localhost:' + port);
client = new Client('localhost:' + port, grpc.Credentials.createInsecure());
server.start();
});
after(function() {
@ -169,7 +169,8 @@ describe('Generic client and server', function() {
var port = server.bind('localhost:0');
server.start();
var Client = grpc.makeGenericClientConstructor(string_service_attrs);
client = new Client('localhost:' + port);
client = new Client('localhost:' + port,
grpc.Credentials.createInsecure());
});
after(function() {
server.shutdown();
@ -216,7 +217,7 @@ describe('Echo metadata', function() {
});
var port = server.bind('localhost:0');
var Client = surface_client.makeProtobufClientConstructor(test_service);
client = new Client('localhost:' + port);
client = new Client('localhost:' + port, grpc.Credentials.createInsecure());
server.start();
});
after(function() {
@ -337,7 +338,7 @@ describe('Other conditions', function() {
});
port = server.bind('localhost:0');
var Client = surface_client.makeProtobufClientConstructor(test_service);
client = new Client('localhost:' + port);
client = new Client('localhost:' + port, grpc.Credentials.createInsecure());
server.start();
});
after(function() {
@ -382,7 +383,8 @@ describe('Other conditions', function() {
};
var Client = surface_client.makeClientConstructor(test_service_attrs,
'TestService');
misbehavingClient = new Client('localhost:' + port);
misbehavingClient = new Client('localhost:' + port,
grpc.Credentials.createInsecure());
});
it('should respond correctly to a unary call', function(done) {
misbehavingClient.unary(badArg, function(err, data) {
@ -602,7 +604,7 @@ describe('Cancelling surface client', function() {
});
var port = server.bind('localhost:0');
var Client = surface_client.makeProtobufClientConstructor(mathService);
client = new Client('localhost:' + port);
client = new Client('localhost:' + port, grpc.Credentials.createInsecure());
server.start();
});
after(function() {

@ -8,11 +8,7 @@ Pod::Spec.new do |s|
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.prepare_command = <<-CMD
cd ../../../..
# TODO(jcanizales): Make only Objective-C plugin.
make plugins
cd -
protoc --plugin=protoc-gen-grpc=../../../../bins/opt/grpc_objective_c_plugin --objc_out=. --grpc_out=. *.proto
protoc --plugin=protoc-gen-grpc=../../../../bins/$CONFIG/grpc_objective_c_plugin --objc_out=. --grpc_out=. *.proto
CMD
s.subspec "Messages" do |ms|

@ -8,11 +8,7 @@ Pod::Spec.new do |s|
# Run protoc with the Objective-C and gRPC plugins to generate protocol messages and gRPC clients.
s.prepare_command = <<-CMD
cd ../../../..
# TODO(jcanizales): Make only Objective-C plugin.
make plugins
cd -
protoc --plugin=protoc-gen-grpc=../../../../bins/opt/grpc_objective_c_plugin --objc_out=. --grpc_out=. *.proto
protoc --plugin=protoc-gen-grpc=../../../../bins/$CONFIG/grpc_objective_c_plugin --objc_out=. --grpc_out=. *.proto
CMD
s.subspec "Messages" do |ms|

@ -43,7 +43,8 @@
// These are a few tests similar to InteropTests, but which use the generic gRPC client (GRPCCall)
// rather than a generated proto library on top of it.
static NSString * const kHostAddress = @"grpc-test.sandbox.google.com";
// grpc-test.sandbox.google.com
static NSString * const kHostAddress = @"http://localhost:5050";
static NSString * const kPackage = @"grpc.testing";
static NSString * const kService = @"TestService";

@ -83,8 +83,10 @@
RMTTestService *_service;
}
// grpc-test.sandbox.google.com
- (void)setUp {
_service = [[RMTTestService alloc] initWithHost:@"grpc-test.sandbox.google.com"];
_service = [[RMTTestService alloc] initWithHost:@"http://localhost:5050"];
}
// Tests as described here: https://github.com/grpc/grpc/blob/master/doc/interop-test-descriptions.md

@ -38,6 +38,12 @@
ReferencedContainer = "container:Tests.xcodeproj">
</BuildableReference>
<SkippedTests>
<Test
Identifier = "GRPCClientTests/testConnectionToRemoteServer">
</Test>
<Test
Identifier = "GRPCClientTests/testMetadata">
</Test>
<Test
Identifier = "LocalClearTextTests">
</Test>

@ -0,0 +1,39 @@
#!/bin/bash
# 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.
set -e
cd $(dirname $0)
# The local test server needs to be compiled before this because pod install of
# gRPC renames some C gRPC files and not the server's code references to them.
#
# Suppress error output because Cocoapods issue #3823 causes a flooding warning.
pod install 2>/dev/null

@ -32,9 +32,10 @@ set -e
cd $(dirname $0)
# TODO(jcanizales): Remove when Cocoapods issue #3823 is resolved.
export COCOAPODS_DISABLE_DETERMINISTIC_UUIDS=YES
pod install
# Run the tests server.
../../../bins/$CONFIG/interop_server --port=5050 &
# Kill it when this script exits.
trap 'kill -9 `jobs -p`' EXIT
# xcodebuild is very verbose. We filter its output and tell Bash to fail if any
# element of the pipe fails.

@ -2,3 +2,7 @@ MANIFEST
grpcio.egg-info/
build/
dist/
*.egg
*.egg/
*.eggs/
doc/

@ -0,0 +1,2 @@
graft grpc
include commands.py

@ -0,0 +1,76 @@
# 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.
"""Provides distutils command classes for the GRPC Python setup process."""
import os
import os.path
import sys
import setuptools
_CONF_PY_ADDENDUM = """
extensions.append('sphinx.ext.napoleon')
napoleon_google_docstring = True
napoleon_numpy_docstring = True
html_theme = 'sphinx_rtd_theme'
"""
class SphinxDocumentation(setuptools.Command):
"""Command to generate documentation via sphinx."""
description = ''
user_options = []
def initialize_options(self):
pass
def finalize_options(self):
pass
def run(self):
# We import here to ensure that setup.py has had a chance to install the
# relevant package eggs first.
import sphinx
import sphinx.apidoc
metadata = self.distribution.metadata
src_dir = os.path.join(
os.getcwd(), self.distribution.package_dir['grpc'])
sys.path.append(src_dir)
sphinx.apidoc.main([
'', '--force', '--full', '-H', metadata.name, '-A', metadata.author,
'-V', metadata.version, '-R', metadata.version,
'-o', os.path.join('doc', 'src'), src_dir])
conf_filepath = os.path.join('doc', 'src', 'conf.py')
with open(conf_filepath, 'a') as conf_file:
conf_file.write(_CONF_PY_ADDENDUM)
sphinx.main(['', os.path.join('doc', 'src'), os.path.join('doc', 'build')])

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

Loading…
Cancel
Save